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