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