]> Git Repo - binutils.git/blob - gas/as.c
from gas/testscripts -- may be useful someday
[binutils.git] / gas / as.c
1 /* as.c - GAS main program.
2    Copyright (C) 1987, 1990, 1991, 1992 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 2, 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 <stdio.h>
36 #include <string.h>
37
38 #ifdef _POSIX_SOURCE
39 #include <sys/types.h>          /* For pid_t in signal.h */
40 #endif
41 #include <signal.h>
42
43 #define COMMON
44
45 #include "as.h"
46 #include "config.h"
47 #include "subsegs.h"
48
49 #if __STDC__ == 1
50
51 /* This prototype for got_sig() is ansi.  If you want
52    anything else, then your compiler is lying to you when
53    it says that it is __STDC__.  If you want to change it,
54    #ifdef protect it from those of us with real ansi
55    compilers. */
56
57 #define SIGTY void
58
59 static void got_sig (int sig);
60 static void perform_an_assembly_pass (int argc, char **argv);
61
62 #else /* __STDC__ */
63
64 #ifndef SIGTY
65 #define SIGTY int
66 #endif
67
68 static SIGTY got_sig ();
69 static void perform_an_assembly_pass ();
70
71 #endif /* not __STDC__ */
72
73 #ifndef EXIT_SUCCESS
74 #define EXIT_SUCCESS 0
75 #define EXIT_FAILURE 1
76 #endif
77
78 int listing;                    /* true if a listing is wanted */
79
80 char *myname;                   /* argv[0] */
81 #ifdef BFD_ASSEMBLER
82 segT big_section, reg_section, pass1_section;
83 segT diff_section, absent_section;
84 segT text_section, data_section, bss_section;
85 #endif
86 \f
87 int 
88 main (argc, argv)
89      int argc;
90      char **argv;
91 {
92   int work_argc;                /* variable copy of argc */
93   char **work_argv;             /* variable copy of argv */
94   char *arg;                    /* an arg to program */
95   char a;                       /* an arg flag (after -) */
96
97 #if 0 /* do we need any of this?? */
98   {
99     static const int sig[] = {SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
100
101     for (a = 0; sig[a] != 0; a++)
102       if (signal (sig[a], SIG_IGN) != SIG_IGN)
103         signal (sig[a], got_sig);
104   }
105 #endif
106
107   myname = argv[0];
108   memset (flagseen, '\0', sizeof (flagseen));   /* aint seen nothing yet */
109 #ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME
110 #define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out"
111 #endif
112   out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME;
113
114 #ifdef BFD_ASSEMBLER
115   bfd_init ();
116 #endif
117
118   symbol_begin ();
119   subsegs_begin ();
120   read_begin ();
121   md_begin ();
122   input_scrub_begin ();
123   frag_init ();
124   /*
125    * Parse arguments, but we are only interested in flags.
126    * When we find a flag, we process it then make it's argv[] NULL.
127    * This helps any future argv[] scanners avoid what we processed.
128    * Since it is easy to do here we interpret the special arg "-"
129    * to mean "use stdin" and we set that argv[] pointing to "".
130    * After we have munged argv[], the only things left are source file
131    * name(s) and ""(s) denoting stdin. These file names are used
132    * (perhaps more than once) later.
133    */
134   /* FIXME-SOMEDAY this should use getopt. */
135   work_argc = argc - 1;         /* don't count argv[0] */
136   work_argv = argv + 1;         /* skip argv[0] */
137   for (; work_argc--; work_argv++)
138     {
139       arg = *work_argv;         /* work_argv points to this argument */
140
141       if (*arg != '-')          /* Filename. We need it later. */
142         continue;               /* Keep scanning args looking for flags. */
143       if (arg[1] == '-' && arg[2] == 0)
144         {
145           /* "--" as an argument means read STDIN */
146           /* on this scan, we don't want to think about filenames */
147           *work_argv = "";      /* Code that means 'use stdin'. */
148           continue;
149         }
150       /* This better be a switch. */
151       arg++;                    /*->letter. */
152
153       while ((a = *arg) != '\0')
154         {                       /* scan all the 1-char flags */
155           arg++;                /* arg->after letter. */
156           a &= 0x7F;            /* ascii only please */
157           flagseen[a] = 1;
158           switch (a)
159             {
160             case 'a':
161               {
162                 int loop = 1;
163
164                 while (loop)
165                   {
166                     switch (*arg)
167                       {
168                       case 'l':
169                         listing |= LISTING_LISTING;
170                         arg++;
171                         break;
172                       case 's':
173                         listing |= LISTING_SYMBOLS;
174                         arg++;
175                         break;
176                       case 'h':
177                         listing |= LISTING_HLL;
178                         arg++;
179                         break;
180
181                       case 'n':
182                         listing |= LISTING_NOFORM;
183                         arg++;
184                         break;
185                       case 'd':
186                         listing |= LISTING_NODEBUG;
187                         arg++;
188                         break;
189                       default:
190                         if (!listing)
191                           listing = LISTING_DEFAULT;
192                         loop = 0;
193                         break;
194                       }
195                   }
196               }
197
198               break;
199
200
201             case 'f':
202               break;            /* -f means fast - no need for "app" preprocessor. */
203
204             case 'D':
205               /* DEBUG is implemented: it debugs different */
206               /* things to other people's assemblers. */
207               break;
208
209             case 'I':
210               {                 /* Include file directory */
211
212                 char *temp = NULL;
213                 if (*arg)
214                   {
215                     temp = strdup (arg);
216                     if (!temp)
217                       as_fatal ("virtual memory exhuasted");
218                   }
219                 else if (work_argc)
220                   {
221                     *work_argv = NULL;
222                     work_argc--;
223                     temp = *++work_argv;
224                   }
225                 else
226                   as_warn ("%s: I expected a filename after -I", myname);
227                 add_include_dir (temp);
228                 arg = "";       /* Finished with this arg. */
229                 break;
230               }
231
232 #ifdef WARN_SIGNED_OVERFLOW_WORD
233               /* Don't warn about signed overflow.  */
234             case 'J':
235               break;
236 #endif
237
238 #ifndef WORKING_DOT_WORD
239             case 'K':
240               break;
241 #endif
242
243             case 'L':           /* -L means keep L* symbols */
244               break;
245
246             case 'o':
247               if (*arg)         /* Rest of argument is object file-name. */
248                 {
249                   out_file_name = strdup (arg);
250                   if (!out_file_name)
251                     as_fatal ("virtual memory exhausted");
252                 }
253               else if (work_argc)
254                 {               /* Want next arg for a file-name. */
255                   *work_argv = NULL;    /* This is not a file-name. */
256                   work_argc--;
257                   out_file_name = *++work_argv;
258                 }
259               else
260                 as_warn ("%s: I expected a filename after -o. \"%s\" assumed.",
261                          myname, out_file_name);
262               arg = "";         /* Finished with this arg. */
263               break;
264
265             case 'R':
266               /* -R means put data into text segment */
267               flag_readonly_data_in_text = 1;
268               break;
269
270             case 'v':
271 #ifdef  VMS
272               {
273                 extern char *compiler_version_string;
274                 compiler_version_string = arg;
275               }
276 #else /* not VMS */
277               if (*arg && strcmp (arg, "ersion"))
278                 {
279                   as_warn ("Unknown -v option ignored");
280                   arg += strlen (arg);
281                   break;
282                 }
283
284               fprintf (stderr, "GNU assembler version %s (%s)",
285                        GAS_VERSION, TARGET_ALIAS);
286 #ifdef BFD_ASSEMBLER
287               fprintf (stderr, ", using BFD version %s", BFD_VERSION);
288 #endif
289               fprintf (stderr, "\n");
290 #endif /* not VMS */
291               while (*arg)
292                 arg++;          /* Skip the rest */
293               break;
294
295             case 'W':
296               /* -W means don't warn about things */
297               flag_suppress_warnings = 1;
298               break;
299
300             case 'w':
301             case 'X':
302               /* -X means treat warnings as errors */
303               break;
304             case 'Z':
305               /* -Z means attempt to generate object file even after errors. */
306               flag_always_generate_output = 1;
307               break;
308
309             default:
310               --arg;
311               if (md_parse_option (&arg, &work_argc, &work_argv) == 0)
312                 as_warn ("%s: I don't understand '%c' flag.", myname, a);
313               if (arg && *arg)
314                 arg++;
315               break;
316             }
317         }
318       /*
319        * We have just processed a "-..." arg, which was not a
320        * file-name. Smash it so the
321        * things that look for filenames won't ever see it.
322        *
323        * Whatever work_argv points to, it has already been used
324        * as part of a flag, so DON'T re-use it as a filename.
325        */
326       *work_argv = NULL;        /* NULL means 'not a file-name' */
327     }
328
329 #ifdef BFD_ASSEMBLER
330   output_file_create (out_file_name);
331   assert (stdoutput != 0);
332 #endif
333
334   /* Here with flags set up in flagseen[]. */
335   perform_an_assembly_pass (argc, argv);        /* Assemble it. */
336 #ifdef TC_I960
337   brtab_emit ();
338 #endif
339   if (seen_at_least_1_file ()
340       && !((had_warnings () && flag_always_generate_output)
341            || had_errors () > 0))
342     {
343       write_object_file ();     /* relax() addresses then emit object file */
344     }                           /* we also check in write_object_file() just before emit. */
345
346   input_scrub_end ();
347   md_end ();                    /* MACHINE.c */
348
349 #ifndef NO_LISTING
350   listing_print ("");
351 #endif
352
353   if ((had_warnings () && flagseen['Z'])
354       || had_errors () > 0)
355     return EXIT_FAILURE;
356   return EXIT_SUCCESS;
357 }
358 \f
359
360 /*                      perform_an_assembly_pass()
361  *
362  * Here to attempt 1 pass over each input file.
363  * We scan argv[*] looking for filenames or exactly "" which is
364  * shorthand for stdin. Any argv that is NULL is not a file-name.
365  * We set need_pass_2 TRUE if, after this, we still have unresolved
366  * expressions of the form (unknown value)+-(unknown value).
367  *
368  * Note the un*x semantics: there is only 1 logical input file, but it
369  * may be a catenation of many 'physical' input files.
370  */
371 static void 
372 perform_an_assembly_pass (argc, argv)
373      int argc;
374      char **argv;
375 {
376   int saw_a_file = 0;
377   unsigned int i;
378 #ifdef BFD_ASSEMBLER
379   flagword applicable;
380 #endif
381
382   need_pass_2 = 0;
383
384 #ifndef BFD_ASSEMBLER
385 #ifdef MANY_SEGMENTS
386   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
387     {
388       segment_info[i].fix_root = 0;
389     }
390   /* Create the three fixed ones */
391   subseg_new (SEG_E0, 0);
392   subseg_new (SEG_E1, 0);
393   subseg_new (SEG_E2, 0);
394   strcpy (segment_info[SEG_E0].scnhdr.s_name, ".text");
395   strcpy (segment_info[SEG_E1].scnhdr.s_name, ".data");
396   strcpy (segment_info[SEG_E2].scnhdr.s_name, ".bss");
397
398   subseg_new (SEG_E0, 0);
399 #else /* not MANY_SEGMENTS */
400   text_fix_root = NULL;
401   data_fix_root = NULL;
402   bss_fix_root = NULL;
403
404   subseg_new (SEG_TEXT, 0);
405 #endif /* not MANY_SEGMENTS */
406 #else /* BFD_ASSEMBLER */
407   /* Create the standard sections, and those the assembler uses
408      internally.  */
409   text_section = subseg_new (".text", 0);
410   text_section->output_section = text_section;
411   data_section = subseg_new (".data", 0);
412   data_section->output_section = data_section;
413   bss_section = subseg_new (".bss", 0);
414   bss_section->output_section = bss_section;
415   /* @@ FIXME -- we're setting the RELOC flag so that sections are assumed
416      to have relocs, otherwise we don't find out in time. */
417   applicable = bfd_applicable_section_flags (stdoutput);
418   bfd_set_section_flags (stdoutput, text_section,
419                          applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
420                                        | SEC_CODE | SEC_READONLY));
421   /* @@ FIXME -- SEC_CODE seems to mean code only, rather than code possibly.*/
422   bfd_set_section_flags (stdoutput, data_section,
423                          applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC));
424   bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC);
425   subseg_new (BFD_ABS_SECTION_NAME, 0);
426   subseg_new (BFD_UND_SECTION_NAME, 0);
427   big_section = subseg_new ("*GAS `big' section*", 0);
428   reg_section = subseg_new ("*GAS `reg' section*", 0);
429   pass1_section = subseg_new ("*GAS `pass1' section*", 0);
430   diff_section = subseg_new ("*GAS `diff' section*", 0);
431   absent_section = subseg_new ("*GAS `absent' section*", 0);
432
433   subseg_new (".text", 0);
434 #endif /* BFD_ASSEMBLER */
435
436   argv++;                       /* skip argv[0] */
437   argc--;                       /* skip argv[0] */
438   while (argc--)
439     {
440       if (*argv)
441         {                       /* Is it a file-name argument? */
442           saw_a_file++;
443           /* argv->"" if stdin desired, else->filename */
444           read_a_source_file (*argv);
445         }
446       argv++;                   /* completed that argv */
447     }
448   if (!saw_a_file)
449     read_a_source_file ("");
450 }                               /* perform_an_assembly_pass() */
451 \f
452 static SIGTY
453 got_sig (sig)
454      int sig;
455 {
456   static here_before = 0;
457
458   as_bad ("Interrupted by signal %d", sig);
459   if (here_before++)
460     exit (EXIT_FAILURE);
461   return ((SIGTY) 0);
462 }
463
464 /* end of as.c */
This page took 0.051302 seconds and 4 git commands to generate.