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