LCOV - code coverage report
Current view: top level - rsc/source/rscpp - cpp5.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 118 318 37.1 %
Date: 2012-08-25 Functions: 5 8 62.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 276 27.2 %

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

Generated by: LCOV version 1.10