|
|
1.1 ! root 1: /* as.c - GAS main program. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: /* ! 21: * Main program for AS; a 32-bit assembler of GNU. ! 22: * Understands command arguments. ! 23: * Has a few routines that don't fit in other modules because they ! 24: * are shared. ! 25: * ! 26: * ! 27: * bugs ! 28: * ! 29: * : initialisers ! 30: * Since no-one else says they will support them in future: I ! 31: * don't support them now. ! 32: * ! 33: */ ! 34: ! 35: #include <signal.h> ! 36: #include <string.h> ! 37: ! 38: #include "as.h" ! 39: #include "input-scrub.h" ! 40: #include "symbols.h" ! 41: #include "sections.h" ! 42: #include "read.h" ! 43: #include "md.h" ! 44: #include "messages.h" ! 45: #include "xmalloc.h" ! 46: #include "layout.h" ! 47: #include "write_object.h" ! 48: ! 49: /* ['x'] TRUE if "-x" seen. */ ! 50: char flagseen[128] = { 0 }; ! 51: ! 52: /* TRUE if -force_cpusubtype_ALL is specified */ ! 53: int force_cpusubtype_ALL = 0; ! 54: ! 55: /* set to the corresponding cpusubtype if -arch flag is specified */ ! 56: cpu_subtype_t archflag_cpusubtype = -1; ! 57: ! 58: /* ! 59: * .include "file" looks in source file dir, then stack. ! 60: * -I directories are added to the end, then the defaults are added. ! 61: */ ! 62: struct directory_stack include_defaults[] = { ! 63: { 0, "/NextDeveloper/Headers/" }, ! 64: { 0, "/LocalDeveloper/Headers/" }, ! 65: { 0, NULL } ! 66: }; ! 67: struct directory_stack *include = NULL; /* First dir to search */ ! 68: static struct directory_stack *include_tail = NULL; /* Last in chain */ ! 69: ! 70: /* next_version is in next_version.c which is created by the Makefile */ ! 71: extern char next_version[]; ! 72: /* this is only used here, thus defined here (was in version.c in GAS) */ ! 73: static char version_string[] = "GNU assembler version 1.38\n"; ! 74: ! 75: /* ! 76: * The list of signals to catch if not ignored. ! 77: */ ! 78: static int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0}; ! 79: static void got_sig( ! 80: int sig); ! 81: ! 82: static void perform_an_assembly_pass( ! 83: int argc, ! 84: char **argv); ! 85: ! 86: void ! 87: main( ! 88: int argc, ! 89: char **argv, ! 90: char **envp) ! 91: { ! 92: char *progname; /* argv[0] */ ! 93: int work_argc; /* variable copy of argc */ ! 94: char **work_argv; /* variable copy of argv */ ! 95: char *arg; /* an arg to program */ ! 96: char a; /* an arg flag (after -) */ ! 97: char *out_file_name;/* name of object file, argument to -o if specified */ ! 98: int i; ! 99: char *specific_archflag; ! 100: struct directory_stack *dirtmp; ! 101: ! 102: progname = argv[0]; ! 103: ! 104: /* ! 105: * Set up to catch the signals listed in sig[] that are not ignored. ! 106: */ ! 107: for(i = 0; sig[i] != 0; i++) ! 108: if(signal(sig[i], SIG_IGN) != SIG_IGN) ! 109: signal(sig[i], got_sig); ! 110: /* ! 111: * Set the default for the flags that will be parsed. ! 112: */ ! 113: memset(flagseen, '\0', sizeof(flagseen)); /* aint seen nothing yet */ ! 114: specific_archflag = NULL; ! 115: out_file_name = "a.out"; /* default .o file */ ! 116: ! 117: /* ! 118: * Call the initialization routines. ! 119: */ ! 120: check_for_ProjectBuilder(); /* messages.c */ ! 121: symbol_begin(); /* symbols.c */ ! 122: sections_begin(); /* sections.c */ ! 123: read_begin(); /* read.c */ ! 124: md_begin(); /* MACHINE.c */ ! 125: input_scrub_begin(); /* input_scrub.c */ ! 126: ! 127: /* ! 128: * Parse arguments, but we are only interested in flags. ! 129: * When we find a flag, we process it then make it's argv[] NULL. ! 130: * This helps any future argv[] scanners avoid what we processed. ! 131: * Since it is easy to do here we interpret the special arg "-" ! 132: * to mean "use stdin" and we set that argv[] pointing to "". ! 133: * After we have munged argv[], the only things left are source file ! 134: * name(s) and ""(s) denoting stdin. These file names are used ! 135: * (perhaps more than once) later. ! 136: */ ! 137: work_argc = argc - 1; /* don't count argv[0] */ ! 138: work_argv = argv + 1; /* skip argv[0] */ ! 139: for( ; work_argc-- ; work_argv++){ ! 140: ! 141: /* work_argv points to this argument */ ! 142: arg = *work_argv; ! 143: ! 144: /* Filename. We need it later. */ ! 145: if(*arg != '-') ! 146: continue; ! 147: ! 148: /* Keep scanning args looking for flags. */ ! 149: if (arg[1] == '-' && arg[2] == 0) { ! 150: /* "--" as an argument means read STDIN */ ! 151: /* on this scan, we don't want to think about filenames */ ! 152: *work_argv = ""; /* Code that means 'use stdin'. */ ! 153: continue; ! 154: } ! 155: ! 156: /* This better be a switch ( -l where l is a letter. */ ! 157: arg++; /* -> letter. */ ! 158: ! 159: /* scan all the 1-char flags */ ! 160: while((a = *arg)){ ! 161: arg ++; /* arg -> after letter. */ ! 162: a &= 0x7F; /* ascii only please */ ! 163: if(flagseen[(int)a] && (a != 'I') && (a != 'a') && (a != 'f')) ! 164: as_warn("%s: Flag option -%c has already been seen!", ! 165: progname, a); ! 166: if(a != 'f') ! 167: flagseen[(int)a] = TRUE; ! 168: switch(a){ ! 169: case 'f': ! 170: if(strcmp(arg-1, "force_cpusubtype_ALL") == 0){ ! 171: force_cpusubtype_ALL = 1; ! 172: arg = ""; /* Finished with this arg. */ ! 173: break; ! 174: } ! 175: /* -f means fast - no need for "app" preprocessor. */ ! 176: flagseen[(int)a] = TRUE; ! 177: break; ! 178: ! 179: case 'L': /* -L means keep L* symbols */ ! 180: break; ! 181: ! 182: case 'o': ! 183: if(*arg != '\0') /* Rest of argument is object file-name. */ ! 184: out_file_name = arg; ! 185: else if(work_argc){ /* Want next arg for a file-name. */ ! 186: *work_argv = NULL; /* This is not a file-name. */ ! 187: work_argc--; ! 188: out_file_name = *++work_argv; ! 189: } ! 190: else ! 191: as_warn("%s: I expected a filename after -o. \"%s\" " ! 192: "assumed.", progname, out_file_name); ! 193: arg = ""; /* Finished with this arg. */ ! 194: break; ! 195: ! 196: case 'R': ! 197: /* -R means put data into text segment */ ! 198: as_warn("%s: -R option not supported (use the " ! 199: ".const directive)", progname); ! 200: flagseen['R'] = FALSE; ! 201: break; ! 202: ! 203: case 'v': ! 204: fprintf(stderr,"NeXT Computer, Inc. version " ! 205: "%s, ", next_version); ! 206: fprintf(stderr, version_string); ! 207: if(*arg && strcmp(arg,"ersion")) ! 208: as_warn("Unknown -v option ignored"); ! 209: while(*arg) ! 210: arg++; /* Skip the rest */ ! 211: break; ! 212: ! 213: case 'W': ! 214: /* -W means don't warn about things */ ! 215: break; ! 216: ! 217: case 'I': ! 218: /* Add directory to path for includes */ ! 219: dirtmp = (struct directory_stack *) ! 220: xmalloc(sizeof(struct directory_stack)); ! 221: /* New one goes on the end */ ! 222: dirtmp->next = 0; ! 223: if(include == 0) ! 224: include = dirtmp; ! 225: else ! 226: include_tail->next = dirtmp; ! 227: /* Tail follows the last one */ ! 228: include_tail = dirtmp; ! 229: /* Rest of argument is include file-name. */ ! 230: if(*arg) ! 231: dirtmp->fname = arg; ! 232: else if (work_argc){ ! 233: /* Want next arg for a file-name. */ ! 234: /* This is not a file-name. */ ! 235: *work_argv = NULL; ! 236: work_argc--; ! 237: dirtmp->fname = *++work_argv; ! 238: } ! 239: else ! 240: as_warn("I expected a filename after -I."); ! 241: arg = ""; /* Finished with this arg. */ ! 242: break; ! 243: ! 244: case 'g': ! 245: /* generate stabs for debugging assembly code */ ! 246: break; ! 247: ! 248: case 'n': ! 249: /* no default .text section */ ! 250: break; ! 251: ! 252: case 'd': ! 253: if(strcmp(arg-1, "dynamic") == 0){ ! 254: arg = ""; /* Finished with this arg. */ ! 255: flagseen[(int)'k'] = TRUE; ! 256: break; ! 257: } ! 258: goto unknown_flag; ! 259: ! 260: case 's': ! 261: if(strcmp(arg-1, "static") == 0){ ! 262: arg = ""; /* Finished with this arg. */ ! 263: flagseen[(int)'k'] = FALSE; ! 264: break; ! 265: } ! 266: goto unknown_flag; ! 267: ! 268: case 'N': ! 269: if(strcmp(arg-1, "NEXTSTEP-deployment-target") == 0){ ! 270: arg = ""; /* Finished with this arg. */ ! 271: /* Want next arg for a <release_tag> */ ! 272: if(work_argc){ ! 273: /* This, "-NEXTST..." is not a file-name. */ ! 274: *work_argv = NULL; ! 275: work_argc--; ! 276: work_argv++; ! 277: if(strcmp(*work_argv, "3.3") == 0){ ! 278: flagseen[(int)'k'] = TRUE; ! 279: } ! 280: else if(strcmp(*work_argv, "3.2") == 0){ ! 281: flagseen[(int)'k'] = FALSE; ! 282: } ! 283: else{ ! 284: as_fatal("I expected '3.2' or '3.3' after " ! 285: "-NEXTSTEP-deployment-target."); ! 286: } ! 287: } ! 288: else ! 289: as_fatal("I expected a <release_tag> " ! 290: "after -NEXTSTEP-deployment-target."); ! 291: break; ! 292: } ! 293: goto unknown_flag; ! 294: ! 295: case 'k': ! 296: /* use new features incompatible with 3.2 */ ! 297: break; ! 298: ! 299: case 'V': ! 300: /* as driver's -V, verbose, flag */ ! 301: break; ! 302: ! 303: case 'a': ! 304: if(strcmp(arg-1, "arch_multiple") == 0){ ! 305: arch_multiple = 1; ! 306: arg = ""; /* Finished with this arg. */ ! 307: break; ! 308: } ! 309: else if(strcmp(arg-1, "arch") == 0){ ! 310: arg = ""; /* Finished with this arg. */ ! 311: /* Want next arg for a <arch_type> */ ! 312: if(work_argc){ ! 313: /* This, "-arch" is not a file-name. */ ! 314: *work_argv = NULL; ! 315: work_argc--; ! 316: work_argv++; ! 317: #ifdef M68K ! 318: if(strcmp(*work_argv, "m68030") == 0){ ! 319: if(archflag_cpusubtype != -1 && ! 320: archflag_cpusubtype != ! 321: CPU_SUBTYPE_MC68030_ONLY) ! 322: as_fatal("can't specify both " ! 323: "-arch m68030 and -arch " ! 324: "m68040"); ! 325: specific_archflag = *work_argv; ! 326: archflag_cpusubtype = ! 327: CPU_SUBTYPE_MC68030_ONLY; ! 328: } ! 329: else if(strcmp(*work_argv, ! 330: "m68040") == 0){ ! 331: if(archflag_cpusubtype != -1 && ! 332: archflag_cpusubtype != ! 333: CPU_SUBTYPE_MC68040) ! 334: as_fatal("can't specify both " ! 335: "-arch m68030 and -arch " ! 336: "m68040"); ! 337: specific_archflag = *work_argv; ! 338: archflag_cpusubtype = ! 339: CPU_SUBTYPE_MC68040; ! 340: } ! 341: else if(strcmp(*work_argv, "m68k") != 0) ! 342: as_fatal("I expected 'm68k', " ! 343: "'m68030' or 'm68040' after " ! 344: "-arch for this assembler."); ! 345: #endif ! 346: #ifdef M88K ! 347: if(strcmp(*work_argv, "m88k") != 0) ! 348: as_fatal("I expected 'm88k' after " ! 349: "-arch for this assembler."); ! 350: #endif ! 351: #ifdef I860 ! 352: if(strcmp(*work_argv, "i860") != 0) ! 353: as_fatal("I expected 'i860' after " ! 354: "-arch for this assembler."); ! 355: #endif ! 356: #ifdef I386 ! 357: if(strcmp(*work_argv, "i486") == 0){ ! 358: if(archflag_cpusubtype != -1 && ! 359: archflag_cpusubtype != ! 360: CPU_SUBTYPE_486) ! 361: as_fatal("can't specify more " ! 362: "than one -arch flag "); ! 363: specific_archflag = *work_argv; ! 364: archflag_cpusubtype = ! 365: CPU_SUBTYPE_486; ! 366: } ! 367: else if(strcmp(*work_argv, ! 368: "i486SX") == 0){ ! 369: if(archflag_cpusubtype != -1 && ! 370: archflag_cpusubtype != ! 371: CPU_SUBTYPE_486SX) ! 372: as_fatal("can't specify more " ! 373: "than one -arch flag "); ! 374: specific_archflag = *work_argv; ! 375: archflag_cpusubtype = ! 376: CPU_SUBTYPE_486SX; ! 377: } ! 378: else if(strcmp(*work_argv, "i586") ==0){ ! 379: if(archflag_cpusubtype != -1 && ! 380: archflag_cpusubtype != ! 381: CPU_SUBTYPE_586) ! 382: as_fatal("can't specify more " ! 383: "than one -arch flag "); ! 384: specific_archflag = *work_argv; ! 385: archflag_cpusubtype = ! 386: CPU_SUBTYPE_586; ! 387: } ! 388: else if(strcmp(*work_argv, ! 389: "i586SX") == 0){ ! 390: if(archflag_cpusubtype != -1 && ! 391: archflag_cpusubtype != ! 392: CPU_SUBTYPE_586SX) ! 393: as_fatal("can't specify more " ! 394: "than one -arch flag "); ! 395: specific_archflag = *work_argv; ! 396: archflag_cpusubtype = ! 397: CPU_SUBTYPE_586SX; ! 398: } ! 399: else if(strcmp(*work_argv, "i386") != 0) ! 400: as_fatal("I expected 'i386', 'i486'" ! 401: " 'i486SX', 'i586' or 'i586SX' " ! 402: "after -arch for this " ! 403: "assembler."); ! 404: #endif ! 405: #ifdef HPPA ! 406: if(strcmp(*work_argv, "hppa") != 0) ! 407: as_fatal("I expected 'hppa' after " ! 408: "-arch for this assembler."); ! 409: #endif ! 410: #ifdef SPARC ! 411: if(strcmp(*work_argv, "sparc") != 0) ! 412: as_fatal("I expected 'sparc' after " ! 413: "-arch for this assembler."); ! 414: #endif ! 415: } ! 416: else ! 417: as_fatal("I expected an <arch_type> " ! 418: "after -arch."); ! 419: break; ! 420: } ! 421: /* fall through for non -arch flag */ ! 422: default: ! 423: unknown_flag: ! 424: --arg; ! 425: if(md_parse_option(&arg, &work_argc, &work_argv) == 0) ! 426: as_warn("%s: I don't understand '%c' flag!", progname, ! 427: a); ! 428: if(arg && *arg) ! 429: arg++; ! 430: break; ! 431: } ! 432: } ! 433: /* ! 434: * We have just processed a "-..." arg, which was not a ! 435: * file-name. Smash it so the ! 436: * things that look for filenames won't ever see it. ! 437: * ! 438: * Whatever work_argv points to, it has already been used ! 439: * as part of a flag, so DON'T re-use it as a filename. ! 440: */ ! 441: *work_argv = NULL; /* NULL means 'not a file-name' */ ! 442: } ! 443: if(flagseen['g'] == TRUE && flagseen['n'] == TRUE) ! 444: as_fatal("-g can't be specified if -n is specified"); ! 445: /* ! 446: * If we haven't seen a -force_cpusubtype_ALL or an -arch flag for a ! 447: * specific architecture then let the machine instructions in the ! 448: * assembly determine the cpusubtype of the output file. ! 449: */ ! 450: if(force_cpusubtype_ALL && specific_archflag) ! 451: archflag_cpusubtype = -1; ! 452: ! 453: /* Here with flags set up in flagseen[]. */ ! 454: perform_an_assembly_pass(argc, argv); /* Assemble it. */ ! 455: ! 456: if(seen_at_least_1_file() && bad_error != TRUE){ ! 457: layout_addresses(); ! 458: write_object(out_file_name); ! 459: } ! 460: ! 461: input_scrub_end(); ! 462: md_end(); /* MACHINE.c */ ! 463: ! 464: exit(bad_error); /* WIN */ ! 465: } ! 466: ! 467: /* perform_an_assembly_pass() ! 468: * ! 469: * Here to attempt 1 pass over each input file. ! 470: * We scan argv[*] looking for filenames or exactly "" which is ! 471: * shorthand for stdin. Any argv that is NULL is not a file-name. ! 472: * We set need_pass_2 TRUE if, after this, we still have unresolved ! 473: * expressions of the form (unknown value)+-(unknown value). ! 474: * ! 475: * Note the un*x semantics: there is only 1 logical input file, but it ! 476: * may be a catenation of many 'physical' input files. ! 477: */ ! 478: static ! 479: void ! 480: perform_an_assembly_pass( ! 481: int argc, ! 482: char **argv) ! 483: { ! 484: char *buffer; /* Where each bufferful of lines will start. */ ! 485: int saw_a_file; ! 486: ! 487: saw_a_file = 0; ! 488: ! 489: argv++; /* skip argv[0] */ ! 490: argc--; /* skip argv[0] */ ! 491: while(argc--){ ! 492: if(*argv){ /* Is it a file-name argument? */ ! 493: /* argv -> "" if stdin desired, else -> filename */ ! 494: if((buffer = input_scrub_new_file(*argv))){ ! 495: saw_a_file++; ! 496: read_a_source_file(buffer); ! 497: } ! 498: } ! 499: argv++; /* completed that argv */ ! 500: } ! 501: if(!saw_a_file) ! 502: if((buffer = input_scrub_new_file(""))) ! 503: read_a_source_file(buffer); ! 504: } ! 505: ! 506: static ! 507: void ! 508: got_sig( ! 509: int sig) ! 510: { ! 511: static int here_before = 0; ! 512: ! 513: as_bad("Interrupted by signal %d",sig); ! 514: if(here_before++) ! 515: exit(1); ! 516: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.