LCOV - code coverage report
Current view: top level - soltools/cpp - _eval.c (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 90 301 29.9 %
Date: 2015-06-13 12:38:46 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "cpp.h"
      21             : 
      22             : #define NSTAK   32
      23             : #define SGN 0
      24             : #define UNS 1
      25             : #define UND 2
      26             : 
      27             : #define UNSMARK 0x1000
      28             : 
      29             : struct value
      30             : {
      31             :     long val;
      32             :     int type;
      33             : };
      34             : 
      35             : /* conversion types */
      36             : #define RELAT   1
      37             : #define ARITH   2
      38             : #define LOGIC   3
      39             : #define SPCL    4
      40             : #define SHIFT   5
      41             : #define UNARY   6
      42             : 
      43             : /* operator priority, arity, and conversion type, indexed by tokentype */
      44             : struct pri
      45             : {
      46             :     char pri;
      47             :     char arity;
      48             :     char ctype;
      49             : }   priority[] =
      50             : 
      51             : {
      52             :     {
      53             :         0, 0, 0
      54             :     },                                  /* END */
      55             :     {
      56             :         0, 0, 0
      57             :     },                                  /* UNCLASS */
      58             :     {
      59             :         0, 0, 0
      60             :     },                                  /* NAME */
      61             :     {
      62             :         0, 0, 0
      63             :     },                                  /* NUMBER */
      64             :     {
      65             :         0, 0, 0
      66             :     },                                  /* STRING */
      67             :     {
      68             :         0, 0, 0
      69             :     },                                  /* CCON */
      70             :     {
      71             :         0, 0, 0
      72             :     },                                  /* NL */
      73             :     {
      74             :         0, 0, 0
      75             :     },                                  /* WS */
      76             :     {
      77             :         0, 0, 0
      78             :     },                                  /* DSHARP */
      79             :     {
      80             :         11, 2, RELAT
      81             :     },                                  /* EQ */
      82             :     {
      83             :         11, 2, RELAT
      84             :     },                                  /* NEQ */
      85             :     {
      86             :         12, 2, RELAT
      87             :     },                                  /* LEQ */
      88             :     {
      89             :         12, 2, RELAT
      90             :     },                                  /* GEQ */
      91             :     {
      92             :         13, 2, SHIFT
      93             :     },                                  /* LSH */
      94             :     {
      95             :         13, 2, SHIFT
      96             :     },                                  /* RSH */
      97             :     {
      98             :         7, 2, LOGIC
      99             :     },                                  /* LAND */
     100             :     {
     101             :         6, 2, LOGIC
     102             :     },                                  /* LOR */
     103             :     {
     104             :         0, 0, 0
     105             :     },                                  /* PPLUS */
     106             :     {
     107             :         0, 0, 0
     108             :     },                                  /* MMINUS */
     109             :     {
     110             :         0, 0, 0
     111             :     },                                  /* ARROW */
     112             :     {
     113             :         0, 0, 0
     114             :     },                                  /* SBRA */
     115             :     {
     116             :         0, 0, 0
     117             :     },                                  /* SKET */
     118             :     {
     119             :         3, 0, 0
     120             :     },                                  /* LP */
     121             :     {
     122             :         3, 0, 0
     123             :     },                                  /* RP */
     124             :     {
     125             :         0, 0, 0
     126             :     },                                  /* DOT */
     127             :     {
     128             :         10, 2, ARITH
     129             :     },                                  /* AND */
     130             :     {
     131             :         15, 2, ARITH
     132             :     },                                  /* STAR */
     133             :     {
     134             :         14, 2, ARITH
     135             :     },                                  /* PLUS */
     136             :     {
     137             :         14, 2, ARITH
     138             :     },                                  /* MINUS */
     139             :     {
     140             :         16, 1, UNARY
     141             :     },                                  /* TILDE */
     142             :     {
     143             :         16, 1, UNARY
     144             :     },                                  /* NOT */
     145             :     {
     146             :         15, 2, ARITH
     147             :     },                                  /* SLASH */
     148             :     {
     149             :         15, 2, ARITH
     150             :     },                                  /* PCT */
     151             :     {
     152             :         12, 2, RELAT
     153             :     },                                  /* LT */
     154             :     {
     155             :         12, 2, RELAT
     156             :     },                                  /* GT */
     157             :     {
     158             :         9, 2, ARITH
     159             :     },                                  /* CIRC */
     160             :     {
     161             :         8, 2, ARITH
     162             :     },                                  /* OR */
     163             :     {
     164             :         5, 2, SPCL
     165             :     },                                  /* QUEST */
     166             :     {
     167             :         5, 2, SPCL
     168             :     },                                  /* COLON */
     169             :     {
     170             :         0, 0, 0
     171             :     },                                  /* ASGN */
     172             :     {
     173             :         4, 2, 0
     174             :     },                                  /* COMMA */
     175             :     {
     176             :         0, 0, 0
     177             :     },                                  /* SHARP */
     178             :     {
     179             :         0, 0, 0
     180             :     },                                  /* SEMIC */
     181             :     {
     182             :         0, 0, 0
     183             :     },                                  /* CBRA */
     184             :     {
     185             :         0, 0, 0
     186             :     },                                  /* CKET */
     187             :     {
     188             :         0, 0, 0
     189             :     },                                  /* ASPLUS */
     190             :     {
     191             :         0, 0, 0
     192             :     },                                  /* ASMINUS */
     193             :     {
     194             :         0, 0, 0
     195             :     },                                  /* ASSTAR */
     196             :     {
     197             :         0, 0, 0
     198             :     },                                  /* ASSLASH */
     199             :     {
     200             :         0, 0, 0
     201             :     },                                  /* ASPCT */
     202             :     {
     203             :         0, 0, 0
     204             :     },                                  /* ASCIRC */
     205             :     {
     206             :         0, 0, 0
     207             :     },                                  /* ASLSH */
     208             :     {
     209             :         0, 0, 0
     210             :     },                                  /* ASRSH */
     211             :     {
     212             :         0, 0, 0
     213             :     },                                  /* ASOR */
     214             :     {
     215             :         0, 0, 0
     216             :     },                                  /* ASAND */
     217             :     {
     218             :         0, 0, 0
     219             :     },                                  /* ELLIPS */
     220             :     {
     221             :         0, 0, 0
     222             :     },                                  /* DSHARP1 */
     223             :     {
     224             :         0, 0, 0
     225             :     },                                  /* NAME1 */
     226             :     {
     227             :         0, 0, 0
     228             :     },                                  /* NAME2 */
     229             :     {
     230             :         16, 1, UNARY
     231             :     },                                  /* DEFINED */
     232             :     {
     233             :         16, 0, UNARY
     234             :     },                                  /* UMINUS */
     235             :     {
     236             :         16, 1, UNARY
     237             :     },                                  /* ARCHITECTURE */
     238             : };
     239             : 
     240             : int evalop(struct pri);
     241             : struct value tokval(Token *);
     242             : struct value vals[NSTAK], *vp;
     243             : enum toktype ops[NSTAK], *op;
     244             : 
     245             : /*
     246             :  * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword.
     247             :  */
     248             : long
     249        1170 :     eval(Tokenrow * trp, int kw)
     250             : {
     251             :     Token *tp;
     252             :     Nlist *np;
     253             :     size_t  ntok;
     254             :     int rnd;
     255             : 
     256        1170 :     trp->tp++;
     257        1170 :     if (kw == KIFDEF || kw == KIFNDEF)
     258             :     {
     259         790 :         if (trp->lp - trp->bp != 4 || trp->tp->type != NAME)
     260             :         {
     261           0 :             error(ERROR, "Syntax error in #ifdef/#ifndef");
     262           0 :             return 0;
     263             :         }
     264         790 :         np = lookup(trp->tp, 0);
     265         790 :         return (kw == KIFDEF) == (np && np->flag & (ISDEFINED | ISMAC));
     266             :     }
     267         380 :     ntok = trp->tp - trp->bp;
     268         380 :     kwdefined->val = KDEFINED;          /* activate special meaning of
     269             :                                          * defined */
     270         380 :     expandrow(trp, "<if>");
     271         380 :     kwdefined->val = NAME;
     272         380 :     vp = vals;
     273         380 :     op = ops;
     274         380 :     *op++ = END;
     275        1800 :     for (rnd = 0, tp = trp->bp + ntok; tp < trp->lp; tp++)
     276             :     {
     277        1420 :         switch (tp->type)
     278             :         {
     279             :             case WS:
     280             :             case NL:
     281         380 :                 continue;
     282             : 
     283             :                 /* nilary */
     284             :             case NAME:
     285             :             case NAME1:
     286             :             case NAME2:
     287             :             case NUMBER:
     288             :             case CCON:
     289             :             case STRING:
     290         415 :                 if (rnd)
     291           0 :                     goto syntax;
     292         415 :                 *vp++ = tokval(tp);
     293         415 :                 rnd = 1;
     294         415 :                 continue;
     295             : 
     296             :                 /* unary */
     297             :             case DEFINED:
     298             :             case TILDE:
     299             :             case NOT:
     300         442 :                 if (rnd)
     301           0 :                     goto syntax;
     302         442 :                 *op++ = tp->type;
     303         442 :                 continue;
     304             : 
     305             :                 /* unary-binary */
     306             :             case PLUS:
     307             :             case MINUS:
     308             :             case STAR:
     309             :             case AND:
     310           0 :                 if (rnd == 0)
     311             :                 {
     312           0 :                     if (tp->type == MINUS)
     313           0 :                         *op++ = UMINUS;
     314           0 :                     if (tp->type == STAR || tp->type == AND)
     315             :                     {
     316           0 :                         error(ERROR, "Illegal operator * or & in #if/#elif");
     317           0 :                         return 0;
     318             :                     }
     319           0 :                     continue;
     320             :                 }
     321             :                 /* flow through */
     322             : 
     323             :                 /* plain binary */
     324             :             case EQ:
     325             :             case NEQ:
     326             :             case LEQ:
     327             :             case GEQ:
     328             :             case LSH:
     329             :             case RSH:
     330             :             case LAND:
     331             :             case LOR:
     332             :             case SLASH:
     333             :             case PCT:
     334             :             case LT:
     335             :             case GT:
     336             :             case CIRC:
     337             :             case OR:
     338             :             case QUEST:
     339             :             case COLON:
     340             :             case COMMA:
     341          35 :                 if (rnd == 0)
     342           0 :                     goto syntax;
     343          35 :                 if (evalop(priority[tp->type]) != 0)
     344           0 :                     return 0;
     345          35 :                 *op++ = tp->type;
     346          35 :                 rnd = 0;
     347          35 :                 continue;
     348             : 
     349             :             case LP:
     350          74 :                 if (rnd)
     351           0 :                     goto syntax;
     352          74 :                 *op++ = LP;
     353          74 :                 continue;
     354             : 
     355             :             case RP:
     356          74 :                 if (!rnd)
     357           0 :                     goto syntax;
     358          74 :                 if (evalop(priority[RP]) != 0)
     359           0 :                     return 0;
     360          74 :                 if (op <= ops || op[-1] != LP)
     361             :                 {
     362             :                     goto syntax;
     363             :                 }
     364          74 :                 op--;
     365          74 :                 continue;
     366             : 
     367             :             case SHARP:
     368           0 :                 if ((tp + 1) < trp->lp)
     369             :                 {
     370           0 :                     np = lookup(tp + 1, 0);
     371           0 :                     if (np && (np->val == KMACHINE))
     372             :                     {
     373           0 :                         tp++;
     374           0 :                         if (rnd)
     375           0 :                             goto syntax;
     376           0 :                         *op++ = ARCHITECTURE;
     377           0 :                         continue;
     378             :                     }
     379             :                 }
     380             :                 /* fall through */
     381             : 
     382             :             default:
     383           0 :                 error(ERROR, "Bad operator (%t) in #if/#elif", tp);
     384           0 :                 return 0;
     385             :         }
     386             :     }
     387         380 :     if (rnd == 0)
     388           0 :         goto syntax;
     389         380 :     if (evalop(priority[END]) != 0)
     390           0 :         return 0;
     391         380 :     if (op != &ops[1] || vp != &vals[1])
     392             :     {
     393           0 :         error(ERROR, "Botch in #if/#elif");
     394           0 :         return 0;
     395             :     }
     396         380 :     if (vals[0].type == UND)
     397           0 :         error(ERROR, "Undefined expression value");
     398         380 :     return vals[0].val;
     399             : syntax:
     400           0 :     error(ERROR, "Syntax error in #if/#elif");
     401           0 :     return 0;
     402             : }
     403             : 
     404             : int
     405         489 :     evalop(struct pri pri)
     406             : {
     407             :     struct value v1;
     408         489 :     struct value v2 = { 0, UND };
     409             :     long rv1, rv2;
     410             :     int rtype, oper;
     411             : 
     412         489 :     rv2 = 0;
     413         489 :     rtype = 0;
     414        1455 :     while (pri.pri < priority[op[-1]].pri)
     415             :     {
     416         477 :         oper = *--op;
     417         477 :         if (priority[oper].arity == 2)
     418             :         {
     419          35 :             v2 = *--vp;
     420          35 :             rv2 = v2.val;
     421             :         }
     422         477 :         v1 = *--vp;
     423         477 :         rv1 = v1.val;
     424             : /*lint -e574 -e644 */
     425         477 :         switch (priority[oper].ctype)
     426             :         {
     427             :             case 0:
     428             :             default:
     429           0 :                 error(WARNING, "Syntax error in #if/#endif");
     430           0 :                 return 1;
     431             :             case ARITH:
     432             :             case RELAT:
     433           0 :                 if (v1.type == UNS || v2.type == UNS)
     434           0 :                     rtype = UNS;
     435             :                 else
     436           0 :                     rtype = SGN;
     437           0 :                 if (v1.type == UND || v2.type == UND)
     438           0 :                     rtype = UND;
     439           0 :                 if (priority[oper].ctype == RELAT && rtype == UNS)
     440             :                 {
     441           0 :                     oper |= UNSMARK;
     442           0 :                     rtype = SGN;
     443             :                 }
     444           0 :                 break;
     445             :             case SHIFT:
     446           0 :                 if (v1.type == UND || v2.type == UND)
     447           0 :                     rtype = UND;
     448             :                 else
     449           0 :                     rtype = v1.type;
     450           0 :                 if (rtype == UNS)
     451           0 :                     oper |= UNSMARK;
     452           0 :                 break;
     453             :             case UNARY:
     454         442 :                 rtype = v1.type;
     455         442 :                 break;
     456             :             case LOGIC:
     457             :             case SPCL:
     458          35 :                 break;
     459             :         }
     460         477 :         switch (oper)
     461             :         {
     462             :             case EQ:
     463             :             case EQ | UNSMARK:
     464           0 :                 rv1 = rv1 == rv2;
     465           0 :                 break;
     466             :             case NEQ:
     467             :             case NEQ | UNSMARK:
     468           0 :                 rv1 = rv1 != rv2;
     469           0 :                 break;
     470             :             case LEQ:
     471           0 :                 rv1 = rv1 <= rv2;
     472           0 :                 break;
     473             :             case GEQ:
     474           0 :                 rv1 = rv1 >= rv2;
     475           0 :                 break;
     476             :             case LT:
     477           0 :                 rv1 = rv1 < rv2;
     478           0 :                 break;
     479             :             case GT:
     480           0 :                 rv1 = rv1 > rv2;
     481           0 :                 break;
     482             :             case LEQ | UNSMARK:
     483           0 :                 rv1 = (unsigned long)rv1 <= (unsigned long)rv2;
     484           0 :                 break;
     485             :             case GEQ | UNSMARK:
     486           0 :                 rv1 = (unsigned long)rv1 >= (unsigned long)rv2;
     487           0 :                 break;
     488             :             case LT | UNSMARK:
     489           0 :                 rv1 = (unsigned long)rv1 < (unsigned long)rv2;
     490           0 :                 break;
     491             :             case GT | UNSMARK:
     492           0 :                 rv1 = (unsigned long)rv1 > (unsigned long)rv2;
     493           0 :                 break;
     494             :             case LSH:
     495           0 :                 rv1 <<= rv2;
     496           0 :                 break;
     497             :             case LSH | UNSMARK:
     498           0 :                 rv1 = (unsigned long) rv1 << rv2;
     499           0 :                 break;
     500             :             case RSH:
     501           0 :                 rv1 >>= rv2;
     502           0 :                 break;
     503             :             case RSH | UNSMARK:
     504           0 :                 rv1 = (unsigned long) rv1 >> rv2;
     505           0 :                 break;
     506             :             case LAND:
     507          28 :                 rtype = UND;
     508          28 :                 if (v1.type == UND)
     509           0 :                     break;
     510          28 :                 if (rv1 != 0)
     511             :                 {
     512          21 :                     if (v2.type == UND)
     513           0 :                         break;
     514          21 :                     rv1 = rv2 != 0;
     515             :                 }
     516             :                 else
     517           7 :                     rv1 = 0;
     518          28 :                 rtype = SGN;
     519          28 :                 break;
     520             :             case LOR:
     521           7 :                 rtype = UND;
     522           7 :                 if (v1.type == UND)
     523           0 :                     break;
     524           7 :                 if (rv1 == 0)
     525             :                 {
     526           5 :                     if (v2.type == UND)
     527           0 :                         break;
     528           5 :                     rv1 = rv2 != 0;
     529             :                 }
     530             :                 else
     531           2 :                     rv1 = 1;
     532           7 :                 rtype = SGN;
     533           7 :                 break;
     534             :             case AND:
     535           0 :                 rv1 &= rv2;
     536           0 :                 break;
     537             :             case STAR:
     538           0 :                 rv1 *= rv2;
     539           0 :                 break;
     540             :             case PLUS:
     541           0 :                 rv1 += rv2;
     542           0 :                 break;
     543             :             case MINUS:
     544           0 :                 rv1 -= rv2;
     545           0 :                 break;
     546             :             case UMINUS:
     547           0 :                 if (v1.type == UND)
     548           0 :                     rtype = UND;
     549           0 :                 rv1 = -rv1;
     550           0 :                 break;
     551             :             case OR:
     552           0 :                 rv1 |= rv2;
     553           0 :                 break;
     554             :             case CIRC:
     555           0 :                 rv1 ^= rv2;
     556           0 :                 break;
     557             :             case TILDE:
     558           0 :                 rv1 = ~rv1;
     559           0 :                 break;
     560             :             case NOT:
     561          27 :                 rv1 = !rv1;
     562          27 :                 if (rtype != UND)
     563          27 :                     rtype = SGN;
     564          27 :                 break;
     565             :             case SLASH:
     566           0 :                 if (rv2 == 0)
     567             :                 {
     568           0 :                     rtype = UND;
     569           0 :                     break;
     570             :                 }
     571           0 :                 if (rtype == UNS)
     572           0 :                     rv1 /= (unsigned long) rv2;
     573             :                 else
     574           0 :                     rv1 /= rv2;
     575           0 :                 break;
     576             :             case PCT:
     577           0 :                 if (rv2 == 0)
     578             :                 {
     579           0 :                     rtype = UND;
     580           0 :                     break;
     581             :                 }
     582           0 :                 if (rtype == UNS)
     583           0 :                     rv1 %= (unsigned long) rv2;
     584             :                 else
     585           0 :                     rv1 %= rv2;
     586           0 :                 break;
     587             :             case COLON:
     588           0 :                 if (op[-1] != QUEST)
     589           0 :                     error(ERROR, "Bad ?: in #if/endif");
     590             :                 else
     591             :                 {
     592           0 :                     op--;
     593           0 :                     if ((--vp)->val == 0)
     594           0 :                         v1 = v2;
     595           0 :                     rtype = v1.type;
     596           0 :                     rv1 = v1.val;
     597             :                 }
     598           0 :                 break;
     599             : 
     600             :             case DEFINED:
     601             :             case ARCHITECTURE:
     602         415 :                 break;
     603             : 
     604             :             default:
     605           0 :                 error(ERROR, "Eval botch (unknown operator)");
     606           0 :                 return 1;
     607             :         }
     608             : /*lint +e574 +e644 */
     609         477 :         v1.val = rv1;
     610         477 :         v1.type = rtype;
     611         477 :         *vp++ = v1;
     612             :     }
     613         489 :     return 0;
     614             : }
     615             : 
     616             : struct value
     617         415 :     tokval(Token * tp)
     618             : {
     619             :     struct value v;
     620             :     Nlist *np;
     621             :     int i, base;
     622             :     unsigned long n;
     623             :     uchar *p, c;
     624             : 
     625         415 :     v.type = SGN;
     626         415 :     v.val = 0;
     627         415 :     switch (tp->type)
     628             :     {
     629             : 
     630             :         case NAME:
     631           0 :             v.val = 0;
     632           0 :             break;
     633             : 
     634             :         case NAME1:
     635         415 :             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISDEFINED | ISMAC))
     636          32 :                 v.val = 1;
     637         415 :             break;
     638             : 
     639             :         case NAME2:
     640           0 :             if ((np = lookup(tp, 0)) != NULL && np->flag & (ISARCHITECTURE))
     641           0 :                 v.val = 1;
     642           0 :             break;
     643             : 
     644             :         case NUMBER:
     645           0 :             n = 0;
     646           0 :             base = 10;
     647           0 :             p = tp->t;
     648           0 :             c = p[tp->len];
     649           0 :             p[tp->len] = '\0';
     650           0 :             if (*p == '0')
     651             :             {
     652           0 :                 base = 8;
     653           0 :                 if (p[1] == 'x' || p[1] == 'X')
     654             :                 {
     655           0 :                     base = 16;
     656           0 :                     p++;
     657             :                 }
     658           0 :                 p++;
     659             :             }
     660           0 :             for (;; p++)
     661             :             {
     662           0 :                 if ((i = digit(*p)) < 0)
     663           0 :                     break;
     664           0 :                 if (i >= base)
     665           0 :                     error(WARNING,
     666             :                           "Bad digit in number %t", tp);
     667           0 :                 n *= base;
     668           0 :                 n += i;
     669           0 :             }
     670           0 :             if (n >= 0x80000000 && base != 10)
     671           0 :                 v.type = UNS;
     672           0 :             for (; *p; p++)
     673             :             {
     674           0 :                 if (*p == 'u' || *p == 'U')
     675           0 :                     v.type = UNS;
     676             :                 else
     677           0 :                     if (*p == 'l' || *p == 'L')
     678             :                         ;
     679             :                     else
     680             :                     {
     681           0 :                         error(ERROR,
     682             :                               "Bad number %t in #if/#elif", tp);
     683           0 :                         break;
     684             :                     }
     685             :             }
     686           0 :             v.val = n;
     687           0 :             tp->t[tp->len] = c;
     688           0 :             break;
     689             : 
     690             :         case CCON:
     691           0 :             n = 0;
     692           0 :             p = tp->t;
     693           0 :             if (*p == 'L')
     694             :             {
     695           0 :                 p += 1;
     696           0 :                 error(WARNING, "Wide char constant value undefined");
     697             :             }
     698           0 :             p += 1;
     699           0 :             if (*p == '\\')
     700             :             {
     701           0 :                 p += 1;
     702           0 :                 if ((i = digit(*p)) >= 0 && i <= 7)
     703             :                 {
     704           0 :                     n = i;
     705           0 :                     p += 1;
     706           0 :                     if ((i = digit(*p)) >= 0 && i <= 7)
     707             :                     {
     708           0 :                         p += 1;
     709           0 :                         n <<= 3;
     710           0 :                         n += i;
     711           0 :                         if ((i = digit(*p)) >= 0 && i <= 7)
     712             :                         {
     713           0 :                             p += 1;
     714           0 :                             n <<= 3;
     715           0 :                             n += i;
     716             :                         }
     717             :                     }
     718             :                 }
     719             :                 else
     720           0 :                     if (*p == 'x')
     721             :                     {
     722           0 :                         p += 1;
     723           0 :                         while ((i = digit(*p)) >= 0 && i <= 15)
     724             :                         {
     725           0 :                             p += 1;
     726           0 :                             n <<= 4;
     727           0 :                             n += i;
     728             :                         }
     729             :                     }
     730             :                     else
     731             :                     {
     732             :                         static const char cvcon[] = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
     733             :                         static size_t cvlen = sizeof(cvcon) - 1;
     734             : 
     735             :                         size_t j;
     736           0 :                         for (j = 0; j < cvlen; j += 2)
     737             :                         {
     738           0 :                             if (*p == cvcon[j])
     739             :                             {
     740           0 :                                 n = cvcon[j + 1];
     741           0 :                                 break;
     742             :                             }
     743             :                         }
     744           0 :                         p += 1;
     745           0 :                         if (j >= cvlen)
     746           0 :                             error(WARNING,
     747             :                                "Undefined escape in character constant");
     748             :                     }
     749             :             }
     750             :             else
     751           0 :                 if (*p == '\'')
     752           0 :                     error(ERROR, "Empty character constant");
     753             :                 else
     754           0 :                     n = *p++;
     755           0 :             if (*p != '\'')
     756           0 :                 error(WARNING, "Multibyte character constant undefined");
     757             :             else
     758           0 :                 if (n > 127)
     759           0 :                     error(WARNING, "Character constant taken as not signed");
     760           0 :             v.val = n;
     761           0 :             break;
     762             : 
     763             :         case STRING:
     764           0 :             error(ERROR, "String in #if/#elif");
     765           0 :             break;
     766             :     }
     767         415 :     return v;
     768             : }
     769             : 
     770             : int
     771           0 :     digit(int i)
     772             : {
     773           0 :     if ('0' <= i && i <= '9')
     774           0 :         i -= '0';
     775             :     else
     776           0 :         if ('a' <= i && i <= 'f')
     777           0 :             i -= 'a' - 10;
     778             :         else
     779           0 :             if ('A' <= i && i <= 'F')
     780           0 :                 i -= 'A' - 10;
     781             :             else
     782           0 :                 i = -1;
     783           0 :     return i;
     784             : }
     785             : 
     786             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11