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