00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include "ifparser.h"
00064 #include <ctype.h>
00065 #include <string.h>
00066
00067 extern long strtol(const char *nptr, char **endptr, int base);
00068
00069
00070
00071
00072
00073 #define DO(val) if (!(val)) return NULL
00074 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
00075 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
00076 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
00077
00078
00079 static const char *
00080 parse_variable(g, cp, varp)
00081 IfParser *g;
00082 const char *cp;
00083 const char **varp;
00084 {
00085 SKIPSPACE(cp);
00086
00087 if (!isvarfirstletter(*cp))
00088 return CALLFUNC(g, handle_error)(g, cp, "variable name");
00089
00090 *varp = cp;
00091
00092 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
00093 return cp;
00094 }
00095
00096
00097 static const char *
00098 parse_number(g, cp, valp)
00099 IfParser *g;
00100 const char *cp;
00101 long *valp;
00102 {
00103 SKIPSPACE(cp);
00104
00105 if (!isdigit(*cp))
00106 return CALLFUNC(g, handle_error)(g, cp, "number");
00107
00108 *valp = strtol(cp, &cp, 0);
00109
00110 while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
00111 #if 0
00112 *valp = atoi(cp);
00113
00114 for (cp++; isdigit(*cp); cp++) ;
00115 #endif
00116 return cp;
00117 }
00118
00119 static const char *
00120 parse_character(g, cp, valp)
00121 IfParser *g;
00122 const char *cp;
00123 long *valp;
00124 {
00125 char val;
00126 if (g) { }
00127
00128 SKIPSPACE(cp);
00129 if (*cp == '\\')
00130 switch (cp[1]) {
00131 case 'n':
00132 val = '\n';
00133 break;
00134 case 't':
00135 val = '\t';
00136 break;
00137 case 'v':
00138 val = '\v';
00139 break;
00140 case 'b':
00141 val = '\b';
00142 break;
00143 case 'r':
00144 val = '\r';
00145 break;
00146 case 'f':
00147 val = '\f';
00148 break;
00149 case 'a':
00150 val = '\a';
00151 break;
00152 case '\\':
00153 val = '\\';
00154 break;
00155 case '?':
00156 val = '\?';
00157 break;
00158 case '\'':
00159 val = '\'';
00160 break;
00161 case '\"':
00162 val = '\"';
00163 break;
00164 case 'x':
00165 val = (char) strtol(cp + 2, NULL, 16);
00166 break;
00167 default:
00168 val = (char) strtol(cp + 1, NULL, 8);
00169 break;
00170 }
00171 else
00172 val = *cp;
00173 while (*cp != '\'') cp++;
00174 *valp = (long) val;
00175 return cp;
00176 }
00177
00178 static const char *
00179 parse_value(g, cp, valp)
00180 IfParser *g;
00181 const char *cp;
00182 long *valp;
00183 {
00184 const char *var;
00185
00186 *valp = 0;
00187
00188 SKIPSPACE(cp);
00189 if (!*cp)
00190 return cp;
00191
00192 switch (*cp) {
00193 case '(':
00194 DO(cp = ParseIfExpression(g, cp + 1, valp));
00195 SKIPSPACE(cp);
00196 if (*cp != ')')
00197 return CALLFUNC(g, handle_error)(g, cp, ")");
00198
00199 return cp + 1;
00200
00201 case '!':
00202 DO(cp = parse_value(g, cp + 1, valp));
00203 *valp = !(*valp);
00204 return cp;
00205
00206 case '-':
00207 DO(cp = parse_value(g, cp + 1, valp));
00208 *valp = -(*valp);
00209 return cp;
00210
00211 case '~':
00212 DO(cp = parse_value(g, cp + 1, valp));
00213 *valp = ~(*valp);
00214 return cp;
00215
00216 case '#':
00217 DO(cp = parse_variable(g, cp + 1, &var));
00218 SKIPSPACE(cp);
00219 if (*cp != '(')
00220 return CALLFUNC(g, handle_error)(g, cp, "(");
00221 do {
00222 DO(cp = parse_variable(g, cp + 1, &var));
00223 SKIPSPACE(cp);
00224 } while (*cp && *cp != ')');
00225 if (*cp != ')')
00226 return CALLFUNC(g, handle_error)(g, cp, ")");
00227 *valp = 1;
00228 return cp + 1;
00229
00230 case '\'':
00231 DO(cp = parse_character(g, cp + 1, valp));
00232 if (*cp != '\'')
00233 return CALLFUNC(g, handle_error)(g, cp, "'");
00234 return cp + 1;
00235
00236 case 'd':
00237 if (strncmp(cp, "defined", 7) == 0 && !isalnum(cp[7])) {
00238 int paren = 0;
00239 int len;
00240
00241 cp += 7;
00242 SKIPSPACE(cp);
00243 if (*cp == '(') {
00244 paren = 1;
00245 cp++;
00246 }
00247 DO(cp = parse_variable(g, cp, &var));
00248 len = cp - var;
00249 SKIPSPACE(cp);
00250 if (paren && *cp != ')')
00251 return CALLFUNC(g, handle_error)(g, cp, ")");
00252 *valp = (*(g->funcs.eval_defined))(g, var, len);
00253 return cp + paren;
00254 }
00255
00256 }
00257
00258 if (isdigit(*cp)) {
00259 DO(cp = parse_number(g, cp, valp));
00260 } else if (!isvarfirstletter(*cp))
00261 return CALLFUNC(g, handle_error)(g, cp, "variable or number");
00262 else {
00263 DO(cp = parse_variable(g, cp, &var));
00264 *valp = (*(g->funcs.eval_variable))(g, var, cp - var);
00265 }
00266
00267 return cp;
00268 }
00269
00270
00271
00272 static const char *
00273 parse_product(g, cp, valp)
00274 IfParser *g;
00275 const char *cp;
00276 long *valp;
00277 {
00278 long rightval;
00279
00280 DO(cp = parse_value(g, cp, valp));
00281 SKIPSPACE(cp);
00282
00283 switch (*cp) {
00284 case '*':
00285 DO(cp = parse_product(g, cp + 1, &rightval));
00286 *valp = (*valp * rightval);
00287 break;
00288
00289 case '/':
00290 DO(cp = parse_product(g, cp + 1, &rightval));
00291 if (rightval)
00292 *valp = (*valp / rightval);
00293 break;
00294
00295 case '%':
00296 DO(cp = parse_product(g, cp + 1, &rightval));
00297 if (rightval)
00298 *valp = (*valp % rightval);
00299 break;
00300 }
00301 return cp;
00302 }
00303
00304
00305 static const char *
00306 parse_sum(g, cp, valp)
00307 IfParser *g;
00308 const char *cp;
00309 long *valp;
00310 {
00311 long rightval;
00312
00313 DO(cp = parse_product(g, cp, valp));
00314 SKIPSPACE(cp);
00315
00316 switch (*cp) {
00317 case '+':
00318 DO(cp = parse_sum(g, cp + 1, &rightval));
00319 *valp = (*valp + rightval);
00320 break;
00321
00322 case '-':
00323 DO(cp = parse_sum(g, cp + 1, &rightval));
00324 *valp = (*valp - rightval);
00325 break;
00326 }
00327 return cp;
00328 }
00329
00330
00331 static const char *
00332 parse_shift(g, cp, valp)
00333 IfParser *g;
00334 const char *cp;
00335 long *valp;
00336 {
00337 long rightval;
00338
00339 DO(cp = parse_sum(g, cp, valp));
00340 SKIPSPACE(cp);
00341
00342 switch (*cp) {
00343 case '<':
00344 if (cp[1] == '<') {
00345 DO(cp = parse_shift(g, cp + 2, &rightval));
00346 *valp = (*valp << rightval);
00347 }
00348 break;
00349
00350 case '>':
00351 if (cp[1] == '>') {
00352 DO(cp = parse_shift(g, cp + 2, &rightval));
00353 *valp = (*valp >> rightval);
00354 }
00355 break;
00356 }
00357 return cp;
00358 }
00359
00360
00361 static const char *
00362 parse_inequality(g, cp, valp)
00363 IfParser *g;
00364 const char *cp;
00365 long *valp;
00366 {
00367 long rightval;
00368
00369 DO(cp = parse_shift(g, cp, valp));
00370 SKIPSPACE(cp);
00371
00372 switch (*cp) {
00373 case '<':
00374 if (cp[1] == '=') {
00375 DO(cp = parse_inequality(g, cp + 2, &rightval));
00376 *valp = (*valp <= rightval);
00377 } else {
00378 DO(cp = parse_inequality(g, cp + 1, &rightval));
00379 *valp = (*valp < rightval);
00380 }
00381 break;
00382
00383 case '>':
00384 if (cp[1] == '=') {
00385 DO(cp = parse_inequality(g, cp + 2, &rightval));
00386 *valp = (*valp >= rightval);
00387 } else {
00388 DO(cp = parse_inequality(g, cp + 1, &rightval));
00389 *valp = (*valp > rightval);
00390 }
00391 break;
00392 }
00393 return cp;
00394 }
00395
00396
00397 static const char *
00398 parse_equality(g, cp, valp)
00399 IfParser *g;
00400 const char *cp;
00401 long *valp;
00402 {
00403 long rightval;
00404
00405 DO(cp = parse_inequality(g, cp, valp));
00406 SKIPSPACE(cp);
00407
00408 switch (*cp) {
00409 case '=':
00410 if (cp[1] == '=')
00411 cp++;
00412 DO(cp = parse_equality(g, cp + 1, &rightval));
00413 *valp = (*valp == rightval);
00414 break;
00415
00416 case '!':
00417 if (cp[1] != '=')
00418 break;
00419 DO(cp = parse_equality(g, cp + 2, &rightval));
00420 *valp = (*valp != rightval);
00421 break;
00422 }
00423 return cp;
00424 }
00425
00426
00427 static const char *
00428 parse_band(g, cp, valp)
00429 IfParser *g;
00430 const char *cp;
00431 long *valp;
00432 {
00433 long rightval;
00434
00435 DO(cp = parse_equality(g, cp, valp));
00436 SKIPSPACE(cp);
00437
00438 switch (*cp) {
00439 case '&':
00440 if (cp[1] != '&') {
00441 DO(cp = parse_band(g, cp + 1, &rightval));
00442 *valp = (*valp & rightval);
00443 }
00444 break;
00445 }
00446 return cp;
00447 }
00448
00449
00450 static const char *
00451 parse_bxor(g, cp, valp)
00452 IfParser *g;
00453 const char *cp;
00454 long *valp;
00455 {
00456 long rightval;
00457
00458 DO(cp = parse_band(g, cp, valp));
00459 SKIPSPACE(cp);
00460
00461 switch (*cp) {
00462 case '^':
00463 DO(cp = parse_bxor(g, cp + 1, &rightval));
00464 *valp = (*valp ^ rightval);
00465 break;
00466 }
00467 return cp;
00468 }
00469
00470
00471 static const char *
00472 parse_bor(g, cp, valp)
00473 IfParser *g;
00474 const char *cp;
00475 long *valp;
00476 {
00477 long rightval;
00478
00479 DO(cp = parse_bxor(g, cp, valp));
00480 SKIPSPACE(cp);
00481
00482 switch (*cp) {
00483 case '|':
00484 if (cp[1] != '|') {
00485 DO(cp = parse_bor(g, cp + 1, &rightval));
00486 *valp = (*valp | rightval);
00487 }
00488 break;
00489 }
00490 return cp;
00491 }
00492
00493
00494 static const char *
00495 parse_land(g, cp, valp)
00496 IfParser *g;
00497 const char *cp;
00498 long *valp;
00499 {
00500 long rightval;
00501
00502 DO(cp = parse_bor(g, cp, valp));
00503 SKIPSPACE(cp);
00504
00505 switch (*cp) {
00506 case '&':
00507 if (cp[1] != '&')
00508 return CALLFUNC(g, handle_error)(g, cp, "&&");
00509 DO(cp = parse_land(g, cp + 2, &rightval));
00510 *valp = (*valp && rightval);
00511 break;
00512 }
00513 return cp;
00514 }
00515
00516
00517 static const char *
00518 parse_lor(g, cp, valp)
00519 IfParser *g;
00520 const char *cp;
00521 long *valp;
00522 {
00523 long rightval;
00524
00525 DO(cp = parse_land(g, cp, valp));
00526 SKIPSPACE(cp);
00527
00528 switch (*cp) {
00529 case '|':
00530 if (cp[1] != '|')
00531 return CALLFUNC(g, handle_error)(g, cp, "||");
00532 DO(cp = parse_lor(g, cp + 2, &rightval));
00533 *valp = (*valp || rightval);
00534 break;
00535 }
00536 return cp;
00537 }
00538
00539
00540 static const char *
00541 parse_cond(g, cp, valp)
00542 IfParser *g;
00543 const char *cp;
00544 long *valp;
00545 {
00546 long trueval, falseval;
00547
00548 DO(cp = parse_lor(g, cp, valp));
00549 SKIPSPACE(cp);
00550
00551 switch (*cp) {
00552 case '?':
00553 DO(cp = parse_cond(g, cp + 1, &trueval));
00554 SKIPSPACE(cp);
00555 if (*cp != ':')
00556 return CALLFUNC(g, handle_error)(g, cp, ":");
00557 DO(cp = parse_cond(g, cp + 1, &falseval));
00558 *valp = (*valp ? trueval : falseval);
00559 break;
00560 }
00561 return cp;
00562 }
00563
00564
00565
00566
00567
00568
00569 const char *
00570 ParseIfExpression(g, cp, valp)
00571 IfParser *g;
00572 const char *cp;
00573 long *valp;
00574 {
00575 return parse_cond(g, cp, valp);
00576 }