home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 502b.lha / cc / src / cc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  24.8 KB  |  911 lines

  1. /*
  2.  * cc -- unix-like compiler driver for amiga lattice c
  3.  *
  4.  * adapted for lattice version 5.0 and extensively modified
  5.  *   by Miles Bader, from the original by Fred Fish (copyright
  6.  *   follows).
  7.  *
  8.  * Modified 8/29/90 by The Starbound Software Group, Dave Lowrey - programmer.
  9.  *   The invocation of blink used the explicit path name of blink's
  10.  *   executable (i.e. usr:lc/bin/blink) instead of relying on PATH (as is
  11.  *   done with all of the other commands, such as lc1). I changed the
  12.  *   code to just specify 'BLINK'. This simplifies things when making BLINK
  13.  *   resident.
  14.  *
  15.  *   Made the '-g' option add the ADDSYM parameter to the blink
  16.  *   command line (cpr can guru the system if the executable wasn't linked
  17.  *   with ADDSYM).
  18.  *
  19.  *    Moved the "-m" flag to the lc2 command. It was incorrectly placed on the
  20.  *    lc1 command line.
  21.  *
  22.  *    Fixed to work with SAS/C as well as Lattice/C
  23.  *
  24.  */
  25.  
  26. /************************************************************************
  27.  *                                                                      *
  28.  *                      Copyright (c) 1985, Fred Fish                   *
  29.  *                          All Rights Reserved                         *
  30.  *                                                                      *
  31.  *      This software and/or documentation is released into the         *
  32.  *      public domain for personal, non-commercial use only.            *
  33.  *      Limited rights to use, modify, and redistribute are hereby      *
  34.  *      granted for non-commercial purposes, provided that all          *
  35.  *      copyright notices remain intact and all changes are clearly     *
  36.  *      documented.  The author makes no warranty of any kind with      *
  37.  *      respect to this product and explicitly disclaims any implied    *
  38.  *      warranties of merchantability or fitness for any particular     *
  39.  *      purpose.                                                        *
  40.  *                                                                      *
  41.  ************************************************************************
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47.  
  48. #include <dos.h>
  49. #include <proto/dos.h>
  50. #include <ios1.h> /* magic */
  51.  
  52. #include "common.h"
  53. #include "list.h"
  54. #include "dstr.h"
  55. #include "op.h"
  56. #include "options.h"
  57.  
  58. #include "config.h"
  59.  
  60. static char *locate(char *file,struct list *list);      /* find a file */
  61. static void cleanObjects(int mustExist);        /* Remove .o for link and go mode */
  62. static int makeObjs();                  /* Reduce to list of object files */
  63. static int parseCommandLine();          /* Deal with command line */
  64. static int compile(struct op *op);      /* Translate from .c to .o */
  65. static int assemble(struct op *op);     /* Translate from .s to .o */
  66. static int link();                      /* Gather .o's into executable */
  67. static int runCmd(struct dstr *cmd);
  68.  
  69. #ifdef amiga
  70. #define CHECK_ABORT chkabort()
  71. #else
  72. #define CHECK_ABORT                             /* NULL expansion */
  73. #endif  /* amiga */
  74.  
  75. DBUG_GLOBALS
  76.  
  77. /*
  78.  *      flags set by command line arguments
  79.  */
  80. static int debugLevel=DEFAULT_DEBUGLEVEL;       /* -g (debugging level) */
  81.  
  82. struct list *libDirs=NULL;
  83. struct list *incDirs=NULL;
  84. struct list *binDirs=NULL;
  85. struct list *defines=NULL;
  86. struct list *undefines=NULL;
  87. struct list *libs=NULL;
  88.  
  89. struct list *pass1PassThrus=NULL;
  90. struct list *pass2PassThrus=NULL;
  91. struct list *optPassThrus=NULL;
  92. struct list *linkPassThrus=NULL;
  93.  
  94. struct list *ops=NULL;
  95.  
  96. static char *outfile=DEFAULT_EXEC;      /* output file name from linker */
  97. static char *tempDir=TEMPDIR;           /* where to keep quad files */
  98. static char *sinkFile=SINKFILE;         /* where to put output from passes */
  99.  
  100. struct dstr *cmdLine=NULL;
  101.  
  102. static int abortmsg()
  103. {
  104.     if(options_IsSet(OPT_ECHO))
  105.         fprintf(stderr,"cc: aborting\n");
  106.     return 1; /* abort */
  107. }
  108.  
  109. static int cleanup(status)
  110. int status;
  111. {
  112.     if(cmdLine!=NULL)   dstr_Free(cmdLine);
  113.  
  114.     if(libDirs!=NULL)   list_Free(libDirs);
  115.     if(incDirs!=NULL)   list_Free(incDirs);
  116.     if(binDirs!=NULL)   list_Free(binDirs);
  117.     if(defines!=NULL)   list_Free(defines);
  118.     if(undefines!=NULL) list_Free(undefines);
  119.     if(libs!=NULL)      list_Free(libs);
  120.  
  121.     if(pass1PassThrus!=NULL)    list_Free(pass1PassThrus);
  122.     if(pass2PassThrus!=NULL)    list_Free(pass2PassThrus);
  123.     if(optPassThrus!=NULL)      list_Free(optPassThrus);
  124.     if(linkPassThrus!=NULL)     list_Free(linkPassThrus);
  125.  
  126.     if(ops!=NULL)       list_Free(ops);
  127.  
  128.     return status;
  129. }
  130.  
  131. static void init()
  132. {
  133.     int *opt;
  134.  
  135.     options_Init();
  136.     for(opt=defaultOptions; *opt!=0; opt++)
  137.         options_Set(*opt);
  138.  
  139.     cmdLine=dstr_Create(30);            /* global command buffer */
  140.  
  141.     libDirs=list_Create((void **)libDirsInit);
  142.     incDirs=list_Create((void **)incDirsInit);
  143.     binDirs=list_Create((void **)binDirsInit);
  144.     defines=list_Create((void **)definesInit);
  145.     undefines=list_Create((void **)undefinesInit);
  146.     libs=list_Create((void **)libsInit);
  147.  
  148.     pass1PassThrus=list_Create(NULL);
  149.     pass2PassThrus=list_Create(NULL);
  150.     optPassThrus=list_Create(NULL);
  151.     linkPassThrus=list_Create(NULL);
  152.  
  153.     ops=list_Create(NULL);
  154.     list_SetFree(ops,op_Free);
  155. }
  156.  
  157. void main(argc, argv)
  158. int argc;
  159. char *argv[];
  160. {
  161.     int status;
  162.  
  163.     DBUG_ENTER("main");
  164.  
  165.     onexit(cleanup);
  166.     init();
  167.  
  168.     onbreak(abortmsg);
  169.  
  170.     if(parseCommandLine(argc,argv)==0)
  171.         fatal("no files specified");
  172.  
  173.     cleanObjects(FALSE);        /* get rid of existing object files if any */
  174.  
  175.     status=makeObjs();
  176.     if(status==0 && options_IsSet(OPT_LINK)){
  177.         status=link();
  178.         if(list_GetLen(ops)==1)
  179.             cleanObjects(TRUE);
  180.     }
  181.  
  182.     exit(status);
  183. }
  184.  
  185. /*
  186.  *      The following macro is used to allow optional whitespace between
  187.  *      an option and it's argument.  Argp is left pointing at the option
  188.  *      and argv and argc are adjusted accordingly if necessary.
  189.  *
  190.  *      Note that there is no check for missing option arguments.  In
  191.  *      particular, -o -V will blindly take -V as the output file name.
  192.  *
  193.  */
  194.  
  195. #define XARG(argc,argv,argp) {if(*++argp=='\0'){argp=(*argv++);argc--;}}
  196.  
  197. static int parseCommandLine(argc,argv)
  198. int argc;
  199. char **argv;
  200. {
  201.     register char *argp;
  202.  
  203.     DBUG_ENTER("parseCommandLine");
  204.  
  205.     argc--;
  206.     argv++;
  207.     while(argc-- > 0){
  208.         CHECK_ABORT;
  209.  
  210.         argp=*argv++;
  211.  
  212.         if(*argp=='+')
  213.             options_SetByName(argp+1);
  214.         else if(*argp!='-')
  215.             list_Add(ops,(void *)op_Create(argp));
  216.         else
  217.             switch(*++argp){
  218.                 case 'c':
  219.                     options_Clear(OPT_LINK);    /* don't link object modules */
  220.                     break;
  221.                 case 'p':                       /* pass thru args to a pass */
  222.                     switch(*++argp){
  223.                         case '1':               /* pass 1 */
  224.                             XARG(argc,argv,argp);
  225.                             list_Add(pass1PassThrus,argp);
  226.                             break;
  227.                         case '2':               /* pass 2 */
  228.                             XARG(argc,argv,argp);
  229.                             list_Add(pass2PassThrus,argp);
  230.                             break;
  231.                         case 'o':               /* optimizer */
  232.                             XARG(argc,argv,argp);
  233.                             list_Add(optPassThrus,argp);
  234.                             break;
  235.                         case 'l':               /* linking */
  236.                             XARG(argc,argv,argp);
  237.                             list_Add(linkPassThrus,argp);
  238.                             break;
  239.                         default:
  240.                             fatal("unknown pass '%c'; must be one of [12ol]",argp[-1]);
  241.                     }
  242.                     break;
  243.                 case 'D':
  244.                     XARG(argc,argv,argp);
  245.                     list_Add(defines,(void *)argp);
  246.                     break;
  247.                 case 'E':
  248.                     warning("-E unimplemented, converted to -P instead");
  249.                     /* fall through */
  250.                 case 'P':
  251.                     options_Clear(OPT_COMPILE);
  252.                     options_Clear(OPT_ASSEMBLE);
  253.                     options_Clear(OPT_LINK);
  254.                     break;
  255.                 case 'g':
  256.                     if(*++argp!='\0') /* optional debuggin level */
  257.                         debugLevel=atoi(argp);
  258.                     options_Set(OPT_DEBUG);
  259.                     break;
  260.                 case 'I':
  261.                     XARG(argc,argv,argp);
  262.                     list_Add(incDirs,(void *)argp);
  263.                     break;
  264.                 case 'l':
  265.                     XARG(argc,argv,argp);
  266.                     list_Add(libs,(void *)argp);
  267.                     break;
  268.                 case 'L':
  269.                     XARG(argc,argv,argp);
  270.                     list_Add(libDirs,(void *)argp);
  271.                     break;
  272.                 case 'B':
  273.                     XARG(argc,argv,argp);
  274.                     list_Add(binDirs,(void *)argp);
  275.                     break;
  276.                 case 'O':
  277.                     options_Set(OPT_OPTIMIZE);
  278.                     break;
  279.                 case 'o':
  280.                     XARG(argc,argv,argp);
  281.                     outfile=argp;
  282.                     break;
  283.                 case 't':               /* warning, non-standard */
  284.                     XARG(argc,argv,argp);
  285.                     tempDir=argp;
  286.                     break;
  287.                 case 'S':
  288.                     warning("-S option not yet implemented, ignored");
  289.                     options_Clear(OPT_ASSEMBLE);
  290.                     break;
  291.                 case 'U':
  292.                     XARG(argc,argv,argp);
  293.                     list_Add(undefines,(void *)argp);
  294.                     break;
  295.                 default:
  296.                     fatal("unknown option '%c'",*argp);
  297.                     break;
  298.             }
  299.     }
  300.  
  301.     DBUG_RETURN(int,list_GetLen(ops));
  302. }
  303.  
  304. /*
  305.  *      For each operand, do compilation or assembly as necessary, to
  306.  *      reduce to an object file in the current directory.
  307.  */
  308. static int makeObjs()
  309. {
  310.     int n;
  311.     void **els;
  312.     int numOps=list_GetLen(ops);
  313.     int status=0;
  314.  
  315.     DBUG_ENTER("makeObjs");
  316.  
  317.     for(n=numOps,els=list_GetEls(ops); n>0; n--,els++){
  318.         struct op *op=(struct op *)*els;
  319.  
  320.         CHECK_ABORT;
  321.  
  322.         if(numOps>1 && (op_IsC(op) || op_IsS(op)))
  323.             printf("%s.%s:\n",op->rootname,op->suffix);
  324.  
  325.         if(op_IsC(op))
  326.             status=compile(op);
  327.         else if(op_IsS(op))
  328.             status=assemble(op);
  329.     }
  330.  
  331.     DBUG_RETURN(int,status);
  332. }
  333.  
  334. /* handy little routine */
  335. void addfList(ds,fmt,list)
  336. struct dstr *ds;
  337. char *fmt;
  338. struct list *list;
  339. {
  340.     int n;
  341.     void **els;
  342.  
  343.     for(n=list_GetLen(list),els=list_GetEls(list); n>0; n--,els++)
  344.         dstr_Addf(ds,fmt,(char *)*els);
  345. }
  346.  
  347. /*
  348.  *      Note that commands to cc of the form "-l<name>" get interpreted
  349.  *      to mean use a library called "name.lib" from the library
  350.  *      directory.
  351.  *      -lm is specially interpreted to be the appropriate math library.
  352.  */
  353. static int link()
  354. {
  355.     int n;
  356.     void **els;
  357.  
  358.     DBUG_ENTER("link");
  359.  
  360.     dstr_Clear(cmdLine);
  361. /* Change 'blink' command invocation to use normal PATH search DWL */
  362. /*    dstr_Addf(cmdLine,"%s ",locate("blink",binDirs)); */  /* DWL */
  363.     dstr_Addf(cmdLine,"blink  ");                            /* DWL */
  364.  
  365.     if(options_IsSet(OPT_DETACH))
  366.         dstr_Append(cmdLine,locate("cback.o",libDirs));
  367.     else if(options_IsSet(OPT_RESIDENT)){
  368.         if(options_IsSet(OPT_CATCH))
  369.             dstr_Append(cmdLine,locate("catchres.o",libDirs));
  370.         else
  371.             dstr_Append(cmdLine,locate("cres.o",libDirs));
  372.     }else if(options_IsSet(OPT_CATCH))
  373.         dstr_Append(cmdLine,locate("catch.o",libDirs));
  374.     else
  375.         dstr_Append(cmdLine,locate("c.o",libDirs));
  376.  
  377.     for(n=list_GetLen(ops),els=list_GetEls(ops); n>0; n--,els++){
  378.         struct op *op=(struct op *)*els;
  379.         char *name=(op_IsO(op) ? op->rootname : op->basename);
  380.  
  381.         dstr_Addf(cmdLine,"+%s.o",name);
  382.     }
  383.  
  384.     if(options_IsSet(OPT_TINYMAIN))
  385.         dstr_Addf(cmdLine," define __main=__tinymain ");
  386.  
  387.     dstr_Addf(cmdLine," library ");
  388.     for(n=list_GetLen(libs),els=list_GetEls(libs); n>0; n--,els++){
  389.         char buffer[50];
  390.         char *lib=(char *)*els;
  391.  
  392.         if(strcmp(lib,"m")==0){
  393.             /* map -lm to appropiate library */
  394.  
  395.             strcpy(buffer,"lib:lcm");
  396.  
  397.             if(options_IsSet(OPT_FFP))
  398.                 strcat(buffer,"ffp");
  399.             else if(options_IsSet(OPT_IEEE))
  400.                 strcat(buffer,"ieee");
  401.             else if(options_IsSet(OPT_881))
  402.                 strcat(buffer,"881");
  403.  
  404.             /*
  405.              * there are only r and s libraries for lcm.lib in the lattice
  406.              * distribution; if there is a way to get the lcmieee, lcmffp,
  407.              * & lcm881 libraries to work with reg-args & short-ints, I
  408.              * couldn't find it.
  409.              */
  410.             if(options_IsSet(OPT_SHORTINTS))
  411.                 strcat(buffer,"s");
  412.             if(options_IsSet(OPT_REGARGS))
  413.                 strcat(buffer,"r");
  414.  
  415.             strcat(buffer,".lib");
  416.         }else if(strcmp(lib,"lc")==0){
  417.             /* do the standard c library */
  418.  
  419.             strcpy(buffer,"lib:lc");
  420.  
  421.             if(options_IsSet(OPT_SHORTINTS))
  422.                 strcat(buffer,"s");
  423.             if(options_IsSet(OPT_REGARGS))
  424.                 strcat(buffer,"r");
  425.             if(options_IsSet(OPT_ABSDATA))
  426.                 strcat(buffer,"nb");
  427.  
  428.             strcat(buffer,".lib");
  429.  
  430.             if(options_IsSet(OPT_REGARGS)){
  431.                 /*
  432.                  * Now, do it AGAIN, but without registers, to catch any missing refs.
  433.                  * I don't think this is exactly the right thing to do, but there seem
  434.                  * to be internal functions missing from the register-fied libraries
  435.                  */
  436.  
  437.                 strcat(buffer,"+lib:lc");
  438.  
  439.                 if(options_IsSet(OPT_SHORTINTS))
  440.                     strcat(buffer,"s");
  441.                 if(options_IsSet(OPT_ABSDATA))
  442.                     strcat(buffer,"nb");
  443.  
  444.                 strcat(buffer,".lib");
  445.             }
  446.         }else{
  447.             sprintf(buffer,"%s.lib",lib);
  448.             strcpy(buffer,locate(buffer,libDirs));
  449.         }
  450.  
  451.         if(n==1)
  452.             dstr_Append(cmdLine,buffer);
  453.         else
  454.             dstr_Addf(cmdLine,"%s+",buffer);
  455.     }
  456.  
  457.     if(outfile==NULL)
  458.         /* there better be at least one source file! */
  459.         outfile=((struct op *)list_GetEls(ops))->basename;
  460. /* For some reason, this doesn't work with SAS/C 5.10          */
  461. /* It isn't really needed, as there is no map file produced DWL */
  462. /*    dstr_Addf(cmdLine," to %s map nil:",outfile); */  /* DWL */
  463.     dstr_Addf(cmdLine," to %s",outfile);
  464.                                                 /* DWL */
  465.     if(options_IsSet(OPT_DEBUG))                /* DWL */
  466.         dstr_Append(cmdLine, " ADDSYM ");        /* DWL */
  467.  
  468.     addfList(cmdLine," %s",linkPassThrus);
  469.  
  470.     DBUG_RETURN(int,runCmd(cmdLine));
  471. }
  472.  
  473. /*
  474.  *      compile one operand from a C source program to an object module.
  475.  */
  476. static int compile(op)
  477. struct op *op;
  478. {
  479.     int status=0;
  480.  
  481.     DBUG_ENTER("compile");
  482.  
  483.     if(options_IsSet(OPT_ASSEMBLE)){
  484.         status=pass1(op);
  485.         if(status==0 && options_IsSet(OPT_COMPILE)){
  486.             CHECK_ABORT;
  487.             if(options_IsSet(OPT_OPTIMIZE))
  488.                 status=optimize(op);
  489.             if(status==0)
  490.                 status=pass2(op);
  491.         }
  492.     }
  493.  
  494.     DBUG_RETURN(int,status);
  495. }
  496.  
  497. /*
  498.  *      Note that because of brain-damage in the fact that -p to lc1 removes
  499.  *      all predefined defs, we must add them so replacing -c with -P in the
  500.  *      cc command line will result in the same set of predefined symbols.
  501.  *      This is rather ugly and leaves a hole for future problems if we
  502.  *      get out of sync with respect to what names the compiler predefines.
  503.  */
  504. static int pass1(op)
  505. register struct op *op;
  506. {
  507.     char tmpFile[MAXPATH];
  508.     int status;
  509.     int n;
  510.     void **els;
  511.  
  512.     DBUG_ENTER("pass1");
  513.  
  514.     dstr_Clear(cmdLine);
  515.  
  516.     dstr_Append(cmdLine,locate((options_IsSet(OPT_BIGLC1) ? "lc1b" : "lc1"),binDirs));
  517.  
  518.     if(options_IsSet(OPT_DEBUG)){
  519.         dstr_Addf(cmdLine," -d%d",debugLevel);
  520.         if(options_IsSet(OPT_OPTIMIZE)){
  521.             warning("-g incompatible with -O, -O turned off");
  522.             options_Clear(OPT_OPTIMIZE);
  523.         }
  524.     }
  525.  
  526.     if(options_IsSet(OPT_FFP))
  527.         dstr_Addf(cmdLine," -ff");
  528.     else if(options_IsSet(OPT_881))
  529.         dstr_Addf(cmdLine," -f8");
  530.     else if(options_IsSet(OPT_IEEE))
  531.         dstr_Addf(cmdLine," -fi");
  532.     else
  533.         dstr_Addf(cmdLine," -fl");
  534.  
  535.     if(options_IsSet(OPT_SHORTINTS))
  536.         dstr_Addf(cmdLine," -w");
  537.     if(options_IsSet(OPT_LONGALIGN))
  538.         dstr_Addf(cmdLine," -l");
  539. /*                                     Moved this to lc2
  540.     if(options_IsSet(OPT_020))
  541.         dstr_Addf(cmdLine," -m2");
  542.     else if(options_IsSet(OPT_030))
  543.         dstr_Addf(cmdLine," -m3");
  544. */
  545.     if(options_IsSet(OPT_CATCH) && !options_IsSet(OPT_ABSDATA)){
  546.         warning("+catch implies +abs-data");
  547.         options_Set(OPT_ABSDATA);
  548.     }
  549.  
  550.     dstr_Addf(cmdLine," -b%d",options_IsSet(OPT_ABSDATA) ? 0 : 1);
  551.     dstr_Addf(cmdLine," -r%d",options_IsSet(OPT_ABSCODE) ? 0 : 1);
  552.  
  553.     if(options_IsSet(OPT_REGARGS))
  554.         dstr_Addf(cmdLine,"r"); /* part of -r switch */
  555.  
  556.     {
  557.         char buf[15], *p=buf;
  558.  
  559.         if(options_IsSet(OPT_ANSI))             *p++='a';
  560.         if(options_IsSet(OPT_CPP))              *p++='+';
  561.         if(options_IsSet(OPT_TRAD))             *p++='l', *p++='o';
  562.         if(options_IsSet(OPT_REGARGS))          *p++='r';
  563.         if(options_IsSet(OPT_PURESTRINGS))      *p++='s';
  564.  
  565.         if(p>buf){
  566.             *p='\0';
  567.             dstr_Addf(cmdLine," -c%s",buf);
  568.         }
  569.     }
  570.  
  571.     if(options_IsSet(OPT_COMPILE)){
  572.         strcpy(tmpFile,tempDir);
  573.         strcat(tmpFile,op->basename);
  574.         strcat(tmpFile,".q");
  575.         dstr_Addf(cmdLine," -o%s",tmpFile);
  576.     }else{
  577.         strcpy(tmpFile,op->basename);
  578.         strcat(tmpFile,".pp");
  579.  
  580.         dstr_Addf(cmdLine," -o%s -p",tmpFile);
  581.     }
  582.  
  583.     for(n=list_GetLen(undefines),els=list_GetEls(undefines); n>0; n--,els++){
  584.         /*************************
  585.         dstr_Addf(cmdLine," -u%s",(char *)*els);
  586.         **************************/
  587.         warning("-U%s ignored! (unimplemented)",(char *)*els);
  588.     }
  589.  
  590.     addfList(cmdLine," -d%s",defines);
  591.     addfList(cmdLine," %s",pass1PassThrus);
  592.  
  593.     for(n=list_GetLen(incDirs),els=list_GetEls(incDirs); n>0; n--,els++){
  594.         char *id=(*els);
  595.         int len=strlen(id);
  596.  
  597.         dstr_Addf(cmdLine," -i%s",*els);
  598.  
  599.         if(len>0 && id[len-1]!=':' && id[len-1]!='/')
  600.             dstr_Addf(cmdLine,"/");
  601.     }
  602.  
  603.     dstr_Addf(cmdLine," %s",op->rootname);
  604.  
  605.     status=runCmd(cmdLine);
  606.     if(status==0 && options_IsSet(OPT_EXEC) && !readable(tmpFile))
  607.         status=1;
  608.  
  609.     DBUG_RETURN(int,status);
  610. }
  611.  
  612. /* run the optimizer */
  613. static int optimize(op)
  614. struct op *op;
  615. {
  616.     DBUG_ENTER("optimize");
  617.  
  618.     dstr_Clear(cmdLine);
  619.     dstr_Addf(cmdLine,"%s %s%s",locate("go",binDirs),tempDir,op->basename);
  620.  
  621.     addfList(cmdLine," %s",optPassThrus);
  622.  
  623.     DBUG_RETURN(int,runCmd(cmdLine));
  624. }
  625.  
  626. /*
  627.  *      Run second pass of compiler on a single operand.
  628.  */
  629. static int pass2(op)
  630. struct op *op;
  631. {
  632.     char objFile[MAXPATH];
  633.     int status;
  634.  
  635. #ifdef DBUG
  636.     fprintf(stderr,"Entering pass2...\n");
  637. #endif
  638.  
  639.     DBUG_ENTER("pass2");
  640.  
  641.     dstr_Clear(cmdLine);
  642.  
  643.     dstr_Append(cmdLine,locate("lc2",binDirs));
  644.  
  645.     if(!options_IsSet(OPT_STACKCHECK))
  646.         dstr_Addf(cmdLine," -v");
  647.  
  648. /* Moved -m from lc1 to lc2 (The lattice doc doesn't say WHERE it goes!) DWL */
  649.  
  650.     if(options_IsSet(OPT_020))            /* DWL */
  651.         dstr_Addf(cmdLine," -m2");        /* DWL */
  652.     else if(options_IsSet(OPT_030))        /* DWL */
  653.         dstr_Addf(cmdLine," -m3");        /* DWL */
  654.  
  655.     strcpy(objFile,op->basename);
  656.     strcat(objFile,".o");
  657.  
  658.     dstr_Addf(cmdLine," -o%s",objFile);
  659.  
  660.     dstr_Addf(cmdLine," %s%s",tempDir,op->basename);
  661.  
  662.     addfList(cmdLine," %s",pass2PassThrus);
  663.  
  664.     status=runCmd(cmdLine);
  665.     if(status==0 && options_IsSet(OPT_EXEC) && !readable(objFile))
  666.         status=1;
  667.  
  668.     DBUG_RETURN(int,status);
  669. }
  670.  
  671. /*
  672.  *      I have not yet had occasion to use the macro assembler,so this
  673.  *      part is not yet implemented.  If anyone wants to send me the
  674.  *      appropriate code, I will be glad to install it.
  675.  */
  676. static int assemble(op)
  677. struct op *op;
  678. {
  679.     DBUG_ENTER("assemble");
  680.     warning("assembly pass not yet implemented");
  681.     DBUG_RETURN(int,1);
  682. }
  683.  
  684. static void filteredOutputFrom(source,filter)
  685. FILE *source;
  686. char **filter;
  687. {
  688.     char buf[200];
  689.  
  690.     DBUG_ENTER("FilteredOutputFrom");
  691.  
  692.     while(!feof(source)){
  693.         char **ignore;
  694.  
  695.         fgets(buf,sizeof(buf),source);
  696.  
  697.         for(ignore=filter; *ignore!=NULL; ignore++)
  698.             if(strncmp(*ignore,buf,strlen(*ignore))==0)
  699.                 break;
  700.  
  701.         if(*ignore==NULL)
  702.             fputs(buf,stdout);
  703.     }
  704.  
  705.     DBUG_VOID_RETURN;
  706. }
  707.  
  708. #ifdef AMIGA
  709.  
  710. static int execToFile(cmd,sink)
  711. char *cmd;
  712. FILE *sink;
  713. {
  714.     /* this is a dopey version that uses Execute, since I can't get fork to work */
  715.     long fh;
  716.  
  717.     DBUG_ENTER("execToFile");
  718.  
  719.     if(sink==NULL)
  720.         fh=0;
  721.     else
  722.         fh=chkufb(fileno(sink))->ufbfh;
  723.  
  724.     DBUG_RETURN(int,Execute(cmd,0L,fh)!=(-1));
  725.  
  726. #if 0
  727.     char *argv[50],**argp=argv;
  728.     struct ProcID child;
  729.     static struct FORKENV env={0,0,0,0,0,NULL};
  730.     int i;
  731.  
  732.     DBUG_ENTER("execToFile");
  733.  
  734.     if(cmd==NULL)
  735.         DBUG_RETURN(int,1);
  736.  
  737.     /* this is sort of stupid, cause forkv will just put them back together,
  738.      * but oh well...
  739.      */
  740.     *argp=strtok(cmd," \t");
  741.     while(*argp!=NULL)
  742.         *++argp=strtok(NULL," \t");
  743.  
  744.     if(sink==NULL)
  745.         env.std_out=0;
  746.     else{
  747.         struct UFB *ufb=chkufb(fileno(sink));
  748.         int i;
  749.  
  750.         printf("argv[%d]:",argp-argv);
  751.         for(argp=argv;*argp!=NULL;argp++)
  752.             printf(" %s",*argp);
  753.         putchar('\n');
  754.  
  755.         printf("env: %d, %d, %d, %d, %d, %d\n",
  756.                 env.priority, env.stack, env.std_in, env.std_out,
  757.                 env.console, env.msgport);
  758.  
  759.         printf("ufb==0x%x, fh==0x%x, go? ",ufb,ufb->ufbfh);
  760.  
  761.         fflush(stdout);
  762.  
  763.         env.std_out=ufb->ufbfh; /* magic to get amigados handle from FILE */
  764.     }
  765.  
  766.     if((i=forkv(argv[0],argv,&env,&child))==-1){
  767.         poserr("forkv");
  768.         DBUG_RETURN(int,1);
  769.     }
  770.  
  771.     printf("Fork returns: %d\n",i);
  772.  
  773.     DBUG_RETURN(int,wait(&child));
  774. #endif
  775. }
  776.  
  777. #endif
  778.  
  779. static int runCmd(cmd)
  780. struct dstr *cmd;
  781. {
  782.     int status;
  783.     char *buf=dstr_GetBuf(cmd);
  784.  
  785.     DBUG_ENTER("RunCommand");
  786.  
  787.     DBUG_3("cmd","execute '%s'",buf);
  788.     if(options_IsSet(OPT_ECHO)){
  789.         puts(buf);
  790.         fflush(stdout);
  791.     }
  792.  
  793.     CHECK_ABORT;
  794.  
  795.     if(options_IsSet(OPT_EXEC)){
  796.         FILE *sink;
  797.  
  798.         if(sinkFile!=NULL && options_IsSet(OPT_FILTER)){
  799.             sink=fopen(sinkFile,"w+");
  800.             if(sink==NULL)
  801.                 perror(sinkFile);
  802.         }else
  803.             sink=NULL;
  804.  
  805.         status=execToFile(buf,sink);
  806.         DBUG_3("sys","subcommand returns status %d",status);
  807.  
  808.         if(sink!=NULL){
  809.             rewind(sink);
  810.             filteredOutputFrom(sink,filteredPrefixes);
  811.             fclose(sink);
  812.             unlink(sinkFile);
  813.         }
  814.  
  815.         DBUG_RETURN(int,status);
  816.     }else
  817.         DBUG_RETURN(int,0);
  818. }
  819.  
  820. /*
  821.  *      Look through the list of paths pointed to by "vec" until we find
  822.  *      a file with name given pointed to by "namep".  If none is found,
  823.  *      the name pointed to by namep is returned.
  824.  */
  825. static char *locate(name,paths)
  826. char *name;
  827. struct list *paths;
  828. {
  829.     static char namebuf[MAXPATH];
  830.     void **els;
  831.     int n;
  832.  
  833.     DBUG_ENTER("locate");
  834.  
  835.     if(strchr(name,':')!=NULL || *name=='/')
  836.         return name;    /* absolute */
  837.  
  838.     for(n=list_GetLen(paths),els=list_GetEls(paths); n>0; n--,els++){
  839.         int len=strlen((char *)*els);
  840.  
  841.         strcpy(namebuf,(char *)*els);
  842.         if(len>0 && namebuf[len-1]!=':' && namebuf[len-1]!='/')
  843.             strcat(namebuf,"/");
  844.         strcat(namebuf,name);
  845.  
  846.         DBUG_3("try","look for '%s'",namebuf);
  847.         if(readable(namebuf)){
  848.             name=namebuf;
  849.             break;
  850.         }
  851.     }
  852.  
  853.     DBUG_RETURN(char *,name);
  854. }
  855.  
  856. /*
  857.  *      Check to see if the file exists and is readable.
  858.  */
  859. static int readable(name)
  860. char *name;
  861. {
  862.     register int status=0;
  863.     register long fildes;
  864.  
  865.     DBUG_ENTER("readable");
  866.  
  867. #ifdef unix
  868.     fildes=open(name,O_RDONLY);
  869.     if(fildes >= 0){
  870.         (void) close(fildes);
  871.         status=1;
  872.     }
  873. #else
  874.     fildes=Lock(name,ACCESS_READ);
  875.     if(fildes != 0){
  876.         UnLock(fildes);
  877.         status=1;
  878.     }
  879. #endif
  880.  
  881.     DBUG_RETURN(int,status);
  882. }
  883.  
  884. /*
  885.  *      If an executable is made from a single C file, the normal behavior
  886.  *      for the unix environment is to treat the .o file as an intermediate
  887.  *      file and remove it, so we follow suit.
  888.  */
  889. static void cleanObjects(mustExist)
  890. int mustExist;
  891. {
  892.     int n;
  893.     void **els;
  894.  
  895.     DBUG_ENTER("cleanObjects");
  896.  
  897.     for(n=list_GetLen(ops),els=list_GetEls(ops); n>0; n--,els++){
  898.         char buf[MAXPATH];
  899.         struct op *op=(struct op *)*els;
  900.  
  901.         if(!op_IsO(op)){
  902.             strcpy(buf,op->basename);
  903.             strcat(buf,".o");
  904.             if(unlink(buf)!=0 && mustExist)
  905.                 warning("can't delete '%s'",buf);
  906.         }
  907.     }
  908.  
  909.     DBUG_VOID_RETURN;
  910. }
  911.