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