OpenCOBOL 1.1pre-rel
|
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 }