Back to home page

MITgcm

 
 

    


File indexing completed on 2018-03-02 18:44:42 UTC

view on githubraw file Latest commit bf5846c3 on 2004-02-25 18:19:54 UTC
bf5846c3a1 Ed H*0001 /*
                0002  * $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws Exp $
                0003  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
                0004  *
                0005  * Redistribution and use in source and binary forms, with or without
                0006  * modification, are permitted provided that the following conditions
                0007  * are met:
                0008  *
                0009  * 1. Redistributions of source code must retain the above copyright
                0010  *    notice, this list of conditions and the following disclaimer. 
                0011  *
                0012  * 2. Redistributions in binary form must reproduce the above copyright
                0013  *    notice, this list of conditions and the following disclaimer in
                0014  *    the documentation and/or other materials provided with the
                0015  *    distribution.
                0016  *
                0017  * 3. The name "Carnegie Mellon University" must not be used to
                0018  *    endorse or promote products derived from this software without
                0019  *    prior written permission. For permission or any other legal
                0020  *    details, please contact  
                0021  *      Office of Technology Transfer
                0022  *      Carnegie Mellon University
                0023  *      5000 Forbes Avenue
                0024  *      Pittsburgh, PA  15213-3890
                0025  *      (412) 268-4387, fax: (412) 268-7395
                0026  *      tech-transfer@andrew.cmu.edu
                0027  *
                0028  * 4. Redistributions of any form whatsoever must retain the following
                0029  *    acknowledgment:
                0030  *    "This product includes software developed by Computing Services
                0031  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
                0032  *
                0033  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0034  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0035  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0036  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0037  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0038  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0039  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                0040  *
                0041  *
                0042  * Copyright 1992 Network Computing Devices, Inc.
                0043  * 
                0044  * Permission to use, copy, modify, and distribute this software and its
                0045  * documentation for any purpose and without fee is hereby granted, provided
                0046  * that the above copyright notice appear in all copies and that both that
                0047  * copyright notice and this permission notice appear in supporting
                0048  * documentation, and that the name of Network Computing Devices may not be
                0049  * used in advertising or publicity pertaining to distribution of the software
                0050  * without specific, written prior permission.  Network Computing Devices makes
                0051  * no representations about the suitability of this software for any purpose.
                0052  * It is provided ``as is'' without express or implied warranty.
                0053  * 
                0054  * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
                0055  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                0056  * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
                0057  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                0058  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
                0059  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                0060  * PERFORMANCE OF THIS SOFTWARE.
                0061  * 
                0062  * Author:  Jim Fulton
                0063  *          Network Computing Devices, Inc.
                0064  * 
                0065  * Simple if statement processor
                0066  *
                0067  * This module can be used to evaluate string representations of C language
                0068  * if constructs.  It accepts the following grammar:
                0069  * 
                0070  *     EXPRESSION   :=  VALUE
                0071  *           |  VALUE  BINOP    EXPRESSION
                0072  * 
                0073  *     VALUE        :=  '('  EXPRESSION  ')'
                0074  *           |  '!'  VALUE
                0075  *           |  '-'  VALUE
                0076  *           |  'defined'  '('  variable  ')'
                0077  *           |  'defined'  variable
                0078  *           |  # variable '(' variable-list ')'
                0079  *           |  variable
                0080  *           |  number
                0081  * 
                0082  *     BINOP        :=  '*' |  '/'  |  '%'
                0083  *           |  '+' |  '-'
                0084  *           |  '<<'    |  '>>'
                0085  *           |  '<' |  '>'  |  '<='  |  '>='
                0086  *           |  '=='    |  '!='
                0087  *           |  '&' |  '|'
                0088  *           |  '&&'    |  '||'
                0089  * 
                0090  * The normal C order of precidence is supported.
                0091  * 
                0092  * 
                0093  * External Entry Points:
                0094  * 
                0095  *     ParseIfExpression        parse a string for #if
                0096  */
                0097 
                0098 #include "ifparser.h"
                0099 #include <ctype.h>
                0100 
                0101 /****************************************************************************
                0102            Internal Macros and Utilities for Parser
                0103  ****************************************************************************/
                0104 
                0105 #define DO(val) if (!(val)) return NULL
                0106 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
                0107 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
                0108 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
                0109 
                0110 
                0111 static const char *
                0112 parse_variable (g, cp, varp)
                0113     IfParser *g;
                0114     const char *cp;
                0115     const char **varp;
                0116 {
                0117     SKIPSPACE (cp);
                0118 
                0119     if (!isvarfirstletter (*cp))
                0120     return CALLFUNC(g, handle_error) (g, cp, "variable name");
                0121 
                0122     *varp = cp;
                0123     /* EMPTY */
                0124     for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
                0125     return cp;
                0126 }
                0127 
                0128 
                0129 static const char *
                0130 parse_number (g, cp, valp)
                0131     IfParser *g;
                0132     const char *cp;
                0133     int *valp;
                0134 {
                0135     SKIPSPACE (cp);
                0136 
                0137     if (!isdigit(*cp))
                0138     return CALLFUNC(g, handle_error) (g, cp, "number");
                0139 
                0140 #ifdef WIN32
                0141     *valp = strtol(cp, &cp, 0);
                0142 #else
                0143     *valp = atoi (cp);
                0144     /* EMPTY */
                0145     for (cp++; isdigit(*cp); cp++) ;
                0146 #endif
                0147     return cp;
                0148 }
                0149 
                0150 
                0151 static const char *
                0152 parse_value (g, cp, valp)
                0153     IfParser *g;
                0154     const char *cp;
                0155     int *valp;
                0156 {
                0157     const char *var;
                0158 
                0159     *valp = 0;
                0160 
                0161     SKIPSPACE (cp);
                0162     if (!*cp)
                0163     return cp;
                0164 
                0165     switch (*cp) {
                0166       case '(':
                0167     DO (cp = ParseIfExpression (g, cp + 1, valp));
                0168     SKIPSPACE (cp);
                0169     if (*cp != ')') 
                0170         return CALLFUNC(g, handle_error) (g, cp, ")");
                0171 
                0172     return cp + 1;          /* skip the right paren */
                0173 
                0174       case '!':
                0175     DO (cp = parse_value (g, cp + 1, valp));
                0176     *valp = !(*valp);
                0177     return cp;
                0178 
                0179       case '-':
                0180     DO (cp = parse_value (g, cp + 1, valp));
                0181     *valp = -(*valp);
                0182     return cp;
                0183 
                0184       case '#':
                0185     DO (cp = parse_variable (g, cp + 1, &var));
                0186     SKIPSPACE (cp);
                0187     if (*cp != '(')
                0188         return CALLFUNC(g, handle_error) (g, cp, "(");
                0189     do {
                0190         DO (cp = parse_variable (g, cp + 1, &var));
                0191         SKIPSPACE (cp);
                0192     } while (*cp && *cp != ')');
                0193     if (*cp != ')')
                0194         return CALLFUNC(g, handle_error) (g, cp, ")");
                0195     *valp = 1; /* XXX */
                0196     return cp + 1;
                0197 
                0198       case 'd':
                0199     if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
                0200         int paren = 0;
                0201         cp += 7;
                0202         SKIPSPACE (cp);
                0203         if (*cp == '(') {
                0204         paren = 1;
                0205         cp++;
                0206         }
                0207         DO (cp = parse_variable (g, cp, &var));
                0208         SKIPSPACE (cp);
                0209         if (paren && *cp != ')')
                0210         return CALLFUNC(g, handle_error) (g, cp, ")");
                0211         *valp = (*(g->funcs.eval_defined)) (g, var, cp - var);
                0212         return cp + paren;      /* skip the right paren */
                0213     }
                0214     /* fall out */
                0215     }
                0216 
                0217     if (isdigit(*cp)) {
                0218     DO (cp = parse_number (g, cp, valp));
                0219     } else if (!isvarfirstletter(*cp))
                0220     return CALLFUNC(g, handle_error) (g, cp, "variable or number");
                0221     else {
                0222     DO (cp = parse_variable (g, cp, &var));
                0223     *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
                0224     }
                0225     
                0226     return cp;
                0227 }
                0228 
                0229 
                0230 
                0231 static const char *
                0232 parse_product (g, cp, valp)
                0233     IfParser *g;
                0234     const char *cp;
                0235     int *valp;
                0236 {
                0237     int rightval;
                0238 
                0239     DO (cp = parse_value (g, cp, valp));
                0240     SKIPSPACE (cp);
                0241 
                0242     switch (*cp) {
                0243       case '*':
                0244     DO (cp = parse_product (g, cp + 1, &rightval));
                0245     *valp = (*valp * rightval);
                0246     break;
                0247 
                0248       case '/':
                0249     DO (cp = parse_product (g, cp + 1, &rightval));
                0250     *valp = (*valp / rightval);
                0251     break;
                0252 
                0253       case '%':
                0254     DO (cp = parse_product (g, cp + 1, &rightval));
                0255     *valp = (*valp % rightval);
                0256     break;
                0257     }
                0258     return cp;
                0259 }
                0260 
                0261 
                0262 static const char *
                0263 parse_sum (g, cp, valp)
                0264     IfParser *g;
                0265     const char *cp;
                0266     int *valp;
                0267 {
                0268     int rightval;
                0269 
                0270     DO (cp = parse_product (g, cp, valp));
                0271     SKIPSPACE (cp);
                0272 
                0273     switch (*cp) {
                0274       case '+':
                0275     DO (cp = parse_sum (g, cp + 1, &rightval));
                0276     *valp = (*valp + rightval);
                0277     break;
                0278 
                0279       case '-':
                0280     DO (cp = parse_sum (g, cp + 1, &rightval));
                0281     *valp = (*valp - rightval);
                0282     break;
                0283     }
                0284     return cp;
                0285 }
                0286 
                0287 
                0288 static const char *
                0289 parse_shift (g, cp, valp)
                0290     IfParser *g;
                0291     const char *cp;
                0292     int *valp;
                0293 {
                0294     int rightval;
                0295 
                0296     DO (cp = parse_sum (g, cp, valp));
                0297     SKIPSPACE (cp);
                0298 
                0299     switch (*cp) {
                0300       case '<':
                0301     if (cp[1] == '<') {
                0302         DO (cp = parse_shift (g, cp + 2, &rightval));
                0303         *valp = (*valp << rightval);
                0304     }
                0305     break;
                0306 
                0307       case '>':
                0308     if (cp[1] == '>') {
                0309         DO (cp = parse_shift (g, cp + 2, &rightval));
                0310         *valp = (*valp >> rightval);
                0311     }
                0312     break;
                0313     }
                0314     return cp;
                0315 }
                0316 
                0317 
                0318 static const char *
                0319 parse_inequality (g, cp, valp)
                0320     IfParser *g;
                0321     const char *cp;
                0322     int *valp;
                0323 {
                0324     int rightval;
                0325 
                0326     DO (cp = parse_shift (g, cp, valp));
                0327     SKIPSPACE (cp);
                0328 
                0329     switch (*cp) {
                0330       case '<':
                0331     if (cp[1] == '=') {
                0332         DO (cp = parse_inequality (g, cp + 2, &rightval));
                0333         *valp = (*valp <= rightval);
                0334     } else {
                0335         DO (cp = parse_inequality (g, cp + 1, &rightval));
                0336         *valp = (*valp < rightval);
                0337     }
                0338     break;
                0339 
                0340       case '>':
                0341     if (cp[1] == '=') {
                0342         DO (cp = parse_inequality (g, cp + 2, &rightval));
                0343         *valp = (*valp >= rightval);
                0344     } else {
                0345         DO (cp = parse_inequality (g, cp + 1, &rightval));
                0346         *valp = (*valp > rightval);
                0347     }
                0348     break;
                0349     }
                0350     return cp;
                0351 }
                0352 
                0353 
                0354 static const char *
                0355 parse_equality (g, cp, valp)
                0356     IfParser *g;
                0357     const char *cp;
                0358     int *valp;
                0359 {
                0360     int rightval;
                0361 
                0362     DO (cp = parse_inequality (g, cp, valp));
                0363     SKIPSPACE (cp);
                0364 
                0365     switch (*cp) {
                0366       case '=':
                0367     if (cp[1] == '=')
                0368         cp++;
                0369     DO (cp = parse_equality (g, cp + 1, &rightval));
                0370     *valp = (*valp == rightval);
                0371     break;
                0372 
                0373       case '!':
                0374     if (cp[1] != '=')
                0375         break;
                0376     DO (cp = parse_equality (g, cp + 2, &rightval));
                0377     *valp = (*valp != rightval);
                0378     break;
                0379     }
                0380     return cp;
                0381 }
                0382 
                0383 
                0384 static const char *
                0385 parse_band (g, cp, valp)
                0386     IfParser *g;
                0387     const char *cp;
                0388     int *valp;
                0389 {
                0390     int rightval;
                0391 
                0392     DO (cp = parse_equality (g, cp, valp));
                0393     SKIPSPACE (cp);
                0394 
                0395     switch (*cp) {
                0396       case '&':
                0397     if (cp[1] != '&') {
                0398         DO (cp = parse_band (g, cp + 1, &rightval));
                0399         *valp = (*valp & rightval);
                0400     }
                0401     break;
                0402     }
                0403     return cp;
                0404 }
                0405 
                0406 
                0407 static const char *
                0408 parse_bor (g, cp, valp)
                0409     IfParser *g;
                0410     const char *cp;
                0411     int *valp;
                0412 {
                0413     int rightval;
                0414 
                0415     DO (cp = parse_band (g, cp, valp));
                0416     SKIPSPACE (cp);
                0417 
                0418     switch (*cp) {
                0419       case '|':
                0420     if (cp[1] != '|') {
                0421         DO (cp = parse_bor (g, cp + 1, &rightval));
                0422         *valp = (*valp | rightval);
                0423     }
                0424     break;
                0425     }
                0426     return cp;
                0427 }
                0428 
                0429 
                0430 static const char *
                0431 parse_land (g, cp, valp)
                0432     IfParser *g;
                0433     const char *cp;
                0434     int *valp;
                0435 {
                0436     int rightval;
                0437 
                0438     DO (cp = parse_bor (g, cp, valp));
                0439     SKIPSPACE (cp);
                0440 
                0441     switch (*cp) {
                0442       case '&':
                0443     if (cp[1] != '&')
                0444         return CALLFUNC(g, handle_error) (g, cp, "&&");
                0445     DO (cp = parse_land (g, cp + 2, &rightval));
                0446     *valp = (*valp && rightval);
                0447     break;
                0448     }
                0449     return cp;
                0450 }
                0451 
                0452 
                0453 static const char *
                0454 parse_lor (g, cp, valp)
                0455     IfParser *g;
                0456     const char *cp;
                0457     int *valp;
                0458 {
                0459     int rightval;
                0460 
                0461     DO (cp = parse_land (g, cp, valp));
                0462     SKIPSPACE (cp);
                0463 
                0464     switch (*cp) {
                0465       case '|':
                0466     if (cp[1] != '|')
                0467         return CALLFUNC(g, handle_error) (g, cp, "||");
                0468     DO (cp = parse_lor (g, cp + 2, &rightval));
                0469     *valp = (*valp || rightval);
                0470     break;
                0471     }
                0472     return cp;
                0473 }
                0474 
                0475 
                0476 /****************************************************************************
                0477                  External Entry Points
                0478  ****************************************************************************/
                0479 
                0480 const char *
                0481 ParseIfExpression (g, cp, valp)
                0482     IfParser *g;
                0483     const char *cp;
                0484     int *valp;
                0485 {
                0486     return parse_lor (g, cp, valp);
                0487 }
                0488 
                0489