LCOV - code coverage report
Current view: top level - libreoffice/soltools/mkdepend - ifparser.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 116 174 66.7 %
Date: 2012-12-27 Functions: 13 13 100.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          68 : parse_variable (g, cp, varp)
      78             :     IfParser *g;
      79             :     const char *cp;
      80             :     const char **varp;
      81             : {
      82          68 :     SKIPSPACE (cp);
      83             : 
      84          68 :     if (!isvarfirstletter (*cp))
      85           0 :         return CALLFUNC(g, handle_error) (g, cp, "variable name");
      86             : 
      87          68 :     *varp = cp;
      88             :     /* EMPTY */
      89          68 :     for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
      90          68 :     return cp;
      91             : }
      92             : 
      93             : 
      94             : static const char *
      95          23 : parse_number (g, cp, valp)
      96             :     IfParser *g;
      97             :     const char *cp;
      98             :     int *valp;
      99             : {
     100          23 :     SKIPSPACE (cp);
     101             : 
     102          23 :     if (!isdigit(*cp))
     103           0 :         return CALLFUNC(g, handle_error) (g, cp, "number");
     104             : 
     105             : #ifdef WIN32
     106             :     {
     107             :         char *cp2;
     108             :         *valp = strtol(cp, &cp2, 0);
     109             :     }
     110             : #else
     111          23 :     *valp = atoi (cp);
     112             :     /* EMPTY */
     113          23 :     for (cp++; isdigit(*cp); cp++) ;
     114             : #endif
     115          23 :     return cp;
     116             : }
     117             : 
     118             : 
     119             : static const char *
     120         104 : parse_value (g, cp, valp)
     121             :     IfParser *g;
     122             :     const char *cp;
     123             :     int *valp;
     124             : {
     125             :     const char *var;
     126             : 
     127         104 :     *valp = 0;
     128             : 
     129         104 :     SKIPSPACE (cp);
     130         104 :     if (!*cp)
     131           0 :         return cp;
     132             : 
     133         104 :     switch (*cp) {
     134             :       case '(':
     135          11 :     DO (cp = ParseIfExpression (g, cp + 1, valp));
     136          11 :     SKIPSPACE (cp);
     137          11 :     if (*cp != ')')
     138           3 :         return CALLFUNC(g, handle_error) (g, cp, ")");
     139             : 
     140           8 :     return cp + 1;          /* skip the right paren */
     141             : 
     142             :       case '!':
     143           2 :     DO (cp = parse_value (g, cp + 1, valp));
     144           2 :     *valp = !(*valp);
     145           2 :     return cp;
     146             : 
     147             :       case '-':
     148           0 :     DO (cp = parse_value (g, cp + 1, valp));
     149           0 :     *valp = -(*valp);
     150           0 :     return cp;
     151             : 
     152             :       case '#':
     153           0 :     DO (cp = parse_variable (g, cp + 1, &var));
     154           0 :     SKIPSPACE (cp);
     155           0 :     if (*cp != '(')
     156           0 :         return CALLFUNC(g, handle_error) (g, cp, "(");
     157             :     do {
     158           0 :         DO (cp = parse_variable (g, cp + 1, &var));
     159           0 :         SKIPSPACE (cp);
     160           0 :     } while (*cp && *cp != ')');
     161           0 :     if (*cp != ')')
     162           0 :         return CALLFUNC(g, handle_error) (g, cp, ")");
     163           0 :     *valp = 1; /* XXX */
     164           0 :     return cp + 1;
     165             : 
     166             :       case 'd':
     167          44 :     if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
     168          44 :         int paren = 0;
     169             :         int len;
     170             : 
     171          44 :         cp += 7;
     172          44 :         SKIPSPACE (cp);
     173          44 :         if (*cp == '(') {
     174          36 :         paren = 1;
     175          36 :         cp++;
     176             :         }
     177          44 :         DO (cp = parse_variable (g, cp, &var));
     178          44 :         len = (int)(cp - var);
     179          44 :         SKIPSPACE (cp);
     180          44 :         if (paren && *cp != ')')
     181           0 :             return CALLFUNC(g, handle_error) (g, cp, ")");
     182          44 :         *valp = (*(g->funcs.eval_defined)) (g, var, len);
     183          44 :         return cp + paren;      /* skip the right paren */
     184             :     }
     185             :     /* fall out */
     186             :     }
     187             : 
     188          47 :     if (isdigit(*cp)) {
     189          23 :     DO (cp = parse_number (g, cp, valp));
     190          24 :     } else if (!isvarfirstletter(*cp))
     191           0 :     return CALLFUNC(g, handle_error) (g, cp, "variable or number");
     192             :     else {
     193          24 :     DO (cp = parse_variable (g, cp, &var));
     194          24 :     *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
     195             :     }
     196             : 
     197          47 :     return cp;
     198             : }
     199             : 
     200             : 
     201             : 
     202             : static const char *
     203         102 : parse_product (g, cp, valp)
     204             :     IfParser *g;
     205             :     const char *cp;
     206             :     int *valp;
     207             : {
     208             :     int rightval;
     209             : 
     210         102 :     DO (cp = parse_value (g, cp, valp));
     211          99 :     SKIPSPACE (cp);
     212             : 
     213          99 :     switch (*cp) {
     214             :       case '*':
     215           0 :     DO (cp = parse_product (g, cp + 1, &rightval));
     216           0 :     *valp = (*valp * rightval);
     217           0 :     break;
     218             : 
     219             :       case '/':
     220           0 :     DO (cp = parse_product (g, cp + 1, &rightval));
     221             : 
     222             :     /* Do nothing in the divide-by-zero case. */
     223           0 :     if (rightval) {
     224           0 :         *valp = (*valp / rightval);
     225             :     }
     226           0 :     break;
     227             : 
     228             :       case '%':
     229           0 :     DO (cp = parse_product (g, cp + 1, &rightval));
     230           0 :     *valp = (*valp % rightval);
     231           0 :     break;
     232             :     }
     233          99 :     return cp;
     234             : }
     235             : 
     236             : 
     237             : static const char *
     238         102 : parse_sum (g, cp, valp)
     239             :     IfParser *g;
     240             :     const char *cp;
     241             :     int *valp;
     242             : {
     243             :     int rightval;
     244             : 
     245         102 :     DO (cp = parse_product (g, cp, valp));
     246          99 :     SKIPSPACE (cp);
     247             : 
     248          99 :     switch (*cp) {
     249             :       case '+':
     250           0 :     DO (cp = parse_sum (g, cp + 1, &rightval));
     251           0 :     *valp = (*valp + rightval);
     252           0 :     break;
     253             : 
     254             :       case '-':
     255           0 :     DO (cp = parse_sum (g, cp + 1, &rightval));
     256           0 :     *valp = (*valp - rightval);
     257           0 :     break;
     258             :     }
     259          99 :     return cp;
     260             : }
     261             : 
     262             : 
     263             : static const char *
     264         102 : parse_shift (g, cp, valp)
     265             :     IfParser *g;
     266             :     const char *cp;
     267             :     int *valp;
     268             : {
     269             :     int rightval;
     270             : 
     271         102 :     DO (cp = parse_sum (g, cp, valp));
     272          99 :     SKIPSPACE (cp);
     273             : 
     274          99 :     switch (*cp) {
     275             :       case '<':
     276           0 :     if (cp[1] == '<') {
     277           0 :         DO (cp = parse_shift (g, cp + 2, &rightval));
     278           0 :         *valp = (*valp << rightval);
     279             :     }
     280           0 :     break;
     281             : 
     282             :       case '>':
     283           9 :     if (cp[1] == '>') {
     284           0 :         DO (cp = parse_shift (g, cp + 2, &rightval));
     285           0 :         *valp = (*valp >> rightval);
     286             :     }
     287           9 :     break;
     288             :     }
     289          99 :     return cp;
     290             : }
     291             : 
     292             : 
     293             : static const char *
     294         102 : parse_inequality (g, cp, valp)
     295             :     IfParser *g;
     296             :     const char *cp;
     297             :     int *valp;
     298             : {
     299             :     int rightval;
     300             : 
     301         102 :     DO (cp = parse_shift (g, cp, valp));
     302          99 :     SKIPSPACE (cp);
     303             : 
     304          99 :     switch (*cp) {
     305             :       case '<':
     306           0 :     if (cp[1] == '=') {
     307           0 :         DO (cp = parse_inequality (g, cp + 2, &rightval));
     308           0 :         *valp = (*valp <= rightval);
     309             :     } else {
     310           0 :         DO (cp = parse_inequality (g, cp + 1, &rightval));
     311           0 :         *valp = (*valp < rightval);
     312             :     }
     313           0 :     break;
     314             : 
     315             :       case '>':
     316           9 :     if (cp[1] == '=') {
     317           6 :         DO (cp = parse_inequality (g, cp + 2, &rightval));
     318           6 :         *valp = (*valp >= rightval);
     319             :     } else {
     320           3 :         DO (cp = parse_inequality (g, cp + 1, &rightval));
     321           3 :         *valp = (*valp > rightval);
     322             :     }
     323           9 :     break;
     324             :     }
     325          99 :     return cp;
     326             : }
     327             : 
     328             : 
     329             : static const char *
     330          93 : parse_equality (g, cp, valp)
     331             :     IfParser *g;
     332             :     const char *cp;
     333             :     int *valp;
     334             : {
     335             :     int rightval;
     336             : 
     337          93 :     DO (cp = parse_inequality (g, cp, valp));
     338          90 :     SKIPSPACE (cp);
     339             : 
     340          90 :     switch (*cp) {
     341             :       case '=':
     342          14 :     if (cp[1] == '=')
     343          14 :         cp++;
     344          14 :     DO (cp = parse_equality (g, cp + 1, &rightval));
     345          14 :     *valp = (*valp == rightval);
     346          14 :     break;
     347             : 
     348             :       case '!':
     349           0 :     if (cp[1] != '=')
     350           0 :         break;
     351           0 :     DO (cp = parse_equality (g, cp + 2, &rightval));
     352           0 :     *valp = (*valp != rightval);
     353           0 :     break;
     354             :     }
     355          90 :     return cp;
     356             : }
     357             : 
     358             : 
     359             : static const char *
     360          79 : parse_band (g, cp, valp)
     361             :     IfParser *g;
     362             :     const char *cp;
     363             :     int *valp;
     364             : {
     365             :     int rightval;
     366             : 
     367          79 :     DO (cp = parse_equality (g, cp, valp));
     368          76 :     SKIPSPACE (cp);
     369             : 
     370          76 :     switch (*cp) {
     371             :       case '&':
     372           9 :     if (cp[1] != '&') {
     373           0 :         DO (cp = parse_band (g, cp + 1, &rightval));
     374           0 :         *valp = (*valp & rightval);
     375             :     }
     376           9 :     break;
     377             :     }
     378          76 :     return cp;
     379             : }
     380             : 
     381             : 
     382             : static const char *
     383          79 : parse_bor (g, cp, valp)
     384             :     IfParser *g;
     385             :     const char *cp;
     386             :     int *valp;
     387             : {
     388             :     int rightval;
     389             : 
     390          79 :     DO (cp = parse_band (g, cp, valp));
     391          76 :     SKIPSPACE (cp);
     392             : 
     393          76 :     switch (*cp) {
     394             :       case '|':
     395          17 :     if (cp[1] != '|') {
     396           0 :         DO (cp = parse_bor (g, cp + 1, &rightval));
     397           0 :         *valp = (*valp | rightval);
     398             :     }
     399          17 :     break;
     400             :     }
     401          76 :     return cp;
     402             : }
     403             : 
     404             : 
     405             : static const char *
     406          79 : parse_land (g, cp, valp)
     407             :     IfParser *g;
     408             :     const char *cp;
     409             :     int *valp;
     410             : {
     411             :     int rightval;
     412             : 
     413          79 :     DO (cp = parse_bor (g, cp, valp));
     414          76 :     SKIPSPACE (cp);
     415             : 
     416          76 :     switch (*cp) {
     417             :       case '&':
     418           9 :     if (cp[1] != '&')
     419           0 :         return CALLFUNC(g, handle_error) (g, cp, "&&");
     420           9 :     DO (cp = parse_land (g, cp + 2, &rightval));
     421           6 :     *valp = (*valp && rightval);
     422           6 :     break;
     423             :     }
     424          73 :     return cp;
     425             : }
     426             : 
     427             : 
     428             : static const char *
     429          70 : parse_lor (g, cp, valp)
     430             :     IfParser *g;
     431             :     const char *cp;
     432             :     int *valp;
     433             : {
     434             :     int rightval;
     435             : 
     436          70 :     DO (cp = parse_land (g, cp, valp));
     437          67 :     SKIPSPACE (cp);
     438             : 
     439          67 :     switch (*cp) {
     440             :       case '|':
     441          17 :     if (cp[1] != '|')
     442           0 :         return CALLFUNC(g, handle_error) (g, cp, "||");
     443          17 :     DO (cp = parse_lor (g, cp + 2, &rightval));
     444          17 :     *valp = (*valp || rightval);
     445          17 :     break;
     446             :     }
     447          67 :     return cp;
     448             : }
     449             : 
     450             : 
     451             : /****************************************************************************
     452             :                  External Entry Points
     453             :  ****************************************************************************/
     454             : 
     455             : const char *
     456          53 : ParseIfExpression (g, cp, valp)
     457             :     IfParser *g;
     458             :     const char *cp;
     459             :     int *valp;
     460             : {
     461          53 :     return parse_lor (g, cp, valp);
     462             : }
     463             : 
     464             : 
     465             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10