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