Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

eval.c File Reference

#include <stdlib.h>
#include <string.h>
#include "cpp.h"

Include dependency graph for eval.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  pri
struct  value

Defines

#define ARITH   2
#define LOGIC   3
#define NSTAK   32
#define RELAT   1
#define SGN   0
#define SHIFT   5
#define SPCL   4
#define UNARY   6
#define UND   2
#define UNS   1
#define UNSMARK   0x1000

Functions

int digit (int i)
long eval (Tokenrow *trp, int kw)
int evalop (struct pri)
value tokval (Token *)

Variables

pri priority []
value vals [NSTAK]
valuevp


Define Documentation

#define ARITH   2
 

Definition at line 19 of file eval.c.

Referenced by evalop().

#define LOGIC   3
 

Definition at line 20 of file eval.c.

Referenced by evalop().

#define NSTAK   32
 

Definition at line 5 of file eval.c.

#define RELAT   1
 

Definition at line 18 of file eval.c.

Referenced by evalop().

#define SGN   0
 

Definition at line 6 of file eval.c.

#define SHIFT   5
 

Definition at line 22 of file eval.c.

Referenced by evalop().

#define SPCL   4
 

Definition at line 21 of file eval.c.

Referenced by evalop().

#define UNARY   6
 

Definition at line 23 of file eval.c.

Referenced by evalop().

#define UND   2
 

Definition at line 8 of file eval.c.

Referenced by evalop().

#define UNS   1
 

Definition at line 7 of file eval.c.

Referenced by evalop().

#define UNSMARK   0x1000
 

Definition at line 10 of file eval.c.

Referenced by evalop().


Function Documentation

int digit int  i  ) 
 

Definition at line 509 of file eval.c.

References i.

Referenced by tokval().

00510 {
00511     if ('0'<=i && i<='9')
00512         i -= '0';
00513     else if ('a'<=i && i<='f')
00514         i -= 'a'-10;
00515     else if ('A'<=i && i<='F')
00516         i -= 'A'-10;
00517     else
00518         i = -1;
00519     return i;
00520 }

long eval Tokenrow trp,
int  kw
 

Definition at line 102 of file eval.c.

References AND, tokenrow::bp, CCON, CIRC, COLON, COMMA, DEFINED, END, EQ, ERROR, error(), evalop(), expandrow(), nlist::flag, GEQ, GT, ISDEFINED, KIFDEF, kwdefined, LAND, LEQ, lookup(), LOR, LP, tokenrow::lp, LSH, LT, MINUS, NAME, NAME1, NEQ, NL, Nlist, NOT, np, NUMBER, op, OR, PCT, PLUS, priority, QUEST, rand(), RP, RSH, SLASH, STAR, STRING, TILDE, Token, Tokenrow, tokval(), tokenrow::tp, value::type, token::type, value::val, nlist::val, vals, vp, and WS.

Referenced by control().

00103 {
00104     Token *tp;
00105     Nlist *np;
00106     int ntok, rand;
00107 
00108     trp->tp++;
00109     if (kw==KIFDEF || kw==KIFNDEF) {
00110         if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) {
00111             error(ERROR, "Syntax error in #ifdef/#ifndef");
00112             return 0;
00113         }
00114         np = lookup(trp->tp, 0);
00115         return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC));
00116     }
00117     ntok = trp->tp - trp->bp;
00118     kwdefined->val = KDEFINED;  /* activate special meaning of defined */
00119     expandrow(trp, "<if>");
00120     kwdefined->val = NAME;
00121     vp = vals;
00122     op = ops;
00123     *op++ = END;
00124     for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) {
00125         switch(tp->type) {
00126         case WS:
00127         case NL:
00128             continue;
00129 
00130         /* nilary */
00131         case NAME:
00132         case NAME1:
00133         case NUMBER:
00134         case CCON:
00135         case STRING:
00136             if (rand)
00137                 goto syntax;
00138             *vp++ = tokval(tp);
00139             rand = 1;
00140             continue;
00141 
00142         /* unary */
00143         case DEFINED:
00144         case TILDE:
00145         case NOT:
00146             if (rand)
00147                 goto syntax;
00148             *op++ = tp->type;
00149             continue;
00150 
00151         /* unary-binary */
00152         case PLUS: case MINUS: case STAR: case AND:
00153             if (rand==0) {
00154                 if (tp->type==MINUS)
00155                     *op++ = UMINUS;
00156                 if (tp->type==STAR || tp->type==AND) {
00157                     error(ERROR, "Illegal operator * or & in #if/#elsif");
00158                     return 0;
00159                 }
00160                 continue;
00161             }
00162             /* flow through */
00163 
00164         /* plain binary */
00165         case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:
00166         case LAND: case LOR: case SLASH: case PCT:
00167         case LT: case GT: case CIRC: case OR: case QUEST:
00168         case COLON: case COMMA:
00169             if (rand==0)
00170                 goto syntax;
00171             if (evalop(priority[tp->type])!=0)
00172                 return 0;
00173             *op++ = tp->type;
00174             rand = 0;
00175             continue;
00176 
00177         case LP:
00178             if (rand)
00179                 goto syntax;
00180             *op++ = LP;
00181             continue;
00182 
00183         case RP:
00184             if (!rand)
00185                 goto syntax;
00186             if (evalop(priority[RP])!=0)
00187                 return 0;
00188             if (op<=ops || op[-1]!=LP) {
00189                 goto syntax;
00190             }
00191             op--;
00192             continue;
00193 
00194         default:
00195             error(ERROR,"Bad operator (%t) in #if/#elsif", tp);
00196             return 0;
00197         }
00198     }
00199     if (rand==0)
00200         goto syntax;
00201     if (evalop(priority[END])!=0)
00202         return 0;
00203     if (op!=&ops[1] || vp!=&vals[1]) {
00204         error(ERROR, "Botch in #if/#elsif");
00205         return 0;
00206     }
00207     if (vals[0].type==UND)
00208         error(ERROR, "Undefined expression value");
00209     return vals[0].val;
00210 syntax:
00211     error(ERROR, "Syntax error in #if/#elsif");
00212     return 0;
00213 }

Here is the call graph for this function:

int evalop struct  pri  ) 
 

Definition at line 216 of file eval.c.

References AND, ARITH, pri::arity, CIRC, COLON, pri::ctype, DEFINED, EQ, ERROR, error(), GEQ, GT, LAND, LEQ, LOGIC, LOR, LSH, LT, MINUS, NEQ, NOT, op, OR, PCT, PLUS, pri::pri, priority, RELAT, RSH, SHIFT, SLASH, SPCL, STAR, TILDE, value::type, UMINUS, UNARY, UND, UNS, UNSMARK, v1, v2, value::val, vp, and WARNING.

Referenced by eval().

00217 {
00218     struct value v1, v2;
00219     long rv1, rv2;
00220     int rtype, oper;
00221 
00222     rv2=0;
00223     rtype=0;
00224     while (pri.pri < priority[op[-1]].pri) {
00225         oper = *--op;
00226         if (priority[oper].arity==2) {
00227             v2 = *--vp;
00228             rv2 = v2.val;
00229         }
00230         v1 = *--vp;
00231         rv1 = v1.val;
00232 /*lint -e574 -e644 */
00233         switch (priority[oper].ctype) {
00234         case 0:
00235         default:
00236             error(WARNING, "Syntax error in #if/#endif");
00237             return 1;
00238         case ARITH:
00239         case RELAT:
00240             if (v1.type==UNS || v2.type==UNS)
00241                 rtype = UNS;
00242             else
00243                 rtype = SGN;
00244             if (v1.type==UND || v2.type==UND)
00245                 rtype = UND;
00246             if (priority[oper].ctype==RELAT && rtype==UNS) {
00247                 oper |= UNSMARK;
00248                 rtype = SGN;
00249             }
00250             break;
00251         case SHIFT:
00252             if (v1.type==UND || v2.type==UND)
00253                 rtype = UND;
00254             else
00255                 rtype = v1.type;
00256             if (rtype==UNS)
00257                 oper |= UNSMARK;
00258             break;
00259         case UNARY:
00260             rtype = v1.type;
00261             break;
00262         case LOGIC:
00263         case SPCL:
00264             break;
00265         }
00266         switch (oper) {
00267         case EQ: case EQ|UNSMARK:
00268             rv1 = rv1==rv2; break;
00269         case NEQ: case NEQ|UNSMARK:
00270             rv1 = rv1!=rv2; break;
00271         case LEQ:
00272             rv1 = rv1<=rv2; break;
00273         case GEQ:
00274             rv1 = rv1>=rv2; break;
00275         case LT:
00276             rv1 = rv1<rv2; break;
00277         case GT:
00278             rv1 = rv1>rv2; break;
00279         case LEQ|UNSMARK:
00280             rv1 = (unsigned long)rv1<=rv2; break;
00281         case GEQ|UNSMARK:
00282             rv1 = (unsigned long)rv1>=rv2; break;
00283         case LT|UNSMARK:
00284             rv1 = (unsigned long)rv1<rv2; break;
00285         case GT|UNSMARK:
00286             rv1 = (unsigned long)rv1>rv2; break;
00287         case LSH:
00288             rv1 <<= rv2; break;
00289         case LSH|UNSMARK:
00290             rv1 = (unsigned long)rv1<<rv2; break;
00291         case RSH:
00292             rv1 >>= rv2; break;
00293         case RSH|UNSMARK:
00294             rv1 = (unsigned long)rv1>>rv2; break;
00295         case LAND:
00296             rtype = UND;
00297             if (v1.type==UND)
00298                 break;
00299             if (rv1!=0) {
00300                 if (v2.type==UND)
00301                     break;
00302                 rv1 = rv2!=0;
00303             } else
00304                 rv1 = 0;
00305             rtype = SGN;
00306             break;
00307         case LOR:
00308             rtype = UND;
00309             if (v1.type==UND)
00310                 break;
00311             if (rv1==0) {
00312                 if (v2.type==UND)
00313                     break;
00314                 rv1 = rv2!=0;
00315             } else
00316                 rv1 = 1;
00317             rtype = SGN;
00318             break;
00319         case AND:
00320             rv1 &= rv2; break;
00321         case STAR:
00322             rv1 *= rv2; break;
00323         case PLUS:
00324             rv1 += rv2; break;
00325         case MINUS:
00326             rv1 -= rv2; break;
00327         case UMINUS:
00328             if (v1.type==UND)
00329                 rtype = UND;
00330             rv1 = -rv1; break;
00331         case OR:
00332             rv1 |= rv2; break;
00333         case CIRC:
00334             rv1 ^= rv2; break;
00335         case TILDE:
00336             rv1 = ~rv1; break;
00337         case NOT:
00338             rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;
00339         case SLASH:
00340             if (rv2==0) {
00341                 rtype = UND;
00342                 break;
00343             }
00344             if (rtype==UNS)
00345                 rv1 /= (unsigned long)rv2;
00346             else
00347                 rv1 /= rv2;
00348             break;
00349         case PCT:
00350             if (rv2==0) {
00351                 rtype = UND;
00352                 break;
00353             }
00354             if (rtype==UNS)
00355                 rv1 %= (unsigned long)rv2;
00356             else
00357                 rv1 %= rv2;
00358             break;
00359         case COLON:
00360             if (op[-1] != QUEST)
00361                 error(ERROR, "Bad ?: in #if/endif");
00362             else {
00363                 op--;
00364                 if ((--vp)->val==0)
00365                     v1 = v2;
00366                 rtype = v1.type;
00367                 rv1 = v1.val;
00368             }
00369             break;
00370         case DEFINED:
00371             break;
00372         default:
00373             error(ERROR, "Eval botch (unknown operator)");
00374             return 1;
00375         }
00376 /*lint +e574 +e644 */
00377         v1.val = rv1;
00378         v1.type = rtype;
00379         *vp++ = v1;
00380     }
00381     return 0;
00382 }

Here is the call graph for this function:

struct value tokval Token  ) 
 

Definition at line 385 of file eval.c.

References c, CCON, digit(), ERROR, error(), nlist::flag, i, ISDEFINED, lookup(), n, NAME, NAME1, Nlist, np, NULL, NUMBER, p, STRING, Token, tokval(), value::type, uchar, v, value::val, and WARNING.

Referenced by eval(), and tokval().

00386 {
00387     struct value v;
00388     Nlist *np;
00389     int i, base, c;
00390     unsigned long n;
00391     uchar *p;
00392 
00393     v.type = SGN;
00394     v.val = 0;
00395     switch (tp->type) {
00396 
00397     case NAME:
00398         v.val = 0;
00399         break;
00400 
00401     case NAME1:
00402         if ((np = lookup(tp, 0)) != NULL && np->flag&(ISDEFINED|ISMAC))
00403             v.val = 1;
00404         break;
00405 
00406     case NUMBER:
00407         n = 0;
00408         base = 10;
00409         p = tp->t;
00410         c = p[tp->len];
00411         p[tp->len] = '\0';
00412         if (*p=='0') {
00413             base = 8;
00414             if (p[1]=='x' || p[1]=='X') {
00415                 base = 16;
00416                 p++;
00417             }
00418             p++;
00419         }
00420         for (;; p++) {
00421             if ((i = digit(*p)) < 0)
00422                 break;
00423             if (i>=base)
00424                 error(WARNING,
00425                   "Bad digit in number %t", tp);
00426             n *= base;
00427             n += i;
00428         }
00429         if (n>=0x80000000 && base!=10)
00430             v.type = UNS;
00431         for (; *p; p++) {
00432             if (*p=='u' || *p=='U')
00433                 v.type = UNS;
00434             else if (*p=='l' || *p=='L')
00435                 ;
00436             else {
00437                 error(ERROR,
00438                   "Bad number %t in #if/#elsif", tp);
00439                 break;
00440             }
00441         }
00442         v.val = n;
00443         tp->t[tp->len] = c;
00444         break;
00445 
00446     case CCON:
00447         n = 0;
00448         p = tp->t;
00449         if (*p=='L') {
00450             p += 1;
00451             error(WARNING, "Wide char constant value undefined");
00452         }
00453         p += 1;
00454         if (*p=='\\') {
00455             p += 1;
00456             if ((i = digit(*p))>=0 && i<=7) {
00457                 n = i;
00458                 p += 1;
00459                 if ((i = digit(*p))>=0 && i<=7) {
00460                     p += 1;
00461                     n <<= 3;
00462                     n += i;
00463                     if ((i = digit(*p))>=0 && i<=7) {
00464                         p += 1;
00465                         n <<= 3;
00466                         n += i;
00467                     }
00468                 }
00469             } else if (*p=='x') {
00470                 p += 1;
00471                 while ((i = digit(*p))>=0 && i<=15) {
00472                     p += 1;
00473                     n <<= 4;
00474                     n += i;
00475                 }
00476             } else {
00477                 static char cvcon[]
00478                   = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";
00479                 for (i=0; i<sizeof(cvcon); i+=2) {
00480                     if (*p == cvcon[i]) {
00481                         n = cvcon[i+1];
00482                         break;
00483                     }
00484                 }
00485                 p += 1;
00486                 if (i>=sizeof(cvcon))
00487                     error(WARNING,
00488                      "Undefined escape in character constant");
00489             }
00490         } else if (*p=='\'')
00491             error(ERROR, "Empty character constant");
00492         else
00493             n = *p++;
00494         if (*p!='\'')
00495             error(WARNING, "Multibyte character constant undefined");
00496         else if (n>127)
00497             error(WARNING, "Character constant taken as not signed");
00498         v.val = n;
00499         break;
00500 
00501     case STRING:
00502         error(ERROR, "String in #if/#elsif");
00503         break;
00504     }
00505     return v;
00506 }

Here is the call graph for this function:


Variable Documentation

struct pri priority[]
 

Referenced by eval(), and evalop().

struct value vals[NSTAK]
 

Definition at line 95 of file eval.c.

Referenced by caselabel(), and eval().

struct value * vp
 

Definition at line 95 of file eval.c.

Referenced by CPlugInManager::AddFaceToBrushHandle(), AddSkyPolygon(), eval(), evalop(), QERApp_AddFace(), QERApp_CommitBrushHandleToMap(), QERApp_DeleteBrushHandle(), QERApp_LoadTextureRGBA(), and stringify().


Generated on Thu Aug 25 15:47:33 2005 for Quake III Arena by  doxygen 1.3.9.1