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