home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / cctools / as / driver.c < prev    next >
C/C++ Source or Header  |  1994-03-21  |  5KB  |  189 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.             case 'N':    /* -NEXTSTEP-deployment-target */
  82.             if(p[1] == '\0')
  83.                 i++;
  84.             break;
  85.  
  86.             case 'a':
  87.             if(strcmp(p, "arch") == 0){
  88.                 if(i + 1 >= argc)
  89.                 fatal("missing argument to %s option", argv[i]);
  90.                 if(arch_name != NULL)
  91.                 fatal("more than one %s option (not allowed, "
  92.                       "use cc(1) instead)", argv[i]);
  93.                 arch_name = argv[i+1];
  94.                 break;
  95.             }
  96.             /* fall through for non "-arch" */
  97.             case 'f':
  98.             case 'k':
  99.             case 'g':
  100.             case 'v':
  101.             case 'W':
  102.             case 'L':
  103.             case 'l':
  104.             default:
  105.             /* just recognize it, do nothing */
  106.             break;
  107.             case 'V':
  108.             verbose = 1;
  109.             break;
  110.             }
  111.         }
  112.         }
  113.     }
  114.  
  115.     /*
  116.      * Construct the name of the assembler to run from the given -arch
  117.      * <arch_flag> or if none then from the value returned from
  118.      * get_arch_from_host().
  119.      */
  120.     if(arch_name == NULL){
  121.         if(get_arch_from_host(&arch_flag, NULL))
  122.         arch_name = arch_flag.name;
  123.         else
  124.         fatal("known host architecture (can't determine which assembler"
  125.               " to run)");
  126.     }
  127.     else{
  128.         /*
  129.          * Convert a possible machine specific architecture name to a
  130.          * family name to base the name of the assembler to run.
  131.          */
  132.         if(get_arch_from_flag(arch_name, &arch_flag) != 0){
  133.         family_arch_flag =
  134.             get_arch_family_from_cputype(arch_flag.cputype);
  135.         if(family_arch_flag != NULL)
  136.             arch_name = (char *)(family_arch_flag->name);
  137.         }
  138.  
  139.     }
  140.     as = makestr(LIB, arch_name, AS, NULL);
  141.  
  142.     /*
  143.      * If this assembler exist try to run it else print an error message.
  144.      */
  145.     if(access(as, F_OK) == 0){
  146.         argv[0] = as;
  147.         if(execute(argv, verbose))
  148.         exit(0);
  149.         else
  150.         exit(1);
  151.     }
  152.     as_local = makestr(LOCALLIB, arch_name, AS, NULL);
  153.     if(access(as_local, F_OK) == 0){
  154.         argv[0] = as_local;
  155.         if(execute(argv, verbose))
  156.         exit(0);
  157.         else
  158.         exit(1);
  159.     }
  160.     else{
  161.         printf("%s: assembler (%s or %s) for architecture %s not "
  162.            "installed\n", progname, as, as_local, arch_name);
  163.         arch_flags = get_arch_flags();
  164.         count = 0;
  165.         for(i = 0; arch_flags[i].name != NULL; i++){
  166.         as = makestr(LIB, arch_flags[i].name, AS, NULL);
  167.         if(access(as, F_OK) == 0){
  168.             if(count == 0)
  169.             printf("Installed assemblers are:\n");
  170.             printf("%s for architecture %s\n", as, arch_flags[i].name);
  171.             count++;
  172.         }
  173.         else{
  174.             as_local = makestr(LOCALLIB, arch_flags[i].name, AS, NULL);
  175.             if(access(as_local, F_OK) == 0){
  176.             if(count == 0)
  177.                 printf("Installed assemblers are:\n");
  178.             printf("%s for architecture %s\n", as_local,
  179.                    arch_flags[i].name);
  180.             count++;
  181.             }
  182.         }
  183.         }
  184.         if(count == 0)
  185.         printf("%s: no assemblers installed\n", progname);
  186.         exit(1);
  187.     }
  188. }
  189.