home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / motasm / motasmdoc / cpp / c / cpp3 < prev    next >
Encoding:
Text File  |  1995-09-06  |  15.8 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.