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