LCOV - code coverage report
Current view: top level - soltools/mkdepend - ifparser.c (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 174 0.0 %
Date: 2015-06-13 12:38:46 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * $XConsortium: ifparser.c,v 1.8 95/06/03 00:01:41 gildea Exp $
       4             :  *
       5             :  * Copyright 1992 Network Computing Devices, Inc.
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software and its
       8             :  * documentation for any purpose and without fee is hereby granted, provided
       9             :  * that the above copyright notice appear in all copies and that both that
      10             :  * copyright notice and this permission notice appear in supporting
      11             :  * documentation, and that the name of Network Computing Devices may not be
      12             :  * used in advertising or publicity pertaining to distribution of the software
      13             :  * without specific, written prior permission.  Network Computing Devices makes
      14             :  * no representations about the suitability of this software for any purpose.
      15             :  * It is provided ``as is'' without express or implied warranty.
      16             :  *
      17             :  * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
      18             :  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
      19             :  * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
      20             :  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      21             :  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      22             :  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      23             :  * PERFORMANCE OF THIS SOFTWARE.
      24             :  *
      25             :  * Author:  Jim Fulton
      26             :  *          Network Computing Devices, Inc.
      27             :  *
      28             :  * Simple if statement processor
      29             :  *
      30             :  * This module can be used to evaluate string representations of C language
      31             :  * if constructs.  It accepts the following grammar:
      32             :  *
      33             :  *     EXPRESSION   :=  VALUE
      34             :  *           |  VALUE  BINOP    EXPRESSION
      35             :  *
      36             :  *     VALUE        :=  '('  EXPRESSION  ')'
      37             :  *           |  '!'  VALUE
      38             :  *           |  '-'  VALUE
      39             :  *           |  'defined'  '('  variable  ')'
      40             :  *           |  'defined'  variable
      41             :  *           |  # variable '(' variable-list ')'
      42             :  *           |  variable
      43             :  *           |  number
      44             :  *
      45             :  *     BINOP        :=  '*' |  '/'  |  '%'
      46             :  *           |  '+' |  '-'
      47             :  *           |  '<<'    |  '>>'
      48             :  *           |  '<' |  '>'  |  '<='  |  '>='
      49             :  *           |  '=='    |  '!='
      50             :  *           |  '&' |  '|'
      51             :  *           |  '&&'    |  '||'
      52             :  *
      53             :  * The normal C order of precidence is supported.
      54             :  *
      55             :  *
      56             :  * External Entry Points:
      57             :  *
      58             :  *     ParseIfExpression        parse a string for #if
      59             :  */
      60             : 
      61             : #include "ifparser.h"
      62             : #include <ctype.h>
      63             : #include <stdlib.h>
      64             : #include <string.h>
      65             : 
      66             : /****************************************************************************
      67             :            Internal Macros and Utilities for Parser
      68             :  ****************************************************************************/
      69             : 
      70             : #define DO(val) if (!(val)) return NULL
      71             : #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
      72             : #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
      73             : #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
      74             : 
      75             : 
      76             : static const char *
      77           0 : parse_variable (IfParser *g, const char *cp, const char **varp)
      78             : {
      79           0 :     SKIPSPACE (cp);
      80             : 
      81           0 :     if (!isvarfirstletter (*cp))
      82           0 :         return CALLFUNC(g, handle_error) (g, cp, "variable name");
      83             : 
      84           0 :     *varp = cp;
      85             :     /* EMPTY */
      86           0 :     for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
      87           0 :     return cp;
      88             : }
      89             : 
      90             : 
      91             : static const char *
      92           0 : parse_number (IfParser *g, const char *cp, int *valp)
      93             : {
      94           0 :     SKIPSPACE (cp);
      95             : 
      96           0 :     if (!isdigit(*cp))
      97           0 :         return CALLFUNC(g, handle_error) (g, cp, "number");
      98             : 
      99             : #ifdef WIN32
     100             :     {
     101             :         char *cp2;
     102             :         *valp = strtol(cp, &cp2, 0);
     103             :     }
     104             : #else
     105           0 :     *valp = atoi (cp);
     106             :     /* EMPTY */
     107           0 :     for (cp++; isdigit(*cp); cp++) ;
     108             : #endif
     109           0 :     return cp;
     110             : }
     111             : 
     112             : 
     113             : static const char *
     114           0 : parse_value (IfParser *g, const char *cp, int *valp)
     115             : {
     116             :     const char *var;
     117             : 
     118           0 :     *valp = 0;
     119             : 
     120           0 :     SKIPSPACE (cp);
     121           0 :     if (!*cp)
     122           0 :         return cp;
     123             : 
     124           0 :     switch (*cp) {
     125             :       case '(':
     126           0 :         DO (cp = ParseIfExpression (g, cp + 1, valp));
     127           0 :         SKIPSPACE (cp);
     128           0 :         if (*cp != ')')
     129           0 :             return CALLFUNC(g, handle_error) (g, cp, ")");
     130             : 
     131           0 :         return cp + 1;          /* skip the right paren */
     132             : 
     133             :       case '!':
     134           0 :         DO (cp = parse_value (g, cp + 1, valp));
     135           0 :         *valp = !(*valp);
     136           0 :         return cp;
     137             : 
     138             :       case '-':
     139           0 :         DO (cp = parse_value (g, cp + 1, valp));
     140           0 :         *valp = -(*valp);
     141           0 :         return cp;
     142             : 
     143             :       case '#':
     144           0 :         DO (cp = parse_variable (g, cp + 1, &var));
     145           0 :         SKIPSPACE (cp);
     146           0 :         if (*cp != '(')
     147           0 :             return CALLFUNC(g, handle_error) (g, cp, "(");
     148             :         do {
     149           0 :             DO (cp = parse_variable (g, cp + 1, &var));
     150           0 :             SKIPSPACE (cp);
     151           0 :         } while (*cp && *cp != ')');
     152           0 :         if (*cp != ')')
     153           0 :             return CALLFUNC(g, handle_error) (g, cp, ")");
     154           0 :         *valp = 1; /* XXX */
     155           0 :         return cp + 1;
     156             : 
     157             :       case 'd':
     158           0 :         if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
     159           0 :             int paren = 0;
     160             :             size_t len;
     161             : 
     162           0 :             cp += 7;
     163           0 :             SKIPSPACE (cp);
     164           0 :             if (*cp == '(') {
     165           0 :               paren = 1;
     166           0 :               cp++;
     167             :             }
     168           0 :             DO (cp = parse_variable (g, cp, &var));
     169           0 :             len = (size_t)(cp - var);
     170           0 :             SKIPSPACE (cp);
     171           0 :             if (paren && *cp != ')')
     172           0 :                 return CALLFUNC(g, handle_error) (g, cp, ")");
     173           0 :             *valp = (*(g->funcs.eval_defined)) (g, var, len);
     174           0 :             return cp + paren;      /* skip the right paren */
     175             :         }
     176             :     /* fall out */
     177             :     }
     178             : 
     179           0 :     if (isdigit(*cp)) {
     180           0 :       DO (cp = parse_number (g, cp, valp));
     181           0 :     } else if (!isvarfirstletter(*cp))
     182           0 :       return CALLFUNC(g, handle_error) (g, cp, "variable or number");
     183             :     else {
     184           0 :       DO (cp = parse_variable (g, cp, &var));
     185           0 :       *valp = (*(g->funcs.eval_variable)) (g, var, (size_t)(cp - var));
     186             :     }
     187             : 
     188           0 :     return cp;
     189             : }
     190             : 
     191             : 
     192             : 
     193             : static const char *
     194           0 : parse_product (IfParser *g, const char *cp, int *valp)
     195             : {
     196             :     int rightval;
     197             : 
     198           0 :     DO (cp = parse_value (g, cp, valp));
     199           0 :     SKIPSPACE (cp);
     200             : 
     201           0 :     switch (*cp) {
     202             :       case '*':
     203           0 :         DO (cp = parse_product (g, cp + 1, &rightval));
     204           0 :         *valp = (*valp * rightval);
     205           0 :         break;
     206             : 
     207             :       case '/':
     208           0 :         DO (cp = parse_product (g, cp + 1, &rightval));
     209             : 
     210             :         /* Do nothing in the divide-by-zero case. */
     211           0 :         if (rightval) {
     212           0 :             *valp = (*valp / rightval);
     213             :         }
     214           0 :         break;
     215             : 
     216             :       case '%':
     217           0 :         DO (cp = parse_product (g, cp + 1, &rightval));
     218           0 :         *valp = (*valp % rightval);
     219           0 :         break;
     220             :     }
     221           0 :     return cp;
     222             : }
     223             : 
     224             : 
     225             : static const char *
     226           0 : parse_sum (IfParser *g, const char *cp, int *valp)
     227             : {
     228             :     int rightval;
     229             : 
     230           0 :     DO (cp = parse_product (g, cp, valp));
     231           0 :     SKIPSPACE (cp);
     232             : 
     233           0 :     switch (*cp) {
     234             :       case '+':
     235           0 :         DO (cp = parse_sum (g, cp + 1, &rightval));
     236           0 :         *valp = (*valp + rightval);
     237           0 :         break;
     238             : 
     239             :       case '-':
     240           0 :         DO (cp = parse_sum (g, cp + 1, &rightval));
     241           0 :         *valp = (*valp - rightval);
     242           0 :         break;
     243             :     }
     244           0 :     return cp;
     245             : }
     246             : 
     247             : 
     248             : static const char *
     249           0 : parse_shift (IfParser *g, const char *cp, int *valp)
     250             : {
     251             :     int rightval;
     252             : 
     253           0 :     DO (cp = parse_sum (g, cp, valp));
     254           0 :     SKIPSPACE (cp);
     255             : 
     256           0 :     switch (*cp) {
     257             :       case '<':
     258           0 :         if (cp[1] == '<') {
     259           0 :             DO (cp = parse_shift (g, cp + 2, &rightval));
     260           0 :             *valp = (*valp << rightval);
     261             :         }
     262           0 :         break;
     263             : 
     264             :       case '>':
     265           0 :         if (cp[1] == '>') {
     266           0 :             DO (cp = parse_shift (g, cp + 2, &rightval));
     267           0 :             *valp = (*valp >> rightval);
     268             :         }
     269           0 :         break;
     270             :     }
     271           0 :     return cp;
     272             : }
     273             : 
     274             : 
     275             : static const char *
     276           0 : parse_inequality (IfParser *g, const char *cp, int *valp)
     277             : {
     278             :     int rightval;
     279             : 
     280           0 :     DO (cp = parse_shift (g, cp, valp));
     281           0 :     SKIPSPACE (cp);
     282             : 
     283           0 :     switch (*cp) {
     284             :       case '<':
     285           0 :         if (cp[1] == '=') {
     286           0 :             DO (cp = parse_inequality (g, cp + 2, &rightval));
     287           0 :             *valp = (*valp <= rightval);
     288             :         } else {
     289           0 :             DO (cp = parse_inequality (g, cp + 1, &rightval));
     290           0 :             *valp = (*valp < rightval);
     291             :         }
     292           0 :         break;
     293             : 
     294             :       case '>':
     295           0 :         if (cp[1] == '=') {
     296           0 :             DO (cp = parse_inequality (g, cp + 2, &rightval));
     297           0 :             *valp = (*valp >= rightval);
     298             :         } else {
     299           0 :             DO (cp = parse_inequality (g, cp + 1, &rightval));
     300           0 :             *valp = (*valp > rightval);
     301             :         }
     302           0 :         break;
     303             :     }
     304           0 :     return cp;
     305             : }
     306             : 
     307             : 
     308             : static const char *
     309           0 : parse_equality (IfParser *g, const char *cp, int *valp)
     310             : {
     311             :     int rightval;
     312             : 
     313           0 :     DO (cp = parse_inequality (g, cp, valp));
     314           0 :     SKIPSPACE (cp);
     315             : 
     316           0 :     switch (*cp) {
     317             :       case '=':
     318           0 :         if (cp[1] == '=')
     319           0 :             cp++;
     320           0 :         DO (cp = parse_equality (g, cp + 1, &rightval));
     321           0 :         *valp = (*valp == rightval);
     322           0 :         break;
     323             : 
     324             :       case '!':
     325           0 :         if (cp[1] != '=')
     326           0 :             break;
     327           0 :         DO (cp = parse_equality (g, cp + 2, &rightval));
     328           0 :         *valp = (*valp != rightval);
     329           0 :         break;
     330             :     }
     331           0 :     return cp;
     332             : }
     333             : 
     334             : 
     335             : static const char *
     336           0 : parse_band (IfParser *g, const char *cp, int *valp)
     337             : {
     338             :     int rightval;
     339             : 
     340           0 :     DO (cp = parse_equality (g, cp, valp));
     341           0 :     SKIPSPACE (cp);
     342             : 
     343           0 :     switch (*cp) {
     344             :       case '&':
     345           0 :         if (cp[1] != '&') {
     346           0 :             DO (cp = parse_band (g, cp + 1, &rightval));
     347           0 :             *valp = (*valp & rightval);
     348             :         }
     349           0 :         break;
     350             :     }
     351           0 :     return cp;
     352             : }
     353             : 
     354             : 
     355             : static const char *
     356           0 : parse_bor (IfParser *g, const char *cp, int *valp)
     357             : {
     358             :     int rightval;
     359             : 
     360           0 :     DO (cp = parse_band (g, cp, valp));
     361           0 :     SKIPSPACE (cp);
     362             : 
     363           0 :     switch (*cp) {
     364             :       case '|':
     365           0 :         if (cp[1] != '|') {
     366           0 :             DO (cp = parse_bor (g, cp + 1, &rightval));
     367           0 :             *valp = (*valp | rightval);
     368             :         }
     369           0 :         break;
     370             :     }
     371           0 :     return cp;
     372             : }
     373             : 
     374             : 
     375             : static const char *
     376           0 : parse_land (IfParser *g, const char *cp, int *valp)
     377             : {
     378             :     int rightval;
     379             : 
     380           0 :     DO (cp = parse_bor (g, cp, valp));
     381           0 :     SKIPSPACE (cp);
     382             : 
     383           0 :     switch (*cp) {
     384             :       case '&':
     385           0 :         if (cp[1] != '&')
     386           0 :             return CALLFUNC(g, handle_error) (g, cp, "&&");
     387           0 :         DO (cp = parse_land (g, cp + 2, &rightval));
     388           0 :         *valp = (*valp && rightval);
     389           0 :         break;
     390             :     }
     391           0 :     return cp;
     392             : }
     393             : 
     394             : 
     395             : static const char *
     396           0 : parse_lor (IfParser *g, const char *cp, int *valp)
     397             : {
     398             :     int rightval;
     399             : 
     400           0 :     DO (cp = parse_land (g, cp, valp));
     401           0 :     SKIPSPACE (cp);
     402             : 
     403           0 :     switch (*cp) {
     404             :       case '|':
     405           0 :         if (cp[1] != '|')
     406           0 :             return CALLFUNC(g, handle_error) (g, cp, "||");
     407           0 :         DO (cp = parse_lor (g, cp + 2, &rightval));
     408           0 :         *valp = (*valp || rightval);
     409           0 :         break;
     410             :     }
     411           0 :     return cp;
     412             : }
     413             : 
     414             : 
     415             : /****************************************************************************
     416             :                  External Entry Points
     417             :  ****************************************************************************/
     418             : 
     419             : const char *
     420           0 : ParseIfExpression (IfParser *g, const char *cp, int *valp)
     421             : {
     422           0 :     return parse_lor (g, cp, valp);
     423             : }
     424             : 
     425             : 
     426             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11