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