OpenCOBOL 1.1pre-rel
cobc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2009 Keisuke Nishida
00003  * Copyright (C) 2007-2009 Roger While
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2, or (at your option)
00008  * any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this software; see the file COPYING.  If not, write to
00017  * the Free Software Foundation, 51 Franklin Street, Fifth Floor
00018  * Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include "config.h"
00022 #include "defaults.h"
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <stdarg.h>
00027 #include <string.h>
00028 #include <setjmp.h>
00029 #ifdef  HAVE_SYS_TYPES_H
00030 #include <sys/types.h>
00031 #endif
00032 #ifdef  HAVE_UNISTD_H
00033 #include <unistd.h>
00034 #endif
00035 #include <time.h>
00036 #include <sys/stat.h>
00037 #ifdef  HAVE_SIGNAL_H
00038 #include <signal.h>
00039 #endif
00040 
00041 #ifdef _WIN32
00042 #include <windows.h>            /* for GetTempPath, GetTempFileName */
00043 #endif
00044 
00045 #ifdef  HAVE_KPATHSEA_GETOPT_H
00046 #include <kpathsea/getopt.h>
00047 #else
00048 #ifdef  HAVE_GETOPT_H
00049 #include <getopt.h>
00050 #else
00051 #include "lib/getopt.h"
00052 #endif
00053 #endif
00054 
00055 #ifdef  HAVE_LOCALE_H
00056 #include <locale.h>
00057 #endif
00058 
00059 #include <tarstamp.h>
00060 
00061 #include "cobc.h"
00062 #include "tree.h"
00063 
00064 /* Compile level */
00065 enum cb_compile_level {
00066         CB_LEVEL_PREPROCESS = 1,
00067         CB_LEVEL_TRANSLATE,
00068         CB_LEVEL_COMPILE,
00069         CB_LEVEL_ASSEMBLE,
00070         CB_LEVEL_MODULE,
00071         CB_LEVEL_LIBRARY,
00072         CB_LEVEL_EXECUTABLE
00073 };
00074 
00075 /*
00076  * Global variables
00077  */
00078 
00079 int     cb_source_format = CB_FORMAT_FIXED;
00080 
00081 #ifdef  COB_EBCDIC_MACHINE
00082 int     cb_display_sign = COB_DISPLAY_SIGN_EBCDIC;      /* 1 */
00083 #else
00084 int     cb_display_sign = COB_DISPLAY_SIGN_ASCII;       /* 0 */
00085 #endif
00086 
00087 #undef  COB_EXCEPTION
00088 #define COB_EXCEPTION(code,tag,name,critical) {name, 0x##code, 0},
00089 struct cb_exception cb_exception_table[] = {
00090         {NULL, 0, 0},           /* CB_EC_ZERO */
00091 #include <libcob/exception.def>
00092         {NULL, 0, 0}            /* CB_EC_MAX */
00093 };
00094 #undef  COB_EXCEPTION
00095 
00096 #undef  CB_FLAG
00097 #define CB_FLAG(var,name,doc)           int var = 0;
00098 #include "flag.def"
00099 #undef  CB_FLAG
00100 
00101 #undef  CB_WARNDEF
00102 #define CB_WARNDEF(var,name,wall,doc)   int var = 0;
00103 #include "warning.def"
00104 #undef  CB_WARNDEF
00105 
00106 #ifdef  _MSC_VER
00107 #define PATHSEPS ";"
00108 #else
00109 #define PATHSEPS ":"
00110 #endif
00111 
00112 int                     cb_id = 1;
00113 int                     cb_attr_id = 1;
00114 int                     cb_literal_id = 1;
00115 int                     cb_field_id = 1;
00116 int                     cb_storage_id = 1;
00117 int                     cb_flag_main = 0;
00118 
00119 int                     errorcount = 0;
00120 int                     warningcount = 0;
00121 int                     alt_ebcdic = 0;
00122 int                     optimize_flag = 0;
00123 
00124 char                    *cb_source_file = NULL;
00125 char                    *cb_oc_build_stamp = NULL;
00126 char                    *source_name;
00127 char                    *demangle_name;
00128 int                     cb_source_line = 0;
00129 
00130 FILE                    *cb_storage_file;
00131 char                    *cb_storage_file_name;
00132 
00133 FILE                    *cb_listing_file = NULL;
00134 FILE                    *cb_depend_file = NULL;
00135 char                    *cb_depend_target = NULL;
00136 struct cb_text_list     *cb_depend_list = NULL;
00137 struct cb_text_list     *cb_include_list = NULL;
00138 struct cb_text_list     *cb_extension_list = NULL;
00139 
00140 int                     cb_saveargc;
00141 char                    **cb_saveargv;
00142 
00143 const char              *cob_config_dir;
00144 
00145 /*
00146  * Local variables
00147  */
00148 
00149 static const char       *const cob_csyns[] = {
00150         "NULL",
00151         "L_initextern",
00152         "LRET_initextern",
00153 #ifndef __GNUC__
00154         "P_switch",
00155 #endif
00156         "alignof",
00157         "asm",
00158         "auto",
00159         "break",
00160         "case",
00161         "char",
00162         "const",
00163         "continue",
00164         "default",
00165         "do",
00166         "double",
00167         "else",
00168         "enum",
00169         "exit_program",
00170         "extern",
00171         "float",
00172         "for",
00173         "frame_pointer",
00174         "frame_stack",
00175         "goto",
00176         "if",
00177         "inline",
00178         "int",
00179         "long",
00180         "offsetof",
00181         "register",
00182         "restrict",
00183         "return",
00184         "short",
00185         "signed",
00186         "sizeof",
00187         "static",
00188         "struct",
00189         "switch",
00190         "typedef",
00191         "typeof",
00192         "union",
00193         "unsigned",
00194         "void",
00195         "volatile",
00196         "_Bool",
00197         "_Complex",
00198         "_Imaginary"
00199 };
00200 
00201 #define COB_NUM_CSYNS   sizeof(cob_csyns) / sizeof(char *)
00202 
00203 static enum cb_compile_level    cb_compile_level = 0;
00204 static enum cb_compile_level    local_level = 0;
00205 
00206 static size_t           iparams = 0;
00207 static int              iargs;
00208 static char             *cobcpy = NULL;
00209 static char             *save_temps_dir = NULL;
00210 
00211 static jmp_buf          cob_jmpbuf;
00212 
00213 static int              wants_nonfinal = 0;
00214 static int              cb_flag_module = 0;
00215 static int              cb_flag_library = 0;
00216 static int              save_temps = 0;
00217 static int              save_csrc = 0;
00218 static int              verbose_output = 0;
00219 static int              cob_iteration = 0;
00220 #ifndef _WIN32
00221 static pid_t            cob_process_id = 0;
00222 #endif
00223 
00224 static int              strip_output = 0;
00225 static int              gflag_set = 0;
00226 
00227 static char             *output_name;
00228 
00229 static const char       *cob_tmpdir;                    /* /tmp */
00230 
00231 static struct filename  *file_list;
00232 
00233 /* NOTE fcopts MUST have at least one leading space */
00234 #if defined (__GNUC__) && (__GNUC__ >= 3)
00235 static const char fcopts[] = " -finline-functions -fno-gcse -freorder-blocks ";
00236 #elif defined(__xlc__)
00237 static const char fcopts[] = " -Q -qro -qroconst ";
00238 #else
00239 static const char fcopts[] = " ";
00240 #endif
00241 
00242 #if defined (__GNUC__) && (__GNUC__ >= 3)
00243 static const char       gccpipe[] = "-pipe";
00244 #else
00245 static const char       gccpipe[] = "\0";
00246 #endif
00247 
00248 #ifdef  HAVE_SIGNAL_H
00249 typedef void (*cob_sighandler_t) (int);
00250 static cob_sighandler_t         hupsig = NULL;
00251 static cob_sighandler_t         intsig = NULL;
00252 static cob_sighandler_t         qutsig = NULL;
00253 #endif
00254 
00255 static const char short_options[] = "hVvECScbmxOgwo:t:I:L:l:D:";
00256 
00257 static const struct option long_options[] = {
00258         {"help", no_argument, NULL, 'h'},
00259         {"version", no_argument, NULL, 'V'},
00260 /* getopt_long_only has a problem with eg. -xv - remove
00261         {"verbose", no_argument, NULL, 'v'},
00262 */
00263         {"list-reserved", no_argument, NULL, 'R'},
00264         {"list-intrinsics", no_argument, NULL, 'Q'},
00265         {"list-mnemonics", no_argument, NULL, 'q'},
00266         {"save-temps", optional_argument, NULL, '_'},
00267         {"std", required_argument, NULL, '$'},
00268         {"conf", required_argument, NULL, '&'},
00269         {"debug", no_argument, NULL, 'd'},
00270         {"ext", required_argument, NULL, 'e'},
00271         {"free", no_argument, &cb_source_format, CB_FORMAT_FREE},
00272         {"fixed", no_argument, &cb_source_format, CB_FORMAT_FIXED},
00273         {"static", no_argument, &cb_flag_static_call, 1},
00274         {"dynamic", no_argument, &cb_flag_static_call, 0},
00275         {"O2", no_argument, NULL, '2'},
00276         {"Os", no_argument, NULL, 's'},
00277         {"MT", required_argument, NULL, '%'},
00278         {"MF", required_argument, NULL, '@'},
00279 #undef  CB_FLAG
00280 #define CB_FLAG(var,name,doc)                   \
00281         {"f"name, no_argument, &var, 1},        \
00282         {"fno-"name, no_argument, &var, 0},
00283 #include "flag.def"
00284 #undef  CB_FLAG
00285         {"Wall", no_argument, NULL, 'W'},
00286         {"W", no_argument, NULL, 'Z'},
00287 #undef  CB_WARNDEF
00288 #define CB_WARNDEF(var,name,wall,doc)           \
00289         {"W"name, no_argument, &var, 1},        \
00290         {"Wno-"name, no_argument, &var, 0},
00291 #include "warning.def"
00292 #undef  CB_WARNDEF
00293         {NULL, 0, NULL, 0}
00294 };
00295 
00296 static const char       *cob_cc;                                /* gcc */
00297 static char             cob_cflags[COB_SMALL_BUFF];             /* -I... */
00298 static char             cob_libs[COB_MEDIUM_BUFF];              /* -L... -lcob */
00299 static char             cob_define_flags[COB_SMALL_BUFF];       /* -D... */
00300 static const char       *cob_ldflags;
00301 static const char       *cob_copy_dir;
00302 
00303 /* cobc functions */
00304 
00305 /*
00306  * Global functions
00307  */
00308 
00309 void
00310 cobc_abort (const char *filename, const int linenum)
00311 {
00312         fprintf (stderr, "%s:%d: Internal compiler error\n", filename, linenum);
00313         (void)longjmp (cob_jmpbuf, 1);
00314 }
00315 
00316 void
00317 cobc_tree_cast_error (cb_tree x, const char *filen, const int linenum, const int tagnum)
00318 {
00319         fprintf (stderr, "%s:%d: Invalid type cast from '%s'\n",
00320                 filen, linenum, x ? cb_name (x) : "null");
00321         fprintf (stderr, "Tag 1 %d Tag 2 %d\n", x ? CB_TREE_TAG(x) : 0,
00322                 tagnum);
00323         (void)longjmp (cob_jmpbuf, 1);
00324 }
00325 
00326 void *
00327 cobc_malloc (const size_t size)
00328 {
00329         void *mptr;
00330 
00331         mptr = calloc (1, size);
00332         if (!mptr) {
00333                 fprintf (stderr, "Cannot allocate %d bytes of memory - Aborting\n", (int)size);
00334                 fflush (stderr);
00335                 (void)longjmp (cob_jmpbuf, 1);
00336         }
00337         return mptr;
00338 }
00339 
00340 void *
00341 cobc_realloc (void *prevptr, const size_t size)
00342 {
00343         void *mptr;
00344 
00345         mptr = realloc (prevptr, size);
00346         if (!mptr) {
00347                 fprintf (stderr, "Cannot reallocate %d bytes of memory - Aborting\n", (int)size);
00348                 fflush (stderr);
00349                 (void)longjmp (cob_jmpbuf, 1);
00350         }
00351         return mptr;
00352 }
00353 
00354 struct cb_text_list *
00355 cb_text_list_add (struct cb_text_list *list, const char *text)
00356 {
00357         struct cb_text_list *p;
00358         struct cb_text_list *l;
00359 
00360         p = cobc_malloc (sizeof (struct cb_text_list));
00361         p->text = strdup (text);
00362         p->next = NULL;
00363         if (!list) {
00364                 return p;
00365         } else {
00366                 for (l = list; l->next; l = l->next) { ; }
00367                 l->next = p;
00368                 return list;
00369         }
00370 }
00371 
00372 size_t
00373 cobc_check_valid_name (char *name)
00374 {
00375         size_t  n;
00376 
00377         for (n = 0; n < COB_NUM_CSYNS; ++n) {
00378                 if (!strcmp (name, cob_csyns[n])) {
00379                         return 1;
00380                 }
00381         }
00382         return 0;
00383 }
00384 
00385 /*
00386  * Local functions
00387  */
00388 
00389 static void
00390 cobc_init_var (char *var, const char *env, const char *def)
00391 {
00392         char *p = getenv (env);
00393 
00394         if (p) {
00395                 strcpy (var, p);
00396         } else {
00397                 strcpy (var, def);
00398         }
00399 }
00400 
00401 static void
00402 cobc_check_action (const char *name)
00403 {
00404         struct stat             st;
00405         char                    buff[COB_SMALL_BUFF];
00406 
00407         if (name && !stat (name, &st)) {
00408                 if (!save_temps) {
00409                         unlink (name);
00410                 } else if (save_temps_dir) {
00411                         memset (buff, 0, sizeof(buff));
00412                         sprintf (buff, "%s/%s", save_temps_dir, name);
00413                         (void)rename (name, buff);
00414                 }
00415         }
00416 }
00417 
00418 static void
00419 cobc_clean_up (int status)
00420 {
00421         struct filename         *fn;
00422         struct local_filename   *lf;
00423         int                     i;
00424         char                    buff[COB_SMALL_BUFF];
00425 
00426         if (cb_listing_file) {
00427                 fclose (cb_listing_file);
00428                 cb_listing_file = NULL;
00429         }
00430         for (fn = file_list; fn; fn = fn->next) {
00431                 if (fn->need_preprocess
00432                     && (status || cb_compile_level > CB_LEVEL_PREPROCESS)) {
00433                         cobc_check_action (fn->preprocess);
00434                 }
00435                 if (!save_csrc && fn->need_translate
00436                     && (status || cb_compile_level > CB_LEVEL_TRANSLATE)) {
00437                         cobc_check_action (fn->translate);
00438                         cobc_check_action (fn->trstorage);
00439                         if (fn->localfile) {
00440                                 for (lf = fn->localfile; lf; lf = lf->next) {
00441                                         cobc_check_action (lf->local_name);
00442                                 }
00443                         } else if (fn->translate) {
00444                                 /* If we get syntax errors, we do not
00445                                    know the number of local include files */
00446                                 memset (buff, 0, sizeof(buff));
00447                                 for (i = 0; i < 30; i++) {
00448                                         if (i) {
00449                                                 sprintf (buff, "%s.l%d.h",
00450                                                         fn->translate, i);
00451                                         } else {
00452                                                 sprintf (buff, "%s.l.h",
00453                                                         fn->translate);
00454                                         }
00455                                         unlink (buff);
00456                                 }
00457                         }
00458                 }
00459                 if (fn->need_assemble
00460                     && (status || cb_compile_level > CB_LEVEL_ASSEMBLE)) {
00461                         cobc_check_action (fn->object);
00462                 }
00463         }
00464 }
00465 
00466 static void
00467 cobc_terminate (const char *str)
00468 {
00469         fprintf (stderr, "cobc: ");
00470         fflush (stderr);
00471         perror (str);
00472         cobc_clean_up (1);
00473         exit (1);
00474 }
00475 
00476 #ifdef  HAVE_SIGNAL_H
00477 static void
00478 cobc_sig_handler (int sig)
00479 {
00480         save_temps = 0;
00481         cobc_clean_up (1);
00482         switch (sig) {
00483 #ifdef  SIGHUP
00484         case SIGHUP:
00485                 if ((hupsig != SIG_IGN) && (hupsig != SIG_DFL)) {
00486                         (*hupsig) (SIGHUP);
00487                 }
00488                 break;
00489 #endif
00490         case SIGINT:
00491                 if ((intsig != SIG_IGN) && (intsig != SIG_DFL)) {
00492                         (*intsig) (SIGINT);
00493                 }
00494                 break;
00495 #ifdef  SIGQUIT
00496         case SIGQUIT:
00497                 if ((qutsig != SIG_IGN) && (qutsig != SIG_DFL)) {
00498                         (*qutsig) (SIGQUIT);
00499                 }
00500                 break;
00501 #endif
00502         }
00503         exit (sig);
00504 }
00505 #endif
00506 
00507 /*
00508  * Command line
00509  */
00510 
00511 static void
00512 cobc_print_version (void)
00513 {
00514         printf ("cobc (%s) %s.%d\n",
00515                 PACKAGE_NAME, PACKAGE_VERSION, PATCH_LEVEL);
00516         puts ("Copyright (C) 2001-2009 Keisuke Nishida / Roger While");
00517         printf ("Built    %s\nPackaged %s\n", cb_oc_build_stamp, octardate);
00518 }
00519 
00520 static void
00521 cobc_print_usage (void)
00522 {
00523         printf ("Usage: cobc [options] file...\n\n");
00524         puts (_("Options:"));
00525         puts (_("  --help                Display this message"));
00526         puts (_("  --version, -V         Display compiler version"));
00527         puts (_("  -v                    Display the programs invoked by the compiler"));
00528         puts (_("  -x                    Build an executable program"));
00529         puts (_("  -m                    Build a dynamically loadable module (default)"));
00530         puts (_("  -std=<dialect>        Compile for a specific dialect :"));
00531         puts (_("                          cobol2002   Cobol 2002"));
00532         puts (_("                          cobol85     Cobol 85"));
00533         puts (_("                          ibm         IBM Compatible"));
00534         puts (_("                          mvs         MVS Compatible"));
00535         puts (_("                          bs2000      BS2000 Compatible"));
00536         puts (_("                          mf          Micro Focus Compatible"));
00537         puts (_("                          default     When not specified"));
00538         puts (_("                        See config/default.conf and config/*.conf"));
00539         puts (_("  -free                 Use free source format"));
00540         puts (_("  -fixed                Use fixed source format (default)"));
00541         puts (_("  -O, -O2, -Os          Enable optimization"));
00542         puts (_("  -g                    Produce debugging information in the output"));
00543         puts (_("  -debug                Enable all run-time error checking"));
00544         puts (_("  -o <file>             Place the output into <file>"));
00545         puts (_("  -b                    Combine all input files into a single"));
00546         puts (_("                        dynamically loadable module"));
00547         puts (_("  -E                    Preprocess only; do not compile, assemble or link"));
00548         puts (_("  -C                    Translation only; convert COBOL to C"));
00549         puts (_("  -S                    Compile only; output assembly file"));
00550         puts (_("  -c                    Compile and assemble, but do not link"));
00551         puts (_("  -t <file>             Generate and place a program listing into <file>"));
00552         puts (_("  -I <directory>        Add <directory> to copy/include search path"));
00553         puts (_("  -L <directory>        Add <directory> to library search path"));
00554         puts (_("  -l <lib>              Link the library <lib>"));
00555         puts (_("  -D <define>           Pass <define> to the C compiler"));
00556         puts (_("  -conf=<file>          User defined dialect configuration - See -std="));
00557         puts (_("  --list-reserved       Display reserved words"));
00558         puts (_("  --list-intrinsics     Display intrinsic functions"));
00559         puts (_("  --list-mnemonics      Display mnemonic names"));
00560         puts (_("  -save-temps(=<dir>)   Save intermediate files (default current directory)"));
00561         puts (_("  -MT <target>          Set target file used in dependency list"));
00562         puts (_("  -MF <file>            Place dependency list into <file>"));
00563         puts (_("  -ext <extension>      Add default file extension"));
00564         puts ("");
00565         puts (_("  -W                    Enable ALL warnings"));
00566         puts (_("  -Wall                 Enable all warnings except as noted below"));
00567 #undef  CB_WARNDEF
00568 #define CB_WARNDEF(var,name,wall,doc)           \
00569         printf ("  -W%-19s %s", name, gettext (doc)); \
00570         if (!wall) { \
00571                 puts (_(" (NOT set with -Wall)")); \
00572         } else { \
00573                 printf ("\n"); \
00574         }
00575 #include "warning.def"
00576 #undef  CB_WARNDEF
00577         puts ("");
00578 #undef  CB_FLAG
00579 #define CB_FLAG(var,name,doc)                   \
00580         if (strcmp (name, "static-call"))       \
00581                 printf ("  -f%-19s %s\n", name, gettext (doc));
00582 #include "flag.def"
00583 #undef  CB_FLAG
00584         puts ("");
00585 }
00586 
00587 static void
00588 cobc_options_error (void)
00589 {
00590         fprintf (stderr, "Only one of options 'E', 'S', 'C' 'c' may be specified\n");
00591         exit (1);
00592 }
00593 
00594 static int
00595 process_command_line (int argc, char *argv[])
00596 {
00597         int                     c, idx;
00598         enum cob_exception_id   i;
00599         struct stat             st;
00600         char                    ext[COB_MINI_BUFF];
00601 
00602         /* Enable default I/O exceptions */
00603         CB_EXCEPTION_ENABLE (COB_EC_I_O) = 1;
00604 
00605         while ((c = getopt_long_only (argc, argv, short_options, long_options, &idx)) >= 0) {
00606                 switch (c) {
00607                 case 0:
00608                         break;
00609                 case '?':
00610                         exit (1);
00611                 case 'h':
00612                         cobc_print_usage ();
00613                         exit (0);
00614                 case 'V':
00615                         cobc_print_version ();
00616                         exit (0);
00617                 case 'R':
00618                         cb_list_reserved ();
00619                         exit (0);
00620                 case 'Q':
00621                         cb_list_intrinsics ();
00622                         exit (0);
00623                 case 'q':
00624                         cb_list_mnemonics ();
00625                         exit (0);
00626 
00627                 case 'E':
00628                         if (wants_nonfinal) {
00629                                 cobc_options_error ();
00630                         }
00631                         wants_nonfinal = 1;
00632                         cb_compile_level = CB_LEVEL_PREPROCESS;
00633                         break;
00634                 case 'C':
00635                         if (wants_nonfinal) {
00636                                 cobc_options_error ();
00637                         }
00638                         wants_nonfinal = 1;
00639                         cb_compile_level = CB_LEVEL_TRANSLATE;
00640                         break;
00641                 case 'S':
00642                         if (wants_nonfinal) {
00643                                 cobc_options_error ();
00644                         }
00645                         wants_nonfinal = 1;
00646                         cb_compile_level = CB_LEVEL_COMPILE;
00647                         break;
00648                 case 'c':
00649                         if (wants_nonfinal) {
00650                                 cobc_options_error ();
00651                         }
00652                         wants_nonfinal = 1;
00653                         cb_compile_level = CB_LEVEL_ASSEMBLE;
00654                         break;
00655                 case 'b':
00656                         if (cb_flag_main || cb_flag_module) {
00657                                 fprintf (stderr, "Only one of options 'm', 'x', 'b' may be specified\n");
00658                                 exit (1);
00659                         }
00660                         cb_flag_library = 1;
00661                         break;
00662                 case 'm':
00663                         if (cb_flag_main || cb_flag_library) {
00664                                 fprintf (stderr, "Only one of options 'm', 'x', 'b' may be specified\n");
00665                                 exit (1);
00666                         }
00667                         cb_flag_module = 1;
00668                         break;
00669                 case 'x':
00670                         if (cb_flag_module || cb_flag_library) {
00671                                 fprintf (stderr, "Only one of options 'm', 'x', 'b' may be specified\n");
00672                                 exit (1);
00673                         }
00674                         cb_flag_main = 1;
00675                         break;
00676                 case 'v':
00677                         verbose_output = 1;
00678                         break;
00679                 case 'o':
00680                         output_name = strdup (optarg);
00681                         break;
00682 
00683                 case 'O':
00684                         strcat (cob_cflags, " -O");
00685                         strcat (cob_cflags, fcopts);
00686                         strcat (cob_cflags, COB_EXTRA_FLAGS);
00687                         optimize_flag = 1;
00688                         break;
00689 
00690                 case '2':       /* -O2 */
00691                         strip_output = 1;
00692 #if defined(__hpux) && !defined(__GNUC__)
00693                         strcat (cob_cflags, " -O");
00694 #else
00695                         strcat (cob_cflags, " -O2");
00696 #endif
00697                         strcat (cob_cflags, fcopts);
00698                         strcat (cob_cflags, COB_EXTRA_FLAGS);
00699                         optimize_flag = 2;
00700                         break;
00701 
00702                 case 's':       /* -Os */
00703                         strip_output = 1;
00704 #if defined(__hpux) && !defined(__GNUC__)
00705                         strcat (cob_cflags, " -O");
00706 #else
00707                         strcat (cob_cflags, " -Os");
00708 #endif
00709                         strcat (cob_cflags, fcopts);
00710                         strcat (cob_cflags, COB_EXTRA_FLAGS);
00711                         optimize_flag = 2;
00712                         break;
00713 
00714                 case 'g':
00715                         save_csrc = 1;
00716                         gflag_set = 1;
00717                         cb_flag_stack_check = 1;
00718                         cb_flag_source_location = 1;
00719 #ifndef _MSC_VER
00720                         strcat (cob_cflags, " -g");
00721 #endif
00722                         break;
00723 
00724                 case '$':       /* -std */
00725                         snprintf (ext, COB_MINI_MAX, "%s.conf", optarg);
00726                         if (cb_load_std (ext) != 0) {
00727                                 fprintf (stderr, _("Invalid option -std=%s\n"), optarg);
00728                                 exit (1);
00729                         }
00730                         break;
00731 
00732                 case '&':       /* -conf */
00733                         if (cb_load_conf (optarg, 1, 0) != 0) {
00734                                 exit (1);
00735                         }
00736                         break;
00737 
00738                 case 'd':       /* -debug */
00739                         /* Turn on all exception conditions */
00740                         for (i = 1; i < COB_EC_MAX; i++) {
00741                                 CB_EXCEPTION_ENABLE (i) = 1;
00742                         }
00743                         cb_flag_source_location = 1;
00744                         cb_flag_stack_check = 1;
00745                         break;
00746 
00747                 case '_':       /* --save-temps */
00748                         save_temps = 1;
00749                         if (optarg) {
00750                                 if (stat (optarg, &st) != 0 || !(S_ISDIR (st.st_mode))) {
00751                                         fprintf (stderr, "Warning - '%s' is not a directory, defaulting to current directory\n", optarg);
00752                                         fflush (stderr);
00753                                 } else {
00754                                         save_temps_dir = optarg;
00755                                 }
00756                         }
00757                         break;
00758 
00759                 case 't':
00760                         cb_listing_file = fopen (optarg, "w");
00761                         if (!cb_listing_file) {
00762                                 perror (optarg);
00763                         }
00764                         break;
00765 
00766                 case 'D':       /* -D */
00767 #ifdef _MSC_VER
00768                         strcat (cob_define_flags, "/D \"");
00769                         strcat (cob_define_flags, optarg);
00770                         strcat (cob_define_flags, "\" ");
00771 #else
00772                         strcat (cob_define_flags, "-D");
00773                         strcat (cob_define_flags, optarg);
00774                         strcat (cob_define_flags, " ");
00775 #endif
00776                         break;
00777 
00778                 case '%':       /* -MT */
00779                         cb_depend_target = strdup (optarg);
00780                         break;
00781 
00782                 case '@':       /* -MF */
00783                         cb_depend_file = fopen (optarg, "w");
00784                         if (!cb_depend_file) {
00785                                 perror (optarg);
00786                         }
00787                         break;
00788 
00789                 case 'I':
00790 #ifdef _MSC_VER
00791                         strcat (cob_define_flags, "/I \"");
00792                         strcat (cob_define_flags, optarg);
00793                         strcat (cob_define_flags, "\" ");
00794 #else
00795                         strcat (cob_define_flags, "-I");
00796                         strcat (cob_define_flags, optarg);
00797                         strcat (cob_define_flags, " ");
00798 #endif
00799                         cb_include_list = cb_text_list_add (cb_include_list, optarg);
00800                         break;
00801 
00802                 case 'L':
00803                         strcat (cob_libs, " -L");
00804                         strcat (cob_libs, optarg);
00805                         break;
00806 
00807                 case 'l':
00808                         strcat (cob_libs, " -l");
00809                         strcat (cob_libs, optarg);
00810                         break;
00811 
00812                 case 'e':
00813                         snprintf (ext, COB_MINI_MAX, ".%s", optarg);
00814                         cb_extension_list = cb_text_list_add (cb_extension_list, ext);
00815                         break;
00816 
00817                 case 'w':
00818 #undef  CB_WARNDEF
00819 #define CB_WARNDEF(var,name,wall,doc)   var = 0;
00820 #include "warning.def"
00821 #undef  CB_WARNDEF
00822                         break;
00823 
00824                 case 'W':
00825 #undef  CB_WARNDEF
00826 #define CB_WARNDEF(var,name,wall,doc)   if (wall) var = 1;
00827 #include "warning.def"
00828 #undef  CB_WARNDEF
00829                         break;
00830 
00831                 case 'Z':
00832 #undef  CB_WARNDEF
00833 #define CB_WARNDEF(var,name,wall,doc)   var = 1;
00834 #include "warning.def"
00835 #undef  CB_WARNDEF
00836                         break;
00837 
00838                 default:
00839                         ABORT ();
00840                 }
00841         }
00842 
00843         if (cb_config_name == NULL) {
00844                 if (cb_load_std ("default.conf") != 0) {
00845                         fprintf (stderr, "Error: failed to load the initial config file\n");
00846                         exit (1);
00847                 }
00848         }
00849 
00850         if (cb_flag_fold_copy_lower && cb_flag_fold_copy_upper) {
00851                 fprintf (stderr, "Error: Invalid option combination\n");
00852                 exit (1);
00853         }
00854 
00855 #ifdef  __GNUC__
00856         strcat (cob_cflags, " -Wno-unused -fsigned-char");
00857 #ifdef  HAVE_PSIGN_OPT
00858         strcat (cob_cflags, " -Wno-pointer-sign");
00859 #endif
00860 #endif
00861 
00862         if (gflag_set) {
00863                 strip_output = 0;
00864                 optimize_flag = 0;
00865         }
00866         if (cb_flag_traceall) {
00867                 cb_flag_trace = 1;
00868                 cb_flag_source_location = 1;
00869         }
00870         if (cb_flag_source_location) {
00871                 optimize_flag = 0;
00872         }
00873 #if defined (__GNUC__) && (__GNUC__ >= 3)
00874         if (strip_output) {
00875                 strcat (cob_cflags, " -fomit-frame-pointer");
00876         }
00877 #endif
00878 
00879         /* default extension list */
00880         cb_extension_list = cb_text_list_add (cb_extension_list, ".CPY");
00881         cb_extension_list = cb_text_list_add (cb_extension_list, ".CBL");
00882         cb_extension_list = cb_text_list_add (cb_extension_list, ".COB");
00883         cb_extension_list = cb_text_list_add (cb_extension_list, ".cpy");
00884         cb_extension_list = cb_text_list_add (cb_extension_list, ".cbl");
00885         cb_extension_list = cb_text_list_add (cb_extension_list, ".cob");
00886         cb_extension_list = cb_text_list_add (cb_extension_list, "");
00887 
00888         return optind;
00889 }
00890 
00891 static void 
00892 process_env_copy_path (void) 
00893 {
00894         char    *value;
00895         char    *token;
00896 
00897         cobcpy = getenv ("COBCPY");
00898         if (cobcpy == NULL || strlen (cobcpy) == 0) {
00899                 /* env. not defined: nothing to do */
00900                 cobcpy = NULL;
00901                 return;
00902         }
00903         
00904         /* clone value to avoid memory corruption */
00905         value = strdup (cobcpy);
00906 
00907         /* tokenizing for path sep. */
00908         token = strtok (value, PATHSEPS);
00909         while (token) {
00910                 cb_include_list = cb_text_list_add (cb_include_list, token);
00911                 token = strtok (NULL, PATHSEPS);
00912         }
00913 
00914         /* release memory of clone */
00915         free (value);
00916         return;
00917 }
00918 
00919 static void
00920 file_basename (const char *filename, char *buff)
00921 {
00922         const char      *startp;
00923         const char      *endp;
00924         size_t          len;
00925 
00926         /* Remove directory name */
00927         startp = strrchr (filename, '/');
00928         if (startp) {
00929                 startp++;
00930         } else {
00931                 startp = filename;
00932         }
00933 
00934         /* Remove extension */
00935         endp = strrchr (filename, '.');
00936         if (endp > startp) {
00937                 len = endp - startp;
00938         } else {
00939                 len = strlen (startp);
00940         }
00941 
00942         /* Copy base name */
00943         strncpy (buff, startp, len);
00944         buff[len] = '\0';
00945 }
00946 
00947 static const char *
00948 file_extension (const char *filename)
00949 {
00950         const char *p;
00951 
00952         p = strrchr (filename, '.');
00953         if (p) {
00954                 return p + 1;
00955         } else {
00956                 return "";
00957         }
00958 }
00959 
00960 static char *
00961 cobc_temp_name (const char *ext)
00962 {
00963         char    buff[COB_MEDIUM_BUFF];
00964 #ifdef _WIN32
00965         char    temp[MAX_PATH];
00966 
00967         GetTempPath (MAX_PATH, temp);
00968         GetTempFileName (temp, "cob", 0, buff);
00969         DeleteFile (buff);
00970         strcpy (buff + strlen (buff) - 4, ext); /* replace ".tmp" by EXT */
00971 #else
00972         sprintf (buff, "%s/cob%d_%d%s", cob_tmpdir, cob_process_id,
00973                  cob_iteration, ext);
00974 #endif
00975         return strdup (buff);
00976 }
00977 
00978 static struct filename *
00979 process_filename (const char *filename)
00980 {
00981         const char      *extension;
00982         struct filename *fn;
00983         struct filename *ffn;
00984         struct stat     st;
00985         char            basename[COB_SMALL_BUFF];
00986 
00987         if (stat (filename, &st) != 0) {
00988                 cobc_terminate (filename);
00989         }
00990         file_basename (filename, basename);
00991         if (cobc_check_valid_name (basename)) {
00992                 fprintf (stderr, "Invalid file base name - %s\n", basename);
00993                 return NULL;
00994         }
00995         fn = cobc_malloc (sizeof (struct filename));
00996         fn->need_preprocess = 1;
00997         fn->need_translate = 1;
00998         fn->need_assemble = 1;
00999         fn->next = NULL;
01000 
01001         if (!file_list) {
01002                 file_list = fn;
01003         } else {
01004                 for (ffn = file_list; ffn->next; ffn = ffn->next)
01005                         ;
01006                 ffn->next = fn;
01007         }
01008 
01009         fn->demangle_source =  cb_encode_program_id (basename);
01010         extension = file_extension (filename);
01011 
01012         /* Check input file type */
01013         if (strcmp (extension, "i") == 0) {
01014                 /* already preprocessed */
01015                 fn->need_preprocess = 0;
01016         } else if (strcmp (extension, "c") == 0 || strcmp (extension, "s") == 0) {
01017                 /* already compiled */
01018                 fn->need_preprocess = 0;
01019                 fn->need_translate = 0;
01020 #ifdef _MSC_VER
01021         } else if (strcmp (extension, "obj") == 0 ||
01022                    strcmp (extension, "lib") == 0) {
01023 #else
01024         } else if (strcmp (extension, "o") == 0) {
01025 #endif
01026                 /* already assembled */
01027                 fn->need_preprocess = 0;
01028                 fn->need_translate = 0;
01029                 fn->need_assemble = 0;
01030         }
01031 
01032         /* Set source filename */
01033         fn->source = cobc_malloc (strlen (filename) + 3);
01034         strcpy (fn->source, filename);
01035 
01036         /* Set preprocess filename */
01037         if (!fn->need_preprocess) {
01038                 fn->preprocess = strdup (fn->source);
01039         } else if (output_name && cb_compile_level == CB_LEVEL_PREPROCESS) {
01040                 fn->preprocess = strdup (output_name);
01041         } else if (save_temps) {
01042                 fn->preprocess = cobc_malloc (strlen (basename) + 5);
01043                 sprintf (fn->preprocess, "%s.i", basename);
01044         } else {
01045                 fn->preprocess = cobc_temp_name (".cob");
01046         }
01047 
01048         /* Set translate filename */
01049         if (!fn->need_translate) {
01050                 fn->translate = strdup (fn->source);
01051         } else if (output_name && cb_compile_level == CB_LEVEL_TRANSLATE) {
01052                 fn->translate = strdup (output_name);
01053         } else if (save_csrc || save_temps ||
01054                    cb_compile_level == CB_LEVEL_TRANSLATE) {
01055                 fn->translate = cobc_malloc (strlen (basename) + 5);
01056                 sprintf (fn->translate, "%s.c", basename);
01057         } else {
01058                 fn->translate = cobc_temp_name (".c");
01059         }
01060 
01061         /* Set storage filename */
01062         if (fn->need_translate) {
01063                 fn->trstorage = cobc_malloc (strlen (fn->translate) + 5);
01064                 sprintf (fn->trstorage, "%s.h", fn->translate);
01065         }
01066 
01067         /* Set object filename */
01068         if (!fn->need_assemble) {
01069                 fn->object = strdup (fn->source);
01070         } else if (output_name && cb_compile_level == CB_LEVEL_ASSEMBLE) {
01071                 fn->object = strdup (output_name);
01072         } else if (save_temps || cb_compile_level == CB_LEVEL_ASSEMBLE) {
01073                 fn->object = cobc_malloc (strlen (basename) + 5);
01074 #ifdef  _MSC_VER
01075                 sprintf (fn->object, "%s.obj", basename);
01076 #else
01077                 sprintf (fn->object, "%s.o", basename);
01078 #endif
01079         } else {
01080 #ifdef  _MSC_VER
01081                 fn->object = cobc_malloc (strlen (basename) + 5);
01082                 sprintf (fn->object, "%s.obj", basename);
01083 #else
01084                 fn->object = cobc_temp_name (".o");
01085 #endif
01086         }
01087 
01088         cob_iteration++;
01089 
01090         return fn;
01091 }
01092 
01093 static int
01094 process (const char *cmd)
01095 {
01096         char    *p;
01097         char    *buffptr;
01098         size_t  clen;
01099         int     ret;
01100         char    buff[COB_MEDIUM_BUFF];
01101 
01102         if (strchr (cmd, '$') == NULL) {
01103                 if (verbose_output) {
01104                         fprintf (stderr, "%s\n", (char *)cmd);
01105                 }
01106                 return system (cmd);
01107         }
01108         clen = strlen (cmd) + 32;
01109         if (clen > COB_MEDIUM_BUFF) {
01110                 buffptr = cobc_malloc (clen);
01111         } else {
01112                 buffptr = buff;
01113         }
01114         p = buffptr;
01115         /* quote '$' */
01116         for (; *cmd; cmd++) {
01117                 if (*cmd == '$') {
01118                         p += sprintf (p, "\\$");
01119                 } else {
01120                         *p++ = *cmd;
01121                 }
01122         }
01123         *p = 0;
01124 
01125         if (verbose_output) {
01126                 fprintf (stderr, "%s\n", buffptr);
01127         }
01128         ret = system (buffptr);
01129         if (buffptr != buff) {
01130                 free (buffptr);
01131         }
01132         return ret;
01133 }
01134 
01135 static int
01136 preprocess (struct filename *fn)
01137 {
01138         struct cb_text_list     *l;
01139         int                     i;
01140         char                    line[COB_MEDIUM_BUFF];
01141 
01142         errorcount = 0;
01143 
01144         if (output_name || cb_compile_level > CB_LEVEL_PREPROCESS) {
01145                 ppout = fopen (fn->preprocess, "w");
01146                 if (!ppout) {
01147                         cobc_terminate (fn->preprocess);
01148                 }
01149         } else {
01150                 ppout = stdout;
01151         }
01152 
01153         if (ppopen (fn->source, NULL) != 0) {
01154                 if (ppout != stdout) {
01155                         fclose (ppout);
01156                         if (fn->preprocess) {
01157                                 unlink (fn->preprocess);
01158                         }
01159                 }
01160                 exit (1);
01161         }
01162 
01163         if (verbose_output) {
01164                 fprintf (stderr, "preprocessing %s into %s\n", fn->source, fn->preprocess);
01165         }
01166 
01167         ppparse ();
01168 
01169         if (ppout != stdout) {
01170                 fclose (ppout);
01171                 if (cb_listing_file) {
01172                         ppout = fopen (fn->preprocess, "r");
01173                         if (ppout) {
01174                                 memset (line, 0, sizeof (line));
01175                                 fprintf (cb_listing_file,
01176                                         "# Generated by %s.%d\n",
01177                                         PACKAGE_STRING, PATCH_LEVEL);
01178                                 fprintf (cb_listing_file,
01179                                         "# Built        %s\n", cb_oc_build_stamp);
01180                                 fprintf (cb_listing_file,
01181                                         "# Packaged     %s\n", octardate);
01182                                 fprintf (cb_listing_file,
01183                                         "# Environment\n");
01184                                 fprintf (cb_listing_file,
01185                                         "#  TMPDIR :    %s\n", cob_tmpdir);
01186                                 fprintf (cb_listing_file,
01187                                         "#  COBCPY :    %s\n",
01188                                         cobcpy != NULL ? cobcpy : "is not set");
01189                                 fprintf (cb_listing_file,
01190                                         "# Command :    ");
01191                                 for (i = 0; i < cb_saveargc; i++) {
01192                                         fprintf (cb_listing_file, "%s ", cb_saveargv[i]);
01193                                 }
01194                                 fprintf (cb_listing_file, "\n#\n");
01195                                 while (fgets (line, COB_MEDIUM_BUFF, ppout) != NULL) {
01196                                         if (cb_source_format != CB_FORMAT_FIXED) {
01197                                                 fprintf (cb_listing_file,
01198                                                         "%s", line);
01199                                         } else {
01200                                                 if (line[0] == '\n') {
01201                                                         fprintf (cb_listing_file,
01202                                                                 "%s", line);
01203                                                 } else if (line[0] == ' ' &&
01204                                                            line[1] == '\n') {
01205                                                         fprintf (cb_listing_file,
01206                                                                 "\n");
01207                                                 } else if (line[0] == ' ') {
01208                                                         fprintf (cb_listing_file,
01209                                                                 "          %s", line);
01210                                                 } else if (line[0] == '#') {
01211                                                         fprintf (cb_listing_file,
01212                                                                 "%s", line);
01213                                                 } else if (line[0] == 0) {
01214                                                         fprintf (cb_listing_file,
01215                                                                 "%s", line);
01216                                                 } else {
01217                                                         fprintf (cb_listing_file,
01218                                                                 "       %s", line);
01219                                                 }
01220                                         }
01221                                         memset (line, 0, sizeof (line));
01222                                 }
01223                                 fclose (ppout);
01224                         }
01225                 }
01226         }
01227         fclose (ppin);
01228 
01229         if (errorcount > 0) {
01230                 return -1;
01231         }
01232 
01233         /* Output dependency list */
01234         if (cb_depend_file) {
01235                 if (!cb_depend_target) {
01236                         fputs (_("-MT must be given to specify target file\n"), stderr);
01237                         exit (1);
01238                 }
01239                 fprintf (cb_depend_file, "%s: \\\n", cb_depend_target);
01240                 for (l = cb_depend_list; l; l = l->next) {
01241                         fprintf (cb_depend_file, " %s%s\n", l->text, l->next ? " \\" : "");
01242                 }
01243                 for (l = cb_depend_list; l; l = l->next) {
01244                         fprintf (cb_depend_file, "%s:\n", l->text);
01245                 }
01246                 fclose (cb_depend_file);
01247         }
01248 
01249         return 0;
01250 }
01251 
01252 static struct cb_program *
01253 program_list_reverse (struct cb_program *p)
01254 {
01255         struct cb_program       *next;
01256         struct cb_program       *last = NULL;
01257 
01258         for (; p; p = next) {
01259                 next = p->next_program;
01260                 p->next_program = last;
01261                 last = p;
01262         }
01263         return last;
01264 }
01265 
01266 static int
01267 process_translate (struct filename *fn)
01268 {
01269         struct cb_program       *p;
01270         struct cb_program       *q;
01271         struct cb_program       *r;
01272         struct handler_struct   *hstr1;
01273         struct handler_struct   *hstr2;
01274         struct local_filename   *lf;
01275         int                     ret;
01276         int                     i;
01277 
01278         /* initialize */
01279         cb_source_file = NULL;
01280         cb_source_line = 0;
01281         cb_init_constants ();
01282         cb_init_reserved ();
01283 
01284         /* open the input file */
01285         yyin = fopen (fn->preprocess, "r");
01286         if (!yyin) {
01287                 cobc_terminate (fn->preprocess);
01288         }
01289 
01290         /* parse */
01291         ret = yyparse ();
01292         fclose (yyin);
01293         if (ret) {
01294                 return ret;
01295         }
01296         if (cb_flag_syntax_only || current_program->entry_list == NULL) {
01297                 return 0;
01298         }
01299 
01300         /* Set up USE GLOBAL handlers */
01301         p = current_program;
01302         for (q = p; q; q = q->next_program) {
01303                 q->global_file_list = cb_list_reverse (q->global_file_list);
01304                 if (q->nested_level) {
01305                         for (r = q->next_program; r; r = r->next_program) {
01306                                 if (r->nested_level >= q->nested_level) {
01307                                         continue;
01308                                 }
01309                                 for (i = COB_OPEN_INPUT; i <= COB_OPEN_EXTEND; i++) {
01310                                         hstr1 = &q->global_handler[i];
01311                                         hstr2 = &r->global_handler[i];
01312                                         if (!hstr1->handler_label &&
01313                                             hstr2->handler_label &&
01314                                             hstr2->handler_label->is_global) {
01315                                                 hstr1->handler_label = hstr2->handler_label;
01316                                                 hstr1->handler_prog = r;
01317                                         }
01318                                 }
01319                                 if (!r->nested_level) {
01320                                         break;
01321                                 }
01322                         }
01323                 }
01324         }
01325 
01326         if (verbose_output) {
01327                 fprintf (stderr, "translating %s into %s\n", fn->preprocess, fn->translate);
01328         }
01329 
01330         /* open the output file */
01331         yyout = fopen (fn->translate, "w");
01332         if (!yyout) {
01333                 cobc_terminate (fn->translate);
01334         }
01335 
01336         /* open the common storage file */
01337         cb_storage_file_name = fn->trstorage;
01338         cb_storage_file = fopen (cb_storage_file_name, "w");
01339         if (!cb_storage_file) {
01340                 cobc_terminate (cb_storage_file_name);
01341         }
01342 
01343         p = program_list_reverse (current_program);
01344 
01345         /* set up local storage files */
01346         ret = 1;
01347         for (q = p; q; q = q->next_program, ret++) {
01348                 lf = cobc_malloc (sizeof(struct local_filename));
01349                 lf->local_name = cobc_malloc (strlen (fn->translate) + 9);
01350                 if (q == p && !q->next_program) {
01351                         sprintf (lf->local_name, "%s.l.h", fn->translate);
01352                 } else {
01353                         sprintf (lf->local_name, "%s.l%d.h", fn->translate, ret);
01354                 }
01355                 lf->local_fp = fopen (lf->local_name, "w");
01356                 if (!lf->local_fp) {
01357                         cobc_terminate (lf->local_name);
01358                 }
01359                 q->local_storage_file = lf->local_fp;
01360                 q->local_storage_name = lf->local_name;
01361                 lf->next = fn->localfile;
01362                 fn->localfile = lf;
01363         }
01364 
01365         /* translate to C */
01366         codegen (p, 0);
01367 
01368         /* close the files */
01369         fclose (cb_storage_file);
01370         fclose (yyout);
01371         for (q = p; q; q = q->next_program) {
01372                 fclose (q->local_storage_file);
01373         }
01374         return 0;
01375 }
01376 
01377 static int
01378 process_compile (struct filename *fn)
01379 {
01380         char buff[COB_MEDIUM_BUFF];
01381         char name[COB_MEDIUM_BUFF];
01382 
01383         if (output_name) {
01384                 strcpy (name, output_name);
01385         } else {
01386                 file_basename (fn->source, name);
01387 #ifndef _MSC_VER
01388                 strcat (name, ".s");
01389 #endif
01390         }
01391 #ifdef _MSC_VER
01392         sprintf (buff, gflag_set ? 
01393                 "%s /c %s %s /Od /MDd /Zi /FR /c /Fa%s /Fo%s %s" :
01394                 "%s /c %s %s /MD /c /Fa%s /Fo%s %s",
01395                         cob_cc, cob_cflags, cob_define_flags, name,
01396                         name, fn->translate);
01397 #else
01398         sprintf (buff, "%s %s -S -o %s %s %s %s", cob_cc, gccpipe, name,
01399                         cob_cflags, cob_define_flags, fn->translate);
01400 #endif
01401         return process (buff);
01402 }
01403 
01404 static int
01405 process_assemble (struct filename *fn)
01406 {
01407         char buff[COB_MEDIUM_BUFF];
01408 
01409 #ifdef _MSC_VER
01410         sprintf (buff, gflag_set ? 
01411                 "%s /c %s %s /Od /MDd /Zi /FR /Fo%s %s" :
01412                 "%s /c %s %s /MD /Fo%s %s",
01413                         cob_cc, cob_cflags, cob_define_flags,
01414                         fn->object, fn->translate);
01415 #else
01416         if (cb_compile_level == CB_LEVEL_MODULE ||
01417             cb_compile_level == CB_LEVEL_LIBRARY) {
01418                 sprintf (buff, "%s %s -c %s %s %s -o %s %s",
01419                          cob_cc, gccpipe, cob_cflags, cob_define_flags,
01420                          COB_PIC_FLAGS, fn->object, fn->translate);
01421         } else {
01422                 sprintf (buff, "%s %s -c %s %s -o %s %s",
01423                          cob_cc, gccpipe, cob_cflags, cob_define_flags,
01424                          fn->object, fn->translate);
01425         }
01426 #endif
01427         return process (buff);
01428 }
01429 
01430 static int
01431 process_module_direct (struct filename *fn)
01432 {
01433         int     ret;
01434         char    buff[COB_MEDIUM_BUFF];
01435         char    name[COB_MEDIUM_BUFF];
01436 
01437         if (output_name) {
01438                 strcpy (name, output_name);
01439 #ifndef _MSC_VER
01440                 if (strchr (output_name, '.') == NULL) {
01441                         strcat (name, ".");
01442                         strcat (name, COB_MODULE_EXT);
01443                 }
01444 #endif
01445         } else {
01446                 file_basename (fn->source, name);
01447 #ifndef _MSC_VER
01448                 strcat (name, ".");
01449                 strcat (name, COB_MODULE_EXT);
01450 #endif
01451         }
01452 #ifdef _MSC_VER
01453         sprintf (buff, gflag_set ? 
01454                 "%s %s %s /Od /MDd /LDd /Zi /FR /Fe%s /Fo%s %s %s %s" :
01455                 "%s %s %s /MD /LD /Fe%s /Fo%s %s %s %s",
01456                         cob_cc, cob_cflags, cob_define_flags, name, name,
01457                         cob_ldflags, fn->translate, cob_libs);
01458         ret = process (buff);
01459 #if _MSC_VER >= 1400
01460         /* Embedding manifest */
01461         if (ret == 0) {
01462                 sprintf (buff, "mt /manifest %s.dll.manifest /outputresource:%s.dll;#2", name, name);
01463                 ret = process (buff);
01464         }
01465 #endif
01466 #else   /* _MSC_VER */
01467         sprintf (buff, "%s %s %s %s %s %s %s %s -o %s %s %s",
01468                  cob_cc, gccpipe, cob_cflags, cob_define_flags, COB_SHARED_OPT,
01469                  cob_ldflags, COB_PIC_FLAGS, COB_EXPORT_DYN, name,
01470                  fn->translate, cob_libs);
01471         ret = process (buff);
01472 #ifdef  COB_STRIP_CMD
01473         if (strip_output && ret == 0) {
01474                 sprintf (buff, "%s %s", COB_STRIP_CMD, name);
01475                 ret = process (buff);
01476         }
01477 #endif
01478 #endif  /* _MSC_VER */
01479         return ret;
01480 }
01481 
01482 static int
01483 process_module (struct filename *fn)
01484 {
01485         int     ret;
01486         char    buff[COB_MEDIUM_BUFF];
01487         char    name[COB_MEDIUM_BUFF];
01488 
01489         if (output_name) {
01490                 strcpy (name, output_name);
01491 #ifndef _MSC_VER
01492                 if (strchr (output_name, '.') == NULL) {
01493                         strcat (name, ".");
01494                         strcat (name, COB_MODULE_EXT);
01495                 }
01496 #endif
01497         } else {
01498                 file_basename (fn->source, name);
01499                 strcat (name, ".");
01500                 strcat (name, COB_MODULE_EXT);
01501         }
01502 #ifdef _MSC_VER
01503         sprintf (buff, gflag_set ? 
01504                 "%s /Od /MDd /LDd /Zi /FR /Fe%s %s %s %s" :
01505                 "%s /MD /LD /Fe%s %s %s %s",
01506                         cob_cc, name, cob_ldflags, fn->object, cob_libs);
01507         ret = process (buff);
01508 #if _MSC_VER >= 1400
01509         /* Embedding manifest */
01510         if (ret == 0) {
01511                 sprintf (buff, "mt /manifest %s.dll.manifest /outputresource:%s.dll;#2", name, name);
01512                 ret = process (buff);
01513         }
01514 #endif
01515 #else   /* _MSC_VER */
01516         sprintf (buff, "%s %s %s %s %s %s -o %s %s %s",
01517                  cob_cc, gccpipe, COB_SHARED_OPT, cob_ldflags, COB_PIC_FLAGS,
01518                  COB_EXPORT_DYN, name, fn->object, cob_libs);
01519         ret = process (buff);
01520 #ifdef  COB_STRIP_CMD
01521         if (strip_output && ret == 0) {
01522                 sprintf (buff, "%s %s", COB_STRIP_CMD, name);
01523                 ret = process (buff);
01524         }
01525 #endif
01526 #endif  /* _MSC_VER */
01527         return ret;
01528 }
01529 
01530 static int
01531 process_library (struct filename *l)
01532 {
01533         char            *buffptr;
01534         char            *objsptr;
01535         struct filename *f;
01536         size_t          bufflen;
01537         int             ret;
01538         char            buff[COB_MEDIUM_BUFF];
01539         char            name[COB_MEDIUM_BUFF];
01540         char            objs[COB_MEDIUM_BUFF] = "\0";
01541 
01542         bufflen = 0;
01543         for (f = l; f; f = f->next) {
01544                 bufflen += strlen (f->object) + 2;
01545         }
01546         if (bufflen >= COB_MEDIUM_BUFF) {
01547                 objsptr = cobc_malloc (bufflen);
01548         } else {
01549                 objsptr = objs;
01550         }
01551         for (f = l; f; f = f->next) {
01552                 strcat (objsptr, f->object);
01553                 strcat (objsptr, " ");
01554         }
01555 
01556         if (output_name) {
01557                 strcpy (name, output_name);
01558 #ifndef _MSC_VER
01559                 if (strchr (output_name, '.') == NULL) {
01560                         strcat (name, ".");
01561                         strcat (name, COB_MODULE_EXT);
01562                 }
01563 #endif
01564         } else {
01565                 file_basename (l->source, name);
01566 #ifndef _MSC_VER
01567                 strcat (name, ".");
01568                 strcat (name, COB_MODULE_EXT);
01569 #endif
01570         }
01571 
01572         bufflen = strlen (cob_cc) + strlen (gccpipe) + strlen (cob_ldflags)
01573                         + strlen (COB_EXPORT_DYN) + strlen (COB_SHARED_OPT)
01574                         + strlen (name) + strlen (objsptr) + strlen (cob_libs)
01575                         + strlen (COB_PIC_FLAGS) + 16;
01576         if (bufflen >= COB_MEDIUM_BUFF) {
01577                 buffptr = cobc_malloc (bufflen);
01578         } else {
01579                 buffptr = buff;
01580         }
01581 
01582 #ifdef _MSC_VER
01583         sprintf (buff, gflag_set ? 
01584                 "%s /Od /MDd /LDd /Zi /FR /Fe%s %s %s %s" :
01585                 "%s /MD /LD /Fe%s %s %s %s",
01586                         cob_cc, name, cob_ldflags, objsptr, cob_libs);
01587         ret = process (buff);
01588 #if _MSC_VER >= 1400
01589         /* Embedding manifest */
01590         if (ret == 0) {
01591                 sprintf (buff, "mt /manifest %s.dll.manifest /outputresource:%s.dll;#2", name, name);
01592                 ret = process (buff);
01593         }
01594 #endif
01595 #else   /* _MSC_VER */
01596         sprintf (buffptr, "%s %s %s %s %s %s -o %s %s %s",
01597                  cob_cc, gccpipe, COB_SHARED_OPT, cob_ldflags, COB_PIC_FLAGS,
01598                  COB_EXPORT_DYN, name, objsptr, cob_libs);
01599         ret = process (buffptr);
01600 #ifdef  COB_STRIP_CMD
01601         if (strip_output && ret == 0) {
01602                 sprintf (buff, "%s %s", COB_STRIP_CMD, name);
01603                 ret = process (buff);
01604         }
01605 #endif
01606 #endif  /* _MSC_VER */
01607         return ret;
01608 }
01609 
01610 static int
01611 process_link (struct filename *l)
01612 {
01613         char            *buffptr;
01614         char            *objsptr;
01615         struct filename *f;
01616         size_t          bufflen;
01617         int             ret;
01618         char            buff[COB_MEDIUM_BUFF];
01619         char            name[COB_MEDIUM_BUFF];
01620         char            objs[COB_MEDIUM_BUFF] = "\0";
01621 
01622         bufflen = 0;
01623         for (f = l; f; f = f->next) {
01624                 bufflen += strlen (f->object) + 2;
01625         }
01626         if (bufflen >= COB_MEDIUM_BUFF) {
01627                 objsptr = cobc_malloc (bufflen);
01628         } else {
01629                 objsptr = objs;
01630         }
01631         for (f = l; f; f = f->next) {
01632                 strcat (objsptr, f->object);
01633                 strcat (objsptr, " ");
01634         }
01635 
01636         if (output_name) {
01637                 strcpy (name, output_name);
01638         } else {
01639                 file_basename (l->source, name);
01640         }
01641 
01642         bufflen = strlen (cob_cc) + strlen (gccpipe) + strlen (cob_ldflags)
01643                         + strlen (COB_EXPORT_DYN) + strlen (name)
01644                         + strlen (objsptr) + strlen (cob_libs) + 16;
01645         if (bufflen >= COB_MEDIUM_BUFF) {
01646                 buffptr = cobc_malloc (bufflen);
01647         } else {
01648                 buffptr = buff;
01649         }
01650 #ifdef _MSC_VER
01651         sprintf (buff, gflag_set ? 
01652                 "%s /Od /MDd /Zi /FR /Fe%s %s %s %s" :
01653                 "%s /MD /Fe%s %s %s %s",
01654                         cob_cc, name, cob_ldflags, objsptr, cob_libs);
01655         ret = process (buff);
01656 #if _MSC_VER >= 1400
01657         /* Embedding manifest */
01658         if (ret == 0) {
01659                 sprintf (buff, "mt /manifest %s.exe.manifest /outputresource:%s.exe;#2", name, name);
01660                 ret = process (buff);
01661         }
01662 #endif
01663 #else   /* _MSC_VER */
01664         sprintf (buffptr, "%s %s %s %s -o %s %s %s",
01665                  cob_cc, gccpipe, cob_ldflags, COB_EXPORT_DYN, name,
01666                  objsptr, cob_libs);
01667 
01668         ret = process (buffptr);
01669 #ifdef  __hpux
01670         if (ret == 0) {
01671                 sprintf (buff, "chatr -s +s enable %s%s 1>/dev/null 2>&1", name, COB_EXEEXT);
01672                 process (buff);
01673         }
01674 #endif
01675 #ifdef  COB_STRIP_CMD
01676         if (strip_output && ret == 0) {
01677                 sprintf (buff, "%s %s%s", COB_STRIP_CMD, name, COB_EXEEXT);
01678                 ret = process (buff);
01679         }
01680 #endif
01681 #endif  /* _MSC_VER */
01682         return ret;
01683 }
01684 
01685 int
01686 main (int argc, char *argv[])
01687 {
01688         struct filename         *fn;
01689         char                    *p;
01690         int                     status = 1;
01691         int                     year;
01692         int                     day;
01693         char                    month[32];
01694         char                    buff[COB_SMALL_BUFF];
01695 
01696 #ifdef  HAVE_SIGNAL_H
01697         if ((intsig = signal (SIGINT, cobc_sig_handler)) == SIG_IGN) {
01698                 (void)signal (SIGINT, SIG_IGN);
01699         }
01700 #ifdef  SIGHUP
01701         if ((hupsig = signal (SIGHUP, cobc_sig_handler)) == SIG_IGN) {
01702                 (void)signal (SIGHUP, SIG_IGN);
01703         }
01704 #endif
01705 #ifdef  SIGQUIT
01706         if ((qutsig = signal (SIGQUIT, cobc_sig_handler)) == SIG_IGN) {
01707                 (void)signal (SIGQUIT, SIG_IGN);
01708         }
01709 #endif
01710 #endif
01711 
01712         cb_saveargc = argc;
01713         cb_saveargv = argv;
01714 
01715 #ifdef  HAVE_SETLOCALE
01716         setlocale (LC_ALL, "");
01717 #endif
01718 
01719 #ifdef  ENABLE_NLS
01720         bindtextdomain (PACKAGE, LOCALEDIR);
01721         textdomain (PACKAGE);
01722 #endif
01723 
01724 #ifndef _WIN32
01725         cob_process_id = getpid ();
01726 #endif
01727 
01728         /* Initialize global variables */
01729         memset (buff, 0, sizeof(buff));
01730         memset (month, 0, sizeof(month));
01731         day = 0;
01732         year = 0;
01733         sscanf (__DATE__, "%s %d %d", month, &day, &year);
01734         if (day && year) {
01735                 sprintf (buff, "%s %2.2d %4.4d %s", month, day, year, __TIME__);
01736         } else {
01737                 sprintf (buff, "%s %s", __DATE__, __TIME__);
01738         }
01739         cb_oc_build_stamp = cobc_malloc (strlen (buff) + 1);
01740         strcpy (cb_oc_build_stamp, buff);
01741 
01742         output_name = NULL;
01743 
01744         if ((p = getenv ("TMPDIR")) != NULL) {
01745                 cob_tmpdir = p;
01746         } else if ((p = getenv ("TMP")) != NULL) {
01747                 cob_tmpdir = p;
01748                 sprintf (buff, "TMPDIR=%s", p);
01749                 p = strdup (buff);
01750                 putenv (p);
01751         } else {
01752                 cob_tmpdir = "/tmp";
01753                 putenv ((char *)"TMPDIR=/tmp");
01754         }
01755         cob_cc = getenv ("COB_CC");
01756         if (cob_cc == NULL) {
01757                 cob_cc = COB_CC;
01758         }
01759         cobc_init_var (cob_cflags, "COB_CFLAGS", COB_CFLAGS);
01760         cobc_init_var (cob_libs, "COB_LIBS", COB_LIBS);
01761         cob_ldflags = getenv ("COB_LDFLAGS");
01762         if (cob_ldflags == NULL) {
01763                 cob_ldflags = COB_LDFLAGS;
01764         }
01765         cob_config_dir = getenv ("COB_CONFIG_DIR");
01766         if (cob_config_dir == NULL) {
01767                 cob_config_dir = COB_CONFIG_DIR;
01768         }
01769         cob_copy_dir = getenv ("COB_COPY_DIR");
01770         if (cob_copy_dir == NULL) {
01771                 cob_copy_dir = COB_COPY_DIR;
01772         }
01773         memset (cob_define_flags, 0, sizeof (cob_define_flags));
01774 
01775         p = getenv ("COB_LDADD");
01776         if (p) {
01777                 strcat (cob_libs, " ");
01778                 strcat (cob_libs, p);
01779         }
01780         p = getenv ("COB_EBCDIC");
01781         if (p && (*p == 'F' || *p == 'f')) {
01782                 alt_ebcdic = 1;
01783         }
01784 
01785         /* Process command line arguments */
01786         iargs = process_command_line (argc, argv);
01787 
01788         /* Check the filename */
01789         if (iargs == argc) {
01790                 fprintf (stderr, "cobc: No input files\n");
01791                 exit (1);
01792         }
01793 
01794         /* processes COBCPY environment variable */
01795         process_env_copy_path ();
01796 
01797         cb_include_list = cb_text_list_add (cb_include_list, cob_copy_dir);
01798         
01799         file_list = NULL;
01800 
01801         if (setjmp (cob_jmpbuf) != 0) {
01802                 fprintf (stderr, "Aborting compile of %s at line %d\n",
01803                          cb_source_file, cb_source_line);
01804                 fflush (stderr);
01805                 if (yyout) {
01806                         fflush (yyout);
01807                 }
01808                 if (cb_storage_file) {
01809                         fflush (cb_storage_file);
01810                 }
01811                 status = 1;
01812                 cobc_clean_up (status);
01813                 return status;
01814         }
01815 
01816         /* Defaults are set here */
01817         if (!cb_flag_syntax_only) {
01818                 if (!wants_nonfinal) {
01819                         if (cb_flag_main) {
01820                                 cb_compile_level = CB_LEVEL_EXECUTABLE;
01821                         }
01822                         if (cb_flag_module) {
01823                                 cb_compile_level = CB_LEVEL_MODULE;
01824                         }
01825                         if (cb_flag_library) {
01826                                 cb_compile_level = CB_LEVEL_LIBRARY;
01827                         }
01828                 }
01829                 if (cb_compile_level == 0 && !wants_nonfinal) {
01830                         cb_compile_level = CB_LEVEL_MODULE;
01831                         cb_flag_module = 1;
01832                 }
01833                 if (wants_nonfinal && cb_compile_level != CB_LEVEL_PREPROCESS &&
01834                     !cb_flag_main && !cb_flag_module && !cb_flag_library) {
01835                         cb_flag_module = 1;
01836                 }
01837         } else {
01838                         cb_compile_level = CB_LEVEL_TRANSLATE;
01839         }
01840 
01841         if (output_name && cb_compile_level < CB_LEVEL_LIBRARY &&
01842             (argc - iargs) > 1) {
01843                 fprintf (stderr, "cobc: -o option invalid in this combination\n");
01844                 exit (1);
01845         }
01846         if (cb_flag_sign_ascii && cb_flag_sign_ebcdic) {
01847                 fprintf (stderr, "Only one of -fsign-ascii or -fsign-ebcdic may be specified\n");
01848                 exit (1);
01849         }
01850         if (cb_flag_sign_ascii) {
01851                 cb_display_sign = COB_DISPLAY_SIGN_ASCII;
01852         }
01853         if (cb_flag_sign_ebcdic) {
01854                 cb_display_sign = COB_DISPLAY_SIGN_EBCDIC;
01855         }
01856         if (cb_flag_notrunc) {
01857                 cb_binary_truncate = 0;
01858                 cb_pretty_display = 0;
01859         }
01860 
01861         while (iargs < argc) {
01862                 fn = process_filename (argv[iargs++]);
01863                 if (!fn) {
01864                         status = 1;
01865                         cobc_clean_up (status);
01866                         return status;
01867                 }
01868                 /* Preprocess */
01869                 if (cb_compile_level >= CB_LEVEL_PREPROCESS && fn->need_preprocess) {
01870                         if (preprocess (fn) != 0) {
01871                                 cobc_clean_up (status);
01872                                 return status;
01873                         }
01874                 }
01875         }
01876         for (fn = file_list; fn; fn = fn->next) {
01877                 cb_id = 1;
01878                 cb_attr_id = 1;
01879                 cb_literal_id = 1;
01880                 cb_field_id = 1;
01881                 cb_storage_id = 1;
01882                 iparams++;
01883                 demangle_name = fn->demangle_source;
01884                 if (iparams > 1 && cb_compile_level == CB_LEVEL_EXECUTABLE &&
01885                     !cb_flag_syntax_only) {
01886                         local_level = cb_compile_level;
01887                         cb_flag_main = 0;
01888                         cb_compile_level = CB_LEVEL_ASSEMBLE;
01889                 }
01890                 /* Translate */
01891                 if (cb_compile_level >= CB_LEVEL_TRANSLATE && fn->need_translate) {
01892                         if (process_translate (fn) != 0) {
01893                                 cobc_clean_up (status);
01894                                 return status;
01895                         }
01896                 }
01897                 if (cb_flag_syntax_only) {
01898                         continue;
01899                 }
01900 
01901                 /* Compile */
01902                 if (cb_compile_level == CB_LEVEL_COMPILE) {
01903                         if (process_compile (fn) != 0) {
01904                                 cobc_clean_up (status);
01905                                 return status;
01906                         }
01907                 }
01908 
01909                 /* Build module */
01910                 if (cb_compile_level == CB_LEVEL_MODULE && fn->need_assemble) {
01911                         if (process_module_direct (fn) != 0) {
01912                                 cobc_clean_up (status);
01913                                 return status;
01914                         }
01915                 } else {
01916                         /* Assemble */
01917                         if (cb_compile_level >= CB_LEVEL_ASSEMBLE && fn->need_assemble) {
01918                                 if (process_assemble (fn) != 0) {
01919                                         cobc_clean_up (status);
01920                                         return status;
01921                                 }
01922                         }
01923 
01924                         /* Build module */
01925                         if (cb_compile_level == CB_LEVEL_MODULE) {
01926                                 if (process_module (fn) != 0) {
01927                                         cobc_clean_up (status);
01928                                         return status;
01929                                 }
01930                         }
01931                 }
01932         }
01933 
01934         if (!cb_flag_syntax_only) {
01935                 /* Link */
01936                 if (local_level == CB_LEVEL_EXECUTABLE) {
01937                         cb_compile_level = CB_LEVEL_EXECUTABLE;
01938                         cb_flag_main = 1;
01939                 }
01940                 if (cb_compile_level == CB_LEVEL_LIBRARY) {
01941                         if (process_library (file_list) != 0) {
01942                                 cobc_clean_up (status);
01943                                 return status;
01944                         }
01945                 } else if (cb_compile_level == CB_LEVEL_EXECUTABLE) {
01946                         if (process_link (file_list) != 0) {
01947                                 cobc_clean_up (status);
01948                                 return status;
01949                         }
01950                 }
01951         }
01952 
01953         /* We have successfully completed */
01954         status = 0;
01955         cobc_clean_up (status);
01956 
01957         return status;
01958 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines