1*47442Sdonn /* @(#)as.c 6.2 (Berkeley) 03/15/91 2*47442Sdonn 3*47442Sdonn Modified for Berkeley Unix by Donn Seeley, donn@okeeffe.berkeley.edu */ 4*47442Sdonn 547427Sdonn /* as.c - GAS main program. 647427Sdonn Copyright (C) 1987 Free Software Foundation, Inc. 747427Sdonn 847427Sdonn This file is part of GAS, the GNU Assembler. 947427Sdonn 1047427Sdonn GAS is free software; you can redistribute it and/or modify 1147427Sdonn it under the terms of the GNU General Public License as published by 1247427Sdonn the Free Software Foundation; either version 1, or (at your option) 1347427Sdonn any later version. 1447427Sdonn 1547427Sdonn GAS is distributed in the hope that it will be useful, 1647427Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of 1747427Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1847427Sdonn GNU General Public License for more details. 1947427Sdonn 2047427Sdonn You should have received a copy of the GNU General Public License 2147427Sdonn along with GAS; see the file COPYING. If not, write to 2247427Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 2347427Sdonn 2447427Sdonn /* 2547427Sdonn * Main program for AS; a 32-bit assembler of GNU. 2647427Sdonn * Understands command arguments. 2747427Sdonn * Has a few routines that don't fit in other modules because they 2847427Sdonn * are shared. 2947427Sdonn * 3047427Sdonn * 3147427Sdonn * bugs 3247427Sdonn * 3347427Sdonn * : initialisers 3447427Sdonn * Since no-one else says they will support them in future: I 3547427Sdonn * don't support them now. 3647427Sdonn * 3747427Sdonn */ 3847427Sdonn 3947427Sdonn #ifdef _POSIX_SOURCE 4047427Sdonn #include <sys/types.h> /* For pid_t in signal.h */ 4147427Sdonn #endif 4247427Sdonn #include <signal.h> 4347427Sdonn 4447427Sdonn #define COMMON 4547427Sdonn #include "as.h" 4647427Sdonn #include "struc-symbol.h" 4747427Sdonn #include "write.h" 4847427Sdonn /* Warning! This may have some slightly strange side effects 4947427Sdonn if you try to compile two or more assemblers in the same 5047427Sdonn directory! 5147427Sdonn */ 5247427Sdonn 5347427Sdonn #ifndef SIGTY 5447427Sdonn #define SIGTY int 5547427Sdonn #endif 5647427Sdonn 5747427Sdonn SIGTY got_sig(); 5847427Sdonn 5947427Sdonn #ifdef DONTDEF 6047427Sdonn static char * gdb_symbol_file_name; 6147427Sdonn long int gdb_begin(); 6247427Sdonn #endif 6347427Sdonn 6447427Sdonn char *myname; /* argv[0] */ 6547427Sdonn extern char version_string[]; 6647427Sdonn 6747427Sdonn main(argc,argv) 6847427Sdonn int argc; 6947427Sdonn char **argv; 7047427Sdonn { 7147427Sdonn int work_argc; /* variable copy of argc */ 7247427Sdonn char **work_argv; /* variable copy of argv */ 7347427Sdonn char *arg; /* an arg to program */ 7447427Sdonn char a; /* an arg flag (after -) */ 7547427Sdonn static const int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0}; 7647427Sdonn 7747427Sdonn extern int bad_error; /* Did we hit a bad error ? */ 7847427Sdonn 7947427Sdonn char *stralloc(); /* Make a (safe) copy of a string. */ 8047427Sdonn void symbol_begin(); 8147427Sdonn void read_begin(); 8247427Sdonn void write_object_file(); 8347427Sdonn 8447427Sdonn for(a=0;sig[a]!=0;a++) 8547427Sdonn if(signal(sig[a], SIG_IGN) != SIG_IGN) 8647427Sdonn signal(sig[a], got_sig); 8747427Sdonn 8847427Sdonn myname=argv[0]; 8947427Sdonn bzero (flagseen, sizeof(flagseen)); /* aint seen nothing yet */ 9047427Sdonn out_file_name = "a.out"; /* default .o file */ 9147427Sdonn symbol_begin(); /* symbols.c */ 9247427Sdonn subsegs_begin(); /* subsegs.c */ 9347427Sdonn read_begin(); /* read.c */ 9447427Sdonn md_begin(); /* MACHINE.c */ 9547427Sdonn input_scrub_begin(); /* input_scrub.c */ 9647427Sdonn #ifdef DONTDEF 9747427Sdonn gdb_symbol_file_name = 0; 9847427Sdonn #endif 9947427Sdonn /* 10047427Sdonn * Parse arguments, but we are only interested in flags. 10147427Sdonn * When we find a flag, we process it then make it's argv[] NULL. 10247427Sdonn * This helps any future argv[] scanners avoid what we processed. 10347427Sdonn * Since it is easy to do here we interpret the special arg "-" 10447427Sdonn * to mean "use stdin" and we set that argv[] pointing to "". 10547427Sdonn * After we have munged argv[], the only things left are source file 10647427Sdonn * name(s) and ""(s) denoting stdin. These file names are used 10747427Sdonn * (perhaps more than once) later. 10847427Sdonn */ 10947427Sdonn work_argc = argc-1; /* don't count argv[0] */ 11047427Sdonn work_argv = argv+1; /* skip argv[0] */ 11147427Sdonn for (;work_argc--;work_argv++) { 11247427Sdonn arg = * work_argv; /* work_argv points to this argument */ 11347427Sdonn 11447427Sdonn if (*arg!='-') /* Filename. We need it later. */ 11547427Sdonn continue; /* Keep scanning args looking for flags. */ 11647427Sdonn if (arg[1] == '-' && arg[2] == 0) { 11747427Sdonn /* "--" as an argument means read STDIN */ 11847427Sdonn /* on this scan, we don't want to think about filenames */ 11947427Sdonn * work_argv = ""; /* Code that means 'use stdin'. */ 12047427Sdonn continue; 12147427Sdonn } 12247427Sdonn /* This better be a switch. */ 12347427Sdonn arg ++; /* -> letter. */ 12447427Sdonn 12547427Sdonn while (a = * arg) {/* scan all the 1-char flags */ 12647427Sdonn arg ++; /* arg -> after letter. */ 12747427Sdonn a &= 0x7F; /* ascii only please */ 12847427Sdonn if (flagseen[a]) 12947427Sdonn as_warn("%s: Flag option -%c has already been seen!",myname,a); 13047427Sdonn flagseen[a] = TRUE; 13147427Sdonn switch (a) { 13247427Sdonn case 'f': 13347427Sdonn break; /* -f means fast - no need for "app" preprocessor. */ 13447427Sdonn 13547427Sdonn case 'D': 13647427Sdonn /* DEBUG is implemented: it debugs different */ 13747427Sdonn /* things to other people's assemblers. */ 13847427Sdonn break; 13947427Sdonn 14047427Sdonn #ifdef DONTDEF 14147427Sdonn case 'G': /* GNU AS switch: include gdbsyms. */ 14247427Sdonn if (*arg) /* Rest of argument is file-name. */ 14347427Sdonn gdb_symbol_file_name = stralloc (arg); 14447427Sdonn else if (work_argc) { /* Next argument is file-name. */ 14547427Sdonn work_argc --; 14647427Sdonn * work_argv = NULL; /* Not a source file-name. */ 14747427Sdonn gdb_symbol_file_name = * ++ work_argv; 14847427Sdonn } else 14947427Sdonn as_warn( "%s: I expected a filename after -G",myname); 15047427Sdonn arg = ""; /* Finished with this arg. */ 15147427Sdonn break; 15247427Sdonn #endif 15347427Sdonn 15447427Sdonn #ifndef WORKING_DOT_WORD 15547427Sdonn case 'k': 15647427Sdonn break; 15747427Sdonn #endif 15847427Sdonn 15947427Sdonn case 'L': /* -L means keep L* symbols */ 16047427Sdonn break; 16147427Sdonn 16247427Sdonn case 'o': 16347427Sdonn if (*arg) /* Rest of argument is object file-name. */ 16447427Sdonn out_file_name = stralloc (arg); 16547427Sdonn else if (work_argc) { /* Want next arg for a file-name. */ 16647427Sdonn * work_argv = NULL; /* This is not a file-name. */ 16747427Sdonn work_argc--; 16847427Sdonn out_file_name = * ++ work_argv; 16947427Sdonn } else 17047427Sdonn as_warn("%s: I expected a filename after -o. \"%s\" assumed.",myname,out_file_name); 17147427Sdonn arg = ""; /* Finished with this arg. */ 17247427Sdonn break; 17347427Sdonn 17447427Sdonn case 'R': 17547427Sdonn /* -R means put data into text segment */ 17647427Sdonn break; 17747427Sdonn 17847427Sdonn case 'v': 17947427Sdonn #ifdef VMS 18047427Sdonn { 18147427Sdonn extern char *compiler_version_string; 18247427Sdonn compiler_version_string = arg; 18347427Sdonn } 18447427Sdonn #else /* not VMS */ 18547427Sdonn fprintf(stderr,version_string); 18647427Sdonn if(*arg && strcmp(arg,"ersion")) 18747427Sdonn as_warn("Unknown -v option ignored"); 18847427Sdonn #endif 18947427Sdonn while(*arg) arg++; /* Skip the rest */ 19047427Sdonn break; 19147427Sdonn 19247427Sdonn case 'W': 19347427Sdonn /* -W means don't warn about things */ 19447427Sdonn break; 19547427Sdonn 196*47442Sdonn case 'g': 197*47442Sdonn /* 198*47442Sdonn * -g asks gas to produce gdb/dbx line number 199*47442Sdonn * and file name stabs so that an assembly 200*47442Sdonn * file can be handled by a source debugger. 201*47442Sdonn */ 202*47442Sdonn break; 203*47442Sdonn 20447427Sdonn default: 20547427Sdonn --arg; 20647427Sdonn if(md_parse_option(&arg,&work_argc,&work_argv)==0) 20747427Sdonn as_warn("%s: I don't understand '%c' flag!",myname,a); 20847427Sdonn if(arg && *arg) 20947427Sdonn arg++; 21047427Sdonn break; 21147427Sdonn } 21247427Sdonn } 21347427Sdonn /* 21447427Sdonn * We have just processed a "-..." arg, which was not a 21547427Sdonn * file-name. Smash it so the 21647427Sdonn * things that look for filenames won't ever see it. 21747427Sdonn * 21847427Sdonn * Whatever work_argv points to, it has already been used 21947427Sdonn * as part of a flag, so DON'T re-use it as a filename. 22047427Sdonn */ 22147427Sdonn *work_argv = NULL; /* NULL means 'not a file-name' */ 22247427Sdonn } 22347427Sdonn #ifdef DONTDEF 22447427Sdonn if (gdb_begin(gdb_symbol_file_name) == 0) 22547427Sdonn flagseen ['G'] = 0; /* Don't do any gdbsym stuff. */ 22647427Sdonn #endif 22747427Sdonn /* Here with flags set up in flagseen[]. */ 22847427Sdonn perform_an_assembly_pass(argc,argv); /* Assemble it. */ 22947427Sdonn if (seen_at_least_1_file() && !bad_error) 23047427Sdonn write_object_file();/* relax() addresses then emit object file */ 23147427Sdonn input_scrub_end(); 23247427Sdonn md_end(); /* MACHINE.c */ 23347427Sdonn #ifndef VMS 23447427Sdonn exit(bad_error); /* WIN */ 23547427Sdonn #else /* VMS */ 23647427Sdonn exit(!bad_error); /* WIN */ 23747427Sdonn #endif /* VMS */ 23847427Sdonn } 23947427Sdonn 24047427Sdonn 24147427Sdonn /* perform_an_assembly_pass() 24247427Sdonn * 24347427Sdonn * Here to attempt 1 pass over each input file. 24447427Sdonn * We scan argv[*] looking for filenames or exactly "" which is 24547427Sdonn * shorthand for stdin. Any argv that is NULL is not a file-name. 24647427Sdonn * We set need_pass_2 TRUE if, after this, we still have unresolved 24747427Sdonn * expressions of the form (unknown value)+-(unknown value). 24847427Sdonn * 24947427Sdonn * Note the un*x semantics: there is only 1 logical input file, but it 25047427Sdonn * may be a catenation of many 'physical' input files. 25147427Sdonn */ 25247427Sdonn perform_an_assembly_pass (argc, argv) 25347427Sdonn int argc; 25447427Sdonn char ** argv; 25547427Sdonn { 25647427Sdonn char * buffer; /* Where each bufferful of lines will start. */ 25747427Sdonn void read_a_source_file(); 25847427Sdonn int saw_a_file = 0; 25947427Sdonn 26047427Sdonn text_fix_root = NULL; 26147427Sdonn data_fix_root = NULL; 26247427Sdonn need_pass_2 = FALSE; 26347427Sdonn 26447427Sdonn argv++; /* skip argv[0] */ 26547427Sdonn argc--; /* skip argv[0] */ 26647427Sdonn while (argc--) { 26747427Sdonn if (*argv) { /* Is it a file-name argument? */ 26847427Sdonn /* argv -> "" if stdin desired, else -> filename */ 26947427Sdonn if (buffer = input_scrub_new_file (*argv) ) { 27047427Sdonn saw_a_file++; 27147427Sdonn read_a_source_file(buffer); 27247427Sdonn } 27347427Sdonn } 27447427Sdonn argv++; /* completed that argv */ 27547427Sdonn } 27647427Sdonn if(!saw_a_file) 27747427Sdonn if(buffer = input_scrub_new_file("") ) 27847427Sdonn read_a_source_file(buffer); 27947427Sdonn } 28047427Sdonn 28147427Sdonn /* 28247427Sdonn * stralloc() 28347427Sdonn * 28447427Sdonn * Allocate memory for a new copy of a string. Copy the string. 28547427Sdonn * Return the address of the new string. Die if there is any error. 28647427Sdonn */ 28747427Sdonn 28847427Sdonn char * 28947427Sdonn stralloc (str) 29047427Sdonn char * str; 29147427Sdonn { 29247427Sdonn register char * retval; 29347427Sdonn register long int len; 29447427Sdonn 29547427Sdonn len = strlen (str) + 1; 29647427Sdonn retval = xmalloc (len); 29747427Sdonn (void)strcpy (retval, str); 29847427Sdonn return (retval); 29947427Sdonn } 30047427Sdonn 30147427Sdonn lose() 30247427Sdonn { 30347427Sdonn as_fatal( "%s: 2nd pass not implemented - get your code from random(3)",myname ); 30447427Sdonn } 30547427Sdonn 30647427Sdonn SIGTY 30747427Sdonn got_sig(sig) 30847427Sdonn int sig; 30947427Sdonn { 31047427Sdonn static here_before = 0; 31147427Sdonn 31247427Sdonn as_bad("Interrupted by signal %d",sig); 31347427Sdonn if(here_before++) 31447427Sdonn exit(1); 31547427Sdonn } 31647427Sdonn 31747427Sdonn /* end: as.c */ 318