home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / cctools / as / as.c < prev    next >
C/C++ Source or Header  |  1996-04-18  |  14KB  |  518 lines

  1. /* as.c - GAS main program.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Main program for AS; a 32-bit assembler of GNU.
  22.  * Understands command arguments.
  23.  * Has a few routines that don't fit in other modules because they
  24.  * are shared.
  25.  *
  26.  *
  27.  *            bugs
  28.  *
  29.  * : initialisers
  30.  *    Since no-one else says they will support them in future: I
  31.  * don't support them now.
  32.  *
  33.  */
  34.  
  35. #include <signal.h>
  36. #include <string.h>
  37.  
  38. #include "as.h"
  39. #include "input-scrub.h"
  40. #include "symbols.h"
  41. #include "sections.h"
  42. #include "read.h"
  43. #include "md.h"
  44. #include "messages.h"
  45. #include "xmalloc.h"
  46. #include "layout.h"
  47. #include "write_object.h"
  48.  
  49. /* ['x'] TRUE if "-x" seen. */
  50. char flagseen[128] = { 0 };
  51.  
  52. /* TRUE if -force_cpusubtype_ALL is specified */
  53. int force_cpusubtype_ALL = 0;
  54.  
  55. /* set to the corresponding cpusubtype if -arch flag is specified */
  56. cpu_subtype_t archflag_cpusubtype = -1;
  57.  
  58. /*
  59.  * .include "file" looks in source file dir, then stack.
  60.  * -I directories are added to the end, then the defaults are added.
  61.  */
  62. struct directory_stack include_defaults[] = {
  63.     { 0, "/NextDeveloper/Headers/" },
  64.     { 0, "/LocalDeveloper/Headers/" },
  65.     { 0, NULL }
  66. };
  67. struct directory_stack *include = NULL;    /* First dir to search */
  68. static struct directory_stack *include_tail = NULL;    /* Last in chain */
  69.  
  70. /* next_version is in next_version.c which is created by the Makefile */
  71. extern char next_version[];
  72. /* this is only used here, thus defined here (was in version.c in GAS) */
  73. static char version_string[] = "GNU assembler version 1.38\n";
  74.  
  75. /*
  76.  * The list of signals to catch if not ignored.
  77.  */
  78. static int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
  79. static void got_sig(
  80.     int sig);
  81.  
  82. static void perform_an_assembly_pass(
  83.     int argc,
  84.     char **argv);
  85.  
  86. void
  87. main(
  88. int argc,
  89. char **argv,
  90. char **envp)
  91. {
  92.     char *progname;    /* argv[0] */
  93.     int    work_argc;    /* variable copy of argc */
  94.     char **work_argv;    /* variable copy of argv */
  95.     char *arg;        /* an arg to program */
  96.     char a;        /* an arg flag (after -) */
  97.     char *out_file_name;/* name of object file, argument to -o if specified */
  98.     int i;
  99.     char *specific_archflag;
  100.     struct directory_stack *dirtmp;
  101.  
  102.     progname = argv[0];
  103.  
  104.     /*
  105.      * Set up to catch the signals listed in sig[] that are not ignored.
  106.      */
  107.     for(i = 0; sig[i] != 0; i++)
  108.         if(signal(sig[i], SIG_IGN) != SIG_IGN)
  109.         signal(sig[i], got_sig);
  110.     /*
  111.      * Set the default for the flags that will be parsed.
  112.      */
  113.     memset(flagseen, '\0', sizeof(flagseen)); /* aint seen nothing yet */
  114.     specific_archflag = NULL;
  115.     out_file_name = "a.out";    /* default .o file */
  116.  
  117.     /*
  118.      * Call the initialization routines.
  119.      */
  120.     check_for_ProjectBuilder();    /* messages.c */
  121.     symbol_begin();            /* symbols.c */
  122.     sections_begin();        /* sections.c */
  123.     read_begin();            /* read.c */
  124.     md_begin();            /* MACHINE.c */
  125.     input_scrub_begin();        /* input_scrub.c */
  126.  
  127.     /* This is the -dynamic flag, which is now the default */
  128.     flagseen[(int)'k'] = TRUE;
  129.  
  130.     /*
  131.      * Parse arguments, but we are only interested in flags.
  132.      * When we find a flag, we process it then make it's argv[] NULL.
  133.      * This helps any future argv[] scanners avoid what we processed.
  134.      * Since it is easy to do here we interpret the special arg "-"
  135.      * to mean "use stdin" and we set that argv[] pointing to "".
  136.      * After we have munged argv[], the only things left are source file
  137.      * name(s) and ""(s) denoting stdin. These file names are used
  138.      * (perhaps more than once) later.
  139.      */
  140.     work_argc = argc - 1;        /* don't count argv[0] */
  141.     work_argv = argv + 1;        /* skip argv[0] */
  142.     for( ; work_argc-- ; work_argv++){
  143.  
  144.         /* work_argv points to this argument */
  145.         arg = *work_argv;
  146.  
  147.         /* Filename. We need it later. */
  148.         if(*arg != '-')
  149.         continue;
  150.  
  151.         /* Keep scanning args looking for flags. */
  152.         if (arg[1] == '-' && arg[2] == 0) {
  153.         /* "--" as an argument means read STDIN */
  154.         /* on this scan, we don't want to think about filenames */
  155.         *work_argv = "";    /* Code that means 'use stdin'. */
  156.         continue;
  157.         }
  158.  
  159.         /* This better be a switch ( -l where l is a letter. */
  160.         arg++;        /* -> letter. */
  161.  
  162.         /* scan all the 1-char flags */
  163.         while((a = *arg)){
  164.         arg ++;    /* arg -> after letter. */
  165.         a &= 0x7F;    /* ascii only please */
  166.         if(flagseen[(int)a] && (a != 'I') && (a != 'a') && (a != 'f') &&
  167.            (a != 'd') && (a != 's') && (a != 'k'))
  168.             as_warn("%s: Flag option -%c has already been seen!",
  169.                 progname, a);
  170.         if(a != 'f')
  171.             flagseen[(int)a] = TRUE;
  172.         switch(a){
  173.         case 'f':
  174.             if(strcmp(arg-1, "force_cpusubtype_ALL") == 0){
  175.             force_cpusubtype_ALL = 1;
  176.             arg = "";    /* Finished with this arg. */
  177.             break;
  178.             }
  179.             /* -f means fast - no need for "app" preprocessor. */
  180.             flagseen[(int)a] = TRUE;
  181.             break;
  182.  
  183.         case 'L': /* -L means keep L* symbols */
  184.             break;
  185.  
  186.         case 'o':
  187.             if(*arg != '\0') /* Rest of argument is object file-name. */
  188.             out_file_name = arg;
  189.             else if(work_argc){    /* Want next arg for a file-name. */
  190.             *work_argv = NULL; /* This is not a file-name. */
  191.             work_argc--;
  192.             out_file_name = *++work_argv;
  193.             }
  194.             else
  195.             as_warn("%s: I expected a filename after -o. \"%s\" "
  196.                 "assumed.", progname, out_file_name);
  197.             arg = "";    /* Finished with this arg. */
  198.             break;
  199.  
  200.         case 'R':
  201.             /* -R means put data into text segment */
  202.             as_warn("%s: -R option not supported (use the "
  203.                 ".const directive)", progname);
  204.             flagseen['R'] = FALSE;
  205.             break;
  206.  
  207.         case 'v':
  208.             fprintf(stderr,"NeXT Computer, Inc. version "
  209.                 "%s, ", next_version);
  210.             fprintf(stderr, version_string);
  211.             if(*arg && strcmp(arg,"ersion"))
  212.             as_warn("Unknown -v option ignored");
  213.             while(*arg)
  214.             arg++;    /* Skip the rest */
  215.             break;
  216.  
  217.         case 'W':
  218.             /* -W means don't warn about things */
  219.             break;
  220.  
  221.         case 'I':
  222.             /* Add directory to path for includes */
  223.             dirtmp = (struct directory_stack *)
  224.             xmalloc(sizeof(struct directory_stack));
  225.             /* New one goes on the end */
  226.             dirtmp->next = 0;
  227.             if(include == 0)
  228.             include = dirtmp;
  229.             else
  230.             include_tail->next = dirtmp;
  231.             /* Tail follows the last one */
  232.             include_tail = dirtmp;
  233.             /* Rest of argument is include file-name. */
  234.             if(*arg)
  235.             dirtmp->fname = arg;
  236.             else if (work_argc){
  237.             /* Want next arg for a file-name. */
  238.             /* This is not a file-name. */
  239.             *work_argv = NULL;
  240.             work_argc--;
  241.             dirtmp->fname = *++work_argv;
  242.             }
  243.             else
  244.             as_warn("I expected a filename after -I.");
  245.             arg = "";    /* Finished with this arg. */
  246.             break;
  247.  
  248.         case 'g':
  249.             /* generate stabs for debugging assembly code */
  250.             break;
  251.  
  252.         case 'n':
  253.             /* no default .text section */
  254.             break;
  255.  
  256.         case 'd':
  257.             if(strcmp(arg-1, "dynamic") == 0){
  258.             arg = "";    /* Finished with this arg. */
  259.             flagseen[(int)'k'] = TRUE;
  260.             break;
  261.             }
  262.             goto unknown_flag;
  263.  
  264.         case 's':
  265.             if(strcmp(arg-1, "static") == 0){
  266.             arg = "";    /* Finished with this arg. */
  267.             flagseen[(int)'k'] = FALSE;
  268.             break;
  269.             }
  270.             goto unknown_flag;
  271.  
  272.         case 'N':
  273.             if(strcmp(arg-1, "NEXTSTEP-deployment-target") == 0){
  274.             arg = "";    /* Finished with this arg. */
  275.             /* Want next arg for a <release_tag> */
  276.             if(work_argc){
  277.                 /* This, "-NEXTST..." is not a file-name. */
  278.                 *work_argv = NULL;
  279.                 work_argc--;
  280.                 work_argv++;
  281.                 if(strcmp(*work_argv, "3.3") == 0){
  282.                 flagseen[(int)'k'] = TRUE;
  283.                 }
  284.                 else if(strcmp(*work_argv, "3.2") == 0){
  285.                 flagseen[(int)'k'] = FALSE;
  286.                 }
  287.                 else{
  288.                 as_fatal("I expected '3.2' or '3.3' after "
  289.                     "-NEXTSTEP-deployment-target.");
  290.                 }
  291.             }
  292.             else
  293.                 as_fatal("I expected a <release_tag> "
  294.                      "after -NEXTSTEP-deployment-target.");
  295.             break;
  296.             }
  297.             goto unknown_flag;
  298.  
  299.         case 'k':
  300.             /* use new features incompatible with 3.2 */
  301.             break;
  302.  
  303.         case 'V':
  304.             /* as driver's -V, verbose, flag */
  305.             break;
  306.  
  307.         case 'a':
  308.             if(strcmp(arg-1, "arch_multiple") == 0){
  309.             arch_multiple = 1;
  310.             arg = "";    /* Finished with this arg. */
  311.             break;
  312.             }
  313.             else if(strcmp(arg-1, "arch") == 0){
  314.             arg = "";    /* Finished with this arg. */
  315.             /* Want next arg for a <arch_type> */
  316.             if(work_argc){
  317.                 /* This, "-arch" is not a file-name. */
  318.                 *work_argv = NULL;
  319.                 work_argc--;
  320.                 work_argv++;
  321. #ifdef M68K
  322.                 if(strcmp(*work_argv, "m68030") == 0){
  323.                 if(archflag_cpusubtype != -1 &&
  324.                    archflag_cpusubtype !=
  325.                     CPU_SUBTYPE_MC68030_ONLY)
  326.                     as_fatal("can't specify both "
  327.                     "-arch m68030 and -arch "
  328.                     "m68040");
  329.                 specific_archflag = *work_argv;
  330.                 archflag_cpusubtype =
  331.                     CPU_SUBTYPE_MC68030_ONLY;
  332.                 }
  333.                 else if(strcmp(*work_argv,
  334.                         "m68040") == 0){
  335.                 if(archflag_cpusubtype != -1 &&
  336.                    archflag_cpusubtype !=
  337.                     CPU_SUBTYPE_MC68040)
  338.                     as_fatal("can't specify both "
  339.                     "-arch m68030 and -arch "
  340.                     "m68040");
  341.                 specific_archflag = *work_argv;
  342.                 archflag_cpusubtype =
  343.                     CPU_SUBTYPE_MC68040;
  344.                 }
  345.                 else if(strcmp(*work_argv, "m68k") != 0)
  346.                 as_fatal("I expected 'm68k', "
  347.                     "'m68030' or 'm68040' after "
  348.                     "-arch for this assembler.");
  349. #endif
  350. #ifdef M88K
  351.                 if(strcmp(*work_argv, "m88k") != 0)
  352.                 as_fatal("I expected 'm88k' after "
  353.                        "-arch for this assembler.");
  354. #endif
  355. #ifdef I860
  356.                 if(strcmp(*work_argv, "i860") != 0)
  357.                 as_fatal("I expected 'i860' after "
  358.                        "-arch for this assembler.");
  359. #endif
  360. #ifdef I386
  361.                 if(strcmp(*work_argv, "i486") == 0){
  362.                 if(archflag_cpusubtype != -1 &&
  363.                    archflag_cpusubtype !=
  364.                     CPU_SUBTYPE_486)
  365.                     as_fatal("can't specify more "
  366.                        "than one -arch flag ");
  367.                 specific_archflag = *work_argv;
  368.                 archflag_cpusubtype =
  369.                     CPU_SUBTYPE_486;
  370.                 }
  371.                 else if(strcmp(*work_argv,
  372.                        "i486SX") == 0){
  373.                 if(archflag_cpusubtype != -1 &&
  374.                    archflag_cpusubtype !=
  375.                     CPU_SUBTYPE_486SX)
  376.                     as_fatal("can't specify more "
  377.                        "than one -arch flag ");
  378.                 specific_archflag = *work_argv;
  379.                 archflag_cpusubtype =
  380.                     CPU_SUBTYPE_486SX;
  381.                 }
  382.                 else if(strcmp(*work_argv, "i586") ==0){
  383.                 if(archflag_cpusubtype != -1 &&
  384.                    archflag_cpusubtype !=
  385.                     CPU_SUBTYPE_586)
  386.                     as_fatal("can't specify more "
  387.                        "than one -arch flag ");
  388.                 specific_archflag = *work_argv;
  389.                 archflag_cpusubtype =
  390.                     CPU_SUBTYPE_586;
  391.                 }
  392.                 else if(strcmp(*work_argv,
  393.                        "i586SX") == 0){
  394.                 if(archflag_cpusubtype != -1 &&
  395.                    archflag_cpusubtype !=
  396.                     CPU_SUBTYPE_586SX)
  397.                     as_fatal("can't specify more "
  398.                        "than one -arch flag ");
  399.                 specific_archflag = *work_argv;
  400.                 archflag_cpusubtype =
  401.                     CPU_SUBTYPE_586SX;
  402.                 }
  403.                 else if(strcmp(*work_argv, "i386") != 0)
  404.                 as_fatal("I expected 'i386', 'i486'"
  405.                    " 'i486SX', 'i586' or 'i586SX' "
  406.                    "after -arch for this "
  407.                    "assembler.");
  408. #endif
  409. #ifdef HPPA
  410.                 if(strcmp(*work_argv, "hppa") != 0)
  411.                 as_fatal("I expected 'hppa' after "
  412.                      "-arch for this assembler.");
  413. #endif
  414. #ifdef SPARC
  415.                 if(strcmp(*work_argv, "sparc") != 0)
  416.                 as_fatal("I expected 'sparc' after "
  417.                      "-arch for this assembler.");
  418. #endif
  419.             }
  420.             else
  421.                 as_fatal("I expected an <arch_type> "
  422.                      "after -arch.");
  423.             break;
  424.             }
  425.             /* fall through for non -arch flag */
  426.         default:
  427. unknown_flag:
  428.             --arg;
  429.             if(md_parse_option(&arg, &work_argc, &work_argv) == 0)
  430.             as_warn("%s: I don't understand '%c' flag!", progname,
  431.                 a);
  432.             if(arg && *arg)
  433.             arg++;
  434.             break;
  435.         }
  436.         }
  437.         /*
  438.          * We have just processed a "-..." arg, which was not a
  439.          * file-name. Smash it so the
  440.          * things that look for filenames won't ever see it.
  441.          *
  442.          * Whatever work_argv points to, it has already been used
  443.          * as part of a flag, so DON'T re-use it as a filename.
  444.          */
  445.         *work_argv = NULL; /* NULL means 'not a file-name' */
  446.     }
  447.     if(flagseen['g'] == TRUE && flagseen['n'] == TRUE)
  448.         as_fatal("-g can't be specified if -n is specified");
  449.     /*
  450.      * If we haven't seen a -force_cpusubtype_ALL or an -arch flag for a
  451.      * specific architecture then let the machine instructions in the
  452.      * assembly determine the cpusubtype of the output file.
  453.      */
  454.     if(force_cpusubtype_ALL && specific_archflag)
  455.         archflag_cpusubtype = -1;
  456.  
  457.     /* Here with flags set up in flagseen[]. */
  458.     perform_an_assembly_pass(argc, argv); /* Assemble it. */
  459.  
  460.     if(seen_at_least_1_file() && bad_error != TRUE){
  461.         layout_addresses();
  462.         write_object(out_file_name);
  463.     }
  464.  
  465.     input_scrub_end();
  466.     md_end();            /* MACHINE.c */
  467.  
  468.     exit(bad_error);        /* WIN */
  469. }
  470.  
  471. /*            perform_an_assembly_pass()
  472.  *
  473.  * Here to attempt 1 pass over each input file.
  474.  * We scan argv[*] looking for filenames or exactly "" which is
  475.  * shorthand for stdin. Any argv that is NULL is not a file-name.
  476.  * We set need_pass_2 TRUE if, after this, we still have unresolved
  477.  * expressions of the form (unknown value)+-(unknown value).
  478.  *
  479.  * Note the un*x semantics: there is only 1 logical input file, but it
  480.  * may be a catenation of many 'physical' input files.
  481.  */
  482. static
  483. void
  484. perform_an_assembly_pass(
  485. int argc,
  486. char **argv)
  487. {
  488.     char *buffer;        /* Where each bufferful of lines will start. */
  489.     int saw_a_file;
  490.  
  491.     saw_a_file = 0;
  492.  
  493.     argv++;            /* skip argv[0] */
  494.     argc--;            /* skip argv[0] */
  495.     while(argc--){
  496.         if(*argv){        /* Is it a file-name argument? */
  497.         /* argv -> "" if stdin desired, else -> filename */
  498.         if((buffer = input_scrub_new_file(*argv))){
  499.             saw_a_file++;
  500.             read_a_source_file(buffer);
  501.         }
  502.         }
  503.         argv++;            /* completed that argv */
  504.     }
  505.     if(!saw_a_file)
  506.         if((buffer = input_scrub_new_file("")))
  507.             read_a_source_file(buffer);
  508. }
  509.  
  510. static
  511. void
  512. got_sig(
  513. int sig)
  514. {
  515.     as_bad("Interrupted by signal %d",sig);
  516.     exit(1);
  517. }
  518.