LCOV - code coverage report
Current view: top level - workdir/unxlngi6.pro/CustomTarget/ucpp/source - eval.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 40 315 12.7 %
Date: 2012-08-25 Functions: 5 12 41.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 19 587 3.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * (c) Thomas Pornin 1999 - 2002
       3                 :            :  *
       4                 :            :  * Redistribution and use in source and binary forms, with or without
       5                 :            :  * modification, are permitted provided that the following conditions
       6                 :            :  * are met:
       7                 :            :  * 1. Redistributions of source code must retain the above copyright
       8                 :            :  *    notice, this list of conditions and the following disclaimer.
       9                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      10                 :            :  *    notice, this list of conditions and the following disclaimer in the
      11                 :            :  *    documentation and/or other materials provided with the distribution.
      12                 :            :  * 4. The name of the authors may not be used to endorse or promote
      13                 :            :  *    products derived from this software without specific prior written
      14                 :            :  *    permission.
      15                 :            :  *
      16                 :            :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
      17                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      18                 :            :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      19                 :            :  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
      20                 :            :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      21                 :            :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
      22                 :            :  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
      23                 :            :  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      24                 :            :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
      25                 :            :  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
      26                 :            :  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27                 :            :  *
      28                 :            :  */
      29                 :            : 
      30                 :            : #include "tune.h"
      31                 :            : #include <stdio.h>
      32                 :            : #include <string.h>
      33                 :            : #include <setjmp.h>
      34                 :            : #include <limits.h>
      35                 :            : #include "ucppi.h"
      36                 :            : #include "mem.h"
      37                 :            : 
      38                 :            : JMP_BUF eval_exception;
      39                 :            : long eval_line;
      40                 :            : static int emit_eval_warnings;
      41                 :            : 
      42                 :            : /*
      43                 :            :  * If you want to hardcode a conversion table, define a static array
      44                 :            :  * of 256 int, and make transient_characters point to it.
      45                 :            :  */
      46                 :            : int *transient_characters = 0;
      47                 :            : 
      48                 :            : #define OCTAL(x)       ((x) >= '0' && (x) <= '7')
      49                 :            : #define DECIM(x)       ((x) >= '0' && (x) <= '9')
      50                 :            : #define HEXAD(x)       (DECIM(x) \
      51                 :            :                        || (x) == 'a' || (x) == 'b' || (x) == 'c' \
      52                 :            :                        || (x) == 'd' || (x) == 'e' || (x) == 'f' \
      53                 :            :                        || (x) == 'A' || (x) == 'B' || (x) == 'C' \
      54                 :            :                        || (x) == 'D' || (x) == 'E' || (x) == 'F')
      55                 :            : #define OVAL(x)        ((int)((x) - '0'))
      56                 :            : #define DVAL(x)        ((int)((x) - '0'))
      57                 :            : #define HVAL(x)        (DECIM(x) ? DVAL(x) \
      58                 :            :                        : (x) == 'a' || (x) == 'A' ? 10 \
      59                 :            :                        : (x) == 'b' || (x) == 'B' ? 11 \
      60                 :            :                        : (x) == 'c' || (x) == 'C' ? 12 \
      61                 :            :                        : (x) == 'd' || (x) == 'D' ? 13 \
      62                 :            :                        : (x) == 'e' || (x) == 'E' ? 14 : 15)
      63                 :            : 
      64                 :            : #define ARITH_TYPENAME             big
      65                 :            : #define ARITH_FUNCTION_HEADER      static inline
      66                 :            : 
      67                 :            : #define ARITH_ERROR(type)          z_error(type)
      68                 :            : static void z_error(int type);
      69                 :            : 
      70                 :            : #ifdef ARITHMETIC_CHECKS
      71                 :            : #define ARITH_WARNING(type)        z_warn(type)
      72                 :            : static void z_warn(int type);
      73                 :            : #endif
      74                 :            : 
      75                 :            : #include "arith.c"
      76                 :            : 
      77                 :          0 : static void z_error(int type)
      78                 :            : {
      79   [ #  #  #  #  :          0 :         switch (type) {
                      # ]
      80                 :            :         case ARITH_EXCEP_SLASH_D:
      81                 :          0 :                 error(eval_line, "division by 0");
      82                 :          0 :                 break;
      83                 :            :         case ARITH_EXCEP_SLASH_O:
      84                 :          0 :                 error(eval_line, "overflow on division");
      85                 :          0 :                 break;
      86                 :            :         case ARITH_EXCEP_PCT_D:
      87                 :          0 :                 error(eval_line, "division by 0 on modulus operator");
      88                 :          0 :                 break;
      89                 :            :         case ARITH_EXCEP_CONST_O:
      90                 :          0 :                 error(eval_line, "constant too large for destination type");
      91                 :          0 :                 break;
      92                 :            : #ifdef AUDIT
      93                 :            :         default:
      94                 :            :                 ouch("erroneous integer error: %d", type);
      95                 :            : #endif
      96                 :            :         }
      97                 :          0 :         throw(eval_exception);
      98                 :            : }
      99                 :            : 
     100                 :            : #ifdef ARITHMETIC_CHECKS
     101                 :          0 : static void z_warn(int type)
     102                 :            : {
     103   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     104                 :            :         case ARITH_EXCEP_CONV_O:
     105                 :          0 :                 warning(eval_line, "overflow on integer conversion");
     106                 :          0 :                 break;
     107                 :            :         case ARITH_EXCEP_NEG_O:
     108                 :          0 :                 warning(eval_line, "overflow on unary minus");
     109                 :          0 :                 break;
     110                 :            :         case ARITH_EXCEP_NOT_T:
     111                 :          0 :                 warning(eval_line,
     112                 :            :                         "bitwise inversion yields trap representation");
     113                 :          0 :                 break;
     114                 :            :         case ARITH_EXCEP_PLUS_O:
     115                 :          0 :                 warning(eval_line, "overflow on addition");
     116                 :          0 :                 break;
     117                 :            :         case ARITH_EXCEP_PLUS_U:
     118                 :          0 :                 warning(eval_line, "underflow on addition");
     119                 :          0 :                 break;
     120                 :            :         case ARITH_EXCEP_MINUS_O:
     121                 :          0 :                 warning(eval_line, "overflow on subtraction");
     122                 :          0 :                 break;
     123                 :            :         case ARITH_EXCEP_MINUS_U:
     124                 :          0 :                 warning(eval_line, "underflow on subtraction");
     125                 :          0 :                 break;
     126                 :            :         case ARITH_EXCEP_AND_T:
     127                 :          0 :                 warning(eval_line,
     128                 :            :                         "bitwise AND yields trap representation");
     129                 :          0 :                 break;
     130                 :            :         case ARITH_EXCEP_XOR_T:
     131                 :          0 :                 warning(eval_line,
     132                 :            :                         "bitwise XOR yields trap representation");
     133                 :          0 :                 break;
     134                 :            :         case ARITH_EXCEP_OR_T:
     135                 :          0 :                 warning(eval_line,
     136                 :            :                         "bitwise OR yields trap representation");
     137                 :          0 :                 break;
     138                 :            :         case ARITH_EXCEP_LSH_W:
     139                 :          0 :                 warning(eval_line, "left shift count greater than "
     140                 :            :                         "or equal to type width");
     141                 :          0 :                 break;
     142                 :            :         case ARITH_EXCEP_LSH_C:
     143                 :          0 :                 warning(eval_line, "left shift count negative");
     144                 :          0 :                 break;
     145                 :            :         case ARITH_EXCEP_LSH_O:
     146                 :          0 :                 warning(eval_line, "overflow on left shift");
     147                 :          0 :                 break;
     148                 :            :         case ARITH_EXCEP_RSH_W:
     149                 :          0 :                 warning(eval_line, "right shift count greater than "
     150                 :            :                         "or equal to type width");
     151                 :          0 :                 break;
     152                 :            :         case ARITH_EXCEP_RSH_C:
     153                 :          0 :                 warning(eval_line, "right shift count negative");
     154                 :          0 :                 break;
     155                 :            :         case ARITH_EXCEP_RSH_N:
     156                 :          0 :                 warning(eval_line, "right shift of negative value");
     157                 :          0 :                 break;
     158                 :            :         case ARITH_EXCEP_STAR_O:
     159                 :          0 :                 warning(eval_line, "overflow on multiplication");
     160                 :          0 :                 break;
     161                 :            :         case ARITH_EXCEP_STAR_U:
     162                 :          0 :                 warning(eval_line, "underflow on multiplication");
     163                 :          0 :                 break;
     164                 :            : #ifdef AUDIT
     165                 :            :         default:
     166                 :            :                 ouch("erroneous integer warning: %d", type);
     167                 :            : #endif
     168                 :            :         }
     169                 :          0 : }
     170                 :            : #endif
     171                 :            : 
     172                 :            : typedef struct {
     173                 :            :         int sign;
     174                 :            :         union {
     175                 :            :                 u_big uv;
     176                 :            :                 s_big sv;
     177                 :            :         } u;
     178                 :            : } ppval;
     179                 :            : 
     180                 :          2 : static int boolval(ppval x)
     181                 :            : {
     182         [ +  - ]:          2 :         return x.sign ? big_s_lval(x.u.sv) : big_u_lval(x.u.uv);
     183                 :            : }
     184                 :            : 
     185                 :            : #if !defined(WCHAR_SIGNEDNESS)
     186                 :            : #  if CHAR_MIN == 0
     187                 :            : #    define WCHAR_SIGNEDNESS    0
     188                 :            : #  else
     189                 :            : #    define WCHAR_SIGNEDNESS    1
     190                 :            : #  endif
     191                 :            : #endif
     192                 :            : 
     193                 :            : /*
     194                 :            :  * Check the suffix, return 1 if it is signed, 0 otherwise. 1 is
     195                 :            :  * returned for a void suffix. Legal suffixes are:
     196                 :            :  * unsigned: u U ul uL Ul UL lu Lu lU LU ull uLL Ull ULL llu LLu llU LLU
     197                 :            :  * signed: l L ll LL
     198                 :            :  */
     199                 :          2 : static int pp_suffix(char *d, char *refc)
     200                 :            : {
     201         [ +  - ]:          2 :         if (!*d) return 1;
     202 [ #  # ][ #  # ]:          0 :         if (*d == 'u' || *d == 'U') {
     203         [ #  # ]:          0 :                 if (!*(++ d)) return 0;
     204 [ #  # ][ #  # ]:          0 :                 if (*d == 'l' || *d == 'L') {
     205                 :          0 :                         char *e = d + 1;
     206                 :            : 
     207 [ #  # ][ #  # ]:          0 :                         if (*e && *e != *d) goto suffix_error;
     208 [ #  # ][ #  # ]:          0 :                         if (!*e || !*(e + 1)) return 0;
     209                 :          0 :                         goto suffix_error;
     210                 :            :                 }
     211                 :          0 :                 goto suffix_error;
     212                 :            :         }
     213 [ #  # ][ #  # ]:          0 :         if (*d == 'l' || *d == 'L') {
     214         [ #  # ]:          0 :                 if (!*(++ d)) return 1;
     215         [ #  # ]:          0 :                 if (*d == *(d - 1)) {
     216                 :          0 :                         d ++;
     217         [ #  # ]:          0 :                         if (!*d) return 1;
     218                 :            :                 }
     219 [ #  # ][ #  # ]:          0 :                 if (*d == 'u' || *d == 'U') {
     220                 :          0 :                         d ++;
     221         [ #  # ]:          0 :                         if (!*d) return 0;
     222                 :            :                 }
     223                 :          0 :                 goto suffix_error;
     224                 :            :         }
     225                 :            : suffix_error:
     226                 :          0 :         error(eval_line, "invalid integer constant '%s'", refc);
     227                 :          2 :         throw(eval_exception);
     228                 :            :         return 666;
     229                 :            : }
     230                 :            : 
     231                 :          0 : static unsigned long pp_char(char *c, char *refc)
     232                 :            : {
     233                 :          0 :         unsigned long r = 0;
     234                 :            : 
     235                 :          0 :         c ++;
     236         [ #  # ]:          0 :         if (*c == '\\') {
     237                 :            :                 int i;
     238                 :            : 
     239                 :          0 :                 c ++;
     240   [ #  #  #  #  :          0 :                 switch (*c) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     241                 :          0 :                 case 'n': r = '\n'; c ++; break;
     242                 :          0 :                 case 't': r = '\t'; c ++; break;
     243                 :          0 :                 case 'v': r = '\v'; c ++; break;
     244                 :          0 :                 case 'b': r = '\b'; c ++; break;
     245                 :          0 :                 case 'r': r = '\r'; c ++; break;
     246                 :          0 :                 case 'f': r = '\f'; c ++; break;
     247                 :          0 :                 case 'a': r = '\a'; c ++; break;
     248                 :          0 :                 case '\\': r = '\\'; c ++; break;
     249                 :          0 :                 case '\?': r = '\?'; c ++; break;
     250                 :          0 :                 case '\'': r = '\''; c ++; break;
     251                 :          0 :                 case '\"': r = '\"'; c ++; break;
     252                 :            :                 case 'u':
     253 [ #  # ][ #  # ]:          0 :                         for (i = 0, c ++; i < 4 && HEXAD(*c); i ++, c ++) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     254 [ #  # ][ #  # ]:          0 :                                 r = (r * 16) + HVAL(*c);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     255                 :            :                         }
     256         [ #  # ]:          0 :                         if (i != 4) {
     257                 :          0 :                                 error(eval_line, "malformed UCN in %s", refc);
     258                 :          0 :                                 throw(eval_exception);
     259                 :            :                         }
     260                 :          0 :                         break;
     261                 :            :                 case 'U':
     262 [ #  # ][ #  # ]:          0 :                         for (i = 0, c ++; i < 8 && HEXAD(*c); i ++, c ++) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     263 [ #  # ][ #  # ]:          0 :                                 r = (r * 16) + HVAL(*c);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     264                 :            :                         }
     265         [ #  # ]:          0 :                         if (i != 8) {
     266                 :          0 :                                 error(eval_line, "malformed UCN in %s", refc);
     267                 :          0 :                                 throw(eval_exception);
     268                 :            :                         }
     269                 :          0 :                         break;
     270                 :            :                 case 'x':
     271 [ #  # ][ #  # ]:          0 :                         for (c ++; HEXAD(*c); c ++) r = (r * 16) + HVAL(*c);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     272                 :          0 :                         break;
     273                 :            :                 default:
     274 [ #  # ][ #  # ]:          0 :                         if (OCTAL(*c)) {
     275                 :          0 :                                 r = OVAL(*(c ++));
     276 [ #  # ][ #  # ]:          0 :                                 if (OCTAL(*c)) r = (r * 8) + OVAL(*(c ++));
     277 [ #  # ][ #  # ]:          0 :                                 if (OCTAL(*c)) r = (r * 8) + OVAL(*(c ++));
     278                 :            :                         } else {
     279                 :          0 :                                 error(eval_line, "invalid escape sequence "
     280                 :          0 :                                         "'\\%c'", *c);
     281                 :          0 :                                 throw(eval_exception);
     282                 :            :                         }
     283                 :            :                 }
     284         [ #  # ]:          0 :         } else if (*c == '\'') {
     285                 :          0 :                 error(eval_line, "empty character constant");
     286                 :          0 :                 throw(eval_exception);
     287                 :            :         } else {
     288                 :          0 :                 r = *((unsigned char *)(c ++));
     289                 :            :         }
     290                 :            : 
     291 [ #  # ][ #  # ]:          0 :         if (transient_characters && r < 256) {
     292                 :          0 :                 r = transient_characters[(size_t)r];
     293                 :            :         }
     294                 :            : 
     295 [ #  # ][ #  # ]:          0 :         if (*c != '\'' && emit_eval_warnings) {
     296                 :          0 :                 warning(eval_line, "multicharacter constant");
     297                 :            :         }
     298                 :          0 :         return r;
     299                 :            : }
     300                 :            : 
     301                 :          2 : static ppval pp_strtoconst(char *refc)
     302                 :            : {
     303                 :            :         ppval q;
     304                 :          2 :         char *c = refc, *d;
     305                 :            :         u_big ru;
     306                 :            :         s_big rs;
     307                 :            :         int sp, dec;
     308                 :            : 
     309 [ +  - ][ -  + ]:          2 :         if (*c == '\'' || *c == 'L') {
     310                 :          0 :                 q.sign = (*c == 'L') ? WCHAR_SIGNEDNESS : 1;
     311 [ #  # ][ #  # ]:          0 :                 if (*c == 'L' && *(++ c) != '\'') {
     312                 :          0 :                         error(eval_line,
     313                 :            :                                 "invalid wide character constant: %s", refc);
     314                 :          0 :                         throw(eval_exception);
     315                 :            :                 }
     316         [ #  # ]:          0 :                 if (q.sign) {
     317                 :          0 :                         q.u.sv = big_s_fromlong(pp_char(c, refc));
     318                 :            :                 } else {
     319                 :          0 :                         q.u.uv = big_u_fromulong(pp_char(c, refc));
     320                 :            :                 }
     321                 :          0 :                 return q;
     322                 :            :         }
     323         [ +  - ]:          2 :         if (*c == '0') {
     324                 :            :                 /* octal or hexadecimal */
     325                 :          2 :                 dec = 0;
     326                 :          2 :                 c ++;
     327 [ +  - ][ -  + ]:          2 :                 if (*c == 'x' || *c == 'X') {
     328                 :          0 :                         c ++;
     329                 :          0 :                         d = big_u_hexconst(c, &ru, &rs, &sp);
     330                 :            :                 } else {
     331                 :          2 :                         d = big_u_octconst(c, &ru, &rs, &sp);
     332                 :            :                 }
     333                 :            :         } else {
     334                 :          0 :                 dec = 1;
     335                 :          0 :                 d = big_u_decconst(c, &ru, &rs, &sp);
     336                 :            :         }
     337                 :          2 :         q.sign = pp_suffix(d, refc);
     338         [ +  - ]:          2 :         if (q.sign) {
     339         [ -  + ]:          2 :                 if (!sp) {
     340         [ #  # ]:          0 :                         if (dec) {
     341                 :          0 :                                 error(eval_line, "constant too large "
     342                 :            :                                         "for destination type");
     343                 :          0 :                                 throw(eval_exception);
     344                 :            :                         } else {
     345                 :          0 :                                 warning(eval_line, "constant is so large "
     346                 :            :                                         "that it is unsigned");
     347                 :            :                         }
     348                 :          0 :                         q.u.uv = ru;
     349                 :          0 :                         q.sign = 0;
     350                 :            :                 } else {
     351                 :          2 :                         q.u.sv = rs;
     352                 :            :                 }
     353                 :            :         } else {
     354                 :          0 :                 q.u.uv = ru;
     355                 :            :         }
     356                 :          2 :         return q;
     357                 :            : }
     358                 :            : 
     359                 :            : /*
     360                 :            :  * Used by #line directives -- anything beyond what can be put in an
     361                 :            :  * unsigned long, is considered absurd.
     362                 :            :  */
     363                 :          0 : unsigned long strtoconst(char *c)
     364                 :            : {
     365                 :          0 :         ppval q = pp_strtoconst(c);
     366                 :            : 
     367         [ #  # ]:          0 :         if (q.sign) q.u.uv = big_s_to_u(q.u.sv);
     368                 :          0 :         return big_u_toulong(q.u.uv);
     369                 :            : }
     370                 :            : 
     371                 :            : #define OP_UN(x)        ((x) == LNOT || (x) == NOT || (x) == UPLUS \
     372                 :            :                         || (x) == UMINUS)
     373                 :            : 
     374                 :          0 : static ppval eval_opun(int op, ppval v)
     375                 :            : {
     376         [ #  # ]:          0 :         if (op == LNOT) {
     377                 :          0 :                 v.sign = 1;
     378                 :          0 :                 v.u.sv = big_s_fromint(big_s_lnot(v.u.sv));
     379                 :          0 :                 return v;
     380                 :            :         }
     381         [ #  # ]:          0 :         if (v.sign) {
     382   [ #  #  #  # ]:          0 :                 switch (op) {
     383                 :          0 :                 case NOT: v.u.sv = big_s_not(v.u.sv); break;
     384                 :          0 :                 case UPLUS: break;
     385                 :          0 :                 case UMINUS: v.u.sv = big_s_neg(v.u.sv); break;
     386                 :            :                 }
     387                 :            :         } else {
     388   [ #  #  #  # ]:          0 :                 switch (op) {
     389                 :          0 :                 case NOT: v.u.uv = big_u_not(v.u.uv); break;
     390                 :          0 :                 case UPLUS: break;
     391                 :          0 :                 case UMINUS: v.u.uv = big_u_neg(v.u.uv); break;
     392                 :            :                 }
     393                 :            :         }
     394                 :          0 :         return v;
     395                 :            : }
     396                 :            : 
     397                 :            : #define OP_BIN(x)      ((x) == STAR || (x) == SLASH || (x) == PCT \
     398                 :            :                        || (x) == PLUS || (x) == MINUS || (x) == LSH \
     399                 :            :                        || (x) == RSH || (x) == LT || (x) == LEQ \
     400                 :            :                        || (x) == GT || (x) == GEQ || (x) == SAME \
     401                 :            :                        || (x) == NEQ || (x) == AND || (x) == CIRC \
     402                 :            :                        || (x) == OR || (x) == LAND || (x) == LOR \
     403                 :            :                        || (x) == COMMA)
     404                 :            : 
     405                 :          0 : static ppval eval_opbin(int op, ppval v1, ppval v2)
     406                 :            : {
     407                 :            :         ppval r;
     408                 :          0 :         int iv2 = 0;
     409                 :            : 
     410   [ #  #  #  #  :          0 :         switch (op) {
                   #  # ]
     411                 :            :         case STAR:      case SLASH:     case PCT:
     412                 :            :         case PLUS:      case MINUS:     case AND:
     413                 :            :         case CIRC:      case OR:
     414                 :            :                 /* promote operands, adjust signedness of result */
     415 [ #  # ][ #  # ]:          0 :                 if (!v1.sign || !v2.sign) {
     416         [ #  # ]:          0 :                         if (v1.sign) {
     417                 :          0 :                                 v1.u.uv = big_s_to_u(v1.u.sv);
     418                 :          0 :                                 v1.sign = 0;
     419         [ #  # ]:          0 :                         } else if (v2.sign) {
     420                 :          0 :                                 v2.u.uv = big_s_to_u(v2.u.sv);
     421                 :          0 :                                 v2.sign = 0;
     422                 :            :                         }
     423                 :          0 :                         r.sign = 0;
     424                 :            :                 } else {
     425                 :          0 :                         r.sign = 1;
     426                 :            :                 }
     427                 :          0 :                 break;
     428                 :            :         case LT:        case LEQ:       case GT:
     429                 :            :         case GEQ:       case SAME:      case NEQ:
     430                 :            :                 /* promote operands */
     431 [ #  # ][ #  # ]:          0 :                 if (!v1.sign || !v2.sign) {
     432         [ #  # ]:          0 :                         if (v1.sign) {
     433                 :          0 :                                 v1.u.uv = big_s_to_u(v1.u.sv);
     434                 :          0 :                                 v1.sign = 0;
     435         [ #  # ]:          0 :                         } else if (v2.sign) {
     436                 :          0 :                                 v2.u.uv = big_s_to_u(v2.u.sv);
     437                 :          0 :                                 v2.sign = 0;
     438                 :            :                         }
     439                 :            :                 }
     440                 :            :                 /* fall through */
     441                 :            :         case LAND:
     442                 :            :         case LOR:
     443                 :            :                 /* result is signed anyway */
     444                 :          0 :                 r.sign = 1;
     445                 :          0 :                 break;
     446                 :            :         case LSH:
     447                 :            :         case RSH:
     448                 :            :                 /* result is as signed as left operand; convert right
     449                 :            :                    operand to int */
     450                 :          0 :                 r.sign = v1.sign;
     451         [ #  # ]:          0 :                 if (v2.sign) {
     452                 :          0 :                         iv2 = big_s_toint(v2.u.sv);
     453                 :            :                 } else {
     454                 :          0 :                         iv2 = big_u_toint(v2.u.uv);
     455                 :            :                 }
     456                 :          0 :                 break;
     457                 :            :         case COMMA:
     458         [ #  # ]:          0 :                 if (emit_eval_warnings) {
     459                 :          0 :                         warning(eval_line, "ISO C forbids evaluated comma "
     460                 :            :                                 "operators in #if expressions");
     461                 :            :                 }
     462                 :          0 :                 r.sign = v2.sign;
     463                 :          0 :                 break;
     464                 :            : #ifdef AUDIT
     465                 :            :         default: ouch("a good operator is a dead operator");
     466                 :            : #endif
     467                 :            :         }
     468                 :            : 
     469                 :            : #define SBINOP(x)       if (r.sign) r.u.sv = big_s_ ## x (v1.u.sv, v2.u.sv); \
     470                 :            :                         else r.u.uv = big_u_ ## x (v1.u.uv, v2.u.uv);
     471                 :            : 
     472                 :            : #define NSSBINOP(x)     if (v1.sign) r.u.sv = big_s_fromint(big_s_ ## x \
     473                 :            :                         (v1.u.sv, v2.u.sv)); else r.u.sv = big_s_fromint( \
     474                 :            :                         big_u_ ## x (v1.u.uv, v2.u.uv));
     475                 :            : 
     476                 :            : #define LBINOP(x)       if (v1.sign) r.u.sv = big_s_fromint( \
     477                 :            :                         big_s_lval(v1.u.sv) x big_s_lval(v2.u.sv)); \
     478                 :            :                         else r.u.sv = big_s_fromint( \
     479                 :            :                         big_u_lval(v1.u.uv) x big_u_lval(v2.u.uv));
     480                 :            : 
     481                 :            : #define ABINOP(x)       if (r.sign) r.u.sv = big_s_ ## x (v1.u.sv, iv2); \
     482                 :            :                         else r.u.uv = big_u_ ## x (v1.u.uv, iv2);
     483                 :            : 
     484   [ #  #  #  #  :          0 :         switch (op) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     485         [ #  # ]:          0 :         case STAR: SBINOP(star); break;
     486         [ #  # ]:          0 :         case SLASH: SBINOP(slash); break;
     487         [ #  # ]:          0 :         case PCT: SBINOP(pct); break;
     488         [ #  # ]:          0 :         case PLUS: SBINOP(plus); break;
     489         [ #  # ]:          0 :         case MINUS: SBINOP(minus); break;
     490         [ #  # ]:          0 :         case LSH: ABINOP(lsh); break;
     491         [ #  # ]:          0 :         case RSH: ABINOP(rsh); break;
     492         [ #  # ]:          0 :         case LT: NSSBINOP(lt); break;
     493         [ #  # ]:          0 :         case LEQ: NSSBINOP(leq); break;
     494         [ #  # ]:          0 :         case GT: NSSBINOP(gt); break;
     495         [ #  # ]:          0 :         case GEQ: NSSBINOP(geq); break;
     496         [ #  # ]:          0 :         case SAME: NSSBINOP(same); break;
     497         [ #  # ]:          0 :         case NEQ: NSSBINOP(neq); break;
     498         [ #  # ]:          0 :         case AND: SBINOP(and); break;
     499         [ #  # ]:          0 :         case CIRC: SBINOP(xor); break;
     500         [ #  # ]:          0 :         case OR: SBINOP(or); break;
     501 [ #  # ][ #  # ]:          0 :         case LAND: LBINOP(&&); break;
         [ #  # ][ #  # ]
                 [ #  # ]
     502 [ #  # ][ #  # ]:          0 :         case LOR: LBINOP(||); break;
         [ #  # ][ #  # ]
                 [ #  # ]
     503                 :          0 :         case COMMA: r = v2; break;
     504                 :            :         }
     505                 :          0 :         return r;
     506                 :            : }
     507                 :            : 
     508                 :            : #define ttOP(x)         (OP_UN(x) || OP_BIN(x) || (x) == QUEST || (x) == COLON)
     509                 :            : 
     510                 :          0 : static int op_prec(int op)
     511                 :            : {
     512   [ #  #  #  #  :          0 :         switch (op) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     513                 :            :         case LNOT:
     514                 :            :         case NOT:
     515                 :            :         case UPLUS:
     516                 :            :         case UMINUS:
     517                 :          0 :                 return 13;
     518                 :            :         case STAR:
     519                 :            :         case SLASH:
     520                 :            :         case PCT:
     521                 :          0 :                 return 12;
     522                 :            :         case PLUS:
     523                 :            :         case MINUS:
     524                 :          0 :                 return 11;
     525                 :            :         case LSH:
     526                 :            :         case RSH:
     527                 :          0 :                 return 10;
     528                 :            :         case LT:
     529                 :            :         case LEQ:
     530                 :            :         case GT:
     531                 :            :         case GEQ:
     532                 :          0 :                 return 9;
     533                 :            :         case SAME:
     534                 :            :         case NEQ:
     535                 :          0 :                 return 8;
     536                 :            :         case AND:
     537                 :          0 :                 return 7;
     538                 :            :         case CIRC:
     539                 :          0 :                 return 6;
     540                 :            :         case OR:
     541                 :          0 :                 return 5;
     542                 :            :         case LAND:
     543                 :          0 :                 return 4;
     544                 :            :         case LOR:
     545                 :          0 :                 return 3;
     546                 :            :         case QUEST:
     547                 :          0 :                 return 2;
     548                 :            :         case COMMA:
     549                 :          0 :                 return 1;
     550                 :            :         }
     551                 :            : #ifdef AUDIT
     552                 :            :         ouch("an unknown species should have a higher precedence");
     553                 :            : #endif
     554                 :          0 :         return 666;
     555                 :            : }
     556                 :            : 
     557                 :            : /*
     558                 :            :  * Perform the hard work of evaluation.
     559                 :            :  *
     560                 :            :  * This function works because:
     561                 :            :  * -- all unary operators are right to left associative, and with
     562                 :            :  *    identical precedence
     563                 :            :  * -- all binary operators are left to right associative
     564                 :            :  * -- there is only one non-unary and non-binary operator: the quest-colon
     565                 :            :  *
     566                 :            :  * If do_eval is 0, the evaluation of operators is not done. This is
     567                 :            :  * for sequence point operators (&&, || and ?:).
     568                 :            :  */
     569                 :          2 : static ppval eval_shrd(struct token_fifo *tf, int minprec, int do_eval)
     570                 :            : {
     571                 :            :         ppval top;
     572                 :            :         struct token *ct;
     573                 :            : 
     574                 :          2 :         top.sign = 1;
     575         [ -  + ]:          2 :         if (tf->art == tf->nt) goto trunc_err;
     576                 :          2 :         ct = tf->t + (tf->art ++);
     577         [ -  + ]:          2 :         if (ct->type == LPAR) {
     578                 :          0 :                 top = eval_shrd(tf, 0, do_eval);
     579         [ #  # ]:          0 :                 if (tf->art == tf->nt) goto trunc_err;
     580                 :          0 :                 ct = tf->t + (tf->art ++);
     581         [ #  # ]:          0 :                 if (ct->type != RPAR) {
     582                 :          0 :                         error(eval_line, "a right parenthesis was expected");
     583                 :          0 :                         throw(eval_exception);
     584                 :            :                 }
     585 [ -  + ][ #  # ]:          2 :         } else if (ct->type == NUMBER || ct->type == CHAR) {
     586                 :          2 :                 top = pp_strtoconst(ct->name);
     587 [ #  # ][ #  # ]:          0 :         } else if (OP_UN(ct->type)) {
         [ #  # ][ #  # ]
     588                 :          0 :                 top = eval_opun(ct->type, eval_shrd(tf,
     589                 :            :                         op_prec(ct->type), do_eval));
     590                 :          0 :                 goto eval_loop;
     591 [ #  # ][ #  # ]:          0 :         } else if (ttOP(ct->type)) goto rogue_op_err;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     592                 :            :         else {
     593                 :            :                 goto invalid_token_err;
     594                 :            :         }
     595                 :            : 
     596                 :            : eval_loop:
     597         [ +  - ]:          2 :         if (tf->art == tf->nt) {
     598                 :          2 :                 return top;
     599                 :            :         }
     600                 :          0 :         ct = tf->t + (tf->art ++);
     601 [ #  # ][ #  # ]:          0 :         if (OP_BIN(ct->type)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     602                 :          0 :                 int bp = op_prec(ct->type);
     603                 :            : 
     604         [ #  # ]:          0 :                 if (bp > minprec) {
     605                 :            :                         ppval tr;
     606                 :            : 
     607 [ #  # ][ #  # ]:          0 :                         if ((ct->type == LOR && boolval(top))
     608 [ #  # ][ #  # ]:          0 :                                 || (ct->type == LAND && !boolval(top))) {
     609                 :          0 :                                 tr = eval_shrd(tf, bp, 0);
     610         [ #  # ]:          0 :                                 if (do_eval) {
     611                 :          0 :                                         top.sign = 1;
     612         [ #  # ]:          0 :                                         if (ct->type == LOR)
     613                 :          0 :                                                 top.u.sv = big_s_fromint(1);
     614         [ #  # ]:          0 :                                         if (ct->type == LAND)
     615                 :          0 :                                                 top.u.sv = big_s_fromint(0);
     616                 :            :                                 }
     617                 :            :                         } else {
     618                 :          0 :                                 tr = eval_shrd(tf, bp, do_eval);
     619         [ #  # ]:          0 :                                 if (do_eval)
     620                 :          0 :                                         top = eval_opbin(ct->type, top, tr);
     621                 :            :                         }
     622                 :            :                         goto eval_loop;
     623                 :            :                 }
     624         [ #  # ]:          0 :         } else if (ct->type == QUEST) {
     625                 :          0 :                 int bp = op_prec(QUEST);
     626                 :            :                 ppval r1, r2;
     627                 :            : 
     628         [ #  # ]:          0 :                 if (bp >= minprec) {
     629                 :          0 :                         int qv = boolval(top);
     630                 :            : 
     631         [ #  # ]:          0 :                         r1 = eval_shrd(tf, bp, qv ? do_eval : 0);
     632         [ #  # ]:          0 :                         if (tf->art == tf->nt) goto trunc_err;
     633                 :          0 :                         ct = tf->t + (tf->art ++);
     634         [ #  # ]:          0 :                         if (ct->type != COLON) {
     635                 :          0 :                                 error(eval_line, "a colon was expected");
     636                 :          0 :                                 throw(eval_exception);
     637                 :            :                         }
     638         [ #  # ]:          0 :                         r2 = eval_shrd(tf, bp, qv ? 0 : do_eval);
     639         [ #  # ]:          0 :                         if (do_eval) {
     640         [ #  # ]:          0 :                                 if (qv) top = r1; else top = r2;
     641                 :            :                         }
     642                 :            :                         goto eval_loop;
     643                 :            :                 }
     644                 :            :         }
     645                 :          0 :         tf->art --;
     646                 :          0 :         return top;
     647                 :            : 
     648                 :            : trunc_err:
     649                 :          0 :         error(eval_line, "truncated constant integral expression");
     650                 :          0 :         throw(eval_exception);
     651                 :            : rogue_op_err:
     652                 :          0 :         error(eval_line, "rogue operator '%s' in constant integral "
     653                 :          0 :                 "expression", operators_name[ct->type]);
     654                 :          0 :         throw(eval_exception);
     655                 :            : invalid_token_err:
     656                 :          0 :         error(eval_line, "invalid token in constant integral expression");
     657                 :          2 :         throw(eval_exception);
     658                 :            : }
     659                 :            : 
     660                 :            : #define UNARY(x)        ((x) != NUMBER && (x) != NAME && (x) != CHAR \
     661                 :            :                         && (x) != RPAR)
     662                 :            : 
     663                 :            : /*
     664                 :            :  * Evaluate the integer expression contained in the given token_fifo.
     665                 :            :  * Evaluation is made by precedence of operators, as described in the
     666                 :            :  * Dragon Book. The unary + and - are distinguished from their binary
     667                 :            :  * counterparts using the Fortran way: a + or a - is considered unary
     668                 :            :  * if it does not follow a constant, an identifier or a right parenthesis.
     669                 :            :  */
     670                 :          2 : unsigned long eval_expr(struct token_fifo *tf, int *ret, int ew)
     671                 :            : {
     672                 :            :         size_t sart;
     673                 :            :         ppval r;
     674                 :            : 
     675                 :          2 :         emit_eval_warnings = ew;
     676         [ -  + ]:          2 :         if (catch(eval_exception)) goto eval_err;
     677                 :            :         /* first, distinguish unary + and - from binary + and - */
     678         [ +  + ]:          4 :         for (sart = tf->art; tf->art < tf->nt; tf->art ++) {
     679         [ -  + ]:          2 :                 if (tf->t[tf->art].type == PLUS) {
     680 [ #  # ][ #  # ]:          0 :                         if (sart == tf->art || UNARY(tf->t[tf->art - 1].type))
         [ #  # ][ #  # ]
                 [ #  # ]
     681                 :          0 :                                 tf->t[tf->art].type = UPLUS;
     682         [ -  + ]:          2 :                 } else if (tf->t[tf->art].type == MINUS) {
     683 [ #  # ][ #  # ]:          0 :                         if (sart == tf->art || UNARY(tf->t[tf->art - 1].type))
         [ #  # ][ #  # ]
                 [ #  # ]
     684                 :          0 :                                 tf->t[tf->art].type = UMINUS;
     685                 :            :                 }
     686                 :            :         }
     687                 :          2 :         tf->art = sart;
     688                 :          2 :         r = eval_shrd(tf, 0, 1);
     689         [ -  + ]:          2 :         if (tf->art < tf->nt) {
     690                 :          0 :                 error(eval_line, "trailing garbage in constant integral "
     691                 :            :                         "expression");
     692                 :          0 :                 goto eval_err;
     693                 :            :         }
     694                 :          2 :         *ret = 0;
     695                 :          2 :         return boolval(r);
     696                 :            : eval_err:
     697                 :          0 :         *ret = 1;
     698                 :          2 :         return 0;
     699                 :            : }

Generated by: LCOV version 1.10