LCOV - code coverage report
Current view: top level - rsc/source/rscpp - cpp5.c (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 318 0.0 %
Date: 2014-04-14 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <stdio.h>
      21             : #include <ctype.h>
      22             : #include "cppdef.h"
      23             : #include "cpp.h"
      24             : 
      25             : /*
      26             :  * Evaluate an #if expression.
      27             :  */
      28             : 
      29             : static char *opname[] = {       /* For debug and error messages */
      30             : "end of expression", "val", "id",
      31             :   "+",   "-",  "*",  "/",  "%",
      32             :   "<<", ">>",  "&",  "|",  "^",
      33             :   "==", "!=",  "<", "<=", ">=",  ">",
      34             :   "&&", "||",  "?",  ":",  ",",
      35             :   "unary +", "unary -", "~", "!",  "(",  ")", "(none)",
      36             : };
      37             : 
      38             : /*
      39             :  * opdope[] has the operator precedence:
      40             :  *     Bits
      41             :  *    7 Unused (so the value is always positive)
      42             :  *  6-2 Precedence (000x .. 017x)
      43             :  *  1-0 Binary op. flags:
      44             :  *      01  The binop flag should be set/cleared when this op is seen.
      45             :  *      10  The new value of the binop flag.
      46             :  * Note:  Expected, New binop
      47             :  * constant 0   1   Binop, end, or ) should follow constants
      48             :  * End of line  1   0   End may not be preceeded by an operator
      49             :  * binary   1   0   Binary op follows a value, value follows.
      50             :  * unary    0   0   Unary op doesn't follow a value, value follows
      51             :  *   (      0   0   Doesn't follow value, value or unop follows
      52             :  *   )      1   1   Follows value.  Op follows.
      53             :  */
      54             : 
      55             : static char opdope[OP_MAX] = {
      56             :   0001,                 /* End of expression        */
      57             :   0002,                 /* Digit            */
      58             :   0000,                 /* Letter (identifier)      */
      59             :   0141, 0141, 0151, 0151, 0151,     /* ADD, SUB, MUL, DIV, MOD  */
      60             :   0131, 0131, 0101, 0071, 0071,     /* ASL, ASR, AND,  OR, XOR  */
      61             :   0111, 0111, 0121, 0121, 0121, 0121,   /*  EQ,  NE,  LT,  LE,  GE,  GT */
      62             :   0061, 0051, 0041, 0041, 0031,     /* ANA, ORO, QUE, COL, CMA  */
      63             : /*
      64             :  * Unary op's follow
      65             :  */
      66             :   0160, 0160, 0160, 0160,       /* NEG, PLU, COM, NOT       */
      67             :   0170, 0013, 0023,         /* LPA, RPA, END        */
      68             : };
      69             : /*
      70             :  * OP_QUE and OP_RPA have alternate precedences:
      71             :  */
      72             : #define OP_RPA_PREC 0013
      73             : #define OP_QUE_PREC 0034
      74             : 
      75             : /*
      76             :  * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
      77             :  *  #if FOO != 0 && 10 / FOO ...
      78             :  * doesn't generate an error message.  They are stored in optab.skip.
      79             :  */
      80             : #define S_ANDOR     2
      81             : #define S_QUEST     1
      82             : 
      83             : typedef struct optab {
      84             :     char    op;         /* Operator         */
      85             :     char    prec;           /* Its precedence       */
      86             :     char    skip;           /* Short-circuit: TRUE to skip  */
      87             : } OPTAB;
      88             : static int  evalue;         /* Current value from evallex() */
      89             : 
      90             : #ifdef  nomacargs
      91             : FILE_LOCAL int
      92             : isbinary(op)
      93             : register int    op;
      94             : {
      95             :     return (op >= FIRST_BINOP && op <= LAST_BINOP);
      96             : }
      97             : #else
      98             : #define isbinary(op)    (op >= FIRST_BINOP && op <= LAST_BINOP)
      99             : #endif
     100             : 
     101             : /*
     102             :  * The following definitions are used to specify basic variable sizes.
     103             :  */
     104             : 
     105             : #ifndef S_CHAR
     106             : #define S_CHAR      (sizeof (char))
     107             : #endif
     108             : #ifndef S_SINT
     109             : #define S_SINT      (sizeof (short int))
     110             : #endif
     111             : #ifndef S_INT
     112             : #define S_INT       (sizeof (int))
     113             : #endif
     114             : #ifndef S_LINT
     115             : #define S_LINT      (sizeof (long int))
     116             : #endif
     117             : #ifndef S_FLOAT
     118             : #define S_FLOAT     (sizeof (float))
     119             : #endif
     120             : #ifndef S_DOUBLE
     121             : #define S_DOUBLE    (sizeof (double))
     122             : #endif
     123             : #ifndef S_PCHAR
     124             : #define S_PCHAR     (sizeof (char *))
     125             : #endif
     126             : #ifndef S_PSINT
     127             : #define S_PSINT     (sizeof (short int *))
     128             : #endif
     129             : #ifndef S_PINT
     130             : #define S_PINT      (sizeof (int *))
     131             : #endif
     132             : #ifndef S_PLINT
     133             : #define S_PLINT     (sizeof (long int *))
     134             : #endif
     135             : #ifndef S_PFLOAT
     136             : #define S_PFLOAT    (sizeof (float *))
     137             : #endif
     138             : #ifndef S_PDOUBLE
     139             : #define S_PDOUBLE   (sizeof (double *))
     140             : #endif
     141             : #ifndef S_PFPTR
     142             : #define S_PFPTR     (sizeof (int (*)()))
     143             : #endif
     144             : 
     145             : typedef struct types {
     146             :     short   type;           /* This is the bit if       */
     147             :     char    *name;          /* this is the token word   */
     148             : } TYPES;
     149             : 
     150             : static TYPES basic_types[] = {
     151             :     { T_CHAR,   "char",     },
     152             :     { T_INT,    "int",      },
     153             :     { T_FLOAT,  "float",    },
     154             :     { T_DOUBLE, "double",   },
     155             :     { T_SHORT,  "short",    },
     156             :     { T_LONG,   "long",     },
     157             :     { T_SIGNED, "signed",   },
     158             :     { T_UNSIGNED,   "unsigned", },
     159             :     { 0,        NULL,       },  /* Signal end       */
     160             : };
     161             : 
     162             : /*
     163             :  * Test_table[] is used to test for illegal combinations.
     164             :  */
     165             : static short test_table[] = {
     166             :     T_FLOAT | T_DOUBLE | T_LONG | T_SHORT,
     167             :     T_FLOAT | T_DOUBLE | T_CHAR | T_INT,
     168             :     T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED,
     169             :     T_LONG  | T_SHORT  | T_CHAR,
     170             :     0                       /* end marker   */
     171             : };
     172             : 
     173             : /*
     174             :  * The order of this table is important -- it is also referenced by
     175             :  * the command line processor to allow run-time overriding of the
     176             :  * built-in size values.  The order must not be changed:
     177             :  *  char, short, int, long, float, double (func pointer)
     178             :  */
     179             : SIZES size_table[] = {
     180             :     { T_CHAR,   S_CHAR,     S_PCHAR     },  /* char     */
     181             :     { T_SHORT,  S_SINT,     S_PSINT     },  /* short int    */
     182             :     { T_INT,    S_INT,      S_PINT      },  /* int      */
     183             :     { T_LONG,   S_LINT,     S_PLINT     },  /* long     */
     184             :     { T_FLOAT,  S_FLOAT,    S_PFLOAT    },  /* float    */
     185             :     { T_DOUBLE, S_DOUBLE,   S_PDOUBLE   },  /* double   */
     186             :     { T_FPTR,   0,      S_PFPTR     },  /* int (*())    */
     187             :     { 0,    0,      0       },  /* End of table */
     188             : };
     189             : 
     190           0 : void InitCpp5()
     191             : {
     192             : 
     193           0 : }
     194             : 
     195             : 
     196             : 
     197             : int
     198           0 : eval()
     199             : /*
     200             :  * Evaluate an expression.  Straight-forward operator precedence.
     201             :  * This is called from control() on encountering an #if statement.
     202             :  * It calls the following routines:
     203             :  * evallex  Lexical analyser -- returns the type and value of
     204             :  *      the next input token.
     205             :  * evaleval Evaluate the current operator, given the values on
     206             :  *      the value stack.  Returns a pointer to the (new)
     207             :  *      value stack.
     208             :  * For compatiblity with older cpp's, this return returns 1 (TRUE)
     209             :  * if a syntax error is detected.
     210             :  */
     211             : {
     212             :     register int    op;     /* Current operator     */
     213             :     register int    *valp;      /* -> value vector      */
     214             :     register OPTAB  *opp;       /* Operator stack       */
     215             :     int     prec;       /* Op precedence        */
     216             :     int     binop;      /* Set if binary op. needed */
     217             :     int     op1;        /* Operand from stack       */
     218             :     int     skip;       /* For short-circuit testing    */
     219             :     int     value[NEXP];    /* Value stack          */
     220             :     OPTAB       opstack[NEXP];  /* Operand stack        */
     221             :     extern int  *evaleval();    /* Does actual evaluation   */
     222           0 :     valp = value;
     223           0 :     opp = opstack;
     224           0 :     opp->op = OP_END;       /* Mark bottom of stack     */
     225           0 :     opp->prec = opdope[OP_END]; /* And its precedence       */
     226           0 :     opp->skip = 0;          /* Not skipping now     */
     227           0 :     binop = 0;
     228             : again:  ;
     229             : #ifdef  DEBUG_EVAL
     230             :     fprintf( pCppOut, "In #if at again: skip = %d, binop = %d, line is: %s",
     231             :         opp->skip, binop, infile->bptr);
     232             : #endif
     233           0 :     if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
     234           0 :         op = OP_NEG;            /* Unary minus      */
     235           0 :     else if (op == OP_ADD && binop == 0)
     236           0 :         op = OP_PLU;            /* Unary plus       */
     237           0 :     else if (op == OP_FAIL)
     238           0 :         return (1);             /* Error in evallex */
     239             : #ifdef  DEBUG_EVAL
     240             :     fprintf( pCppOut, "op = %s, opdope = %03o, binop = %d, skip = %d\n",
     241             :         opname[op], opdope[op], binop, opp->skip);
     242             : #endif
     243           0 :     if (op == DIG) {            /* Value?       */
     244           0 :         if (binop != 0) {
     245           0 :         cerror("misplaced constant in #if", NULLST);
     246           0 :         return (1);
     247             :         }
     248           0 :         else if (valp >= &value[NEXP-1]) {
     249           0 :         cerror("#if value stack overflow", NULLST);
     250           0 :         return (1);
     251             :         }
     252             :         else {
     253             : #ifdef  DEBUG_EVAL
     254             :         fprintf( pCppOut, "pushing %d onto value stack[%d]\n",
     255             :             evalue, valp - value);
     256             : #endif
     257           0 :         *valp++ = evalue;
     258           0 :         binop = 1;
     259             :         }
     260           0 :         goto again;
     261             :     }
     262           0 :     else if (op > OP_END) {
     263           0 :         cerror("Illegal #if line", NULLST);
     264           0 :         return (1);
     265             :     }
     266           0 :     prec = opdope[op];
     267           0 :     if (binop != (prec & 1)) {
     268           0 :         cerror("Operator %s in incorrect context", opname[op]);
     269           0 :         return (1);
     270             :     }
     271           0 :     binop = (prec & 2) >> 1;
     272             :     for (;;) {
     273             : #ifdef  DEBUG_EVAL
     274             :         fprintf( pCppOut, "op %s, prec %d., stacked op %s, prec %d, skip %d\n",
     275             :         opname[op], prec, opname[opp->op], opp->prec, opp->skip);
     276             : #endif
     277           0 :         if (prec > opp->prec) {
     278           0 :         if (op == OP_LPA)
     279           0 :             prec = OP_RPA_PREC;
     280           0 :         else if (op == OP_QUE)
     281           0 :             prec = OP_QUE_PREC;
     282           0 :         op1 = opp->skip;        /* Save skip for test   */
     283             :         /*
     284             :          * Push operator onto op. stack.
     285             :          */
     286           0 :         opp++;
     287           0 :         if (opp >= &opstack[NEXP]) {
     288           0 :             cerror("expression stack overflow at op \"%s\"",
     289             :             opname[op]);
     290           0 :             return (1);
     291             :         }
     292           0 :         opp->op = (char)op;
     293           0 :         opp->prec = (char)prec;
     294           0 :         skip = (valp[-1] != 0);     /* Short-circuit tester */
     295             :         /*
     296             :          * Do the short-circuit stuff here.  Short-circuiting
     297             :          * stops automagically when operators are evaluated.
     298             :          */
     299           0 :         if ((op == OP_ANA && !skip)
     300           0 :          || (op == OP_ORO && skip))
     301           0 :             opp->skip = S_ANDOR;    /* And/or skip starts   */
     302           0 :         else if (op == OP_QUE)      /* Start of ?: operator */
     303           0 :             opp->skip = (char)((op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0));
     304           0 :         else if (op == OP_COL) {    /* : inverts S_QUEST    */
     305           0 :             opp->skip = (char)((op1 & S_ANDOR)
     306           0 :                   | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST));
     307             :         }
     308             :         else {              /* Other ops leave  */
     309           0 :             opp->skip = (char)op1;      /*  skipping unchanged. */
     310             :         }
     311             : #ifdef  DEBUG_EVAL
     312             :         fprintf( pCppOut, "stacking %s, valp[-1] == %d at %s",
     313             :             opname[op], valp[-1], infile->bptr);
     314             :         dumpstack(opstack, opp, value, valp);
     315             : #endif
     316           0 :         goto again;
     317             :         }
     318             :         /*
     319             :          * Pop operator from op. stack and evaluate it.
     320             :          * End of stack and '(' are specials.
     321             :          */
     322           0 :         skip = opp->skip;           /* Remember skip value  */
     323           0 :         switch ((op1 = opp->op)) {      /* Look at stacked op   */
     324             :         case OP_END:            /* Stack end marker */
     325           0 :         if (op == OP_EOE)
     326           0 :             return (valp[-1]);      /* Finished ok.     */
     327           0 :         goto again;         /* Read another op. */
     328             : 
     329             :         case OP_LPA:            /* ( on stack       */
     330           0 :         if (op != OP_RPA) {     /* Matches ) on input   */
     331           0 :             cerror("unbalanced paren's, op is \"%s\"", opname[op]);
     332           0 :             return (1);
     333             :         }
     334           0 :         opp--;              /* Unstack it       */
     335             :         /* goto again;          -- Fall through     */
     336             : 
     337             :         case OP_QUE:
     338           0 :         goto again;         /* Evaluate true expr.  */
     339             : 
     340             :         case OP_COL:            /* : on stack.      */
     341           0 :         opp--;              /* Unstack :        */
     342           0 :         if (opp->op != OP_QUE) {    /* Matches ? on stack?  */
     343           0 :             cerror("Misplaced '?' or ':', previous operator is %s",
     344           0 :                    opname[(int)opp->op]);
     345           0 :             return (1);
     346             :         }
     347             :         /*
     348             :          * Evaluate op1.
     349             :          */
     350             :         default:                /* Others:      */
     351           0 :         opp--;              /* Unstack the operator */
     352             : #ifdef  DEBUG_EVAL
     353             :         fprintf( pCppOut, "Stack before evaluation of %s\n", opname[op1]);
     354             :         dumpstack(opstack, opp, value, valp);
     355             : #endif
     356           0 :         valp = evaleval(valp, op1, skip);
     357             : #ifdef  DEBUG_EVAL
     358             :         fprintf( pCppOut, "Stack after evaluation\n");
     359             :         dumpstack(opstack, opp, value, valp);
     360             : #endif
     361             :         }                   /* op1 switch end   */
     362           0 :     }                   /* Stack unwind loop    */
     363             : }
     364             : 
     365             : FILE_LOCAL int
     366           0 : evallex(int skip)
     367             : /*
     368             :  * Return next eval operator or value.  Called from eval().  It
     369             :  * calls a special-purpose routines for 'char' strings and
     370             :  * numeric values:
     371             :  * evalchar called to evaluate 'x'
     372             :  * evalnum  called to evaluate numbers.
     373             :  */
     374             : {
     375             :     register int    c, c1, t;
     376             : 
     377             : again:  do {                    /* Collect the token    */
     378           0 :         c = skipws();
     379           0 :         if ((c = macroid(c)) == EOF_CHAR || c == '\n') {
     380           0 :         unget();
     381           0 :         return (OP_EOE);        /* End of expression    */
     382             :         }
     383           0 :     } while ((t = type[c]) == LET && catenate());
     384           0 :     if (t == INV) {             /* Total nonsense   */
     385           0 :         if (!skip) {
     386           0 :         if (isascii(c) && isprint(c))
     387           0 :             cierror("illegal character '%c' in #if", c);
     388             :         else
     389           0 :             cierror("illegal character (%d decimal) in #if", c);
     390             :         }
     391           0 :         return (OP_FAIL);
     392             :     }
     393           0 :     else if (t == QUO) {            /* ' or "       */
     394           0 :         if (c == '\'') {            /* Character constant   */
     395           0 :         evalue = evalchar(skip);    /* Somewhat messy   */
     396             : #ifdef  DEBUG_EVAL
     397             :         fprintf( pCppOut, "evalchar returns %d.\n", evalue);
     398             : #endif
     399           0 :         return (DIG);           /* Return a value   */
     400             :         }
     401           0 :         cerror("Can't use a string in an #if", NULLST);
     402           0 :         return (OP_FAIL);
     403             :     }
     404           0 :     else if (t == LET) {            /* ID must be a macro   */
     405           0 :         if (streq(token, "defined")) {  /* Or defined name  */
     406           0 :             c1 = c = skipws();
     407           0 :             if (c == '(')           /* Allow defined(name)  */
     408           0 :                 c = skipws();
     409           0 :             if (type[c] == LET) {
     410           0 :                 evalue = (lookid(c) != NULL);
     411           0 :                 if (c1 != '('       /* Need to balance  */
     412           0 :                     || skipws() == ')')    /* Did we balance?  */
     413           0 :                 return (DIG);       /* Parsed ok        */
     414             :             }
     415           0 :             cerror("Bad #if ... defined() syntax", NULLST);
     416           0 :             return (OP_FAIL);
     417             :         }
     418           0 :         else if (streq(token, "sizeof"))    /* New sizeof hackery   */
     419           0 :             return (dosizeof());        /* Gets own routine */
     420             :         /*
     421             :          * The Draft ANSI C Standard says that an undefined symbol
     422             :          * in an #if has the value zero.  We are a bit pickier,
     423             :          * warning except where the programmer was careful to write
     424             :          *      #if defined(foo) ? foo : 0
     425             :          */
     426             : #ifdef STRICT_UNDEF
     427             :         if (!skip)
     428             :             cwarn("undefined symbol \"%s\" in #if, 0 used", token);
     429             : #endif
     430           0 :         evalue = 0;
     431           0 :         return (DIG);
     432             :     }
     433           0 :     else if (t == DIG) {            /* Numbers are harder   */
     434           0 :         evalue = evalnum(c);
     435             : #ifdef  DEBUG_EVAL
     436             :         fprintf( pCppOut, "evalnum returns %d.\n", evalue);
     437             : #endif
     438             :     }
     439           0 :     else if (strchr("!=<>&|\\", c) != NULL) {
     440             :         /*
     441             :          * Process a possible multi-byte lexeme.
     442             :          */
     443           0 :         c1 = cget();            /* Peek at next char    */
     444           0 :         switch (c) {
     445             :         case '!':
     446           0 :         if (c1 == '=')
     447           0 :             return (OP_NE);
     448           0 :         break;
     449             : 
     450             :         case '=':
     451           0 :         if (c1 != '=') {        /* Can't say a=b in #if */
     452           0 :             unget();
     453           0 :             cerror("= not allowed in #if", NULLST);
     454           0 :             return (OP_FAIL);
     455             :         }
     456           0 :         return (OP_EQ);
     457             : 
     458             :         case '>':
     459             :         case '<':
     460           0 :         if (c1 == c)
     461           0 :             return ((c == '<') ? OP_ASL : OP_ASR);
     462           0 :         else if (c1 == '=')
     463           0 :             return ((c == '<') ? OP_LE  : OP_GE);
     464           0 :         break;
     465             : 
     466             :         case '|':
     467             :         case '&':
     468           0 :         if (c1 == c)
     469           0 :             return ((c == '|') ? OP_ORO : OP_ANA);
     470           0 :         break;
     471             : 
     472             :         case '\\':
     473           0 :         if (c1 == '\n')         /* Multi-line if    */
     474           0 :             goto again;
     475           0 :         cerror("Unexpected \\ in #if", NULLST);
     476           0 :         return (OP_FAIL);
     477             :         }
     478           0 :         unget();
     479             :     }
     480           0 :     return (t);
     481             : }
     482             : 
     483             : FILE_LOCAL int
     484           0 : dosizeof()
     485             : /*
     486             :  * Process the sizeof (basic type) operation in an #if string.
     487             :  * Sets evalue to the size and returns
     488             :  *  DIG     success
     489             :  *  OP_FAIL     bad parse or something.
     490             :  */
     491             : {
     492             :     register int    c;
     493             :     register TYPES  *tp;
     494             :     register SIZES  *sizp;
     495             :     register short  *testp;
     496             :     short       typecode;
     497             : 
     498           0 :     if ((c = skipws()) != '(')
     499           0 :         goto nogood;
     500             :     /*
     501             :      * Scan off the tokens.
     502             :      */
     503           0 :     typecode = 0;
     504           0 :     while (0 != (c = skipws())) {
     505           0 :         if ((c = macroid(c)) == EOF_CHAR || c == '\n')
     506             :             goto nogood;            /* End of line is a bug */
     507           0 :         else if (c == '(') {        /* thing (*)() func ptr */
     508           0 :             if (skipws() == '*'
     509           0 :              && skipws() == ')') {      /* We found (*)     */
     510           0 :                 if (skipws() != '(')    /* Let () be optional   */
     511           0 :                     unget();
     512           0 :                 else if (skipws() != ')')
     513           0 :                     goto nogood;
     514           0 :                 typecode |= T_FPTR;     /* Function pointer */
     515             :             }
     516             :             else {              /* Junk is a bug    */
     517             :                 goto nogood;
     518             :             }
     519             :         }
     520           0 :         else if (type[c] != LET)        /* Exit if not a type   */
     521           0 :             break;
     522           0 :         else if (!catenate()) {     /* Maybe combine tokens */
     523             :             /*
     524             :              * Look for this unexpandable token in basic_types.
     525             :              * The code accepts "int long" as well as "long int"
     526             :              * which is a minor bug as bugs go (and one shared with
     527             :              * a lot of C compilers).
     528             :              */
     529           0 :             for (tp = basic_types; tp->name != NULLST; tp++) {
     530           0 :                 if (streq(token, tp->name))
     531           0 :                 break;
     532             :             }
     533           0 :             if (tp->name == NULLST) {
     534           0 :                 cerror("#if sizeof, unknown type \"%s\"", token);
     535           0 :                 return (OP_FAIL);
     536             :             }
     537           0 :         typecode |= tp->type;       /* Or in the type bit   */
     538             :         }
     539             :     }
     540             :     /*
     541             :      * We are at the end of the type scan.  Chew off '*' if necessary.
     542             :      */
     543           0 :     if (c == '*') {
     544           0 :         typecode |= T_PTR;
     545           0 :         c = skipws();
     546             :     }
     547           0 :     if (c == ')') {             /* Last syntax check    */
     548           0 :         for (testp = test_table; *testp != 0; testp++) {
     549           0 :             if (!bittest(typecode & *testp)) {
     550           0 :                 cerror("#if ... sizeof: illegal type combination", NULLST);
     551           0 :                 return (OP_FAIL);
     552             :             }
     553             :         }
     554             :         /*
     555             :          * We assume that all function pointers are the same size:
     556             :          *      sizeof (int (*)()) == sizeof (float (*)())
     557             :          * We assume that signed and unsigned don't change the size:
     558             :          *      sizeof (signed int) == (sizeof unsigned int)
     559             :          */
     560           0 :         if ((typecode & T_FPTR) != 0)   /* Function pointer */
     561           0 :             typecode = T_FPTR | T_PTR;
     562             :         else {              /* Var or var * datum   */
     563           0 :             typecode &= ~(T_SIGNED | T_UNSIGNED);
     564           0 :             if ((typecode & (T_SHORT | T_LONG)) != 0)
     565           0 :                 typecode &= ~T_INT;
     566             :         }
     567           0 :         if ((typecode & ~T_PTR) == 0) {
     568           0 :             cerror("#if sizeof() error, no type specified", NULLST);
     569           0 :             return (OP_FAIL);
     570             :         }
     571             :         /*
     572             :          * Exactly one bit (and possibly T_PTR) may be set.
     573             :          */
     574           0 :         for (sizp = size_table; sizp->bits != 0; sizp++) {
     575           0 :             if ((typecode & ~T_PTR) == sizp->bits) {
     576           0 :                 evalue = ((typecode & T_PTR) != 0)
     577           0 :                 ? sizp->psize : sizp->size;
     578           0 :                 return (DIG);
     579             :             }
     580             :         }                   /* We shouldn't fail    */
     581           0 :         cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
     582           0 :         return (OP_FAIL);
     583             :     }
     584             : 
     585           0 : nogood: unget();
     586           0 :     cerror("#if ... sizeof() syntax error", NULLST);
     587           0 :     return (OP_FAIL);
     588             : }
     589             : 
     590             : FILE_LOCAL int
     591           0 : bittest(int value)
     592             : /*
     593             :  * TRUE if value is zero or exactly one bit is set in value.
     594             :  */
     595             : {
     596             : #if (4096 & ~(-4096)) == 0
     597           0 :     return ((value & ~(-value)) == 0);
     598             : #else
     599             :     /*
     600             :      * Do it the hard way (for non 2's complement machines)
     601             :      */
     602             :     return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
     603             : #endif
     604             : }
     605             : 
     606             : FILE_LOCAL int
     607           0 : evalnum(int c)
     608             : /*
     609             :  * Expand number for #if lexical analysis.  Note: evalnum recognizes
     610             :  * the unsigned suffix, but only returns a signed int value.
     611             :  */
     612             : {
     613             :     register int    value;
     614             :     register int    base;
     615             :     register int    c1;
     616             : 
     617           0 :     if (c != '0')
     618           0 :         base = 10;
     619           0 :     else if ((c = cget()) == 'x' || c == 'X') {
     620           0 :         base = 16;
     621           0 :         c = cget();
     622             :     }
     623           0 :     else base = 8;
     624           0 :     value = 0;
     625             :     for (;;) {
     626           0 :         c1 = c;
     627           0 :         if (isascii(c) && isupper(c1))
     628           0 :             c1 = tolower(c1);
     629             : #ifdef EBCDIC
     630             :         if (c1 <= 'f')
     631             : #else
     632           0 :         if (c1 >= 'a')
     633             : #endif
     634           0 :             c1 -= ('a' - 10);
     635           0 :         else c1 -= '0';
     636           0 :         if (c1 < 0 || c1 >= base)
     637             :             break;
     638           0 :         value *= base;
     639           0 :         value += c1;
     640           0 :         c = cget();
     641           0 :     }
     642           0 :     if (c == 'u' || c == 'U')   /* Unsigned nonsense        */
     643           0 :         cget();
     644           0 :     unget();
     645           0 :     return (value);
     646             : }
     647             : 
     648             : FILE_LOCAL int
     649           0 : evalchar(int skip)
     650             : /*
     651             :  * Get a character constant
     652             :  */
     653             : {
     654             :     register int    c;
     655             :     register int    value;
     656             :     register int    count;
     657             : 
     658           0 :     instring = TRUE;
     659           0 :     if ((c = cget()) == '\\') {
     660           0 :         switch ((c = cget())) {
     661             :         case 'a':               /* New in Standard  */
     662             : #if ('a' == '\a' || '\a' == ALERT)
     663           0 :         value = ALERT;          /* Use predefined value */
     664             : #else
     665             :         value = '\a';           /* Use compiler's value */
     666             : #endif
     667           0 :         break;
     668             : 
     669             :         case 'b':
     670           0 :         value = '\b';
     671           0 :         break;
     672             : 
     673             :         case 'f':
     674           0 :         value = '\f';
     675           0 :         break;
     676             : 
     677             :         case 'n':
     678           0 :         value = '\n';
     679           0 :         break;
     680             : 
     681             :         case 'r':
     682           0 :         value = '\r';
     683           0 :         break;
     684             : 
     685             :         case 't':
     686           0 :         value = '\t';
     687           0 :         break;
     688             : 
     689             :         case 'v':               /* New in Standard  */
     690             : #if ('v' == '\v' || '\v' == VT)
     691           0 :         value = VT;         /* Use predefined value */
     692             : #else
     693             :         value = '\v';           /* Use compiler's value */
     694             : #endif
     695           0 :         break;
     696             : 
     697             :         case 'x':               /* '\xFF'       */
     698           0 :         count = 3;
     699           0 :         value = 0;
     700           0 :         while ((((c = get()) >= '0' && c <= '9')
     701           0 :              || (c >= 'a' && c <= 'f')
     702           0 :              || (c >= 'A' && c <= 'F'))
     703           0 :             && (--count >= 0)) {
     704           0 :             value *= 16;
     705             : #ifdef EBCDIC
     706             :             value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9);
     707             : #else
     708           0 :             value += (c >= '0') ? (c - '0') : ((c & 0xF) + 9);
     709             : #endif
     710             :         }
     711           0 :         unget();
     712           0 :         break;
     713             : 
     714             :         default:
     715           0 :         if (c >= '0' && c <= '7') {
     716           0 :             count = 3;
     717           0 :             value = 0;
     718           0 :             while (c >= '0' && c <= '7' && --count >= 0) {
     719           0 :             value *= 8;
     720           0 :             value += (c - '0');
     721           0 :             c = get();
     722             :             }
     723           0 :             unget();
     724             :         }
     725           0 :         else value = c;
     726           0 :         break;
     727             :         }
     728             :     }
     729           0 :     else if (c == '\'')
     730           0 :         value = 0;
     731           0 :     else value = c;
     732             :     /*
     733             :      * We warn on multi-byte constants and try to hack
     734             :      * (big|little)endian machines.
     735             :      */
     736           0 :     while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n') {
     737           0 :         if (!skip)
     738           0 :             ciwarn("multi-byte constant '%c' isn't portable", c);
     739           0 :         value <<= BITS_CHAR;
     740           0 :         value += c;
     741             :     }
     742           0 :     instring = FALSE;
     743           0 :     return (value);
     744             : }
     745             : 
     746             : FILE_LOCAL int *
     747           0 : evaleval(int* valp, int op, int skip)
     748             : /*
     749             :  * Apply the argument operator to the data on the value stack.
     750             :  * One or two values are popped from the value stack and the result
     751             :  * is pushed onto the value stack.
     752             :  *
     753             :  * OP_COL is a special case.
     754             :  *
     755             :  * evaleval() returns the new pointer to the top of the value stack.
     756             :  */
     757             : {
     758           0 :     register int    v1, v2 = 0;
     759             : 
     760           0 :     if (isbinary(op))
     761           0 :         v2 = *--valp;
     762           0 :     v1 = *--valp;
     763             : #ifdef  DEBUG_EVAL
     764             :     fprintf( pCppOut, "%s op %s", (isbinary(op)) ? "binary" : "unary",
     765             :         opname[op]);
     766             :     if (isbinary(op))
     767             :         fprintf( pCppOut, ", v2 = %d.", v2);
     768             :     fprintf( pCppOut, ", v1 = %d.\n", v1);
     769             : #endif
     770           0 :     switch (op) {
     771             :     case OP_EOE:
     772           0 :          break;
     773             : 
     774             :     case OP_ADD:
     775           0 :         v1 += v2;
     776           0 :         break;
     777             : 
     778             :     case OP_SUB:
     779           0 :         v1 -= v2;
     780           0 :         break;
     781             : 
     782             :     case OP_MUL:
     783           0 :         v1 *= v2;
     784           0 :         break;
     785             : 
     786             :     case OP_DIV:
     787             :     case OP_MOD:
     788           0 :         if (v2 == 0) {
     789           0 :             if (!skip) {
     790           0 :                 cwarn("%s by zero in #if, zero result assumed",
     791             :                 (op == OP_DIV) ? "divide" : "mod");
     792             :             }
     793           0 :             v1 = 0;
     794             :         }
     795           0 :         else if (op == OP_DIV)
     796           0 :             v1 /= v2;
     797             :         else
     798           0 :             v1 %= v2;
     799           0 :         break;
     800             : 
     801             :     case OP_ASL:
     802           0 :         v1 <<= v2;
     803           0 :         break;
     804             : 
     805             :     case OP_ASR:
     806           0 :         v1 >>= v2;
     807           0 :         break;
     808             : 
     809             :     case OP_AND:
     810           0 :         v1 &= v2;
     811           0 :         break;
     812             : 
     813             :     case OP_OR:
     814           0 :         v1 |= v2;
     815           0 :         break;
     816             : 
     817             :     case OP_XOR:
     818           0 :         v1 ^= v2;
     819           0 :         break;
     820             : 
     821             :     case OP_EQ:
     822           0 :         v1 = (v1 == v2);
     823           0 :         break;
     824             : 
     825             :     case OP_NE:
     826           0 :         v1 = (v1 != v2);
     827           0 :         break;
     828             : 
     829             :     case OP_LT:
     830           0 :         v1 = (v1 < v2);
     831           0 :         break;
     832             : 
     833             :     case OP_LE:
     834           0 :         v1 = (v1 <= v2);
     835           0 :         break;
     836             : 
     837             :     case OP_GE:
     838           0 :         v1 = (v1 >= v2);
     839           0 :         break;
     840             : 
     841             :     case OP_GT:
     842           0 :         v1 = (v1 > v2);
     843           0 :         break;
     844             : 
     845             :     case OP_ANA:
     846           0 :         v1 = (v1 && v2);
     847           0 :         break;
     848             : 
     849             :     case OP_ORO:
     850           0 :         v1 = (v1 || v2);
     851           0 :         break;
     852             : 
     853             :     case OP_COL:
     854             :         /*
     855             :          * v1 has the "true" value, v2 the "false" value.
     856             :          * The top of the value stack has the test.
     857             :          */
     858           0 :         v1 = (*--valp) ? v1 : v2;
     859           0 :         break;
     860             : 
     861             :     case OP_NEG:
     862           0 :         v1 = (-v1);
     863           0 :         break;
     864             : 
     865             :     case OP_PLU:
     866           0 :         break;
     867             : 
     868             :     case OP_COM:
     869           0 :         v1 = ~v1;
     870           0 :         break;
     871             : 
     872             :     case OP_NOT:
     873           0 :         v1 = !v1;
     874           0 :         break;
     875             : 
     876             :     default:
     877           0 :         cierror("#if bug, operand = %d.", op);
     878           0 :         v1 = 0;
     879             :     }
     880           0 :     *valp++ = v1;
     881           0 :     return (valp);
     882             : }
     883             : 
     884             : #ifdef  DEBUG_EVAL
     885             : dumpstack(opstack, opp, value, valp)
     886             : OPTAB       opstack[NEXP];  /* Operand stack        */
     887             : register OPTAB  *opp;       /* Operator stack       */
     888             : int     value[NEXP];    /* Value stack          */
     889             : register int    *valp;      /* -> value vector      */
     890             : {
     891             :     fprintf( pCppOut, "index op prec skip name -- op stack at %s", infile->bptr);
     892             :     while (opp > opstack) {
     893             :         fprintf( pCppOut, " [%2d] %2d  %03o    %d %s\n", opp - opstack,
     894             :         opp->op, opp->prec, opp->skip, opname[opp->op]);
     895             :         opp--;
     896             :     }
     897             :     while (--valp >= value) {
     898             :         fprintf( pCppOut, "value[%d] = %d\n", (valp - value), *valp);
     899             :     }
     900             : }
     901             : #endif
     902             : 
     903             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10