xref: /original-bsd/contrib/gas-1.38/as.c (revision f95533f0)
1 /*	@(#)as.c	6.2 (Berkeley) 03/15/91
2 
3 Modified for Berkeley Unix by Donn Seeley, donn@okeeffe.berkeley.edu  */
4 
5 /* as.c - GAS main program.
6    Copyright (C) 1987 Free Software Foundation, Inc.
7 
8 This file is part of GAS, the GNU Assembler.
9 
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 1, or (at your option)
13 any later version.
14 
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING.  If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
23 
24 /*
25  * Main program for AS; a 32-bit assembler of GNU.
26  * Understands command arguments.
27  * Has a few routines that don't fit in other modules because they
28  * are shared.
29  *
30  *
31  *			bugs
32  *
33  * : initialisers
34  *	Since no-one else says they will support them in future: I
35  * don't support them now.
36  *
37  */
38 
39 #ifdef _POSIX_SOURCE
40 #include <sys/types.h>	/* For pid_t in signal.h */
41 #endif
42 #include <signal.h>
43 
44 #define COMMON
45 #include "as.h"
46 #include "struc-symbol.h"
47 #include "write.h"
48 		/* Warning!  This may have some slightly strange side effects
49 		   if you try to compile two or more assemblers in the same
50 		   directory!
51 		 */
52 
53 #ifndef SIGTY
54 #define SIGTY int
55 #endif
56 
57 SIGTY got_sig();
58 
59 #ifdef DONTDEF
60 static char * gdb_symbol_file_name;
61 long int gdb_begin();
62 #endif
63 
64 char *myname;		/* argv[0] */
65 extern char version_string[];
66 
67 main(argc,argv)
68 int	argc;
69 char	**argv;
70 {
71 	int	work_argc;	/* variable copy of argc */
72 	char	**work_argv;	/* variable copy of argv */
73 	char	*arg;		/* an arg to program */
74 	char	a;		/* an arg flag (after -) */
75 	static const int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
76 
77 	extern int bad_error;	/* Did we hit a bad error ? */
78 
79 	char	*stralloc();	/* Make a (safe) copy of a string. */
80 	void	symbol_begin();
81 	void	read_begin();
82 	void	write_object_file();
83 
84 	for(a=0;sig[a]!=0;a++)
85 		if(signal(sig[a], SIG_IGN) != SIG_IGN)
86 			signal(sig[a], got_sig);
87 
88 	myname=argv[0];
89 	bzero (flagseen, sizeof(flagseen)); /* aint seen nothing yet */
90 	out_file_name	= "a.out";	/* default .o file */
91 	symbol_begin();		/* symbols.c */
92 	subsegs_begin();		/* subsegs.c */
93 	read_begin();			/* read.c */
94 	md_begin();			/* MACHINE.c */
95 	input_scrub_begin();		/* input_scrub.c */
96 #ifdef DONTDEF
97 	gdb_symbol_file_name = 0;
98 #endif
99 	/*
100 	 * Parse arguments, but we are only interested in flags.
101 	 * When we find a flag, we process it then make it's argv[] NULL.
102 	 * This helps any future argv[] scanners avoid what we processed.
103 	 * Since it is easy to do here we interpret the special arg "-"
104 	 * to mean "use stdin" and we set that argv[] pointing to "".
105 	 * After we have munged argv[], the only things left are source file
106 	 * name(s) and ""(s) denoting stdin. These file names are used
107 	 * (perhaps more than once) later.
108 	 */
109 	work_argc = argc-1;		/* don't count argv[0] */
110 	work_argv = argv+1;		/* skip argv[0] */
111 	for (;work_argc--;work_argv++) {
112 		arg = * work_argv;	/* work_argv points to this argument */
113 
114 		if (*arg!='-')		/* Filename. We need it later. */
115 			continue;	/* Keep scanning args looking for flags. */
116 		if (arg[1] == '-' && arg[2] == 0) {
117 			/* "--" as an argument means read STDIN */
118 			/* on this scan, we don't want to think about filenames */
119 			* work_argv = "";	/* Code that means 'use stdin'. */
120 			continue;
121 		}
122 				/* This better be a switch. */
123 		arg ++;		/* -> letter. */
124 
125 		while (a = * arg)  {/* scan all the 1-char flags */
126 			arg ++;	/* arg -> after letter. */
127 			a &= 0x7F;	/* ascii only please */
128 			if (flagseen[a])
129 				as_warn("%s: Flag option -%c has already been seen!",myname,a);
130 			flagseen[a] = TRUE;
131 			switch (a) {
132 			case 'f':
133 				break;	/* -f means fast - no need for "app" preprocessor. */
134 
135 			case 'D':
136 				/* DEBUG is implemented: it debugs different */
137 				/* things to other people's assemblers. */
138 				break;
139 
140 #ifdef DONTDEF
141 			case 'G':	/* GNU AS switch: include gdbsyms. */
142 				if (*arg)	/* Rest of argument is file-name. */
143 					gdb_symbol_file_name = stralloc (arg);
144 				else if (work_argc) {	/* Next argument is file-name. */
145 					work_argc --;
146 					* work_argv = NULL; /* Not a source file-name. */
147 					gdb_symbol_file_name = * ++ work_argv;
148 				} else
149 					as_warn( "%s: I expected a filename after -G",myname);
150 				arg = "";	/* Finished with this arg. */
151 				break;
152 #endif
153 
154 #ifndef WORKING_DOT_WORD
155 			case 'k':
156 				break;
157 #endif
158 
159 			case 'L': /* -L means keep L* symbols */
160 				break;
161 
162 			case 'o':
163 				if (*arg)	/* Rest of argument is object file-name. */
164 					out_file_name = stralloc (arg);
165 				else if (work_argc) {	/* Want next arg for a file-name. */
166 					* work_argv = NULL; /* This is not a file-name. */
167 					work_argc--;
168 					out_file_name = * ++ work_argv;
169 				} else
170 					as_warn("%s: I expected a filename after -o. \"%s\" assumed.",myname,out_file_name);
171 				arg = "";	/* Finished with this arg. */
172 				break;
173 
174 			case 'R':
175 				/* -R means put data into text segment */
176 				break;
177 
178 			case 'v':
179 #ifdef	VMS
180 				{
181 				extern char *compiler_version_string;
182 				compiler_version_string = arg;
183 				}
184 #else /* not VMS */
185 				fprintf(stderr,version_string);
186 				if(*arg && strcmp(arg,"ersion"))
187 					as_warn("Unknown -v option ignored");
188 #endif
189 				while(*arg) arg++;	/* Skip the rest */
190 				break;
191 
192 			case 'W':
193 				/* -W means don't warn about things */
194 				break;
195 
196 			case 'g':
197 				/*
198 				 * -g asks gas to produce gdb/dbx line number
199 				 * and file name stabs so that an assembly
200 				 * file can be handled by a source debugger.
201 				 */
202 				break;
203 
204 			default:
205 				--arg;
206 				if(md_parse_option(&arg,&work_argc,&work_argv)==0)
207 					as_warn("%s: I don't understand '%c' flag!",myname,a);
208 				if(arg && *arg)
209 					arg++;
210 				break;
211 			}
212 		}
213 		/*
214 		 * We have just processed a "-..." arg, which was not a
215 		 * file-name. Smash it so the
216 		 * things that look for filenames won't ever see it.
217 		 *
218 		 * Whatever work_argv points to, it has already been used
219 		 * as part of a flag, so DON'T re-use it as a filename.
220 		 */
221 		*work_argv = NULL; /* NULL means 'not a file-name' */
222 	}
223 #ifdef DONTDEF
224 	if (gdb_begin(gdb_symbol_file_name) == 0)
225 		flagseen ['G'] = 0;	/* Don't do any gdbsym stuff. */
226 #endif
227 	/* Here with flags set up in flagseen[]. */
228 	perform_an_assembly_pass(argc,argv); /* Assemble it. */
229 	if (seen_at_least_1_file() && !bad_error)
230 		write_object_file();/* relax() addresses then emit object file */
231 	input_scrub_end();
232 	md_end();			/* MACHINE.c */
233 #ifndef	VMS
234 	exit(bad_error);			/* WIN */
235 #else	/* VMS */
236 	exit(!bad_error);			/* WIN */
237 #endif	/* VMS */
238 }
239 
240 
241 /*			perform_an_assembly_pass()
242  *
243  * Here to attempt 1 pass over each input file.
244  * We scan argv[*] looking for filenames or exactly "" which is
245  * shorthand for stdin. Any argv that is NULL is not a file-name.
246  * We set need_pass_2 TRUE if, after this, we still have unresolved
247  * expressions of the form (unknown value)+-(unknown value).
248  *
249  * Note the un*x semantics: there is only 1 logical input file, but it
250  * may be a catenation of many 'physical' input files.
251  */
252 perform_an_assembly_pass (argc, argv)
253 int	argc;
254 char **	argv;
255 {
256 	char *	buffer;		/* Where each bufferful of lines will start. */
257 	void	read_a_source_file();
258 	int saw_a_file = 0;
259 
260 	text_fix_root		= NULL;
261 	data_fix_root		= NULL;
262 	need_pass_2		= FALSE;
263 
264 	argv++;			/* skip argv[0] */
265 	argc--;			/* skip argv[0] */
266 	while (argc--) {
267 		if (*argv) {		/* Is it a file-name argument? */
268 			/* argv -> "" if stdin desired, else -> filename */
269 			if (buffer = input_scrub_new_file (*argv) ) {
270 				saw_a_file++;
271 				read_a_source_file(buffer);
272 			}
273 		}
274 		argv++;			/* completed that argv */
275 	}
276 	if(!saw_a_file)
277 		if(buffer = input_scrub_new_file("") )
278 			read_a_source_file(buffer);
279 }
280 
281 /*
282  *			stralloc()
283  *
284  * Allocate memory for a new copy of a string. Copy the string.
285  * Return the address of the new string. Die if there is any error.
286  */
287 
288 char *
289 stralloc (str)
290 char *	str;
291 {
292 	register char *	retval;
293 	register long int	len;
294 
295 	len = strlen (str) + 1;
296 	retval = xmalloc (len);
297 	(void)strcpy (retval, str);
298 	return (retval);
299 }
300 
301 lose()
302 {
303 	as_fatal( "%s: 2nd pass not implemented - get your code from random(3)",myname );
304 }
305 
306 SIGTY
307 got_sig(sig)
308 int sig;
309 {
310 	static here_before = 0;
311 
312 	as_bad("Interrupted by signal %d",sig);
313 	if(here_before++)
314 		exit(1);
315 }
316 
317 /* end: as.c */
318