|
|
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.