home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Source / GNU / cctools / as / driver.c < prev    next >
C/C++ Source or Header  |  1992-10-12  |  5KB  |  188 lines

  1. /*
  2.  * The assembler driver that lives in /bin/as and runs the assembler for the
  3.  * "-arch <arch_flag>" (if given) in /lib/<arch_flag>/as or in
  4.  * /usr/local/lib/<arch_flag>/as.  Or runs the assembler for the host
  5.  * architecture as returned by get_arch_from_host().  The driver only checks
  6.  * to make sure their are not multiple arch_flags and then passes all flags to
  7.  * the assembler it will run.
  8.  */
  9. #include "stdio.h"
  10. #include "stdlib.h"
  11. #include "string.h"
  12. #include "libc.h"
  13. #include <sys/file.h>
  14. #include <mach/mach.h>
  15. #include "stuff/arch.h"
  16. #include "stuff/errors.h"
  17. #include "stuff/execute.h"
  18. #include "stuff/allocate.h"
  19.  
  20. /* used by error calls (exported) */
  21. char *progname = NULL;
  22.  
  23. void
  24. main(
  25. int argc,
  26. char **argv,
  27. char **envp)
  28. {
  29.     const char *LIB = "/lib/";
  30.     const char *LOCALLIB = "/usr/local/lib/";
  31.     const char *AS = "/as";
  32.  
  33.     unsigned long i, count, verbose;
  34.     char *p, c, *arch_name, *as, *as_local;
  35.     struct arch_flag arch_flag;
  36.     const struct arch_flag *arch_flags, *family_arch_flag;
  37.  
  38.     progname = argv[0];
  39.     arch_name = NULL;
  40.     verbose = 0;
  41.     /*
  42.      * Process the assembler flags exactly like the assembler would (except
  43.      * let the assembler complain about multiple flags, bad combinations of
  44.      * flags, unknown single letter flags and the like).  The main thing
  45.      * here is to parse out the "-arch <arch_flag>" and to do so the
  46.      * multiple argument and multiple character flags need to be known how
  47.      * to be stepped over correctly.
  48.      */
  49.     for(i = 1; i < argc; i++){
  50.         /*
  51.          * The assembler flags start with '-' except that "--" is recognized
  52.          * as assemble from stdin and that flag "--" is not allowed to be
  53.          * grouped with other flags (so "-a-" is not the same as "-a --").
  54.          */
  55.         if(argv[i][0] == '-' &&
  56.            !(argv[i][1] == '-' && argv[i][2] == '0')){
  57.         /*
  58.          * the assembler allows single letter flags to be grouped
  59.          * together so "-abc" is the same as "-a -b -c".  So that
  60.          * logic must be followed here.
  61.          */
  62.         for(p = &(argv[i][1]); c = *p; p++){
  63.             /*
  64.              * The assembler simply ignores the high bit of flag
  65.              * characters and not treat them as different characters
  66.              * as they are (but the argument following the flag
  67.              * character is not treated this way).  So it's done
  68.              * here as well to match it.
  69.              */
  70.             c &= 0x7F;
  71.             switch(c){
  72.             /*
  73.              * Flags that take a single argument.  The argument is the
  74.              * rest of the current argument if there is any or the it is
  75.              * the next argument.  Again errors like missing arguments
  76.              * are not handled here but left to the assembler.
  77.              */
  78.             case 'o':    /* -o name */
  79.             case 'I':    /* -I directory */
  80.             case 'm':    /* -mc68000, -mc68010 and mc68020 */
  81.             if(p[1] == '\0')
  82.                 i++;
  83.             break;
  84.  
  85.             case 'a':
  86.             if(strcmp(p, "arch") == 0){
  87.                 if(i + 1 >= argc)
  88.                 fatal("missing argument to %s option", argv[i]);
  89.                 if(arch_name != NULL)
  90.                 fatal("more than one %s option (not allowed, "
  91.                       "use cc(1) instead)", argv[i]);
  92.                 arch_name = argv[i+1];
  93.                 break;
  94.             }
  95.             /* fall through for non "-arch" */
  96.             case 'f':
  97.             case 'k':
  98.             case 'g':
  99.             case 'v':
  100.             case 'W':
  101.             case 'L':
  102.             case 'l':
  103.             default:
  104.             /* just recognize it, do nothing */
  105.             break;
  106.             case 'V':
  107.             verbose = 1;
  108.             break;
  109.             }
  110.         }
  111.         }
  112.     }
  113.  
  114.     /*
  115.      * Construct the name of the assembler to run from the given -arch
  116.      * <arch_flag> or if none then from the value returned from
  117.      * get_arch_from_host().
  118.      */
  119.     if(arch_name == NULL){
  120.         if(get_arch_from_host(&arch_flag, NULL))
  121.         arch_name = arch_flag.name;
  122.         else
  123.         fatal("known host architecture (can't determine which assembler"
  124.               " to run)");
  125.     }
  126.     else{
  127.         /*
  128.          * Convert a possible machine specific architecture name to a
  129.          * family name to base the name of the assembler to run.
  130.          */
  131.         if(get_arch_from_flag(arch_name, &arch_flag) != 0){
  132.         family_arch_flag =
  133.             get_arch_family_from_cputype(arch_flag.cputype);
  134.         if(family_arch_flag != NULL)
  135.             arch_name = (char *)(family_arch_flag->name);
  136.         }
  137.  
  138.     }
  139.     as = makestr(LIB, arch_name, AS, NULL);
  140.  
  141.     /*
  142.      * If this assembler exist try to run it else print an error message.
  143.      */
  144.     if(access(as, F_OK) == 0){
  145.         argv[0] = as;
  146.         if(execute(argv, verbose))
  147.         exit(0);
  148.         else
  149.         exit(1);
  150.     }
  151.     as_local = makestr(LOCALLIB, arch_name, AS, NULL);
  152.     if(access(as_local, F_OK) == 0){
  153.         argv[0] = as_local;
  154.         if(execute(argv, verbose))
  155.         exit(0);
  156.         else
  157.         exit(1);
  158.     }
  159.     else{
  160.         printf("%s: assembler (%s or %s) for architecture %s not "
  161.            "installed\n", progname, as, as_local, arch_name);
  162.         arch_flags = get_arch_flags();
  163.         count = 0;
  164.         for(i = 0; arch_flags[i].name != NULL; i++){
  165.         as = makestr(LIB, arch_flags[i].name, AS, NULL);
  166.         if(access(as, F_OK) == 0){
  167.             if(count == 0)
  168.             printf("Installed assemblers are:\n");
  169.             printf("%s for architecture %s\n", as, arch_flags[i].name);
  170.             count++;
  171.         }
  172.         else{
  173.             as_local = makestr(LOCALLIB, arch_flags[i].name, AS, NULL);
  174.             if(access(as_local, F_OK) == 0){
  175.             if(count == 0)
  176.                 printf("Installed assemblers are:\n");
  177.             printf("%s for architecture %s\n", as_local,
  178.                    arch_flags[i].name);
  179.             count++;
  180.             }
  181.         }
  182.         }
  183.         if(count == 0)
  184.         printf("%s: no assemblers installed\n", progname);
  185.         exit(1);
  186.     }
  187. }
  188.