home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / gccdist / gcc-src / vms / gcc.c next >
Encoding:
C/C++ Source or Header  |  1992-09-08  |  19.8 KB  |  712 lines

  1. /* <gcc.c>
  2.  *
  3.  *    A DCL driver for GNU "CC".  It accepts a CLD syntax compatable
  4.  *    with Digital's "VAX C".
  5.  *
  6.  *    Since GCC consists of more than 1 pass we have to do the parsing
  7.  *    here and have a DCL Command (.COM) file do the real work -- so that
  8.  *    multiple images can be invoked WITHOUT having to resort to LIB$SPAWN.
  9.  */
  10. #define GCC_DRIVER_VERSION "2.1.0"
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #undef EXIT_FAILURE
  16. #define EXIT_FAILURE 0x1000002C        /* SS$_ABORT|STS$M_INHIB_MSG */
  17.  
  18. #define LOCAL  0
  19. #define GLOBAL 1
  20. #define VERB_STAT 1    /* verbose */
  21. #define VERB_ECHO 2    /* verify */
  22. #define VERB_SILENT 256 /* suppress GCC-I-foo messages */
  23. #define PROF_FUNC 1    /* function profiling */
  24. #define PROF_BLOC 2    /* block profiling */
  25.  
  26. static char *Input_File =0;        /* Input file specifications */
  27. static char *Debug =0;            /* /DEBUG specification      */
  28. static char *Object =0;            /* Object file name         */
  29. static char *List_File =0;        /* List file name         */
  30. static char *Target_Machine =0;        /* For cross-compiling         */
  31. static char *Assembly_File =0;        /* Assembly file name         */
  32. static int GCC_Version=0;        /* Version of gcc we are running */
  33. static int Optimize=0;            /* Do optimized compile      */
  34. static int G_Float=0;            /* Use G double precision floating */
  35. static int Machine_Code=0;        /* Output assembly lang      */
  36. static int Verbose=0;            /* Make noise while compiling*/
  37. static int Plus=0;            /* Use C++ compiler         */
  38. static int Show=0;            /* Show options             */
  39. static int Profile=0;            /* Use compiler profiler     */
  40. static int Warn=0;            /* Generate warning messages */
  41. static int Case_Hack=1;            /* Hack symbols with upper case*/
  42. static int List=0;            /* Save preprocessor output  */
  43. static int Version=0;            /* Show compiler version number */
  44. static int Generate_Object=0;        /* Should we generate obj?   */
  45. static int Standard=0;            /* traditional vs normal vs pedantic */
  46. /*
  47.  * DCL has a limit of 256 characters for on a single command line.
  48.  */
  49. static char cpp_Options[256];        /* Options for the CPP pass  */
  50. static char cc1_Options[256];        /* Options for the CC1 pass  */
  51. static char gas_Options[256];        /* Options for the GAS pass  */
  52. static char xxx_Overflow[256];    /* kludge; inadequate bounds checking */
  53.  
  54. extern int getpid();
  55. static int cli_present(), cli_get_value(), cli_negated();
  56. extern int cli$present(), cli$get_value();
  57. static int lib_do_command(), lib_set_symbol();
  58. extern int lib$do_command(), lib$set_symbol();
  59.  
  60.         /* - assorted utility routines - */
  61.  
  62. /*
  63.  *    Save a string in dynamic memory
  64.  */
  65. static char *savestr(const char *String)
  66. {
  67.     return strcpy((char *)malloc(strlen(String)+1), String);
  68. }
  69.  
  70. /*
  71.  *    Append one string to another, doubling quote chars as encountered
  72.  */
  73. static void mystrcat(char *string, const char *append)
  74. {
  75.     register char *dst = string + strlen(string);    /* point to nul */
  76.     register const char *src = append;
  77.     while (*src) {
  78.     if (*src == '"') *dst++ = '"';            /* double quotes */
  79.     *dst++ = *src++;
  80.     }
  81.     *dst = '\0';    /* and terminate the string */
  82. }
  83.  
  84. /*
  85.  *    Search one string for another
  86.  */
  87. static char *locate(const char *source, const char *target)    /* strstr() */
  88. {
  89.     register const char *pnt = source;
  90.     while (*pnt) {
  91.     if (*pnt == *target && !strncmp(pnt,target,strlen(target)))
  92.         return (char *)pnt;
  93.     pnt++;
  94.     }
  95.     return (char *)0;
  96. }
  97.  
  98.         /* - command parsing code - */
  99.  
  100. /*
  101.  *    Do the parsing
  102.  */
  103. static void checkswitches(int flag)
  104. {
  105.     char Temp[256];
  106.  
  107.     /*
  108.      *    /INCLUDE_DIRECTORY=(dir1[,dir2,...])
  109.      */
  110.     if (cli_present("INCLUDE_DIRECTORY",0,flag)) {
  111.     while (cli_get_value("INCLUDE_DIRECTORY",Temp,sizeof Temp)) {
  112.         strcat(cpp_Options,"\"-I");
  113.         mystrcat(cpp_Options,Temp);
  114.         strcat(cpp_Options,"\" ");
  115.     }
  116.     }
  117.     /*
  118.      *    /DEFINE=(macro1[=value1][,macro2[=value2],...])
  119.      */
  120.     if (cli_present("DEFINE",0,flag)) {
  121.     while (cli_get_value("DEFINE",Temp,sizeof Temp)) {
  122.         strcat(cpp_Options,"\"-D");
  123.         mystrcat(cpp_Options,Temp);
  124.         strcat(cpp_Options,"\" ");
  125.     }
  126.     }
  127.     /*
  128.      *    /UNDEFINE=(macro1[,macro2,...])
  129.      */
  130.     if (cli_present("UNDEFINE",0,flag)) {
  131.     while (cli_get_value("UNDEFINE",Temp,sizeof Temp)) {
  132.         strcat(cpp_Options,"\"-U");
  133.         mystrcat(cpp_Options,Temp);
  134.         strcat(cpp_Options,"\" ");
  135.     }
  136.     }
  137.     /*
  138.      *    /SCAN=(file1[,file2,...])
  139.      */
  140.     if (cli_present("SCAN",0,flag)) {
  141.     while (cli_get_value("SCAN",Temp,sizeof Temp)) {
  142.         strcat(cpp_Options,GCC_Version==1 ? "\"-i" : "\"-imacros\" ");
  143.         mystrcat(cpp_Options,Temp);
  144.         strcat(cpp_Options,GCC_Version==1 ? "\" " : " ");
  145.     }
  146.     }
  147.     /*
  148.      *    /[NO]OBJECT[=file]
  149.      */
  150.     if (Generate_Object = cli_present("OBJECT",Generate_Object,flag)) {
  151.     if (Object) free(Object);
  152.     if (cli_get_value("OBJECT",Temp,sizeof Temp))
  153.         Object = savestr(Temp);
  154.     else
  155.         Object = 0;
  156.     }
  157.     /*
  158.      *    /[NO]MACHINE_CODE[=file]
  159.      *        used to save the ".s" assembler intermediate output
  160.      */
  161.     if (Machine_Code = cli_present("MACHINE_CODE",Machine_Code,flag)) {
  162.     if (Assembly_File) free(Assembly_File);
  163.     if (cli_get_value("MACHINE_CODE",Temp,sizeof Temp))
  164.         Assembly_File = savestr(Temp);
  165.     else
  166.         Assembly_File = 0;
  167.     }
  168.     /*
  169.      *    /TARGET=[host]
  170.      *        used for cross-compilation.
  171.      */
  172.     if (cli_present("TARGET",0,flag)) {
  173.     if (Target_Machine) free(Target_Machine);
  174.     if (cli_get_value("TARGET",Temp,sizeof Temp))
  175.         Target_Machine = savestr(Temp);
  176.     else
  177.         Target_Machine = 0;
  178.     }
  179.     /*
  180.      *    /[NO]LIST[=file], /PROCESS_ONLY[=file]
  181.      */
  182.     if ((List = cli_present("LIST",List,flag)) != 0
  183.      || (List = cli_present("PREPROCESS_ONLY",List,flag)) != 0) {
  184.     if (List_File) free(List_File),  List_File = 0;
  185.     if (cli_get_value("LIST",Temp,sizeof Temp))
  186.         List_File = savestr(Temp);
  187.     else if (cli_get_value("PREPROCESS_ONLY",Temp,sizeof Temp))
  188.         List_File = savestr(Temp);
  189.     }
  190.     if (cli_present("PREPROCESS_ONLY",0,flag))
  191.     Generate_Object = 0;
  192.     /*
  193.      *    /DEBUG[=ALL|NONE|([NO]TRACEBACK,[NO]SYMBOLS)
  194.      *        note: only /NODEBUG (the default) and /DEBUG=ALL are supported.
  195.      */
  196.     if (cli_present("DEBUG",0,flag)) {
  197.     /* Get the value (Default = ALL), and save it */
  198.     if (!cli_get_value("DEBUG",Temp,sizeof Temp))
  199.         strcpy(Temp,"ALL");
  200.     Debug = savestr(Temp);
  201.     }
  202.     /*
  203.      *    /[NO]OPTIMIZE[=anything...]
  204.      */
  205.     if (cli_present("OPTIMIZE",Optimize,flag)) {
  206.     if (!cli_get_value("OPTIMIZE",Temp,sizeof Temp))
  207.         Optimize = 1;
  208.     else {
  209.         register char *p;
  210.         for (p = Temp; *p; p++)
  211.         if (*p < '0' || *p > '9') break;
  212.         if (!*p)  Optimize = atoi(Temp);
  213.     }
  214.     } else if (cli_negated())
  215.     Optimize = 0;
  216.     /*
  217.      *    /CC1_OPTIONS=arbitrary_string
  218.      */
  219.     if (cli_present("CC1_OPTIONS",0,flag)) {
  220.     cli_get_value("CC1_OPTIONS",cc1_Options,sizeof cc1_Options);
  221.     strcat(cc1_Options," ");
  222.     }
  223.     /*
  224.      *    /[NO]WARNINGS[=ALL|NONE|([NO]INFORMATIONALS,[NO]WARNINGS)]
  225.      *        note:  values are ignored
  226.      */
  227.     Warn = cli_present("WARNINGS",Warn,flag);
  228.     /*
  229.      *    /VERSION
  230.      */
  231.     Version = cli_present("VERSION",Version,flag);
  232.     /*
  233.      *    /[NO]PLUS
  234.      */
  235.     Plus = cli_present("PLUS_PLUS",Plus,flag);
  236.     /*
  237.      *    /[NO]G_FLOAT
  238.      */
  239.     G_Float = cli_present("G_FLOAT",G_Float,flag);
  240.     /*
  241.      *    /[NO]VERBOSE
  242.      */
  243.     if (cli_present("VERBOSE",0,flag)) {
  244.     if ((!cli_get_value("VERBOSE",Temp,sizeof Temp))
  245.      || cli_present("VERBOSE.ALL",0,flag))
  246.         Verbose = VERB_STAT|VERB_ECHO;    /* all */
  247.     else {
  248.         if (cli_present("VERBOSE.STATISTICS",0,flag)) Verbose |= VERB_STAT;
  249.         if (cli_present("VERBOSE.ECHO",0,flag)
  250.          || cli_present("VERBOSE.VERIFY",0,flag)) Verbose |= VERB_ECHO;
  251.     }
  252.     } else if (cli_negated())
  253.     Verbose = VERB_SILENT;
  254.     /*
  255.      *    /PROFILE[=ALL|BLOCK|FUNCTION]
  256.      */
  257.     if (cli_present("PROFILE",0,flag)) {
  258.     if (!cli_get_value("PROFILE",Temp,sizeof Temp))
  259.         Profile = PROF_FUNC;    /* function */
  260.     else {
  261.         if (cli_present("PROFILE.ALL",0,flag))
  262.         Profile = PROF_FUNC|PROF_BLOC;
  263.         if (cli_present("PROFILE.BLOCK",0,flag)) Profile |= PROF_BLOC;
  264.         if (cli_present("PROFILE.FUNCTION",0,flag)) Profile |= PROF_FUNC;
  265.     }
  266.     }
  267.     /*
  268.      *    /SHOW[=ALL|RULES|DEFINITIONS]
  269.      */
  270.     if (cli_present("SHOW",0,flag)) {
  271.     if (!cli_get_value("SHOW",Temp,sizeof Temp))
  272.         Show = 3;        /* all */
  273.     else {
  274.         if        (cli_present("SHOW.ALL",0,flag)) Show = 3;
  275.         else if (cli_present("SHOW.RULES",0,flag)) Show = 2;
  276.         else if (cli_present("SHOW.DEFINITIONS",0,flag)) Show = 1;
  277.         else if (cli_present("SHOW.NONE",0,flag)) Show = 0;
  278.     }
  279.     }
  280.     /*
  281.      *    /NAMES={UPPER|LOWER|MIXED|HEX_SUFFIX}
  282.      */
  283.     if (cli_present("NAMES",0,flag)) {
  284.     if (!cli_get_value("NAMES",Temp,sizeof Temp))
  285.         Case_Hack = 1;    /* HEX */
  286.     else {
  287.         if        (cli_present("NAMES.UPPER",0,flag)) Case_Hack = 0;
  288.         else if (cli_present("NAMES.HEX_SUFFIX",0,flag)) Case_Hack = 1;
  289.         else if (cli_present("NAMES.LOWER",0,flag)) Case_Hack = 2;
  290.         else if (cli_present("NAMES.MIXED",0,flag)
  291.           || cli_present("NAMES.AS_IS",0,flag)) Case_Hack = 3;
  292.     }
  293.     } else {
  294.     /*
  295.      *  /[NO]CASE_HACK
  296.      */
  297.     Case_Hack = cli_present("CASE_HACK",Case_Hack,flag);
  298.     }
  299.     /*
  300.      *    /[NO]STANDARD[=[NO]PORTABLE]
  301.      *        /standard=portable    => -ansi -pedantic
  302.      *        /standard=noportable    => -ansi
  303.      *        /nostandard        => -traditional
  304.      *        (default is "none of the above")
  305.      */
  306.     if (cli_present("STANDARD",0,flag)) {
  307.     Standard = cli_present("STANDARD.PORTABLE",0,flag) ? 2 : 1;
  308.     /* explicit /standard=noansi resets to the default behavior */
  309.     if (!cli_present("STANDARD.ANSI",0,flag) && cli_negated()) Standard = 0;
  310.     } else if (cli_negated())
  311.     Standard = -1;
  312. }
  313.  
  314. /*
  315.  *    Construct GNU syntax gcc-cpp/gcc-cc1/gcc-as commands
  316.  *    from DCL syntax GCC command, then invoke gcc.com to
  317.  *    execute them.
  318.  */
  319. int main(void)
  320. {
  321.     register char *cp,*cp1;
  322.     char *gcc_scratch;
  323.     char Temp[256];
  324.     int pid = getpid ();
  325.  
  326.     cpp_Options[0] = cc1_Options[0] = gas_Options[0] = xxx_Overflow[0] = '\0';
  327.     /*
  328.      *        First we need to figure out which version of GCC we are running.
  329.      */
  330.     cp = getenv("GNU_CC_VERSION");
  331.     if (!cp || (*cp < '1' || *cp > '2')) {
  332.     fprintf(stderr, "\n%s -\n- %s -\n- %s -\n- %s\n",
  333.         "%GCC-E-UNIDENTIFIED_VERSION,",
  334.         "Cannot determine which version of GCC is being run",
  335.         cp ? "because GNU_CC_VERSION has an invalid value."
  336.            : "because GNU_CC_VERSION is not defined.",
  337.         "Please check the installation procedure.");
  338.     exit(EXIT_FAILURE);
  339.     }
  340.     GCC_Version = *cp - '0';    /* major version number, 1 or 2 */
  341.     /*
  342.      * create the default name for the scratch files
  343.      */
  344.     gcc_scratch = getenv ("GNU_CC_SCRATCH");
  345.     gcc_scratch = gcc_scratch ? gcc_scratch : "SYS$SCRATCH:";
  346.     sprintf (Temp, "%sGCC_%08x.CPP", gcc_scratch, pid);
  347.     List_File = savestr(Temp);
  348.     sprintf (Temp, "%sGCC_%08x.S", gcc_scratch, pid);
  349.     Assembly_File = savestr(Temp);
  350.     /*
  351.      *        Get the Input file
  352.      */
  353.     checkswitches(GLOBAL);
  354.     if (cli_get_value("GCC_INPUT",Temp,sizeof Temp)) {
  355.     Input_File = savestr(Temp);
  356.     checkswitches(LOCAL);
  357.     }
  358.     /*
  359.      *        Handle any version identification request early on.
  360.      */
  361.     if (Version) {
  362.     if (!(Verbose & VERB_SILENT)) printf(
  363.         "%%GCC-I-VERSION, this is version %s of the GCC-VMS driver.\n",
  364.                          GCC_DRIVER_VERSION);
  365.     strcat(cpp_Options,"-v ");
  366.     strcat(cc1_Options,"-version ");
  367. #if 0
  368.     strcat(gas_Options,"\"-V\" ");
  369. #endif
  370.     }
  371.     /*
  372.      *        Find the base name of the source file
  373.      */
  374.     cp = Input_File;
  375.     cp1 = strrchr(cp,']');  if (cp1) cp = cp1+1;
  376.     cp1 = strrchr(cp,'>');  if (cp1) cp = cp1+1;
  377.     cp1 = strrchr(cp,':');  if (cp1) cp = cp1+1;
  378.     cp1 = Temp;
  379.     while (*cp != '.' && *cp != ';' && *cp != '\0')
  380.     *cp1++ = *cp++;
  381.     /*
  382.      *        Next check to see if we need to change the name of the list file
  383.      */
  384.     if (Show) {
  385.         Generate_Object = 0;
  386.         Machine_Code = 0;
  387.         switch (Show) {
  388.           case 1:    strcat(cpp_Options,GCC_Version==1 ? "-d " : "\"-dM\" ");
  389.             cp = ".DEF";
  390.             break;
  391.           case 2:    strcat(cpp_Options,"\"-MM\" ");
  392.             cp = ".";    /* ".MAK" perhaps? */
  393.             break;
  394.           case 3:    strcat(cpp_Options,"\"-M\" ");
  395.             cp = ".";
  396.             break;
  397.           default:    cp = 0;
  398.             break;
  399.         }
  400.         if (cp && (!List_File || !List)) {
  401.         if (List_File) free(List_File);
  402.         strcpy(cp1,cp);
  403.         List_File = savestr(Temp);
  404.         }
  405.         List = 1;
  406.     }
  407.     /* Next check and see if we need to supply default file names */
  408.     if (!List_File) {
  409.         strcpy(cp1,".CPP");
  410.         List_File = savestr(Temp);
  411.     }
  412.     if (!Assembly_File) {
  413.         strcpy(cp1,".S");
  414.         Assembly_File = savestr(Temp);
  415.     }
  416.     if (!Object) {
  417.     strcpy(cp1,".OBJ");
  418.     Object = savestr(Temp);
  419.     }
  420.     /* check whether this compilation is just performing syntax checking */
  421.     if (!Generate_Object && !Machine_Code && !List) {
  422.     if (!locate(cc1_Options,"-fsyntax-only")) {
  423.         if (!(Verbose & VERB_SILENT))
  424.         printf("%%GCC-I-NOOUTPUT, no output was requested.\n");
  425. #if 0
  426.         /* -fsyntax-only is available but not reliable under gcc 1.40 */
  427.         if (GCC_Version > 1) strcat(cc1_Options,"-fsyntax-only ");
  428. #endif
  429.     }
  430.     /* preprocess and compile [to the null device] but don't assemble */
  431.     Machine_Code++;
  432.     if (Assembly_File) free(Assembly_File);
  433.     Assembly_File = savestr("_NLA0:");    /* output to /dev/null */
  434.     }
  435.  
  436.     /*
  437.      *        Generate gcc and gas switches from assorted DCL qualifiers.
  438.      */
  439.     if (Standard) {
  440.     if (Standard < 0) {
  441.         strcat(cpp_Options,"-traditional ");
  442.         strcat(cc1_Options,"-traditional ");
  443.     } else {
  444.         strcat(cc1_Options,"-ansi ");
  445.         if (Standard > 1) {
  446.         strcat(cpp_Options,"-pedantic ");
  447.         strcat(cc1_Options,"-pedantic ");
  448.         }
  449.     }
  450.     }
  451. #if 0        /* not used */
  452.     if (List) strcat(cpp_Options,"\"-C\" ");
  453. #endif
  454. #if 0        /* redundant */
  455.     strcat(cpp_Options,"\"-D__GNUC__\" ");
  456. #endif
  457.     if (G_Float) {
  458.     strcat(cpp_Options,"\"-DCC$gfloat\" ");
  459.     strcat(cpp_Options,"\"-D__GFLOAT__\" ");
  460.     strcat(cc1_Options,"-mg ");
  461.     }
  462.     if (Plus) {
  463.     strcat(gas_Options,"-+ ");
  464.     switch (GCC_Version) {
  465.       case 1: strcat(cpp_Options,"-+ \"-D__GNUG__\" \"-D__cplusplus\" ");
  466.         break;
  467.       case 2: strcat(cpp_Options,"-+ \"-D__GNUG__=2\" \"-D__cplusplus\" ");
  468.         break;
  469.       };
  470.       }
  471.     /*
  472.      *        Some version-dependent handling is needed.
  473.      */
  474.     switch (GCC_Version) {
  475.       case 1:    if (Debug) strcat(cc1_Options, Plus ? "-g0 " : "-g ");
  476.         if (Optimize) strcat(cc1_Options,"\"-O\" ");
  477.         if (Plus) strcat(cc1_Options,"-fforce-addr ");
  478.         strcat(gas_Options,"-1 ");
  479.         break;
  480.       case 2:    if (Debug) strcat(cc1_Options,"-g ");
  481.         if (Optimize) {
  482.             sprintf(Temp,"\"-O%d\" ",Optimize);
  483.             strcat(cc1_Options,Temp);
  484.         }
  485.         break;
  486.     }
  487.     if (Optimize && Debug && !(Verbose & VERB_SILENT)) printf(
  488.       "%%GCC-I-DBGOPT, caution: /debug specified with optimization enabled.\n");
  489.     if (Warn) {
  490.     strcat(cc1_Options,"\"-Wall\" ");
  491.     strcat(cpp_Options,"\"-Wall\" ");
  492.     }
  493.     if (!(Verbose & VERB_STAT)) strcat(cc1_Options,"-quiet ");
  494.     else if (Plus) strcat(gas_Options,"\"-H\" ");
  495.  
  496.     if (Profile & PROF_FUNC) strcat(cc1_Options,"-p ");
  497.     if (Profile & PROF_BLOC) strcat(cc1_Options,"-a ");
  498.  
  499.     if        (Case_Hack == 0) strcat(gas_Options,"-h ");
  500.     else if (Case_Hack == 2) strcat(gas_Options,"-h2 ");
  501.     else if (Case_Hack == 3) strcat(gas_Options,"-h3 ");
  502.  
  503.     if (cp = locate(cc1_Options,"-mdont-save-r2-r5")) {
  504.     cp1 = cp + strlen("-mdont-save-r2-r5");
  505.     while (*cp1) *cp++ = *cp1++;
  506.     *cp = '\0';
  507.     strcat(cc1_Options,
  508.            " -fcall-used-r2 -fcall-used-r3 -fcall-used-r4 -fcall-used-r5 ");
  509.     }
  510.     if (cp = locate(cc1_Options,"-mpcc-alignment")) {
  511.     cp1 = cp + strlen("-mpcc-alignment");
  512.     while (*cp1) *cp++ = *cp1++;
  513.     *cp = '\0';
  514.     strcat(cpp_Options,"\"-DPCC_ALIGNMENT\" ");
  515.     } else if (!locate(cc1_Options,"-mvaxc-alignment")) {
  516.     strcat(cc1_Options,"-mvaxc-alignment ");
  517.     }
  518.  
  519.     /*
  520.      *        Generate the command string.
  521.      */
  522.     cp = Temp;
  523.  
  524.     /* Invoke the .COM file */
  525.     cp1 = "@GNU_CC:[000000]GCC";
  526.     while (*cp1) *cp++ = *cp1++;
  527.  
  528.     /* P1 = File to compile */
  529.     *cp++ = ' ';
  530.     cp1 = Input_File;
  531.     while (*cp1) *cp++ = *cp1++;
  532.  
  533.     /* P2 = Options */
  534.     *cp++ = ' ';
  535.     *cp++ = '"';
  536.     if (Plus == 1) *cp++ = 'P';
  537.     if (List == 1) *cp++ = 'L';
  538.     if (Generate_Object == 1) *cp++ = '*';
  539.     if (Machine_Code) *cp++ = 'M';
  540.     if (Verbose & VERB_ECHO) *cp++ = 'V';
  541.     *cp++ = '"';
  542.  
  543.     /* P3 = Name of object file */
  544.     *cp++ = ' ';
  545.     if (Object) {
  546.     cp1 = Object;
  547.     while (*cp1) *cp++ = *cp1++;
  548.     } else {
  549.     *cp++ = '"';
  550.     *cp++ = '"';
  551.     }
  552.  
  553.     /* P4 = Name of listing file */
  554.     *cp++ = ' ';
  555.     if (List_File) {
  556.     cp1 = List_File;
  557.     while (*cp1) *cp++ = *cp1++;
  558.     } else {
  559.     *cp++ = '"';
  560.     *cp++ = '"';
  561.     }
  562.  
  563.     /* P5 = Name of assembly file */
  564.     *cp++ = ' ';
  565.     if (Assembly_File) {
  566.     cp1 = Assembly_File;
  567.     while (*cp1) *cp++ = *cp1++;
  568.     } else {
  569.     *cp++ = '"';
  570.     *cp++ = '"';
  571.     }
  572.  
  573.     /* better late than never...  No bounds checking was performed above. */
  574.     if (strlen(cpp_Options) >= sizeof cpp_Options) {
  575.     fprintf(stderr,"%% gcc-cpp command too long.  Unable to compile.\n");
  576.     exit(EXIT_FAILURE);
  577.     }
  578.     if (strlen(cc1_Options) >= sizeof cc1_Options) {
  579.     fprintf(stderr,"%% gcc-cc1 command too long.  Unable to compile.\n");
  580.     exit(EXIT_FAILURE);
  581.     }
  582.     if (strlen(gas_Options) >= sizeof gas_Options) {
  583.     fprintf(stderr,"%% gcc-as command too long.  Unable to compile.\n");
  584.     exit(EXIT_FAILURE);
  585.     }
  586.  
  587. /*
  588.  * The symbols are assigned in this way, since we do not have to worry about
  589.  * DCL parsing them.  This reduces the complexity, since we do not have to
  590.  * double the single quotes, treble the double quotes, etc.
  591.  *
  592.  * Any single quotes within an include, define, undefine, or scan will be
  593.  * doubled up, since we do require these to be passed along.
  594.  */
  595.  
  596.     if(Target_Machine) lib_set_symbol("GCC_BinDir",Target_Machine);
  597.     else lib_set_symbol("GCC_BinDir","000000");
  598.  
  599.     lib_set_symbol("cc1_Options",cc1_Options);
  600.     lib_set_symbol("cpp_Options",cpp_Options);
  601.     lib_set_symbol("gas_Options",gas_Options);
  602.  
  603.     /*
  604.      *        Do it
  605.      */
  606.     return lib_do_command(Temp, cp - Temp);
  607. }
  608.  
  609.  
  610.         /* - DCL interface routines - */
  611.  
  612. /*
  613.  *    Execute the given DCL command
  614.  */
  615. static int lib_do_command(const char *Text, int Size)
  616. {
  617.     struct {int Size; const char *Ptr;} Descr;
  618.  
  619.     Descr.Ptr = Text;
  620.     Descr.Size = Size;
  621.     return lib$do_command(&Descr);
  622. }
  623.  
  624. /*
  625.  *    Define a local DCL symbol
  626.  */
  627. static int lib_set_symbol(const char *Symbol, const char *Value)
  628. {
  629.     struct {int Size; const char *Ptr;} Symbol_Descr, Value_Descr;
  630.     int sym_typ = 1;        /* LIB$K_CLI_LOCAL_SYM */
  631.  
  632.     Symbol_Descr.Ptr = Symbol;
  633.     Symbol_Descr.Size = strlen(Symbol);
  634.  
  635.     if(Value == 0)
  636.        return lib$delete_symbol(&Symbol_Descr, &sym_typ);
  637.  
  638.     Value_Descr.Ptr = Value;
  639.     Value_Descr.Size = strlen(Value);
  640.     return lib$set_symbol(&Symbol_Descr, &Value_Descr, &sym_typ);
  641. }
  642.  
  643.  
  644. /************        DCL PARSING ROUTINES        **********/
  645.  
  646. #define CLI$_ABSENT    0x381f0
  647. #define CLI$_NEGATED    0x381f8
  648. #define CLI$_LOCNEG    0x38230
  649. #define CLI$_PRESENT    0x3fd19
  650. #define CLI$_DEFAULTED    0x3fd21
  651. #define CLI$_LOCPRES    0x3fd31
  652. #define CLI$_COMMA    0x3fd39
  653.  
  654. static int cli_status;
  655.  
  656. /*
  657.  *    See if "NAME" is present, absent or negated.
  658.  */
  659. static int cli_present(const char *Name, int oldflag, int gblflag)
  660. {
  661.     struct {int Size; const char *Ptr;} Key;
  662.  
  663.     Key.Ptr = Name;
  664.     Key.Size = strlen(Name);
  665.     cli_status = cli$present(&Key);
  666.     switch (cli_status) {
  667.     case CLI$_ABSENT:
  668.         return oldflag;
  669.     case CLI$_NEGATED:
  670.         if (gblflag == LOCAL) return oldflag;
  671.     case CLI$_LOCNEG:
  672.         return 0;
  673.     case CLI$_PRESENT:
  674.     case CLI$_DEFAULTED:
  675.         if (gblflag == LOCAL) return oldflag;
  676.     case CLI$_LOCPRES:
  677.         return 1;
  678.     default:    /*(shouldn't be possible)*/
  679.         return 0;
  680.     }
  681. }
  682.  
  683. /*
  684.  *    Return additional information about the last CLI operation
  685.  */
  686. static int cli_negated(void)
  687. {
  688.     return cli_status == CLI$_NEGATED || cli_status == CLI$_LOCNEG;
  689. }
  690.  
  691. /*
  692.  *    Get value of "NAME"
  693.  */
  694. static int cli_get_value(const char *Name, char *Buffer, int Size)
  695. {
  696.     struct {int Size; const char *Ptr;} Key;
  697.     struct {int Size; char *Ptr;} Value;
  698.  
  699.     Key.Ptr = Name;
  700.     Key.Size = strlen(Name);
  701.     Value.Ptr = Buffer;
  702.     Value.Size = Size - 1;
  703.     cli_status = cli$get_value(&Key, &Value, &Value.Size);
  704.     if (cli_status & 1) {
  705.     Buffer[Value.Size] = '\0';
  706.     return 1;
  707.     } else {
  708.     Buffer[0] = '\0';
  709.     return 0;
  710.     }
  711. }
  712.