1 /* $EPIC: expr2.c,v 1.19 2004/11/10 03:20:35 jnelson Exp $ */
2 /*
3 * Zsh: math.c,v 3.1.2.1 1997/06/01 06:13:15 hzoli Exp
4 * math.c - mathematical expression evaluation
5 * This file is based on 'math.c', which is part of zsh, the Z shell.
6 *
7 * Copyright (c) 1992-1997 Paul Falstad, All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the copyright notice,
13 * this list of conditions and the two following paragraphs.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimers in the
16 * documentation and/or other materials provided with the distribution
17 * 3. The names of the author(s) may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
21 * In no event shall Paul Falstad or the Zsh Development Group be liable
22 * to any party for direct, indirect, special, incidental, or consequential
23 * damages arising out of the use of this software and its documentation,
24 * even if Paul Falstad and the Zsh Development Group have been advised of
25 * the possibility of such damage.
26 *
27 * Paul Falstad and the Zsh Development Group specifically disclaim any
28 * warranties, including, but not limited to, the implied warranties of
29 * merchantability and fitness for a particular purpose. The software
30 * provided hereunder is on an "as is" basis, and Paul Falstad and the
31 * Zsh Development Group have no obligation to provide maintenance,
32 * support, updates, enhancements, or modifications.
33 *
34 */
35 /*
36 * Substantial modifications by Jeremy Nelson which are
37 * Coypright 1998, 2003 EPIC Software Labs, All rights reserved.
38 *
39 * You may distribute this file under the same terms as the above, by
40 * including the parties "Jeremy Nelson" and "EPIC Software Labs" to the
41 * limitations of liability and the express disclaimer of all warranties.
42 * This software is provided "AS IS".
43 */
44 #include <math.h>
45
46 #define STACKSZ 80
47 #define TOKENCOUNT 80
48 #define MAGIC_TOKEN -14
49
50 /*
51 * THIS IS THE "NEW NEW" MATH PARSER -- or shall I say, this is the
52 * new math parser, second edition.
53 */
54 /*
55 * Question: Why is this math parser so much more hideous than the old one?
56 *
57 * Answer: The implementation looks very very complex, and to a certain
58 * extent it is. However, do not be frightened by the malicious abuse of
59 * macros and the over-use of inline functions. The design of this math
60 * parser is not nearly as complex as its implementation. Maybe that is
61 * due to my not being the world's best C programmer, and I probably wrote
62 * this code too quickly. One of the most important design considerations
63 * was that it should be possible to prove correctness, while maintaining
64 * the possibility for general optimization. Those are conflicting goals
65 * and this implementation tries to balance the two.
66 */
67 /*
68 * Question: Why should I use this math parser instead of the old one?
69 *
70 * Answer: Like the old math parser, this new math parser evaluates infix
71 * notation expressions and returns the resulting value of the entire
72 * expression. Unlike the old math parser, this new math parser correctly
73 * obeys both operator precedence as well as associativity. It still can
74 * do short-circuiting of &&, ||, and ?: operators. All operands start
75 * off their life as text strings, but can be converted to and from other
76 * data types (such as floating point, integer, and boolean). Type conversion
77 * is automatic and efficient, and the results of every conversion is cached,
78 * so the conversion is only done once, and only when it is actually needed.
79 * This new math parser has a slew of new operators, as well as correct
80 * implementations of some of the old operators. This new math parser also
81 * handles both integer and floating point operations gracefully.
82 */
83 /*
84 * Question: Why is everything stored in a struct?
85 *
86 * Answer: All the information for each expression is stored in a struct.
87 * This is done so that there are no global variables in use (they're all
88 * collected making them easier to handle), and makes re-entrancy possible
89 * since you don't have to worry about whether or not all of the state
90 * information is accounted for (it's all on the stack).
91 */
92 /*
93 * Question: Why do you keep a 'symbol table' for each expression?
94 *
95 * By keeping a record of every direct symbol or derived symbol during
96 * the entire lifetime of the expression, we can be assured that we have
97 * a clean way to clean up after an expression (no memory leaks), and
98 * permit a reference to any operator to persist for the entire lifetime
99 * of the expression, without having to worry about who might be holding
100 * a reference to an operand (tokens never change over their lifetime).
101 * By refering to each token through an integer, rather than a pointer,
102 * we can also prevent stale pointers, which can cause crashes.
103 *
104 * This also solves several more problems. There is never any concern over
105 * whether or not a certain string is malloced(), or just who is responsible
106 * for free()ing it. If you need a value to stay around as a temporary value
107 * you can always tokenize() it and get a handle which you then use further.
108 * The value will not go away until the entire expression has been parsed.
109 */
110 /*
111 * Question: Why don't you support pre-compiled expressions?
112 *
113 * Because this implementation does not create a compiled spanning tree
114 * out of the expression before executing it, but rather tokenizes the
115 * operands and reduces the operations based on prior operations. Perhaps
116 * this might change in the future, but don't count on it. The lexer uses
117 * the results of prior operations to support such things as short circuits
118 * and changing that would be a big pain.
119 */
120
121 typedef int TOKEN;
122 typedef int BooL;
123
124 /*
125 * These flags tell us whether or not a given token has a useful value
126 * of the given type. This is used to tell us when we need to do automatic
127 * conversion, or whether the conversion was done before and we can just
128 * grab the cached value. These flags are used by the "used" field, and
129 * are cumulative.
130 */
131 #define USED_NONE 0
132 #define USED_LVAL 1 << 0
133 #define USED_RAW 1 << 1
134 #define USED_EXPANDED 1 << 2
135 #define USED_INTEGER 1 << 3
136 #define USED_FLOAT 1 << 4
137 #define USED_BOOLEAN 1 << 5
138
139 /*
140 * Theoretically, all these macros are independant because the return value of
141 * INT*FUNC is typecasted back to INTTYPE. One caveat is that INT2STR
142 * must return a malloc'd string.
143 */
144 #ifdef HAVE_LONG_LONG
145 typedef long long INTTYPE;
146 #define FORMAT "%lld"
147 #define STR2INT(x) ((INTTYPE)atoll(x))
148 #define INT2STR(x) (malloc_sprintf(NULL, FORMAT , (INTTYPE)(x)))
149 #else
150 typedef long INTTYPE;
151 #define FORMAT "%ld"
152 #define STR2INT(x) ((INTTYPE)atol(x))
153 #define INT2STR(x) (malloc_sprintf(NULL, FORMAT , (INTTYPE)(x)))
154 #endif
155
156 /*
157 * This is a symbol table entry.
158 */
159 typedef struct TOKEN_type
160 {
161 int used; /* Which fields contain useful info? */
162 char * lval; /* Cached unexpanded variable name */
163 char * raw_value; /* Cached unexpected string */
164 char * expanded_value; /* Cached full expanded string */
165 INTTYPE integer_value; /* Cached integer value */
166 double float_value; /* Cached floating point value */
167 short boolean_value; /* Cached boolean value */
168 } SYMBOL;
169
170 #define __inline
171
172 /*
173 * This is an expression context
174 */
175 typedef struct
176 {
177 /* POSITION AND STATE INFORMATION */
178 /*
179 * This is the current position in the lexing.
180 */
181 char *ptr;
182
183 /*
184 * When set, the expression is lexed, but nothing that may have a side
185 * effect (function calls, assignments, etc) are actually performed.
186 * Dummy values are instead substituted.
187 */
188 int noeval;
189
190 /*
191 * When set, this means the next token may either be a prefix operator
192 * or an operand. When clear, it means the next operator must be a
193 * non-prefix operator.
194 */
195 int operand;
196
197
198 /* TOKEN TABLE */
199 /*
200 * Each registered 'token' is given a TOKEN id. The idea is
201 * that we want TOKEN to be an opaque type to be used to refer
202 * to a token in a generic way, but in practice its just an integer
203 * offset into a char ** table. We register all tokens sequentially,
204 * so this just gets incremented when we want to register a new token.
205 */
206 TOKEN token;
207
208 /*
209 * This is the list of operand (string) tokens we have extracted
210 * so far from the expression. Offsets into this array are stored
211 * into the parsing stack.
212 */
213 SYMBOL tokens[TOKENCOUNT + 1];
214
215
216 /* OPERAND STACK */
217 /*
218 * This is the operand shift stack. These are the operands that
219 * are currently awaiting reduction. Note that rather than keeping
220 * track of the lvals and rvals here, we simply keep track of offsets
221 * to the 'tokens' table that actually stores all the relevant data.
222 * Then we can just call the token-class functions to get that data.
223 * This is more efficient because it allows us to recycle tokens
224 * more reasonably without wasteful malloc-copies.
225 */
226 TOKEN stack[STACKSZ + 1];
227
228 /* Current index to the operand stack */
229 int sp;
230
231 /* This is the last token that was lexed. */
232 TOKEN mtok;
233
234 /* This is set when an error happens */
235 int errflag;
236
237 TOKEN last_token;
238
239 const char *args;
240 int *args_flag;
241 } expr_info;
242
243 /*
244 * Useful macro to get at a specific token.
245 * 'c' is the expression context, 'v' is the token handle.
246 */
247 #define TOK(c, v) c->tokens[v]
248
249 /* Forward function references */
250 __inline static TOKEN tokenize_raw (expr_info *c, char *t);
251 static char * after_expando_special (expr_info *c);
252 static char * alias_special_char (char **buffer, char *ptr,
253 const char *args, char *quote_em,
254 int *args_flag);
255
256
257 /******************** EXPRESSION CONSTRUCTOR AND DESTRUCTOR ****************/
258 /*
259 * Clean the expression context pointed to by 'c'.
260 * This function must be called before you call mathparse().
261 */
setup_expr_info(expr_info * c)262 static void setup_expr_info (expr_info *c)
263 {
264 int i;
265
266 c->ptr = NULL;
267 c->noeval = 0;
268 c->operand = 1;
269 c->token = 0;
270 for (i = 0; i <= TOKENCOUNT; i++)
271 {
272 TOK(c, i).used = USED_NONE;
273 TOK(c, i).lval = NULL;
274 TOK(c, i).raw_value = NULL;
275 TOK(c, i).expanded_value = NULL;
276 TOK(c, i).integer_value = 0;
277 TOK(c, i).float_value = 0;
278 TOK(c, i).boolean_value = 0;
279 }
280 for (i = 0; i <= STACKSZ; i++)
281 c->stack[i] = 0;
282 c->sp = -1;
283 c->mtok = 0;
284 c->errflag = 0;
285 c->last_token = 0;
286 tokenize_raw(c, empty_string); /* Always token 0 */
287 }
288
289 /*
290 * Clean up the expression context pointed to by 'c'.
291 * This function must be called after you call mathparse().
292 */
destroy_expr_info(expr_info * c)293 static void destroy_expr_info (expr_info *c)
294 {
295 int i;
296
297 c->ptr = NULL;
298 c->noeval = -1;
299 c->operand = -1;
300 for (i = 0; i < c->token; i++)
301 {
302 TOK(c, i).used = USED_NONE;
303 new_free(&TOK(c, i).lval);
304 new_free(&TOK(c, i).raw_value);
305 new_free(&TOK(c, i).expanded_value);
306 }
307 c->token = -1;
308 for (i = 0; i <= STACKSZ; i++)
309 c->stack[i] = -1;
310 c->sp = -1;
311 c->mtok = -1;
312 c->errflag = -1;
313 c->last_token = -1;
314 }
315
316
317 /**************** TOKEN, PRECEDENCE, and ASSOCITIVITY TABLES ****************/
318 /*
319 * LR = left-to-right associativity
320 * RL = right-to-left associativity
321 * BOOL = short-circuiting boolean
322 */
323 #define LR 0
324 #define RL 1
325 #define BOOL 2
326
327 /*
328 * These are all the token-types. Each of the operators is represented,
329 * as is the generic operand type
330 */
331
332 enum LEX {
333 M_INPAR,
334 NOT, COMP, PREMINUS, PREPLUS,
335 UPLUS, UMINUS, STRLEN,
336 WORDC, DEREF,
337 POWER,
338 MUL, DIV, MOD,
339 PLUS, MINUS, STRCAT,
340 SHLEFT, SHRIGHT,
341 LES, LEQ, GRE, GEQ,
342 MATCH, NOMATCH,
343 DEQ, NEQ,
344 AND,
345 XOR,
346 OR,
347 DAND,
348 DXOR,
349 DOR,
350 QUEST, COLON,
351 EQ, PLUSEQ, MINUSEQ, MULEQ, DIVEQ,
352 MODEQ, ANDEQ, XOREQ, OREQ,
353 SHLEFTEQ, SHRIGHTEQ, DANDEQ, DOREQ,
354 DXOREQ, POWEREQ, STRCATEQ, STRPREEQ,
355 SWAP,
356 COMMA,
357 POSTMINUS, POSTPLUS,
358 ID,
359 M_OUTPAR,
360 ERROR,
361 EOI,
362 TOKCOUNT
363 };
364
365
366 /*
367 * Precedence table: Operators with a lower precedence VALUE have a higher
368 * precedence. The theory behind infix notation (algebraic notation) is that
369 * you have a sequence of operands seperated by (typically binary) operators.
370 * The problem of precedence is that each operand is surrounded by two
371 * operators, so it is ambiguous which operator the operand "binds" to. This
372 * is resolved by "precedence rules" which state that given two operators,
373 * which one is allowed to "reduce" (operate on) the operand. For a simple
374 * explanation, take the expression (3+4*5). Now the middle operand is a
375 * '4', but we dont know if it should be reduced via the plus, or via the
376 * multiply. If we look up both operators in the prec table, we see that
377 * multiply has the lower value -- therefore the 4 is reduced via the multiply
378 * and then the result of the multiply is reduced by the addition.
379 */
380 static int prec[TOKCOUNT] =
381 {
382 1,
383 2, 2, 2, 2,
384 2, 2, 2,
385 2, 2,
386 3,
387 4, 4, 4,
388 5, 5, 5,
389 6, 6,
390 7, 7, 7, 7,
391 8, 8,
392 9, 9,
393 10,
394 11,
395 12,
396 13,
397 14,
398 15,
399 16, 16,
400 17, 17, 17, 17, 17,
401 17, 17, 17, 17,
402 17, 17, 17, 17,
403 17, 17, 17, 17,
404 17,
405 18,
406 2, 2,
407 0,
408 137,
409 156,
410 200
411 };
412 #define TOPPREC 21
413
414
415 /*
416 * Associativity table: But precedence isnt enough. What happens when you
417 * have two identical operations to determine between? Well, the easy way
418 * is to say that the first operation is always done first. But some
419 * operators dont work that way (like the assignment operator) and always
420 * reduce the LAST (or rightmost) operation first. For example:
421 * (3+4+5) ((4+3)+5) (7+5) (12)
422 * (v1=v2=3) (v1=(v2=3)) (v1=3) (3)
423 * So for each operator we need to specify how to determine the precedence
424 * of the same operator against itself. This is called "associativity".
425 * Left-to-right associativity means that the operations occur left-to-right,
426 * or first-operator, first-reduced. Right-to-left associativity means
427 * that the operations occur right-to-left, or last-operator, first-reduced.
428 *
429 * We have a special case of associativity called BOOL, which is just a
430 * special type of left-to-right associtivity whereby the right hand side
431 * of the operand is not automatically parsed. (not really, but its the
432 * theory that counts.)
433 */
434 static int assoc[TOKCOUNT] =
435 {
436 LR,
437 RL, RL, RL, RL,
438 RL, RL, RL,
439 RL, RL,
440 RL,
441 LR, LR, LR,
442 LR, LR, LR,
443 LR, LR,
444 LR, LR, LR, LR,
445 LR, LR,
446 LR, LR,
447 LR,
448 LR,
449 LR,
450 BOOL,
451 BOOL,
452 BOOL,
453 RL, RL,
454 RL, RL, RL, RL, RL,
455 RL, RL, RL, RL,
456 RL, RL, RL, RL,
457 RL, RL, RL, RL,
458 RL,
459 LR,
460 RL, RL,
461 LR,
462 LR,
463 LR,
464 LR
465 };
466
467
468 /* ********************* CREATE NEW SYMBOLS AND TOKENS ********************/
469 /* Lvalues are stored via this routine */
tokenize_lval(expr_info * c,const char * t)470 __inline static TOKEN tokenize_lval (expr_info *c, const char *t)
471 {
472 if (c->token >= TOKENCOUNT)
473 {
474 error("Too many tokens for this expression");
475 return -1;
476 }
477 TOK(c, c->token).used = USED_LVAL;
478 malloc_strcpy(&TOK(c, c->token).lval, t);
479 return c->token++;
480 }
481
482 /*
483 * This is where we store our rvalues, kind of. What we really store here
484 * are all of the string operands from the original expression. Whenever
485 * one of the original operands is parsed, it is converted to a string and
486 * put in here and the index into the 'token' table is returned. Only the
487 * operands of the original expression go here. All derived operands (the
488 * result of operators) directly create "expanded" tokens.
489 */
490 /* THIS FUNCTION MAKES A NEW COPY OF 'T'. YOU MUST DISPOSE OF 'T' YOURSELF */
tokenize_raw(expr_info * c,char * t)491 __inline static TOKEN tokenize_raw (expr_info *c, char *t)
492 {
493 if (c->token >= TOKENCOUNT)
494 {
495 error("Too many tokens for this expression");
496 return -1;
497 }
498 TOK(c, c->token).used = USED_RAW;
499 malloc_strcpy(&TOK(c, c->token).raw_value, t);
500 return c->token++;
501 }
502
503 /*
504 * This is where any rvalues are stored. The result of any operation that
505 * yeilds a string creates an 'expanded' token. Tokens that begin life as
506 * 'expanded' tokens never can be passed through expand_alias() again. This
507 * protects against possible security holes in the client.
508 */
tokenize_expanded(expr_info * c,char * t)509 __inline static TOKEN tokenize_expanded (expr_info *c, char *t)
510 {
511 if (c->token >= TOKENCOUNT)
512 {
513 error("Too many tokens for this expression");
514 return -1;
515 }
516 TOK(c, c->token).used = USED_EXPANDED;
517 malloc_strcpy(&TOK(c, c->token).expanded_value, t);
518 return c->token++;
519 }
520
521 /*
522 * This creates an integer token. This is useful for quick operation on
523 * complex mathematical expressions, where conversions to and from strings
524 * is both expensive, and unnecesary. This type of token is created by
525 * integer-only operations like &, |, ^, <<, >>.
526 */
tokenize_integer(expr_info * c,INTTYPE t)527 __inline static TOKEN tokenize_integer (expr_info *c, INTTYPE t)
528 {
529 if (c->token >= TOKENCOUNT)
530 {
531 error("Too many tokens for this expression");
532 return -1;
533 }
534 TOK(c, c->token).used = USED_INTEGER;
535 TOK(c, c->token).integer_value = t;
536 return c->token++;
537 }
538
539 /*
540 * This creates a floating point token. This is useful for the same things
541 * that integer tokens are, and this is the token generated by floating
542 * point operations, such as +, -, *, /, %, **.
543 */
tokenize_float(expr_info * c,double t)544 __inline static TOKEN tokenize_float (expr_info *c, double t)
545 {
546 if (c->token >= TOKENCOUNT)
547 {
548 error("Too many tokens for this expression");
549 return -1;
550 }
551 TOK(c, c->token).used = USED_FLOAT;
552 TOK(c, c->token).float_value = t;
553 return c->token++;
554 }
555
556 /*
557 * This creates a boolean token. This is useful for the same things as
558 * integer tokens are. This token is generated by any sort of logic
559 * operation, such as ==, !=, >, <, &&, ||.
560 */
tokenize_bool(expr_info * c,BooL t)561 __inline static TOKEN tokenize_bool (expr_info *c, BooL t)
562 {
563 if (c->token >= TOKENCOUNT)
564 {
565 error("Too many tokens for this expression");
566 return -1;
567 }
568 TOK(c, c->token).used = USED_BOOLEAN;
569 TOK(c, c->token).boolean_value = t;
570 return c->token++;
571 }
572
573 /******************** RETRIEVE SYMBOLS FROM TOKEN HANDLES *******************/
574 /*
575 * These functions permit you to get at the tokens in various ways.
576 * There is a definite concept of each token being stored in several
577 * different representations: "raw" format (as the user specified it
578 * in the expression), "expanded" format (what the raw value looks like
579 * after it is passed through expand_alias), "integer" format (what the
580 * expanded value looks like after a call to atol()), "float" format,
581 * (what the expanded value looks like after a call to atof()), and
582 * "boolean" format (what the expanded value looks like after a call to
583 * check_val()). Each of these types are created on demand; so that if
584 * a token is never referenced in an integer context, the expensive
585 * conversion to an integer is not performed. This is inteded to keep
586 * the number of unnecesary conversions to an absolute minimum.
587 *
588 * YOU MUST NOT EVER -- EVER -- FREE THE RETURN VALUE FROM ANY OF THESE
589 * FUNCTIONS! TO DO SO WILL CRASH THE CLIENT! YOU HAVE BEEN WARNED!
590 */
591
592 /*
593 * Get the "raw" value of the token. For tokens that have been created
594 * via "tokenize", nothing has to be done since the raw value is already
595 * present. However, for computed tokens (such as the result of a math
596 * operation), the raw token may not actually exist, and so it must be
597 * infered from whatever data is available. We use the value that has
598 * the most information, starting with expanded string, to the boolean
599 * value.
600 */
get_token_raw(expr_info * c,TOKEN v)601 __inline static const char * get_token_raw (expr_info *c, TOKEN v)
602 {
603 if (v == MAGIC_TOKEN) /* Magic token */
604 return c->args; /* XXX Probably wrong */
605
606 if (v < 0 || v >= c->token)
607 {
608 error("Token index [%d] is out of range", v);
609 return get_token_raw(c, 0); /* The empty token */
610 }
611
612 if (v == 0)
613 return empty_string;
614
615 if (c->noeval)
616 return get_token_raw(c, 0);
617 #if 0
618 panic("c->noeval is not valid here. [1]");
619 #endif
620
621
622 if ((TOK(c, v).used & USED_RAW) == 0)
623 {
624 TOK(c, v).used |= USED_RAW;
625
626 if (TOK(c, v).used & USED_EXPANDED)
627 panic("Cannot convert EXPANDED token to RAW");
628 else if (TOK(c, v).used & USED_FLOAT)
629 {
630 TOK(c, v).raw_value =
631 malloc_sprintf(NULL, "%f", TOK(c, v).float_value);
632 canon_number(TOK(c, v).raw_value);
633 }
634 else if (TOK(c, v).used & USED_INTEGER)
635 TOK(c, v).raw_value =
636 INT2STR(TOK(c, v).integer_value);
637 else if (TOK(c, v).used & USED_BOOLEAN)
638 TOK(c, v).raw_value =
639 malloc_sprintf(NULL, "%d", TOK(c, v).boolean_value);
640 else if (TOK(c, v).used & USED_LVAL)
641 {
642 if (x_debug & DEBUG_NEW_MATH_DEBUG)
643 yell(">>> Expanding var name [%d]: [%s]",
644 v, TOK(c, v).lval);
645
646 TOK(c, v).raw_value = expand_alias(TOK(c, v).lval,
647 c->args, c->args_flag, NULL);
648
649 if (x_debug & DEBUG_NEW_MATH_DEBUG)
650 yell(">>> Expanded var name [%d]: [%s] to [%s]",
651 v, TOK(c, v).lval, TOK(c, v).raw_value);
652 }
653 else
654 panic("Can't convert this token to raw format");
655 }
656
657 return TOK(c, v).raw_value;
658 }
659
660 /*
661 * This is kind of funky. This is used to get the "fully qualified"
662 * lvalue for a given token. What that means is that this is not the
663 * raw value of TOK(c, v).lval, but is rather TOK(c, v).raw, but if
664 * and only if (TOK(c, v).used & USED_LVAL)! Otherwise, this returns
665 * NULL and emits an error.
666 */
get_token_lval(expr_info * c,TOKEN v)667 __inline static const char * get_token_lval (expr_info *c, TOKEN v)
668 {
669 if (v == MAGIC_TOKEN) /* Magic token */
670 return c->args; /* XXX Probably wrong */
671
672 if (v < 0 || v >= c->token)
673 {
674 error("Token index [%d] is out of range", v);
675 return NULL; /* No lvalue here! */
676 }
677
678 if (v == 0)
679 return NULL; /* Suppress the operation entirely */
680 else if (c->noeval)
681 {
682 return NULL; /* Suppress the operation entirely */
683 #if 0
684 return get_token_raw(c, 0);
685 panic("c->noeval is not valid here. [0]");
686 #endif
687 }
688 else if (((TOK(c, v).used & USED_LVAL) == 0))
689 {
690 error("Token [%d] is not an lvalue", v);
691 return NULL; /* No lvalue here! */
692 }
693 else
694 return get_token_raw(c, v);
695 }
696
697
698 /*
699 * Get the "expanded" representation of the token. The first time you
700 * call this function, it gets the "raw" value, if there is one, and then
701 * call expand_alias() to get the value. Of course, there is always a
702 * "raw" value, as get_token_raw() can convert from anything.
703 */
get_token_expanded(expr_info * c,TOKEN v)704 __inline static const char * get_token_expanded (expr_info *c, TOKEN v)
705 {
706 if (v == MAGIC_TOKEN) /* Magic token */
707 return c->args;
708
709 if (v < 0 || v >= c->token)
710 {
711 error("Token index [%d] is out of range", v);
712 return get_token_expanded(c, 0); /* The empty token */
713 }
714
715 if (v == 0)
716 return get_token_raw(c, 0);
717
718 if (c->noeval)
719 return get_token_raw(c, 0);
720 #if 0
721 panic("c->noeval is not valid here. [2]");
722 #endif
723
724 if (x_debug & DEBUG_NEW_MATH_DEBUG)
725 yell(">>> Getting token [%d] now.", v);
726
727 if ((TOK(c, v).used & USED_EXPANDED) == 0)
728 {
729 char *myval;
730
731 myval = LOCAL_COPY(get_token_raw(c, v));
732 TOK(c, v).used |= USED_EXPANDED;
733
734 /*
735 * If this token started off life as an lval, then the
736 * "raw" value of this token will yeild the expanded form
737 * of the lvalue, suitable for passing to alias_special_char.
738 */
739 if (TOK(c, v).used & USED_LVAL)
740 {
741 char *buffer = NULL;
742
743 if (x_debug & DEBUG_NEW_MATH_DEBUG)
744 yell(">>> Looking up variable [%d]: [%s]",
745 v, myval);
746
747 alias_special_char(&buffer, myval, c->args,
748 NULL, c->args_flag);
749 if (!buffer)
750 buffer = malloc_strdup(empty_string);
751 TOK(c, v).expanded_value = buffer;
752
753 if (x_debug & DEBUG_NEW_MATH_DEBUG)
754 yell("<<< Expanded variable [%d] [%s] to: [%s]",
755 v, myval, TOK(c, v).expanded_value);
756 }
757
758 /*
759 * Otherwise, this token started off life as an rval
760 * (such as a [...] string), and only needs to be expanded
761 * with alias_special_char to yeild a useful value.
762 */
763 else if (TOK(c, v).used & USED_RAW)
764 {
765 if (x_debug & DEBUG_NEW_MATH_DEBUG)
766 yell(">>> Expanding token [%d]: [%s]",
767 v, myval);
768
769 TOK(c, v).used |= USED_EXPANDED;
770 TOK(c, v).expanded_value =
771 expand_alias(myval, c->args,
772 c->args_flag, NULL);
773
774 if (x_debug & DEBUG_NEW_MATH_DEBUG)
775 yell("<<< Expanded token [%d]: [%s] to: [%s]",
776 v, myval, TOK(c, v).expanded_value);
777 }
778 else
779 panic("Cannot convert from this token to EXPANDED");
780 }
781
782 if (x_debug & DEBUG_NEW_MATH_DEBUG)
783 yell("<<< Token [%d] value is [%s].", v, TOK(c, v).expanded_value);
784 return TOK(c, v).expanded_value;
785 }
786
787 /*
788 * Get the integer representation of the token. The first time you call
789 * this function, it calls atof() on the "raw" value, if there is one,
790 * to get the result.
791 */
get_token_integer(expr_info * c,TOKEN v)792 __inline static INTTYPE get_token_integer (expr_info *c, TOKEN v)
793 {
794 if (v == MAGIC_TOKEN) /* Magic token */
795 return STR2INT(c->args); /* XXX Probably wrong */
796
797 if (v < 0 || v >= c->token)
798 {
799 error("Token index [%d] is out of range", v);
800 return 0; /* The empty token */
801 }
802
803 if ((TOK(c, v).used & USED_INTEGER) == 0)
804 {
805 const char * myval = get_token_expanded(c, v);
806
807 TOK(c, v).used |= USED_INTEGER;
808 TOK(c, v).integer_value = STR2INT(myval);
809 }
810 return TOK(c, v).integer_value;
811 }
812
813 /*
814 * Get the floating point value representation of the token.
815 */
get_token_float(expr_info * c,TOKEN v)816 __inline static double get_token_float (expr_info *c, TOKEN v)
817 {
818 if (v == MAGIC_TOKEN) /* Magic token */
819 return atof(c->args); /* XXX Probably wrong */
820
821 if (v < 0 || v >= c->token)
822 {
823 error("Token index [%d] is out of range", v);
824 return 0.0; /* The empty token */
825 }
826
827 if ((TOK(c, v).used & USED_FLOAT) == 0)
828 {
829 const char * myval = get_token_expanded(c, v);
830
831 TOK(c, v).used |= USED_FLOAT;
832 TOK(c, v).float_value = atof(myval);
833 }
834 return TOK(c, v).float_value;
835 }
836
837 /*
838 * Get the boolean value of the token
839 */
get_token_boolean(expr_info * c,TOKEN v)840 __inline static BooL get_token_boolean (expr_info *c, TOKEN v)
841 {
842 if (v == MAGIC_TOKEN) /* Magic token */
843 return check_val(c->args); /* XXX Probably wrong */
844
845 if (v < 0 || v >= c->token)
846 {
847 error("Token index [%d] is out of range", v);
848 return 0; /* The empty token */
849 }
850
851 if ((TOK(c, v).used & USED_BOOLEAN) == 0)
852 {
853 const char * myval = get_token_expanded(c, v);
854
855 TOK(c, v).used |= USED_BOOLEAN;
856 TOK(c, v).boolean_value = check_val(myval);
857 }
858 return TOK(c, v).boolean_value;
859 }
860
861 /* *********************** ADD TO OPERAND STACK **************************** */
862 /*
863 * Adding (shifting) and Removing (reducing) operands from the stack is a
864 * fairly straightforward process. The general way to add an token to
865 * the stack is to pass in its TOKEN index. However, there are some times
866 * when you want to shift a value that has not been tokenized. So you call
867 * one of the other functions that will do this for you.
868 */
push_token(expr_info * c,TOKEN t)869 __inline static TOKEN push_token (expr_info *c, TOKEN t)
870 {
871 if (c->sp == STACKSZ - 1)
872 {
873 error("Expressions may not have more than %d operands",
874 STACKSZ);
875 return -1;
876 }
877 else
878 c->sp++;
879
880 if (x_debug & DEBUG_NEW_MATH_DEBUG)
881 yell("Pushing token [%d] [%s]", t, get_token_expanded(c, t));
882
883 return ((c->stack[c->sp] = t));
884 }
885
push_string(expr_info * c,char * val)886 __inline static TOKEN push_string (expr_info *c, char *val)
887 {
888 return push_token(c, tokenize_expanded(c, val));
889 }
890
push_float(expr_info * c,double val)891 __inline static TOKEN push_float (expr_info *c, double val)
892 {
893 return push_token(c, tokenize_float(c, val));
894 }
895
push_integer(expr_info * c,INTTYPE val)896 __inline static TOKEN push_integer (expr_info *c, INTTYPE val)
897 {
898 return push_token(c, tokenize_integer(c, val));
899 }
900
push_boolean(expr_info * c,BooL val)901 __inline static TOKEN push_boolean (expr_info *c, BooL val)
902 {
903 return push_token(c, tokenize_bool(c, val));
904 }
905
push_lval(expr_info * c,const char * val)906 __inline static TOKEN push_lval (expr_info *c, const char *val)
907 {
908 return push_token(c, tokenize_lval(c, val));
909 }
910
911
912 /*********************** REMOVE FROM OPERAND STACK **************************/
top(expr_info * c)913 __inline static TOKEN top (expr_info *c)
914 {
915 if (c->sp < 0)
916 {
917 error("No operands.");
918 return -1;
919 }
920 else
921 return c->stack[c->sp];
922 }
923
pop_token(expr_info * c)924 __inline static TOKEN pop_token (expr_info *c)
925 {
926 if (c->sp < 0)
927 {
928 /*
929 * Attempting to pop more operands than are available
930 * Yeilds empty values. Thats probably the most reasonable
931 * course of action.
932 */
933 error("Cannot pop operand: no more operands");
934 return 0;
935 }
936 else
937 return c->stack[c->sp--];
938 }
939
pop_integer(expr_info * c)940 __inline static double pop_integer (expr_info *c)
941 {
942 return get_token_integer(c, pop_token(c));
943 }
944
pop_float(expr_info * c)945 __inline static double pop_float (expr_info *c)
946 {
947 return get_token_float(c, pop_token(c));
948 }
949
pop_expanded(expr_info * c)950 __inline static const char * pop_expanded (expr_info *c)
951 {
952 return get_token_expanded(c, pop_token(c));
953 }
954
pop_boolean(expr_info * c)955 __inline static BooL pop_boolean (expr_info *c)
956 {
957 return get_token_boolean(c, pop_token(c));
958 }
959
pop_2_tokens(expr_info * c,TOKEN * t1,TOKEN * t2)960 __inline static void pop_2_tokens (expr_info *c, TOKEN *t1, TOKEN *t2)
961 {
962 *t2 = pop_token(c);
963 *t1 = pop_token(c);
964 }
965
pop_2_floats(expr_info * c,double * a,double * b)966 __inline static void pop_2_floats (expr_info *c, double *a, double *b)
967 {
968 *b = pop_float(c);
969 *a = pop_float(c);
970 }
971
pop_2_integers(expr_info * c,INTTYPE * a,INTTYPE * b)972 __inline static void pop_2_integers (expr_info *c, INTTYPE *a, INTTYPE *b)
973 {
974 *b = pop_integer(c);
975 *a = pop_integer(c);
976 }
977
pop_2_strings(expr_info * c,const char ** s,const char ** t)978 __inline static void pop_2_strings (expr_info *c, const char **s, const char **t)
979 {
980 *t = pop_expanded(c);
981 *s = pop_expanded(c);
982 }
983
pop_2_booleans(expr_info * c,BooL * a,BooL * b)984 __inline static void pop_2_booleans (expr_info *c, BooL *a, BooL *b)
985 {
986 *b = pop_boolean(c);
987 *a = pop_boolean(c);
988 }
989
pop_3_tokens(expr_info * c,BooL * a,TOKEN * v,TOKEN * w)990 __inline static void pop_3_tokens (expr_info *c, BooL *a, TOKEN *v, TOKEN *w)
991 {
992 TOKEN t1, t2, t3;
993
994 t3 = pop_token(c);
995 t2 = pop_token(c);
996 t1 = pop_token(c);
997 *a = get_token_boolean(c, t1);
998 *v = t2;
999 *w = t3;
1000 }
1001
1002
1003 /******************************* OPERATOR REDUCER **************************/
1004 /*
1005 * This is the reducer. It takes the relevant arguments off the argument
1006 * stack and then performs the neccesary operation on them.
1007 */
reduce(expr_info * cx,int what)1008 static void reduce (expr_info *cx, int what)
1009 {
1010 double a, b;
1011 BooL c, d;
1012 INTTYPE i, j;
1013 const char *s, *t;
1014 TOKEN v, w;
1015
1016 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1017 yell("Reducing last operation...");
1018
1019 if (cx->sp < 0)
1020 {
1021 error("An operator is missing a required operand");
1022 return;
1023 }
1024
1025 if (cx->errflag)
1026 return; /* Dont parse on an error */
1027
1028 /* Check to see if we are evaluating the expression at this point. */
1029 #define CHECK_NOEVAL \
1030 if (cx->noeval) \
1031 { \
1032 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1033 yell("O: Operation short-circuited"); \
1034 push_token(cx, 0); \
1035 break; \
1036 }
1037
1038 /* Perform an ordinary garden variety floating point binary operation. */
1039 #define BINARY_FLOAT(floatop) \
1040 { \
1041 pop_2_floats(cx, &a, &b); \
1042 CHECK_NOEVAL \
1043 push_float(cx, (floatop)); \
1044 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1045 yell("O: %s (%f %f) -> %f", \
1046 #floatop, a, b, floatop); \
1047 break; \
1048 }
1049
1050 /* Perform an ordinary garden variety integer binary operation */
1051 #define BINARY_INTEGER(intop) \
1052 { \
1053 pop_2_integers(cx, &i, &j); \
1054 CHECK_NOEVAL \
1055 push_integer(cx, (intop)); \
1056 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1057 yell("O: %s (" FORMAT " " FORMAT ") -> " FORMAT, \
1058 #intop, i, j, intop); \
1059 break; \
1060 }
1061
1062 /* Perform an ordinary garden variety boolean binary operation */
1063 #define BINARY_BOOLEAN(boolop) \
1064 { \
1065 pop_2_booleans(cx, &c, &d); \
1066 CHECK_NOEVAL \
1067 push_boolean(cx, (boolop)); \
1068 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1069 yell("O: %s (%d %d) -> %d", \
1070 #boolop, c, d, boolop); \
1071 break; \
1072 }
1073
1074 /* Perform a floating point binary operation where the rhs must not be 0. */
1075 #define BINARY_FLOAT_NOZERO(floatop) \
1076 { \
1077 pop_2_floats(cx, &a, &b); \
1078 CHECK_NOEVAL \
1079 if (b == 0.0) \
1080 { \
1081 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1082 yell("O: %s (%f %f) -> []", \
1083 #floatop, a, b); \
1084 error("Division by zero"); \
1085 push_token(cx, 0); \
1086 } \
1087 else \
1088 { \
1089 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1090 yell("O: %s (%f %f) -> %f", \
1091 #floatop, a, b, floatop); \
1092 push_float(cx, (floatop)); \
1093 } \
1094 break; \
1095 }
1096
1097 /* Perform a floating point binary operation where the rhs must not be 0. */
1098 #define BINARY_INTEGER_NOZERO(intop) \
1099 { \
1100 pop_2_integers(cx, &i, &j); \
1101 CHECK_NOEVAL \
1102 if (j == 0) \
1103 { \
1104 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1105 yell("O: %s (" FORMAT " " FORMAT ") -> []", \
1106 #intop, i, j); \
1107 error("Division by zero"); \
1108 push_token(cx, 0); \
1109 } \
1110 else \
1111 { \
1112 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1113 yell("O: %s (" FORMAT " " FORMAT ") -> " FORMAT, \
1114 #intop, i, j, intop); \
1115 push_integer(cx, (intop)); \
1116 } \
1117 break; \
1118 }
1119
1120 /***************** ASSIGNMENT MACROS *******************/
1121 /* Prep the lvalue and the rvalue for a future assignment. */
1122 #define GET_LVAL_RVAL \
1123 pop_2_tokens(cx, &v, &w); \
1124 if (!(s = get_token_lval(cx, v))) \
1125 { \
1126 push_token(cx, 0); \
1127 break; \
1128 }
1129
1130 /* Perform an ordinary integer operation, assigning the result to the lvalue */
1131 #define IMPLIED_INTEGER(intop) \
1132 { \
1133 GET_LVAL_RVAL \
1134 CHECK_NOEVAL \
1135 i = get_token_integer(cx, v); \
1136 j = get_token_integer(cx, w); \
1137 \
1138 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1139 yell("O: %s = %s (" FORMAT " " FORMAT ") -> " FORMAT, \
1140 s, #intop, i, j, intop); \
1141 \
1142 w = tokenize_integer(cx, (intop)); \
1143 t = get_token_expanded(cx, w); \
1144 add_var_alias(s, t, 0); \
1145 push_token(cx, w); \
1146 break; \
1147 }
1148
1149 /* Perform an ordinary float operation, assigning the result to the lvalue */
1150 #define IMPLIED_FLOAT(floatop) \
1151 { \
1152 GET_LVAL_RVAL \
1153 CHECK_NOEVAL \
1154 a = get_token_float(cx, v); \
1155 b = get_token_float(cx, w); \
1156 \
1157 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1158 yell("O: %s = %s (%f %f) -> %f", \
1159 s, #floatop, a, b, floatop); \
1160 \
1161 w = tokenize_float(cx, (floatop)); \
1162 t = get_token_expanded(cx, w); \
1163 add_var_alias(s, t, 0); \
1164 push_token(cx, w); \
1165 break; \
1166 }
1167
1168 /* Perform an ordinary boolean operation, assigning the result to the lvalue */
1169 #define IMPLIED_BOOLEAN(boolop) \
1170 { \
1171 GET_LVAL_RVAL \
1172 CHECK_NOEVAL \
1173 c = get_token_boolean(cx, v); \
1174 d = get_token_boolean(cx, w); \
1175 \
1176 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1177 yell("O: %s = %s (%d %d) -> %d", \
1178 s, #boolop, c, d, boolop); \
1179 \
1180 w = tokenize_bool(cx, (boolop)); \
1181 t = get_token_expanded(cx, w); \
1182 add_var_alias(s, t, 0); \
1183 push_token(cx, w); \
1184 break; \
1185 }
1186
1187
1188 /*
1189 * Perform a float operation, rvalue must not be zero, assigning the result
1190 * to the lvalue.
1191 */
1192 #define IMPLIED_FLOAT_NOZERO(floatop) \
1193 { \
1194 GET_LVAL_RVAL \
1195 CHECK_NOEVAL \
1196 a = get_token_float(cx, v); \
1197 b = get_token_float(cx, w); \
1198 \
1199 if (b == 0.0) \
1200 { \
1201 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1202 yell("O: %s = %s (%f %f) -> 0", \
1203 s, #floatop, a, b); \
1204 error("Division by zero"); \
1205 add_var_alias(s, empty_string, 0); \
1206 push_token(cx, 0); \
1207 break; \
1208 } \
1209 \
1210 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1211 yell("O: %s = %s (%f %f) -> %f", \
1212 s, #floatop, a, b, floatop); \
1213 \
1214 w = tokenize_float(cx, (floatop)); \
1215 t = get_token_expanded(cx, w); \
1216 add_var_alias(s, t, 0); \
1217 push_token(cx, w); \
1218 break; \
1219 }
1220
1221 /*
1222 * Perform a float operation, rvalue must not be zero, assigning the result
1223 * to the lvalue.
1224 */
1225 #define IMPLIED_INTEGER_NOZERO(intop) \
1226 { \
1227 GET_LVAL_RVAL \
1228 CHECK_NOEVAL \
1229 i = get_token_float(cx, v); \
1230 j = get_token_float(cx, w); \
1231 \
1232 if (j == 0) \
1233 { \
1234 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1235 yell("O: %s = %s (" FORMAT " " FORMAT ") -> 0",\
1236 s, #intop, i, j); \
1237 error("Division by zero"); \
1238 add_var_alias(s, empty_string, 0); \
1239 push_token(cx, 0); \
1240 break; \
1241 } \
1242 \
1243 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1244 yell("O: %s = %s (" FORMAT " " FORMAT ") -> " FORMAT,\
1245 s, #intop, i, j, intop); \
1246 \
1247 w = tokenize_float(cx, (intop)); \
1248 t = get_token_expanded(cx, w); \
1249 add_var_alias(s, t, 0); \
1250 push_token(cx, w); \
1251 break; \
1252 }
1253
1254
1255 /*
1256 * Perform an auto(in|de)crement operation on the last operand, assigning
1257 * to it the value of 'x', but pushing the value of 'y' onto the stack.
1258 */
1259 #define AUTO_UNARY(intop_assign, intop_result) \
1260 { \
1261 v = pop_token(cx); \
1262 if (!(s = get_token_lval(cx, v))) \
1263 { \
1264 push_token(cx, 0); \
1265 break; \
1266 } \
1267 CHECK_NOEVAL \
1268 \
1269 j = get_token_integer(cx, v); \
1270 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1271 yell("O: %s (%s " FORMAT ") -> " FORMAT, \
1272 #intop_result, s, j, (intop_result)); \
1273 \
1274 w = tokenize_integer(cx, (intop_assign)); \
1275 t = get_token_expanded(cx, w); \
1276 add_var_alias(s, t, 0); \
1277 \
1278 push_integer(cx, (intop_result)); \
1279 break; \
1280 }
1281
1282 /* ****************** START HERE *********************/
1283 #define dpushn(x1,x2,y1) \
1284 { \
1285 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1286 { \
1287 yell("O: COMPARE"); \
1288 yell("O: %s -> %d", #x2, (x2)); \
1289 } \
1290 push_boolean( x1 , y1 ); \
1291 }
1292
1293 #define COMPARE(x, y) \
1294 { \
1295 pop_2_strings(cx, &s, &t); \
1296 CHECK_NOEVAL \
1297 if (is_real_number(s) && is_real_number(t)) \
1298 { \
1299 a = atof(s), b = atof(t); \
1300 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1301 yell("O: %s N(%f %f) -> %d", #x, a, b, (x)); \
1302 if ((x)) dpushn(cx, x, 1) \
1303 else dpushn(cx, x, 0) \
1304 } \
1305 else \
1306 { \
1307 if (x_debug & DEBUG_NEW_MATH_DEBUG) \
1308 yell("O: %s S(%s %s) -> %d", #x, s, t, (y)); \
1309 if ((y)) dpushn(cx, y, 1) \
1310 else dpushn(cx, y, 0) \
1311 } \
1312 break; \
1313 }
1314
1315 /************** THE OPERATORS THEMSELVES ********************/
1316 switch (what)
1317 {
1318 /* Simple unary prefix operators */
1319 case NOT:
1320 c = pop_boolean(cx);
1321 CHECK_NOEVAL
1322 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1323 yell("O: !%d -> %d", c, !c);
1324 push_boolean(cx, !c);
1325 break;
1326 case COMP:
1327 i = pop_integer(cx);
1328 CHECK_NOEVAL
1329 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1330 yell(": ~" FORMAT " -> " FORMAT, i, ~i);
1331 push_integer(cx, ~i);
1332 break;
1333 case UPLUS:
1334 a = pop_float(cx);
1335 CHECK_NOEVAL
1336 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1337 yell("O: +%f -> %f", a, a);
1338 push_float(cx, a);
1339 break;
1340 case UMINUS:
1341 a = pop_float(cx);
1342 CHECK_NOEVAL
1343 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1344 yell("O: -%f -> %f", a, -a);
1345 push_float(cx, -a);
1346 break;
1347 case STRLEN:
1348 s = pop_expanded(cx);
1349 CHECK_NOEVAL
1350 i = strlen(s);
1351 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1352 yell("O: @(%s) -> " FORMAT, s, i);
1353 push_integer(cx, i);
1354 break;
1355 case WORDC:
1356 s = pop_expanded(cx);
1357 CHECK_NOEVAL
1358 i = count_words(s, DWORD_YES, "\"");
1359 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1360 yell("O: #(%s) -> " FORMAT, s, i);
1361 push_integer(cx, i);
1362 break;
1363 case DEREF:
1364 {
1365 if (top(cx) == MAGIC_TOKEN)
1366 break; /* Dont do anything */
1367
1368 /*
1369 * We need to consume the operand, even if
1370 * we don't intend to use it; plus we need
1371 * to ensure this defeats auto-append. Ick.
1372 */
1373 s = pop_expanded(cx);
1374 *cx->args_flag = 1;
1375
1376 CHECK_NOEVAL
1377 push_lval(cx, s);
1378 break;
1379 }
1380
1381 /* (pre|post)(in|de)crement operators. */
1382 case PREPLUS: AUTO_UNARY(j + 1, j + 1)
1383 case PREMINUS: AUTO_UNARY(j - 1, j - 1)
1384 case POSTPLUS: AUTO_UNARY(j + 1, j)
1385 case POSTMINUS: AUTO_UNARY(j - 1, j)
1386
1387 /* Simple binary operators */
1388 case AND: BINARY_INTEGER(i & j)
1389 case XOR: BINARY_INTEGER(i ^ j)
1390 case OR: BINARY_INTEGER(i | j)
1391 case PLUS: BINARY_FLOAT(a + b)
1392 case MINUS: BINARY_FLOAT(a - b)
1393 case MUL: BINARY_FLOAT(a * b)
1394 case POWER: BINARY_FLOAT(pow(a, b))
1395 case SHLEFT: BINARY_INTEGER(i << j)
1396 case SHRIGHT: BINARY_INTEGER(i >> j)
1397 case DIV: BINARY_FLOAT_NOZERO(a / b)
1398 case MOD: BINARY_INTEGER_NOZERO(i % j)
1399 case DAND: BINARY_BOOLEAN(c && d)
1400 case DOR: BINARY_BOOLEAN(c || d)
1401 case DXOR: BINARY_BOOLEAN((c && !d) || (!c && d))
1402 case STRCAT:
1403 {
1404 char * myval;
1405
1406 pop_2_strings(cx, &s, &t);
1407 CHECK_NOEVAL
1408 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1409 yell("O: (%s) ## (%s) -> %s%s", s, t, s, t);
1410
1411 myval = malloc_strdup2(s, t);
1412 push_string(cx, myval);
1413 new_free(&myval);
1414 break;
1415 }
1416 /* Assignment operators */
1417 case PLUSEQ: IMPLIED_FLOAT(a + b)
1418 case MINUSEQ: IMPLIED_FLOAT(a - b)
1419 case MULEQ: IMPLIED_FLOAT(a * b)
1420 case POWEREQ: IMPLIED_FLOAT(pow(a, b))
1421 case DIVEQ: IMPLIED_FLOAT_NOZERO(a / b)
1422 case MODEQ: IMPLIED_INTEGER_NOZERO(i % j)
1423 case ANDEQ: IMPLIED_INTEGER(i & j)
1424 case XOREQ: IMPLIED_INTEGER(i ^ j)
1425 case OREQ: IMPLIED_INTEGER(i | j)
1426 case SHLEFTEQ: IMPLIED_INTEGER(i << j)
1427 case SHRIGHTEQ: IMPLIED_INTEGER(i >> j)
1428 case DANDEQ: IMPLIED_BOOLEAN(c && d)
1429 case DOREQ: IMPLIED_BOOLEAN(c || d)
1430 case DXOREQ: IMPLIED_BOOLEAN((c && !d) || (!c && d))
1431 case STRCATEQ:
1432 {
1433 char * myval;
1434
1435 GET_LVAL_RVAL
1436 CHECK_NOEVAL
1437 myval = malloc_strdup(get_token_expanded(cx, v));
1438 t = get_token_expanded(cx, w);
1439
1440 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1441 yell("O: %s = (%s ## %s) -> %s%s",
1442 s, myval, t, myval, t);
1443
1444 malloc_strcat(&myval, t);
1445 push_string(cx, myval);
1446 add_var_alias(s, myval, 0);
1447 new_free(&myval);
1448 break;
1449 }
1450 case STRPREEQ:
1451 {
1452 char * myval;
1453
1454 GET_LVAL_RVAL
1455 CHECK_NOEVAL
1456 myval = malloc_strdup(get_token_expanded(cx, w));
1457 t = get_token_expanded(cx, v);
1458
1459 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1460 yell("O: %s = (%s ## %s) -> %s%s",
1461 s, t, myval, t, myval);
1462
1463 malloc_strcat(&myval, t);
1464 push_string(cx, myval);
1465 add_var_alias(s, myval, 0);
1466 new_free(&myval);
1467 break;
1468 }
1469 case EQ:
1470 {
1471 GET_LVAL_RVAL
1472 CHECK_NOEVAL
1473 t = get_token_expanded(cx, w);
1474
1475 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1476 yell("O: %s = (%s)", s, t);
1477
1478 push_token(cx, w);
1479 add_var_alias(s, t, 0);
1480 break;
1481 }
1482 case SWAP:
1483 {
1484 const char *sval, *tval;
1485
1486 pop_2_tokens(cx, &v, &w);
1487 CHECK_NOEVAL
1488 if (!(s = get_token_lval(cx, v)))
1489 {
1490 push_token(cx, 0);
1491 break;
1492 }
1493 if (!(t = get_token_lval(cx, w)))
1494 {
1495 push_token(cx, 0);
1496 break;
1497 }
1498 sval = get_token_expanded(cx, v);
1499 tval = get_token_expanded(cx, w);
1500
1501 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1502 yell("O: %s <=> %s", s, t);
1503
1504 add_var_alias(s, tval, 0);
1505 add_var_alias(t, sval, 0);
1506 push_token(cx, w);
1507 break;
1508 }
1509
1510 /* Comparison operators */
1511 case DEQ:
1512 {
1513 pop_2_strings(cx, &s, &t);
1514 CHECK_NOEVAL
1515 c = my_stricmp(s, t) ? 0 : 1;
1516
1517 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1518 yell("O: %s == %s -> %d", s, t, c);
1519
1520 push_boolean(cx, c);
1521 break;
1522 }
1523 case NEQ:
1524 {
1525 pop_2_strings(cx, &s, &t);
1526 CHECK_NOEVAL
1527 c = my_stricmp(s, t) ? 1 : 0;
1528
1529 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1530 yell("O: %s != %s -> %d", s, t, c);
1531
1532 push_boolean(cx, c);
1533 break;
1534 }
1535 case MATCH:
1536 {
1537 pop_2_strings(cx, &s, &t);
1538 CHECK_NOEVAL
1539 c = wild_match(t, s) ? 1 : 0;
1540
1541 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1542 yell("O: %s =~ %s -> %d", s, t, c);
1543
1544 push_boolean(cx, c);
1545 break;
1546 }
1547 case NOMATCH:
1548 {
1549 pop_2_strings(cx, &s, &t);
1550 CHECK_NOEVAL
1551 c = wild_match(t, s) ? 0 : 1;
1552
1553 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1554 yell("O: %s !~ %s -> %d", s, t, c);
1555
1556 push_boolean(cx, c);
1557 break;
1558 }
1559
1560 case LES: COMPARE(a < b, my_stricmp(s, t) < 0)
1561 case LEQ: COMPARE(a <= b, my_stricmp(s, t) <= 0)
1562 case GRE: COMPARE(a > b, my_stricmp(s, t) > 0)
1563 case GEQ: COMPARE(a >= b, my_stricmp(s, t) >= 0)
1564
1565 /* Miscelaneous operators */
1566 case QUEST:
1567 {
1568 pop_3_tokens(cx, &c, &v, &w);
1569 CHECK_NOEVAL
1570 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1571 {
1572 yell("O: %d ? %s : %s -> %s", c,
1573 get_token_expanded(cx, v),
1574 get_token_expanded(cx, w),
1575 (c ? get_token_expanded(cx, v) :
1576 get_token_expanded(cx, w)));
1577 }
1578 push_token(cx, c ? v : w);
1579 break;
1580 }
1581 case COLON:
1582 break;
1583
1584 case COMMA:
1585 {
1586 pop_2_tokens(cx, &v, &w);
1587 CHECK_NOEVAL
1588
1589 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1590 yell("O: %s , %s -> %s",
1591 get_token_expanded(cx, v),
1592 get_token_expanded(cx, w),
1593 get_token_expanded(cx, w));
1594 push_token(cx, w);
1595 break;
1596 }
1597
1598 default:
1599 error("Unknown operator or out of operators");
1600 return;
1601 }
1602 }
1603
1604
1605 /**************************** EXPRESSION LEXER ******************************/
1606 static int dummy = 1;
1607
lexerr(expr_info * c,const char * format,...)1608 static int lexerr (expr_info *c, const char *format, ...)
1609 {
1610 char buffer[BIG_BUFFER_SIZE + 1];
1611 va_list a;
1612
1613 va_start(a, format);
1614 vsnprintf(buffer, BIG_BUFFER_SIZE, format, a);
1615 va_end(a);
1616
1617 error("%s", buffer);
1618 c->errflag = 1;
1619 return EOI;
1620 }
1621
1622 /*
1623 * 'operand' is state information that tells us about what the next token
1624 * is expected to be. When a binary operator is lexed, then the next token
1625 * is expected to be either a unary operator or an operand. So in this
1626 * case 'operand' is set to 1. When an operand is lexed, then the next token
1627 * is expected to be a binary operator, so 'operand' is set to 0.
1628 */
check_implied_arg(expr_info * c)1629 static __inline int check_implied_arg (expr_info *c)
1630 {
1631 if (c->operand == 2)
1632 {
1633 push_token(c, MAGIC_TOKEN); /* XXXX Bleh */
1634 c->operand = 0;
1635 *c->args_flag = 1;
1636 return 0;
1637 }
1638
1639 return c->operand;
1640 }
1641
operator(expr_info * c,const char * x,int y,TOKEN z)1642 static __inline TOKEN operator (expr_info *c, const char *x, int y, TOKEN z)
1643 {
1644 check_implied_arg(c);
1645 if (c->operand)
1646 return lexerr(c, "A binary operator (%s) was found "
1647 "where an operand was expected", x);
1648 c->ptr += y;
1649 c->operand = 1;
1650 return z;
1651 }
1652
unary(expr_info * c,const char * x,int y,TOKEN z)1653 static __inline TOKEN unary (expr_info *c, const char *x, int y, TOKEN z)
1654 {
1655 if (!c->operand)
1656 return lexerr(c, "A unary operator (%s) was found where "
1657 "a binary operator was expected", x);
1658 c->ptr += y;
1659 c->operand = dummy;
1660 return z;
1661 }
1662
1663
1664 /*
1665 * This finds and extracts the next token in the expression
1666 */
zzlex(expr_info * c)1667 static int zzlex (expr_info *c)
1668 {
1669 char *start = c->ptr;
1670
1671 #define OPERATOR(x, y, z) return operator(c, x, y, z);
1672 #define UNARY(x, y, z) return unary(c, x, y, z);
1673
1674 dummy = 1;
1675 if (x_debug & DEBUG_NEW_MATH_DEBUG)
1676 yell("Parsing next token from: [%s]", c->ptr);
1677
1678 for (;;)
1679 {
1680 switch (*(c->ptr++))
1681 {
1682 case '(':
1683 c->operand = 1;
1684 return M_INPAR;
1685 case ')':
1686 /*
1687 * If we get a close paren and the lexer is expecting
1688 * an operand, then obviously thats a syntax error.
1689 * But we gently just insert the empty value as the
1690 * rhs for the last operand and hope it all works out.
1691 */
1692 if (check_implied_arg(c))
1693 push_token(c, 0);
1694 c->operand = 0;
1695 return M_OUTPAR;
1696
1697 case '+':
1698 {
1699 /*
1700 * Note: In general, any operand that depends on
1701 * whether it is a unary or binary operator based
1702 * upon the context is required to call the func
1703 * 'check_implied_arg' to solidify the context.
1704 * That is because some operators are ambiguous,
1705 * And if you see (# + 4), it can only be determined
1706 * on the fly how to lex that.
1707 */
1708 check_implied_arg(c);
1709 if (*c->ptr == '+' && (c->operand || !isalnum(*c->ptr)))
1710 {
1711 c->ptr++;
1712 return c->operand ? PREPLUS : POSTPLUS;
1713 }
1714 else if (*c->ptr == '=')
1715 OPERATOR("+=", 1, PLUSEQ)
1716 else if (c->operand)
1717 UNARY("+", 0, UPLUS)
1718 else
1719 OPERATOR("+", 0, PLUS)
1720 }
1721 case '-':
1722 {
1723 check_implied_arg(c);
1724 if (*c->ptr == '-' && (c->operand || !isalnum(*c->ptr)))
1725 {
1726 c->ptr++;
1727 return (c->operand) ? PREMINUS : POSTMINUS;
1728 }
1729 else if (*c->ptr == '=')
1730 OPERATOR("-=", 1, MINUSEQ)
1731 else if (c->operand)
1732 UNARY("-", 0, UMINUS)
1733 else
1734 OPERATOR("-", 0, MINUS)
1735 }
1736 case '*':
1737 {
1738 if (*c->ptr == '*')
1739 {
1740 c->ptr++;
1741 if (*c->ptr == '=')
1742 OPERATOR("**=", 1, POWEREQ)
1743 else
1744 OPERATOR("**", 0, POWER)
1745 }
1746 else if (*c->ptr == '=')
1747 OPERATOR("*=", 1, MULEQ)
1748 else if (c->operand)
1749 {
1750 dummy = 2;
1751 UNARY("*", 0, DEREF)
1752 }
1753 else
1754 OPERATOR("*", 0, MUL)
1755 }
1756 case '/':
1757 {
1758 if (*c->ptr == '=')
1759 OPERATOR("/=", 1, DIVEQ)
1760 else
1761 OPERATOR("/", 0, DIV)
1762 }
1763 case '%':
1764 {
1765 if (*c->ptr == '=')
1766 OPERATOR("%=", 1, MODEQ)
1767 else
1768 OPERATOR("%", 0, MOD)
1769 }
1770
1771 case '!':
1772 {
1773 if (*c->ptr == '=')
1774 OPERATOR("!=", 1, NEQ)
1775 else if (*c->ptr == '~')
1776 OPERATOR("!~", 1, NOMATCH)
1777 else
1778 UNARY("!", 0, NOT)
1779 }
1780 case '~':
1781 UNARY("~", 0, COMP)
1782
1783 case '&':
1784 {
1785 if (*c->ptr == '&')
1786 {
1787 c->ptr++;
1788 if (*c->ptr == '=')
1789 OPERATOR("&&=", 1, DANDEQ)
1790 else
1791 OPERATOR("&&", 0, DAND)
1792 }
1793 else if (*c->ptr == '=')
1794 OPERATOR("&=", 1, ANDEQ)
1795 else
1796 OPERATOR("&", 0, AND)
1797 }
1798 case '|':
1799 {
1800 if (*c->ptr == '|')
1801 {
1802 c->ptr++;
1803 if (*c->ptr == '=')
1804 OPERATOR("||=", 1, DOREQ)
1805 else
1806 OPERATOR("||", 0, DOR)
1807 }
1808 else if (*c->ptr == '=')
1809 OPERATOR("|=", 1, OREQ)
1810 else
1811 OPERATOR("|", 0, OR)
1812 }
1813 case '^':
1814 {
1815 if (*c->ptr == '^')
1816 {
1817 c->ptr++;
1818 if (*c->ptr == '=')
1819 OPERATOR("^^=", 1, DXOREQ)
1820 else
1821 OPERATOR("^^", 0, DXOR)
1822 }
1823 else if (*c->ptr == '=')
1824 OPERATOR("^=", 1, XOREQ)
1825 else
1826 OPERATOR("^", 0, XOR)
1827 }
1828 case '#':
1829 {
1830 check_implied_arg(c);
1831 if (*c->ptr == '#')
1832 {
1833 c->ptr++;
1834 if (*c->ptr == '=')
1835 OPERATOR("##=", 1, STRCATEQ)
1836 else
1837 OPERATOR("##", 0, STRCAT)
1838 }
1839 else if (*c->ptr == '=')
1840 OPERATOR("#=", 1, STRCATEQ)
1841 else if (*c->ptr == '~')
1842 OPERATOR("#~", 1, STRPREEQ)
1843 else if (c->operand)
1844 {
1845 dummy = 2;
1846 UNARY("#", 0, WORDC)
1847 }
1848 else
1849 OPERATOR("#", 0, STRCAT)
1850 }
1851
1852 case '@':
1853 dummy = 2;
1854 UNARY("@", 0, STRLEN)
1855
1856 case '<':
1857 {
1858 if (*c->ptr == '<')
1859 {
1860 c->ptr++;
1861 if (*c->ptr == '=')
1862 OPERATOR("<<=", 1, SHLEFTEQ)
1863 else
1864 OPERATOR("<<", 0, SHLEFT)
1865 }
1866 else if (*c->ptr == '=')
1867 {
1868 c->ptr++;
1869 if (*c->ptr == '>')
1870 OPERATOR("<=>", 1, SWAP)
1871 else
1872 OPERATOR("<=", 0, LEQ)
1873 }
1874 else
1875 OPERATOR("<", 0, LES)
1876 }
1877 case '>':
1878 {
1879 if (*c->ptr == '>')
1880 {
1881 c->ptr++;
1882 if (*c->ptr == '=')
1883 OPERATOR(">>=", 1, SHRIGHTEQ)
1884 else
1885 OPERATOR(">>", 0, SHRIGHT)
1886 }
1887 else if (*c->ptr == '=')
1888 OPERATOR(">=", 1, GEQ)
1889 else
1890 OPERATOR(">", 0, GRE)
1891 }
1892
1893 case '=':
1894 if (*c->ptr == '=')
1895 OPERATOR("==", 1, DEQ)
1896 else if (*c->ptr == '~')
1897 OPERATOR("=~", 1, MATCH)
1898 else
1899 OPERATOR("=", 0, EQ)
1900
1901 case '?':
1902 check_implied_arg(c);
1903 c->operand = 1;
1904 return QUEST;
1905
1906 case ':':
1907 /*
1908 * I dont want to hear anything from you anti-goto
1909 * bigots out there. ;-) If you can't figure out
1910 * what this does, you ought to give up programming.
1911 * And a big old :p to everyone who insisted that
1912 * i support this horrid hack.
1913 */
1914 if (c->operand)
1915 goto handle_expando;
1916
1917 c->operand = 1;
1918 return COLON;
1919
1920 case ',':
1921 /* Same song, second verse. */
1922 if (c->operand)
1923 goto handle_expando;
1924
1925 c->operand = 1;
1926 return COMMA;
1927
1928 case '\0':
1929 check_implied_arg(c);
1930 c->operand = 1;
1931 c->ptr--;
1932 return EOI;
1933
1934 /*
1935 * The {...} operator is really a hack that is left over
1936 * from the old math parser. The support for it here is
1937 * a hack. The entire thing is a hack.
1938 */
1939 case '{':
1940 {
1941 char *p = c->ptr;
1942 char oc = 0;
1943 ssize_t span;
1944
1945 if (!c->operand)
1946 return lexerr(c, "Misplaced { token");
1947
1948 if ((span = MatchingBracket(p, '{', '}')) >= 0)
1949 {
1950 c->ptr = p + span;
1951 oc = *c->ptr;
1952 *c->ptr = 0;
1953 }
1954 else
1955 c->ptr = empty_string;
1956
1957 c->last_token = 0;
1958 if (!c->noeval)
1959 {
1960 char * result;
1961
1962 result = call_lambda_function(NULL, p, c->args);
1963 c->last_token = tokenize_expanded(c, result);
1964 new_free(&result);
1965 }
1966
1967 if (oc)
1968 *c->ptr++ = oc;
1969 c->operand = 0;
1970 return ID;
1971 }
1972
1973 /******************** OPERAND TYPES **********************/
1974 /*
1975 * This is an UNEXPANDED-STRING operand type.
1976 * Extract everything inside the [...]'s, and then
1977 * tokenize that as a "raw" token. It will be expanded
1978 * on an as-needed basis.
1979 *
1980 * If we are in the no-eval section of a short-circuit,
1981 * then we throw away this token entirely.
1982 */
1983 case '[':
1984 {
1985 char *p = c->ptr;
1986 char oc = 0;
1987 ssize_t span;
1988
1989 if (!c->operand)
1990 return lexerr(c, "Misplaced [ token");
1991
1992 if ((span = MatchingBracket(p, '[', ']')) >= 0)
1993 {
1994 c->ptr = p + span;
1995 oc = *c->ptr;
1996 *c->ptr = 0;
1997 }
1998 else
1999 c->ptr = empty_string;
2000
2001 if (c->noeval)
2002 c->last_token = 0;
2003 else
2004 c->last_token = tokenize_raw(c, p);
2005
2006 if (oc)
2007 *c->ptr++ = oc;
2008 c->operand = 0;
2009 return ID;
2010 }
2011
2012 /* The "space" characters. */
2013 case 9: case 10: case 11: case 12: case 13: case ' ':
2014 start++;
2015 break;
2016
2017 /*
2018 * This is a NUMBER operand type. This may seem unusual,
2019 * but we actually tokenize the string representation of
2020 * the number as an "expanded" token type. Why do we do
2021 * this? Because in the most common case, the user is
2022 * doing something like:
2023 *
2024 * @ var = 0
2025 *
2026 * Now we already have the "0" in string format (natch),
2027 * and we will never actually reference the 0 as a number
2028 * per se -- all assignments are done on strings, so we
2029 * need the string anyhow. So when we lex a number in the
2030 * expression, we tokenize it as an 'expanded string' and
2031 * then if we ever have to actually use the number in any
2032 * particular context, it will be converted as-needed.
2033 */
2034 case '0': case '1': case '2': case '3': case '4':
2035 case '5': case '6': case '7': case '8': case '9':
2036 {
2037 char *end;
2038 char endc;
2039
2040 c->operand = 0;
2041 c->ptr--;
2042 strtod(c->ptr, &end);
2043 endc = *end;
2044 *end = 0;
2045
2046 if (c->noeval)
2047 c->last_token = 0;
2048 else
2049 c->last_token = tokenize_expanded(c, c->ptr);
2050
2051 *end = endc;
2052 c->ptr = end;
2053 return ID;
2054 }
2055
2056 /*
2057 * Handle those weirdo $-values
2058 */
2059 case '$':
2060 continue;
2061
2062 /*
2063 * This is an LVAL operand type. This also may seem
2064 * unusual, but lval's may contain $'s, which need to
2065 * be expanded. They may contain function calls, which
2066 * must only be expanded *once*. When we lex out an lval
2067 * (such as "var" in "@ var = 5"), we tokenize the lval
2068 * as an unexpanded lval. Then, if we ever actually need
2069 * to reference the proper variable name, we will get the
2070 * "raw" value, which will be the lval after passed through
2071 * expand_alias(). If we want to get the *value of the
2072 * variable $lval), then we will get the "expanded" value,
2073 * which will use the "raw" value to do the variable name
2074 * lookup. See? It's really pretty straightforward. The
2075 * reason we do all this is to make sure that the expansion
2076 * of the variable name happens *at most once*, and that if
2077 * the variable is not actually referenced, then the expansion
2078 * isn't done at all.
2079 */
2080 default:
2081 handle_expando:
2082 {
2083 char *end;
2084 char endc;
2085
2086 c->operand = 0;
2087 c->ptr--;
2088 if ((end = after_expando_special(c)))
2089 {
2090 endc = *end;
2091 *end = 0;
2092
2093 /*
2094 * If we are in the short-circuit of a noeval,
2095 * then we throw the token away.
2096 */
2097 if (c->noeval)
2098 c->last_token = 0;
2099 else
2100 c->last_token = tokenize_lval(c, start);
2101
2102 *end = endc;
2103 c->ptr = end;
2104 }
2105 else
2106 {
2107 c->last_token = 0; /* Empty token */
2108 c->ptr = empty_string;
2109 }
2110
2111 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2112 yell("After token: [%s]", c->ptr);
2113 return ID;
2114 }
2115 }
2116 }
2117 }
2118
2119 /******************************* STATE MACHINE *****************************/
2120 /*
2121 * mathparse -- this is the state machine that actually parses the
2122 * expression. The parsing is done through a shift-reduce mechanism,
2123 * and all the precedence levels lower than 'pc' are evaluated.
2124 */
mathparse(expr_info * c,int pc)2125 static void mathparse (expr_info *c, int pc)
2126 {
2127 int otok,
2128 onoeval;
2129
2130 /*
2131 * Drop out of parsing if an error has occured
2132 */
2133 if (c->errflag)
2134 return;
2135
2136 /*
2137 * Get the next token in the expression
2138 */
2139 c->mtok = zzlex(c);
2140
2141 /*
2142 * For as long as the next operator indicates a shift operation...
2143 */
2144 while (prec[c->mtok] <= pc)
2145 {
2146 /* Drop out if an error has occured */
2147 if (c->errflag)
2148 return;
2149
2150 /*
2151 * Figure out what to do with this token that needs
2152 * to be shifted.
2153 */
2154 switch (c->mtok)
2155 {
2156 /*
2157 * This is any kind of an indentifier. There are several
2158 * that we handle:
2159 *
2160 * VARIABLE REFERENCE ie, "foo" in "@ foo = 2"
2161 * NUMBER ie, "2" in "@ foo = 2"
2162 * UNEXPANDED STRING ie, "[boo]" in "@ foo = [boo]"
2163 *
2164 * The actual determination of which type is done in the lexer.
2165 * We just get a token id for the resulting identifier.
2166 * Getting the value is done on an as-needed basis.
2167 */
2168 case ID:
2169 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2170 yell("Parsed identifier token [%s]",
2171 get_token_expanded(c, c->last_token));
2172
2173 /*
2174 * The lexer sets the last token to
2175 * 0 if noeval is set. This saves us
2176 * from having to tokenize a string
2177 * that we expressly will not use.
2178 */
2179 push_token(c, c->last_token);
2180 break;
2181
2182 /*
2183 * An open-parenthesis indicates that we should
2184 * recursively evaluate the inside of the paren-set.
2185 */
2186 case M_INPAR:
2187 {
2188 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2189 yell("Parsed open paren");
2190 mathparse(c, TOPPREC);
2191
2192 /*
2193 * Of course if the expression ends without
2194 * a matching rparen, then we whine about it.
2195 */
2196 if (c->mtok != M_OUTPAR)
2197 {
2198 if (!c->errflag)
2199 error("')' expected");
2200 return;
2201 }
2202 break;
2203 }
2204
2205 /*
2206 * A question mark requires that we check for short
2207 * circuiting. We check the lhs, and if it is true,
2208 * then we evaluate the lhs of the colon. If it is
2209 * false then we just parse the lhs of the colon and
2210 * evaluate the rhs of the colon.
2211 */
2212 case QUEST:
2213 {
2214 BooL u = pop_boolean(c);
2215
2216 push_boolean(c, u);
2217 if (!u)
2218 c->noeval++;
2219 mathparse(c, prec[QUEST] - 1);
2220 if (!u)
2221 c->noeval--;
2222 else
2223 c->noeval++;
2224 mathparse(c, prec[QUEST]);
2225 if (u)
2226 c->noeval--;
2227 reduce(c, QUEST);
2228
2229 continue;
2230 }
2231
2232 /*
2233 * All other operators handle normally
2234 */
2235 default:
2236 {
2237 /* Save state */
2238 otok = c->mtok;
2239 onoeval = c->noeval;
2240
2241 /*
2242 * Check for short circuiting.
2243 */
2244 if (assoc[otok] == BOOL)
2245 {
2246 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2247 yell("Parsed short circuit operator");
2248
2249 switch (otok)
2250 {
2251 case DAND:
2252 case DANDEQ:
2253 {
2254 BooL u = pop_boolean(c);
2255 push_boolean(c, u);
2256 if (!u)
2257 c->noeval++;
2258 break;
2259 }
2260 case DOR:
2261 case DOREQ:
2262 {
2263 BooL u = pop_boolean(c);
2264 push_boolean(c, u);
2265 if (u)
2266 c->noeval++;
2267 break;
2268 }
2269 }
2270 }
2271
2272 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2273 yell("Parsed operator of type [%d]", otok);
2274
2275 /*
2276 * Parse the right hand side through
2277 * recursion if we're doing things R->L.
2278 */
2279 mathparse(c, prec[otok] - (assoc[otok] != RL));
2280
2281 /*
2282 * Then reduce this operation.
2283 */
2284 c->noeval = onoeval;
2285 reduce(c, otok);
2286 continue;
2287 }
2288 }
2289
2290 /*
2291 * Grab the next token
2292 */
2293 c->mtok = zzlex(c);
2294 }
2295 }
2296
2297 /******************************** HARNASS **********************************/
2298 /*
2299 * This is the new math parser. It sets up an execution context, which
2300 * contains sundry information like all the extracted tokens, intermediate
2301 * tokens, shifted tokens, and the like. The expression context is passed
2302 * around from function to function, each function is totaly independant
2303 * of state information stored in global variables. Therefore, this math
2304 * parser is re-entrant safe.
2305 */
matheval(char * s,const char * args,int * args_flag)2306 static char * matheval (char *s, const char *args, int *args_flag)
2307 {
2308 expr_info context;
2309 char * ret = NULL;
2310
2311 /* Sanity check */
2312 if (!s || !*s)
2313 return malloc_strdup(empty_string);
2314
2315 /* Create new state */
2316 setup_expr_info(&context);
2317 context.ptr = s;
2318 context.args = args;
2319 context.args_flag = args_flag;
2320
2321 /* Actually do the parsing */
2322 mathparse(&context, TOPPREC);
2323
2324 /* Check for error */
2325 if (context.errflag)
2326 {
2327 ret = malloc_strdup(empty_string);
2328 goto cleanup;
2329 }
2330
2331 /* Check for leftover operands */
2332 if (context.sp)
2333 error("The expression has too many operands");
2334
2335 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2336 {
2337 int i;
2338 yell("Terms left: %d", context.sp);
2339 for (i = 0; i <= context.sp; i++)
2340 yell("Term [%d]: [%s]", i,
2341 get_token_expanded(&context, context.stack[i]));
2342 }
2343
2344 /* Get the return value, if requested */
2345 ret = malloc_strdup(get_token_expanded(&context, pop_token(&context)));
2346
2347 cleanup:
2348 /* Clean up and restore order */
2349 destroy_expr_info(&context);
2350
2351 if (x_debug & DEBUG_NEW_MATH_DEBUG)
2352 yell("Returning [%s]", ret);
2353
2354 /* Return the result */
2355 return ret;
2356 }
2357
2358
2359 /******************************* SUPPORT *************************************/
2360 /*
2361 * after_expando_special: This is a special version of after_expando that
2362 * can handle parsing out lvalues in expressions. Due to the eclectic nature
2363 * of lvalues in expressions, this is quite a bit different than the normal
2364 * after_expando, requiring a different function. Ugh.
2365 *
2366 * This replaces some much more complicated logic strewn
2367 * here and there that attempted to figure out just how long an expando
2368 * name was supposed to be. Well, now this changes that. This will slurp
2369 * up everything in 'start' that could possibly be put after a $ that could
2370 * result in a syntactically valid expando. All you need to do is tell it
2371 * if the expando is an rvalue or an lvalue (it *does* make a difference)
2372 */
after_expando_special(expr_info * c)2373 static char * after_expando_special (expr_info *c)
2374 {
2375 char *start;
2376 char *rest;
2377 int call;
2378
2379 if (!(start = c->ptr))
2380 return c->ptr;
2381
2382 for (;;)
2383 {
2384 rest = after_expando(start, 0, &call);
2385 if (*rest != '$')
2386 break;
2387 start = rest + 1;
2388 }
2389
2390 if (c->ptr == rest)
2391 {
2392 yell("Erf. I'm trying to find an lval at [%s] and I'm not "
2393 "having much luck finding one. Punting the rest of "
2394 "this expression", c->ptr);
2395 return NULL;
2396 }
2397
2398 /*
2399 * All done!
2400 */
2401 return rest;
2402 }
2403
2404