home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / comm / tcp / amitcp / src / devtools / cpp / cpp3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-09  |  14.2 KB  |  551 lines

  1. /*
  2.  *                C P P 3 . C
  3.  *
  4.  *            File open and command line options
  5.  *
  6.  * Edit history
  7.  * 13-Nov-84    MM    Split from cpp1.c
  8.  * 21-Oct-85    rms    Make -g command arg not cause an error.
  9.  * 14-Mar-86    FNF    Incorporate macro based C debugging package.
  10.  *            Port to the Commodore AMIGA.
  11.  * 20-Aug-88    Ois    Added __TIME__, and changed __DATE__ to standard.
  12.  */
  13.  
  14. #include    <stdio.h>
  15. #include    <ctype.h>
  16. #include    <time.h>    /*OIS*0.92*/
  17. #include    "cppdef.h"
  18. #include    "cpp.h"
  19. #if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX)
  20. #include    <signal.h>
  21. extern int    abort();                /* For debugging                */
  22. #endif
  23.  
  24. int
  25. openfile(filename)
  26. char        *filename;
  27. /*
  28.  * Open a file, add it to the linked list of open files.
  29.  * This is called only from openfile() above.
  30.  */
  31. {
  32.     register FILE        *fp;
  33.     extern FILE        *fopen ();
  34.  
  35.     DBUG_ENTER ("openfile");
  36.     if ((fp = fopen(filename, "r")) == NULL) {
  37. #if DEBUG
  38.         perror(filename);
  39. #endif
  40.         DBUG_RETURN (FALSE);
  41.     }
  42. #if DEBUG
  43.     if (debug)
  44.         fprintf(stderr, "Reading from \"%s\"\n", filename);
  45. #endif
  46.     addfile(fp, filename);
  47.     DBUG_RETURN (TRUE);
  48. }
  49.  
  50. void
  51. addfile(fp, filename)
  52. FILE        *fp;            /* Open file pointer        */
  53. char        *filename;        /* Name of the file        */
  54. /*
  55.  * Initialize tables for this open file.  This is called from openfile()
  56.  * above (for #include files), and from the entry to cpp to open the main
  57.  * input file.    It calls a common routine, getfile() to build the FILEINFO
  58.  * structure which is used to read characters.    (getfile() is also called
  59.  * to setup a macro replacement.)
  60.  */
  61. {
  62.     register FILEINFO    *file;
  63.     extern FILEINFO     *getfile();
  64.  
  65.     DBUG_ENTER ("addfile");
  66.     file = getfile(NBUFF, filename);
  67.     file->fp = fp;            /* Better remember FILE *    */
  68.     file->buffer[0] = EOS;        /* Initialize for first read    */
  69.     line = 1;            /* Working on line 1 now    */
  70.     wrongline = TRUE;        /* Force out initial #line    */
  71.     DBUG_VOID_RETURN;
  72. }
  73.  
  74. void
  75. setincdirs()
  76. /*
  77.  * Append system-specific directories to the include directory list.
  78.  * Called only when cpp is started.
  79.  */
  80. {
  81.  
  82.     DBUG_ENTER ("setincdirs");
  83. #ifdef    CPP_INCLUDE
  84.     *incend++ = CPP_INCLUDE;
  85. #define IS_INCLUDE    1
  86. #else
  87. #define IS_INCLUDE    0
  88. #endif
  89.  
  90. #if HOST == SYS_UNIX
  91.     *incend++ = "/usr/include";
  92. #define MAXINCLUDE    (NINCLUDE - 1 - IS_INCLUDE)
  93. #endif
  94.  
  95. #if HOST == SYS_AMIGADOS
  96. #ifdef amigados
  97.         {
  98.         /* allow ';' separated list  */
  99.         char *env, *s;
  100.         
  101.         if((env = getenv("CPPINCDIR")) && (env = strdup(env)))
  102.         {
  103.         *incend++ = env; 
  104.         while(s = strchr(env, ';'))
  105.         {
  106.             *s = '\0';
  107.             env = s++;
  108.             *incend++ = env;
  109.         }
  110.         }
  111.     }
  112. #else
  113.     *incend++ = "df0:include/";      /* These should be fixed. fnf */
  114.     *incend++ = "df1:include/";
  115. #endif
  116. #define MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  117. #endif
  118.  
  119. #if HOST == SYS_VMS
  120.     extern char    *getenv();
  121.  
  122.     if (getenv("C$LIBRARY") != NULL)
  123.         *incend++ = "C$LIBRARY:";
  124.     *incend++ = "SYS$LIBRARY:";
  125. #define MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  126. #endif
  127.  
  128. #if HOST == SYS_RSX
  129.     extern int    $$rsts;         /* TRUE on RSTS/E    */
  130.     extern int    $$pos;            /* TRUE on PRO-350 P/OS */
  131.     extern int    $$vms;            /* TRUE on VMS compat.    */
  132.  
  133.     if ($$pos) {                            /* P/OS?                */
  134.         *incend++ = "SY:[ZZDECUSC]";        /* C #includes          */
  135.         *incend++ = "LB:[1,5]";             /* RSX library          */
  136.     }
  137.     else if ($$rsts) {                      /* RSTS/E?              */
  138.         *incend++ = "SY:@";                 /* User-defined account */
  139.         *incend++ = "C:";                   /* Decus-C library      */
  140.         *incend++ = "LB:[1,1]";             /* RSX library          */
  141.     }
  142.     else if ($$vms) {                       /* VMS compatibility?   */
  143.         *incend++ = "C:";
  144.     }
  145.     else {                    /* Plain old RSX/IAS    */
  146.         *incend++ = "LB:[1,1]";
  147.     }
  148. #define MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  149. #endif
  150.  
  151. #if HOST == SYS_RT11
  152.     extern int    $$rsts;         /* RSTS/E emulation?    */
  153.  
  154.     if ($$rsts)
  155.         *incend++ = "SY:@";                 /* User-defined account */
  156.     *incend++ = "C:";                       /* Decus-C library disk */
  157.     *incend++ = "SY:";                      /* System (boot) disk   */
  158. #define MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  159. #endif
  160.     DBUG_VOID_RETURN;
  161. }
  162.  
  163. int
  164. dooptions(argc, argv)
  165. int        argc;
  166. char        *argv[];
  167. /*
  168.  * dooptions is called to process command line arguments (-Detc).
  169.  * It is called only at cpp startup.
  170.  */
  171. {
  172.     register char        *ap;
  173.     register DEFBUF     *dp;
  174.     register int        c;
  175.     int            i, j;
  176.     char            *arg;
  177.     SIZES            *sizp;        /* For -S        */
  178.     int            size;        /* For -S        */
  179.     int            isdatum;    /* FALSE for -S*    */
  180.     int            endtest;    /* For -S        */
  181.  
  182.     DBUG_ENTER ("dooptions");
  183.     for (i = j = 1; i < argc; i++) {
  184.         arg = ap = argv[i];
  185.         if (*ap++ != '-' || *ap == EOS)
  186.         argv[j++] = argv[i];
  187.         else {
  188.         c = *ap++;            /* Option byte        */
  189.         if (islower(c))                 /* Normalize case       */
  190.             c = toupper(c);
  191.         switch (c) {                    /* Command character    */
  192.         case 'C':                       /* Keep comments        */
  193.             cflag = TRUE;
  194.             keepcomments = TRUE;
  195.             break;
  196.  
  197.         case 'D':                       /* Define symbol        */
  198. #if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  199.             zap_uc(ap);                 /* Force define to U.C. */
  200. #endif
  201.             /*
  202.              * If the option is just "-Dfoo", make it -Dfoo=1
  203.              */
  204.             while (*ap != EOS && *ap != '=')
  205.             ap++;
  206.             if (*ap == EOS)
  207.             ap = "1";
  208.             else
  209.             *ap++ = EOS;
  210.             /*
  211.              * Now, save the word and its definition.
  212.              */
  213.             dp = defendel(argv[i] + 2, FALSE);
  214.             dp->repl = savestring(ap);
  215.             dp->nargs = DEF_NOARGS;
  216.             break;
  217.  
  218.         case 'E':                       /* Ignore non-fatal     */
  219.             eflag = TRUE;        /* errors.        */
  220.             break;
  221.  
  222.         case 'G':                       /* Cmpiler's debug switch */
  223.             break;
  224.  
  225.         case 'I':                       /* Include directory    */
  226.             if (incend >= &incdir[MAXINCLUDE])
  227.             cfatal("Too many include directories", NULLST);
  228.             *incend++ = ap;
  229.             break;
  230.  
  231.         case 'N':                       /* No predefineds       */
  232.             nflag++;            /* Repeat to undefine    */
  233.             break;            /* __LINE__, etc.    */
  234.  
  235.         case 'P':                       /* #line insertion      */
  236.             pflag = TRUE;
  237.             break;
  238.  
  239. #if OK_SIZEOF
  240.         case 'S':
  241.             sizp = size_table;
  242.             if (isdatum = (*ap != '*')) /* If it's just -S,     */
  243.             endtest = T_FPTR;    /* Stop here        */
  244.             else {            /* But if it's -S*      */
  245.             ap++;            /* Step over '*'        */
  246.             endtest = 0;        /* Stop at end marker    */
  247.             }
  248.             while (sizp->bits != endtest && *ap != EOS) {
  249.             if (!isdigit(*ap)) {    /* Skip to next digit   */
  250.                 ap++;
  251.                 continue;
  252.             }
  253.             size = 0;        /* Compile the value    */
  254.             while (isdigit(*ap)) {
  255.                 size *= 10;
  256.                 size += (*ap++ - '0');
  257.             }
  258.             if (isdatum)
  259.                 sizp->size = size;    /* Datum size        */
  260.             else
  261.                 sizp->psize = size; /* Pointer size     */
  262.             sizp++;
  263.             }
  264.             if (sizp->bits != endtest)
  265.             cwarn("-S, too few values specified in %s", argv[i]);
  266.             else if (*ap != EOS)
  267.             cwarn("-S, too many values, \"%s\" unused", ap);
  268.             break;
  269. #endif /* OK_SIZEOF */
  270.  
  271.         case 'U':                       /* Undefine symbol      */
  272. #if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  273.             zap_uc(ap);
  274. #endif
  275.             if (defendel(ap, TRUE) == NULL)
  276.             cwarn("\"%s\" wasn't defined", ap);
  277.             break;
  278.         case 'W':
  279.             wflag++;
  280.             break;
  281. #if DEBUG
  282.         case 'X':                       /* Debug                */
  283.             debug = (isdigit(*ap)) ? atoi(ap) : 1;
  284. #if (HOST == SYS_VMS || HOST == SYS_UNIX)
  285.             signal(SIGINT, abort);      /* Trap "interrupt"     */
  286. #endif
  287.             fprintf(stderr, "Debug set to %d\n", debug);
  288.             break;
  289. #endif
  290.  
  291.         default:            /* What is this one?    */
  292.             cwarn("Unknown option \"%s\"", arg);
  293. fprintf(stderr, "The following options are valid:\n");
  294. fprintf(stderr, "  -C\t\t\tWrite source file comments to output\n");
  295. fprintf(stderr, "  -Dsymbol=value");
  296. fprintf(stderr, "\tDefine a symbol with the given (optional) value\n");
  297. fprintf(stderr, "  -Idirectory");
  298. fprintf(stderr, "\t\tAdd a directory to the #include search list\n");
  299. fprintf(stderr, "  -N\t\t\tDon't predefine target-specific names\n");
  300. fprintf(stderr, "  -P\t\t\tDon't insert #line directives\n");
  301. fprintf(stderr, "  -Stext\t\tSpecify sizes for #if sizeof\n");
  302. fprintf(stderr, "  -Usymbol\t\tUndefine symbol\n");
  303. #if DEBUG
  304.             fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
  305. #endif
  306.             break;
  307.         }            /* Switch on all options    */
  308.         }                /* If it's a -option            */
  309.     }                /* For all arguments        */
  310.     if (j > 3) {
  311.         cerror(
  312.         "Too many file arguments.  Usage: cpp [input [output]]",
  313.         NULLST);
  314.     }
  315.     DBUG_RETURN (j);                        /* Return new argc              */
  316. }
  317.  
  318. #if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
  319. FILE_LOCAL
  320. zap_uc(ap)
  321. register char    *ap;
  322. /*
  323.  * Dec operating systems mangle upper-lower case in command lines.
  324.  * This routine forces the -D and -U arguments to uppercase.
  325.  * It is called only on cpp startup by dooptions().
  326.  */
  327. {
  328.     DBUG_ENTER ("zap_uc");
  329.     while (*ap != EOS) {
  330.         /*
  331.          * Don't use islower() here so it works with Multinational
  332.          */
  333.         if (*ap >= 'a' && *ap <= 'z')
  334.         *ap = toupper(*ap);
  335.         ap++;
  336.     }
  337.     DBUG_VOID_RETURN;
  338. }
  339. #endif
  340.  
  341. void
  342. initdefines()
  343. /*
  344.  * Initialize the built-in #define's.  There are two flavors:
  345.  *    #define decus    1        (static definitions)
  346.  *    #define __FILE__ ??        (dynamic, evaluated by magic)
  347.  * Called only on cpp startup.
  348.  *
  349.  * Note: the built-in static definitions are supressed by the -N option.
  350.  * __LINE__, __FILE__, __TIME__ and __DATE__ are always present.
  351.  */
  352. {
  353.     register char        **pp;
  354.     register char        *tp;
  355.     register DEFBUF     *dp;
  356.     register struct tm    *tm, *localtime();
  357.     int            i;
  358.     long            tvec;
  359.  
  360.     static char months[12][4] = {
  361.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  362.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  363.     };
  364.  
  365.     DBUG_ENTER ("initdefines");
  366.     DBUG_2 ("defs", "initialize built in defines");
  367.     /*
  368.      * Predefine the built-in symbols.  Allow the
  369.      * implementor to pre-define a symbol as "" to
  370.      * eliminate it.
  371.      */
  372.     if (nflag == 0) {
  373.         for (pp = preset; *pp != NULL; pp++) {
  374.         if (*pp[0] != EOS) {
  375.             dp = defendel(*pp, FALSE);
  376.             dp->repl = savestring("1");
  377.             dp->nargs = DEF_NOARGS;
  378.         }
  379.         }
  380.     }
  381.     /*
  382.      * The magic pre-defines (__FILE__ and __LINE__ are
  383.      * initialized with negative argument counts.  expand()
  384.      * notices this and calls the appropriate routine.
  385.      * DEF_NOARGS is one greater than the first "magic" definition.
  386.      */
  387.     if (nflag < 2) {
  388.         for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
  389.         dp = defendel(*pp, FALSE);
  390.         dp->nargs = --i;
  391.         }
  392. #if OK_DATE
  393.         /*
  394.          * Define __DATE__ as today's date.
  395.          */
  396.         dp = defendel("__DATE__", FALSE);
  397.         dp->repl = tp = getmem(14);
  398.         dp->nargs = DEF_NOARGS;
  399.         time(&tvec);
  400.         tm = localtime(&tvec);
  401.         sprintf(tp, "\"%3s %2d %4d\"",      /* "Aug 20 1988" */
  402.         months[tm->tm_mon],
  403.         tm->tm_mday,
  404.         tm->tm_year + 1900);
  405.  
  406.         /*
  407.          * Define __TIME__ as this moment's time.
  408.          */
  409.         dp = defendel("__TIME__", FALSE);
  410.         dp->repl = tp = getmem(11);
  411.         dp->nargs = DEF_NOARGS;
  412.         sprintf(tp, "\"%2d:%02d:%02d\"",    /* "20:42:31" */
  413.         tm->tm_hour,
  414.         tm->tm_min,
  415.         tm->tm_sec);
  416. #endif
  417.     }
  418.     DBUG_VOID_RETURN;
  419. }
  420.  
  421. void
  422. deldefines()
  423. /*
  424.  * Delete the built-in #define's.
  425.  */
  426. {
  427.     register char        **pp;
  428.     int            i;
  429.  
  430.  
  431.     DBUG_ENTER ("deldefines");
  432.     DBUG_2 ("deldefs", "delete built in defines");
  433.     /*
  434.      * Delete the built-in symbols, unless -WW.
  435.      */
  436.     if (wflag < 2) {
  437.         for (pp = preset; *pp != NULL; pp++) {
  438.         defendel(*pp, TRUE);
  439.         }
  440.     }
  441.     /*
  442.      * The magic pre-defines __FILE__ and __LINE__
  443.      */
  444.     for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
  445.         defendel(*pp, TRUE);
  446.     }
  447. #if OK_DATE
  448.     /*
  449.      * Undefine __DATE__.
  450.      */
  451.     defendel("__DATE__", TRUE);
  452.  
  453.     /*
  454.      * Undefine __TIME__.
  455.      */
  456.     defendel("__TIME__", TRUE);
  457. #endif
  458.     DBUG_VOID_RETURN;
  459. }
  460.  
  461. #if HOST == SYS_VMS
  462. /*
  463.  * getredirection() is intended to aid in porting C programs
  464.  * to VMS (Vax-11 C) which does not support '>' and '<'
  465.  * I/O redirection.  With suitable modification, it may
  466.  * useful for other portability problems as well.
  467.  */
  468.  
  469. int
  470. getredirection(argc, argv)
  471. int        argc;
  472. char        **argv;
  473. /*
  474.  * Process vms redirection arg's.  Exit if any error is seen.
  475.  * If getredirection() processes an argument, it is erased
  476.  * from the vector.  getredirection() returns a new argc value.
  477.  *
  478.  * Warning: do not try to simplify the code for vms.  The code
  479.  * presupposes that getredirection() is called before any data is
  480.  * read from stdin or written to stdout.
  481.  *
  482.  * Normal usage is as follows:
  483.  *
  484.  *    main(argc, argv)
  485.  *    int        argc;
  486.  *    char        *argv[];
  487.  *    {
  488.  *        argc = getredirection(argc, argv);
  489.  *    }
  490.  */
  491. {
  492.     register char        *ap;    /* Argument pointer    */
  493.     int            i;    /* argv[] index     */
  494.     int            j;    /* Output index     */
  495.     int            file;    /* File_descriptor    */
  496.     extern int        errno;    /* Last vms i/o error    */
  497.  
  498.     DBUG_ENTER ("getredirection");
  499.     for (j = i = 1; i < argc; i++) {   /* Do all arguments  */
  500.         switch (*(ap = argv[i])) {
  501.         case '<':                   /* <file                */
  502.         if (freopen(++ap, "r", stdin) == NULL) {
  503.             perror(ap);         /* Can't find file      */
  504.             exit(errno);        /* Is a fatal error     */
  505.         }
  506.         break;
  507.  
  508.         case '>':                   /* >file or >>file      */
  509.         if (*++ap == '>') {     /* >>file               */
  510.             /*
  511.              * If the file exists, and is writable by us,
  512.              * call freopen to append to the file (using the
  513.              * file's current attributes).  Otherwise, create
  514.              * a new file with "vanilla" attributes as if the
  515.              * argument was given as ">filename".
  516.              * access(name, 2) returns zero if we can write on
  517.              * the specified file.
  518.              */
  519.             if (access(++ap, 2) == 0) {
  520.             if (freopen(ap, "a", stdout) != NULL)
  521.                 break;    /* Exit case statement    */
  522.             perror(ap);     /* Error, can't append  */
  523.             exit(errno);    /* After access test    */
  524.             }            /* If file accessable    */
  525.         }
  526.         /*
  527.          * On vms, we want to create the file using "standard"
  528.          * record attributes.  creat(...) creates the file
  529.          * using the caller's default protection mask and
  530.          * "variable length, implied carriage return"
  531.          * attributes. dup2() associates the file with stdout.
  532.          */
  533.         if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  534.          || dup2(file, fileno(stdout)) == -1) {
  535.             perror(ap);         /* Can't create file    */
  536.             exit(errno);        /* is a fatal error     */
  537.         }            /* If '>' creation      */
  538.         break;            /* Exit case test    */
  539.  
  540.         default:
  541.         argv[j++] = ap;     /* Not a redirector    */
  542.         break;            /* Exit case test    */
  543.         }
  544.     }                /* For all arguments    */
  545.     argv[j] = NULL;         /* Terminate argv[]    */
  546.     DBUG_RETURN (j);                /* Return new argc      */
  547. }
  548. #endif
  549.  
  550.  
  551.