home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gas / as.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  8.5 KB  |  325 lines

  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) 5/8/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.