]> cvs.zerfleddert.de Git - micropolis/blob - src/tcl/tclexpr.c
Fixes for compilation with gcc 15
[micropolis] / src / tcl / tclexpr.c
1 /*
2 * tclExpr.c --
3 *
4 * This file contains the code to evaluate expressions for
5 * Tcl.
6 *
7 * This implementation of floating-point support was modelled
8 * after an initial implementation by Bill Carpenter.
9 *
10 * Copyright 1987-1991 Regents of the University of California
11 * Permission to use, copy, modify, and distribute this
12 * software and its documentation for any purpose and without
13 * fee is hereby granted, provided that the above copyright
14 * notice appear in all copies. The University of California
15 * makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without
17 * express or implied warranty.
18 */
19
20 #ifndef lint
21 static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclExpr.c,v 1.35 92/03/23 09:53:46 ouster Exp $ SPRITE (Berkeley)";
22 #endif
23
24 #include "tclint.h"
25
26 /*
27 * The stuff below is a bit of a workaround so that this file can be used
28 * in environments that include no UNIX, i.e. no errno. Just define
29 * errno here.
30 */
31
32 #ifndef TCL_GENERIC_ONLY
33 #include "tclunix.h"
34 #else
35 int errno;
36 #define ERANGE 34
37 #endif
38
39 /*
40 * The data structure below is used to describe an expression value,
41 * which can be either an integer (the usual case), a double-precision
42 * floating-point value, or a string. A given number has only one
43 * value at a time.
44 */
45
46 #define STATIC_STRING_SPACE 150
47
48 typedef struct {
49 long intValue; /* Integer value, if any. */
50 double doubleValue; /* Floating-point value, if any. */
51 ParseValue pv; /* Used to hold a string value, if any. */
52 char staticSpace[STATIC_STRING_SPACE];
53 /* Storage for small strings; large ones
54 * are malloc-ed. */
55 int type; /* Type of value: TYPE_INT, TYPE_DOUBLE,
56 * or TYPE_STRING. */
57 } Value;
58
59 /*
60 * Valid values for type:
61 */
62
63 #define TYPE_INT 0
64 #define TYPE_DOUBLE 1
65 #define TYPE_STRING 2
66
67
68 /*
69 * The data structure below describes the state of parsing an expression.
70 * It's passed among the routines in this module.
71 */
72
73 typedef struct {
74 char *originalExpr; /* The entire expression, as originally
75 * passed to Tcl_Expr. */
76 char *expr; /* Position to the next character to be
77 * scanned from the expression string. */
78 int token; /* Type of the last token to be parsed from
79 * expr. See below for definitions.
80 * Corresponds to the characters just
81 * before expr. */
82 } ExprInfo;
83
84 /*
85 * The token types are defined below. In addition, there is a table
86 * associating a precedence with each operator. The order of types
87 * is important. Consult the code before changing it.
88 */
89
90 #define VALUE 0
91 #define OPEN_PAREN 1
92 #define CLOSE_PAREN 2
93 #define END 3
94 #define UNKNOWN 4
95
96 /*
97 * Binary operators:
98 */
99
100 #define MULT 8
101 #define DIVIDE 9
102 #define MOD 10
103 #define PLUS 11
104 #define MINUS 12
105 #define LEFT_SHIFT 13
106 #define RIGHT_SHIFT 14
107 #define LESS 15
108 #define GREATER 16
109 #define LEQ 17
110 #define GEQ 18
111 #define EQUAL 19
112 #define NEQ 20
113 #define BIT_AND 21
114 #define BIT_XOR 22
115 #define BIT_OR 23
116 #define AND 24
117 #define OR 25
118 #define QUESTY 26
119 #define COLON 27
120
121 /*
122 * Unary operators:
123 */
124
125 #define UNARY_MINUS 28
126 #define NOT 29
127 #define BIT_NOT 30
128
129 /*
130 * Precedence table. The values for non-operator token types are ignored.
131 */
132
133 int precTable[] = {
134 0, 0, 0, 0, 0, 0, 0, 0,
135 11, 11, 11, /* MULT, DIVIDE, MOD */
136 10, 10, /* PLUS, MINUS */
137 9, 9, /* LEFT_SHIFT, RIGHT_SHIFT */
138 8, 8, 8, 8, /* LESS, GREATER, LEQ, GEQ */
139 7, 7, /* EQUAL, NEQ */
140 6, /* BIT_AND */
141 5, /* BIT_XOR */
142 4, /* BIT_OR */
143 3, /* AND */
144 2, /* OR */
145 1, 1, /* QUESTY, COLON */
146 12, 12, 12 /* UNARY_MINUS, NOT, BIT_NOT */
147 };
148
149 /*
150 * Mapping from operator numbers to strings; used for error messages.
151 */
152
153 char *operatorStrings[] = {
154 "VALUE", "(", ")", "END", "UNKNOWN", "5", "6", "7",
155 "*", "/", "%", "+", "-", "<<", ">>", "<", ">", "<=",
156 ">=", "==", "!=", "&", "^", "|", "&&", "||", "?", ":",
157 "-", "!", "~"
158 };
159
160 /*
161 * Declarations for local procedures to this file:
162 */
163
164 static int ExprGetValue _ANSI_ARGS_((Tcl_Interp *interp,
165 ExprInfo *infoPtr, int prec, Value *valuePtr));
166 static int ExprLex _ANSI_ARGS_((Tcl_Interp *interp,
167 ExprInfo *infoPtr, Value *valuePtr));
168 static void ExprMakeString _ANSI_ARGS_((Value *valuePtr));
169 static int ExprParseString _ANSI_ARGS_((Tcl_Interp *interp,
170 char *string, Value *valuePtr));
171 static int ExprTopLevel _ANSI_ARGS_((Tcl_Interp *interp,
172 char *string, Value *valuePtr));
173 \f
174 /*
175 *--------------------------------------------------------------
176 *
177 * ExprParseString --
178 *
179 * Given a string (such as one coming from command or variable
180 * substitution), make a Value based on the string. The value
181 * will be a floating-point or integer, if possible, or else it
182 * will just be a copy of the string.
183 *
184 * Results:
185 * TCL_OK is returned under normal circumstances, and TCL_ERROR
186 * is returned if a floating-point overflow or underflow occurred
187 * while reading in a number. The value at *valuePtr is modified
188 * to hold a number, if possible.
189 *
190 * Side effects:
191 * None.
192 *
193 *--------------------------------------------------------------
194 */
195
196 static int
197 ExprParseString (
198 Tcl_Interp *interp, /* Where to store error message. */
199 char *string, /* String to turn into value. */
200 Value *valuePtr /* Where to store value information.
201 * Caller must have initialized pv field. */
202 )
203 {
204 register char c;
205
206 /*
207 * Try to convert the string to a number.
208 */
209
210 c = *string;
211 if (((c >= '0') && (c <= '9')) || (c == '-') || (c == '.')) {
212 char *term;
213
214 valuePtr->type = TYPE_INT;
215 errno = 0;
216 valuePtr->intValue = strtol(string, &term, 0);
217 c = *term;
218 if ((c == '\0') && (errno != ERANGE)) {
219 return TCL_OK;
220 }
221 if ((c == '.') || (c == 'e') || (c == 'E') || (errno == ERANGE)) {
222 errno = 0;
223 valuePtr->doubleValue = strtod(string, &term);
224 if (errno == ERANGE) {
225 Tcl_ResetResult(interp);
226 if (valuePtr->doubleValue == 0.0) {
227 Tcl_AppendResult(interp, "floating-point value \"",
228 string, "\" too small to represent",
229 (char *) NULL);
230 } else {
231 Tcl_AppendResult(interp, "floating-point value \"",
232 string, "\" too large to represent",
233 (char *) NULL);
234 }
235 return TCL_ERROR;
236 }
237 if (*term == '\0') {
238 valuePtr->type = TYPE_DOUBLE;
239 return TCL_OK;
240 }
241 }
242 }
243
244 /*
245 * Not a valid number. Save a string value (but don't do anything
246 * if it's already the value).
247 */
248
249 valuePtr->type = TYPE_STRING;
250 if (string != valuePtr->pv.buffer) {
251 int length, shortfall;
252
253 length = strlen(string);
254 valuePtr->pv.next = valuePtr->pv.buffer;
255 shortfall = length - (valuePtr->pv.end - valuePtr->pv.buffer);
256 if (shortfall > 0) {
257 (*valuePtr->pv.expandProc)(&valuePtr->pv, shortfall);
258 }
259 strcpy(valuePtr->pv.buffer, string);
260 }
261 return TCL_OK;
262 }
263 \f
264 /*
265 *----------------------------------------------------------------------
266 *
267 * ExprLex --
268 *
269 * Lexical analyzer for expression parser: parses a single value,
270 * operator, or other syntactic element from an expression string.
271 *
272 * Results:
273 * TCL_OK is returned unless an error occurred while doing lexical
274 * analysis or executing an embedded command. In that case a
275 * standard Tcl error is returned, using interp->result to hold
276 * an error message. In the event of a successful return, the token
277 * and field in infoPtr is updated to refer to the next symbol in
278 * the expression string, and the expr field is advanced past that
279 * token; if the token is a value, then the value is stored at
280 * valuePtr.
281 *
282 * Side effects:
283 * None.
284 *
285 *----------------------------------------------------------------------
286 */
287
288 static int
289 ExprLex (
290 Tcl_Interp *interp, /* Interpreter to use for error
291 * reporting. */
292 register ExprInfo *infoPtr, /* Describes the state of the parse. */
293 register Value *valuePtr /* Where to store value, if that is
294 * what's parsed from string. Caller
295 * must have initialized pv field
296 * correctly. */
297 )
298 {
299 register char *p, c;
300 char *var, *term;
301 int result;
302
303 p = infoPtr->expr;
304 c = *p;
305 while (isspace(c)) {
306 p++;
307 c = *p;
308 }
309 infoPtr->expr = p+1;
310 switch (c) {
311 case '0':
312 case '1':
313 case '2':
314 case '3':
315 case '4':
316 case '5':
317 case '6':
318 case '7':
319 case '8':
320 case '9':
321 case '.':
322
323 /*
324 * Number. First read an integer. Then if it looks like
325 * there's a floating-point number (or if it's too big a
326 * number to fit in an integer), parse it as a floating-point
327 * number.
328 */
329
330 infoPtr->token = VALUE;
331 valuePtr->type = TYPE_INT;
332 errno = 0;
333 valuePtr->intValue = strtoul(p, &term, 0);
334 c = *term;
335 if ((c == '.') || (c == 'e') || (c == 'E') || (errno == ERANGE)) {
336 char *term2;
337
338 errno = 0;
339 valuePtr->doubleValue = strtod(p, &term2);
340 if (errno == ERANGE) {
341 Tcl_ResetResult(interp);
342 if (valuePtr->doubleValue == 0.0) {
343 interp->result =
344 "floating-point value too small to represent";
345 } else {
346 interp->result =
347 "floating-point value too large to represent";
348 }
349 return TCL_ERROR;
350 }
351 if (term2 == infoPtr->expr) {
352 interp->result = "poorly-formed floating-point value";
353 return TCL_ERROR;
354 }
355 valuePtr->type = TYPE_DOUBLE;
356 infoPtr->expr = term2;
357 } else {
358 infoPtr->expr = term;
359 }
360 return TCL_OK;
361
362 case '$':
363
364 /*
365 * Variable. Fetch its value, then see if it makes sense
366 * as an integer or floating-point number.
367 */
368
369 infoPtr->token = VALUE;
370 var = Tcl_ParseVar(interp, p, &infoPtr->expr);
371 if (var == NULL) {
372 return TCL_ERROR;
373 }
374 if (((Interp *) interp)->noEval) {
375 valuePtr->type = TYPE_INT;
376 valuePtr->intValue = 0;
377 return TCL_OK;
378 }
379 return ExprParseString(interp, var, valuePtr);
380
381 case '[':
382 infoPtr->token = VALUE;
383 result = Tcl_Eval(interp, p+1, TCL_BRACKET_TERM,
384 &infoPtr->expr);
385 if (result != TCL_OK) {
386 return result;
387 }
388 infoPtr->expr++;
389 if (((Interp *) interp)->noEval) {
390 valuePtr->type = TYPE_INT;
391 valuePtr->intValue = 0;
392 Tcl_ResetResult(interp);
393 return TCL_OK;
394 }
395 result = ExprParseString(interp, interp->result, valuePtr);
396 if (result != TCL_OK) {
397 return result;
398 }
399 Tcl_ResetResult(interp);
400 return TCL_OK;
401
402 case '"':
403 infoPtr->token = VALUE;
404 result = TclParseQuotes(interp, infoPtr->expr, '"', 0,
405 &infoPtr->expr, &valuePtr->pv);
406 if (result != TCL_OK) {
407 return result;
408 }
409 return ExprParseString(interp, valuePtr->pv.buffer, valuePtr);
410
411 case '{':
412 infoPtr->token = VALUE;
413 result = TclParseBraces(interp, infoPtr->expr, &infoPtr->expr,
414 &valuePtr->pv);
415 if (result != TCL_OK) {
416 return result;
417 }
418 return ExprParseString(interp, valuePtr->pv.buffer, valuePtr);
419
420 case '(':
421 infoPtr->token = OPEN_PAREN;
422 return TCL_OK;
423
424 case ')':
425 infoPtr->token = CLOSE_PAREN;
426 return TCL_OK;
427
428 case '*':
429 infoPtr->token = MULT;
430 return TCL_OK;
431
432 case '/':
433 infoPtr->token = DIVIDE;
434 return TCL_OK;
435
436 case '%':
437 infoPtr->token = MOD;
438 return TCL_OK;
439
440 case '+':
441 infoPtr->token = PLUS;
442 return TCL_OK;
443
444 case '-':
445 infoPtr->token = MINUS;
446 return TCL_OK;
447
448 case '?':
449 infoPtr->token = QUESTY;
450 return TCL_OK;
451
452 case ':':
453 infoPtr->token = COLON;
454 return TCL_OK;
455
456 case '<':
457 switch (p[1]) {
458 case '<':
459 infoPtr->expr = p+2;
460 infoPtr->token = LEFT_SHIFT;
461 break;
462 case '=':
463 infoPtr->expr = p+2;
464 infoPtr->token = LEQ;
465 break;
466 default:
467 infoPtr->token = LESS;
468 break;
469 }
470 return TCL_OK;
471
472 case '>':
473 switch (p[1]) {
474 case '>':
475 infoPtr->expr = p+2;
476 infoPtr->token = RIGHT_SHIFT;
477 break;
478 case '=':
479 infoPtr->expr = p+2;
480 infoPtr->token = GEQ;
481 break;
482 default:
483 infoPtr->token = GREATER;
484 break;
485 }
486 return TCL_OK;
487
488 case '=':
489 if (p[1] == '=') {
490 infoPtr->expr = p+2;
491 infoPtr->token = EQUAL;
492 } else {
493 infoPtr->token = UNKNOWN;
494 }
495 return TCL_OK;
496
497 case '!':
498 if (p[1] == '=') {
499 infoPtr->expr = p+2;
500 infoPtr->token = NEQ;
501 } else {
502 infoPtr->token = NOT;
503 }
504 return TCL_OK;
505
506 case '&':
507 if (p[1] == '&') {
508 infoPtr->expr = p+2;
509 infoPtr->token = AND;
510 } else {
511 infoPtr->token = BIT_AND;
512 }
513 return TCL_OK;
514
515 case '^':
516 infoPtr->token = BIT_XOR;
517 return TCL_OK;
518
519 case '|':
520 if (p[1] == '|') {
521 infoPtr->expr = p+2;
522 infoPtr->token = OR;
523 } else {
524 infoPtr->token = BIT_OR;
525 }
526 return TCL_OK;
527
528 case '~':
529 infoPtr->token = BIT_NOT;
530 return TCL_OK;
531
532 case 0:
533 infoPtr->token = END;
534 infoPtr->expr = p;
535 return TCL_OK;
536
537 default:
538 infoPtr->expr = p+1;
539 infoPtr->token = UNKNOWN;
540 return TCL_OK;
541 }
542 }
543 \f
544 /*
545 *----------------------------------------------------------------------
546 *
547 * ExprGetValue --
548 *
549 * Parse a "value" from the remainder of the expression in infoPtr.
550 *
551 * Results:
552 * Normally TCL_OK is returned. The value of the expression is
553 * returned in *valuePtr. If an error occurred, then interp->result
554 * contains an error message and TCL_ERROR is returned.
555 * InfoPtr->token will be left pointing to the token AFTER the
556 * expression, and infoPtr->expr will point to the character just
557 * after the terminating token.
558 *
559 * Side effects:
560 * None.
561 *
562 *----------------------------------------------------------------------
563 */
564
565 static int
566 ExprGetValue (
567 Tcl_Interp *interp, /* Interpreter to use for error
568 * reporting. */
569 register ExprInfo *infoPtr, /* Describes the state of the parse
570 * just before the value (i.e. ExprLex
571 * will be called to get first token
572 * of value). */
573 int prec, /* Treat any un-parenthesized operator
574 * with precedence <= this as the end
575 * of the expression. */
576 Value *valuePtr /* Where to store the value of the
577 * expression. Caller must have
578 * initialized pv field. */
579 )
580 {
581 Interp *iPtr = (Interp *) interp;
582 Value value2; /* Second operand for current
583 * operator. */
584 int operator; /* Current operator (either unary
585 * or binary). */
586 int badType; /* Type of offending argument; used
587 * for error messages. */
588 int gotOp; /* Non-zero means already lexed the
589 * operator (while picking up value
590 * for unary operator). Don't lex
591 * again. */
592 int result;
593
594 /*
595 * There are two phases to this procedure. First, pick off an initial
596 * value. Then, parse (binary operator, value) pairs until done.
597 */
598
599 gotOp = 0;
600 value2.pv.buffer = value2.pv.next = value2.staticSpace;
601 value2.pv.end = value2.pv.buffer + STATIC_STRING_SPACE - 1;
602 value2.pv.expandProc = TclExpandParseValue;
603 value2.pv.clientData = (ClientData) NULL;
604 result = ExprLex(interp, infoPtr, valuePtr);
605 if (result != TCL_OK) {
606 goto done;
607 }
608 if (infoPtr->token == OPEN_PAREN) {
609
610 /*
611 * Parenthesized sub-expression.
612 */
613
614 result = ExprGetValue(interp, infoPtr, -1, valuePtr);
615 if (result != TCL_OK) {
616 goto done;
617 }
618 if (infoPtr->token != CLOSE_PAREN) {
619 Tcl_ResetResult(interp);
620 sprintf(interp->result,
621 "unmatched parentheses in expression \"%.50s\"",
622 infoPtr->originalExpr);
623 result = TCL_ERROR;
624 goto done;
625 }
626 } else {
627 if (infoPtr->token == MINUS) {
628 infoPtr->token = UNARY_MINUS;
629 }
630 if (infoPtr->token >= UNARY_MINUS) {
631
632 /*
633 * Process unary operators.
634 */
635
636 operator = infoPtr->token;
637 result = ExprGetValue(interp, infoPtr, precTable[infoPtr->token],
638 valuePtr);
639 if (result != TCL_OK) {
640 goto done;
641 }
642 switch (operator) {
643 case UNARY_MINUS:
644 if (valuePtr->type == TYPE_INT) {
645 valuePtr->intValue = -valuePtr->intValue;
646 } else if (valuePtr->type == TYPE_DOUBLE){
647 valuePtr->doubleValue = -valuePtr->doubleValue;
648 } else {
649 badType = valuePtr->type;
650 goto illegalType;
651 }
652 break;
653 case NOT:
654 if (valuePtr->type == TYPE_INT) {
655 valuePtr->intValue = !valuePtr->intValue;
656 } else if (valuePtr->type == TYPE_DOUBLE) {
657 /*
658 * Theoretically, should be able to use
659 * "!valuePtr->intValue", but apparently some
660 * compilers can't handle it.
661 */
662 if (valuePtr->doubleValue == 0.0) {
663 valuePtr->intValue = 1;
664 } else {
665 valuePtr->intValue = 0;
666 }
667 valuePtr->type = TYPE_INT;
668 } else {
669 badType = valuePtr->type;
670 goto illegalType;
671 }
672 break;
673 case BIT_NOT:
674 if (valuePtr->type == TYPE_INT) {
675 valuePtr->intValue = ~valuePtr->intValue;
676 } else {
677 badType = valuePtr->type;
678 goto illegalType;
679 }
680 break;
681 }
682 gotOp = 1;
683 } else if (infoPtr->token != VALUE) {
684 goto syntaxError;
685 }
686 }
687
688 /*
689 * Got the first operand. Now fetch (operator, operand) pairs.
690 */
691
692 if (!gotOp) {
693 result = ExprLex(interp, infoPtr, &value2);
694 if (result != TCL_OK) {
695 goto done;
696 }
697 }
698 while (1) {
699 operator = infoPtr->token;
700 value2.pv.next = value2.pv.buffer;
701 if ((operator < MULT) || (operator >= UNARY_MINUS)) {
702 if ((operator == END) || (operator == CLOSE_PAREN)) {
703 result = TCL_OK;
704 goto done;
705 } else {
706 goto syntaxError;
707 }
708 }
709 if (precTable[operator] <= prec) {
710 result = TCL_OK;
711 goto done;
712 }
713
714 /*
715 * If we're doing an AND or OR and the first operand already
716 * determines the result, don't execute anything in the
717 * second operand: just parse. Same style for ?: pairs.
718 */
719
720 if ((operator == AND) || (operator == OR) || (operator == QUESTY)) {
721 if (valuePtr->type == TYPE_DOUBLE) {
722 valuePtr->intValue = valuePtr->doubleValue != 0;
723 valuePtr->type = TYPE_INT;
724 } else if (valuePtr->type == TYPE_STRING) {
725 badType = TYPE_STRING;
726 goto illegalType;
727 }
728 if (((operator == AND) && !valuePtr->intValue)
729 || ((operator == OR) && valuePtr->intValue)) {
730 iPtr->noEval++;
731 result = ExprGetValue(interp, infoPtr, precTable[operator],
732 &value2);
733 iPtr->noEval--;
734 } else if (operator == QUESTY) {
735 if (valuePtr->intValue != 0) {
736 valuePtr->pv.next = valuePtr->pv.buffer;
737 result = ExprGetValue(interp, infoPtr, precTable[operator],
738 valuePtr);
739 if (result != TCL_OK) {
740 goto done;
741 }
742 if (infoPtr->token != COLON) {
743 goto syntaxError;
744 }
745 value2.pv.next = value2.pv.buffer;
746 iPtr->noEval++;
747 result = ExprGetValue(interp, infoPtr, precTable[operator],
748 &value2);
749 iPtr->noEval--;
750 } else {
751 iPtr->noEval++;
752 result = ExprGetValue(interp, infoPtr, precTable[operator],
753 &value2);
754 iPtr->noEval--;
755 if (result != TCL_OK) {
756 goto done;
757 }
758 if (infoPtr->token != COLON) {
759 goto syntaxError;
760 }
761 valuePtr->pv.next = valuePtr->pv.buffer;
762 result = ExprGetValue(interp, infoPtr, precTable[operator],
763 valuePtr);
764 }
765 } else {
766 result = ExprGetValue(interp, infoPtr, precTable[operator],
767 &value2);
768 }
769 } else {
770 result = ExprGetValue(interp, infoPtr, precTable[operator],
771 &value2);
772 }
773 if (result != TCL_OK) {
774 goto done;
775 }
776 if ((infoPtr->token < MULT) && (infoPtr->token != VALUE)
777 && (infoPtr->token != END)
778 && (infoPtr->token != CLOSE_PAREN)) {
779 goto syntaxError;
780 }
781
782 /*
783 * At this point we've got two values and an operator. Check
784 * to make sure that the particular data types are appropriate
785 * for the particular operator, and perform type conversion
786 * if necessary.
787 */
788
789 switch (operator) {
790
791 /*
792 * For the operators below, no strings are allowed and
793 * ints get converted to floats if necessary.
794 */
795
796 case MULT: case DIVIDE: case PLUS: case MINUS:
797 if ((valuePtr->type == TYPE_STRING)
798 || (value2.type == TYPE_STRING)) {
799 badType = TYPE_STRING;
800 goto illegalType;
801 }
802 if (valuePtr->type == TYPE_DOUBLE) {
803 if (value2.type == TYPE_INT) {
804 value2.doubleValue = value2.intValue;
805 value2.type = TYPE_DOUBLE;
806 }
807 } else if (value2.type == TYPE_DOUBLE) {
808 if (valuePtr->type == TYPE_INT) {
809 valuePtr->doubleValue = valuePtr->intValue;
810 valuePtr->type = TYPE_DOUBLE;
811 }
812 }
813 break;
814
815 /*
816 * For the operators below, only integers are allowed.
817 */
818
819 case MOD: case LEFT_SHIFT: case RIGHT_SHIFT:
820 case BIT_AND: case BIT_XOR: case BIT_OR:
821 if (valuePtr->type != TYPE_INT) {
822 badType = valuePtr->type;
823 goto illegalType;
824 } else if (value2.type != TYPE_INT) {
825 badType = value2.type;
826 goto illegalType;
827 }
828 break;
829
830 /*
831 * For the operators below, any type is allowed but the
832 * two operands must have the same type. Convert integers
833 * to floats and either to strings, if necessary.
834 */
835
836 case LESS: case GREATER: case LEQ: case GEQ:
837 case EQUAL: case NEQ:
838 if (valuePtr->type == TYPE_STRING) {
839 if (value2.type != TYPE_STRING) {
840 ExprMakeString(&value2);
841 }
842 } else if (value2.type == TYPE_STRING) {
843 if (valuePtr->type != TYPE_STRING) {
844 ExprMakeString(valuePtr);
845 }
846 } else if (valuePtr->type == TYPE_DOUBLE) {
847 if (value2.type == TYPE_INT) {
848 value2.doubleValue = value2.intValue;
849 value2.type = TYPE_DOUBLE;
850 }
851 } else if (value2.type == TYPE_DOUBLE) {
852 if (valuePtr->type == TYPE_INT) {
853 valuePtr->doubleValue = valuePtr->intValue;
854 valuePtr->type = TYPE_DOUBLE;
855 }
856 }
857 break;
858
859 /*
860 * For the operators below, no strings are allowed, but
861 * no int->double conversions are performed.
862 */
863
864 case AND: case OR:
865 if (valuePtr->type == TYPE_STRING) {
866 badType = valuePtr->type;
867 goto illegalType;
868 }
869 if (value2.type == TYPE_STRING) {
870 badType = value2.type;
871 goto illegalType;
872 }
873 break;
874
875 /*
876 * For the operators below, type and conversions are
877 * irrelevant: they're handled elsewhere.
878 */
879
880 case QUESTY: case COLON:
881 break;
882
883 /*
884 * Any other operator is an error.
885 */
886
887 default:
888 interp->result = "unknown operator in expression";
889 result = TCL_ERROR;
890 goto done;
891 }
892
893 /*
894 * If necessary, convert one of the operands to the type
895 * of the other. If the operands are incompatible with
896 * the operator (e.g. "+" on strings) then return an
897 * error.
898 */
899
900 switch (operator) {
901 case MULT:
902 if (valuePtr->type == TYPE_INT) {
903 valuePtr->intValue *= value2.intValue;
904 } else {
905 valuePtr->doubleValue *= value2.doubleValue;
906 }
907 break;
908 case DIVIDE:
909 if (valuePtr->type == TYPE_INT) {
910 if (value2.intValue == 0) {
911 divideByZero:
912 interp->result = "divide by zero";
913 result = TCL_ERROR;
914 goto done;
915 }
916 valuePtr->intValue /= value2.intValue;
917 } else {
918 if (value2.doubleValue == 0.0) {
919 goto divideByZero;
920 }
921 valuePtr->doubleValue /= value2.doubleValue;
922 }
923 break;
924 case MOD:
925 if (value2.intValue == 0) {
926 goto divideByZero;
927 }
928 valuePtr->intValue %= value2.intValue;
929 break;
930 case PLUS:
931 if (valuePtr->type == TYPE_INT) {
932 valuePtr->intValue += value2.intValue;
933 } else {
934 valuePtr->doubleValue += value2.doubleValue;
935 }
936 break;
937 case MINUS:
938 if (valuePtr->type == TYPE_INT) {
939 valuePtr->intValue -= value2.intValue;
940 } else {
941 valuePtr->doubleValue -= value2.doubleValue;
942 }
943 break;
944 case LEFT_SHIFT:
945 valuePtr->intValue <<= value2.intValue;
946 break;
947 case RIGHT_SHIFT:
948 /*
949 * The following code is a bit tricky: it ensures that
950 * right shifts propagate the sign bit even on machines
951 * where ">>" won't do it by default.
952 */
953
954 if (valuePtr->intValue < 0) {
955 valuePtr->intValue =
956 ~((~valuePtr->intValue) >> value2.intValue);
957 } else {
958 valuePtr->intValue >>= value2.intValue;
959 }
960 break;
961 case LESS:
962 if (valuePtr->type == TYPE_INT) {
963 valuePtr->intValue =
964 valuePtr->intValue < value2.intValue;
965 } else if (valuePtr->type == TYPE_DOUBLE) {
966 valuePtr->intValue =
967 valuePtr->doubleValue < value2.doubleValue;
968 } else {
969 valuePtr->intValue =
970 strcmp(valuePtr->pv.buffer, value2.pv.buffer) < 0;
971 }
972 valuePtr->type = TYPE_INT;
973 break;
974 case GREATER:
975 if (valuePtr->type == TYPE_INT) {
976 valuePtr->intValue =
977 valuePtr->intValue > value2.intValue;
978 } else if (valuePtr->type == TYPE_DOUBLE) {
979 valuePtr->intValue =
980 valuePtr->doubleValue > value2.doubleValue;
981 } else {
982 valuePtr->intValue =
983 strcmp(valuePtr->pv.buffer, value2.pv.buffer) > 0;
984 }
985 valuePtr->type = TYPE_INT;
986 break;
987 case LEQ:
988 if (valuePtr->type == TYPE_INT) {
989 valuePtr->intValue =
990 valuePtr->intValue <= value2.intValue;
991 } else if (valuePtr->type == TYPE_DOUBLE) {
992 valuePtr->intValue =
993 valuePtr->doubleValue <= value2.doubleValue;
994 } else {
995 valuePtr->intValue =
996 strcmp(valuePtr->pv.buffer, value2.pv.buffer) <= 0;
997 }
998 valuePtr->type = TYPE_INT;
999 break;
1000 case GEQ:
1001 if (valuePtr->type == TYPE_INT) {
1002 valuePtr->intValue =
1003 valuePtr->intValue >= value2.intValue;
1004 } else if (valuePtr->type == TYPE_DOUBLE) {
1005 valuePtr->intValue =
1006 valuePtr->doubleValue >= value2.doubleValue;
1007 } else {
1008 valuePtr->intValue =
1009 strcmp(valuePtr->pv.buffer, value2.pv.buffer) >= 0;
1010 }
1011 valuePtr->type = TYPE_INT;
1012 break;
1013 case EQUAL:
1014 if (valuePtr->type == TYPE_INT) {
1015 valuePtr->intValue =
1016 valuePtr->intValue == value2.intValue;
1017 } else if (valuePtr->type == TYPE_DOUBLE) {
1018 valuePtr->intValue =
1019 valuePtr->doubleValue == value2.doubleValue;
1020 } else {
1021 valuePtr->intValue =
1022 strcmp(valuePtr->pv.buffer, value2.pv.buffer) == 0;
1023 }
1024 valuePtr->type = TYPE_INT;
1025 break;
1026 case NEQ:
1027 if (valuePtr->type == TYPE_INT) {
1028 valuePtr->intValue =
1029 valuePtr->intValue != value2.intValue;
1030 } else if (valuePtr->type == TYPE_DOUBLE) {
1031 valuePtr->intValue =
1032 valuePtr->doubleValue != value2.doubleValue;
1033 } else {
1034 valuePtr->intValue =
1035 strcmp(valuePtr->pv.buffer, value2.pv.buffer) != 0;
1036 }
1037 valuePtr->type = TYPE_INT;
1038 break;
1039 case BIT_AND:
1040 valuePtr->intValue &= value2.intValue;
1041 break;
1042 case BIT_XOR:
1043 valuePtr->intValue ^= value2.intValue;
1044 break;
1045 case BIT_OR:
1046 valuePtr->intValue |= value2.intValue;
1047 break;
1048
1049 /*
1050 * For AND and OR, we know that the first value has already
1051 * been converted to an integer. Thus we need only consider
1052 * the possibility of int vs. double for the second value.
1053 */
1054
1055 case AND:
1056 if (value2.type == TYPE_DOUBLE) {
1057 value2.intValue = value2.doubleValue != 0;
1058 value2.type = TYPE_INT;
1059 }
1060 valuePtr->intValue = valuePtr->intValue && value2.intValue;
1061 break;
1062 case OR:
1063 if (value2.type == TYPE_DOUBLE) {
1064 value2.intValue = value2.doubleValue != 0;
1065 value2.type = TYPE_INT;
1066 }
1067 valuePtr->intValue = valuePtr->intValue || value2.intValue;
1068 break;
1069
1070 case COLON:
1071 interp->result = "can't have : operator without ? first";
1072 result = TCL_ERROR;
1073 goto done;
1074 }
1075 }
1076
1077 done:
1078 if (value2.pv.buffer != value2.staticSpace) {
1079 ckfree(value2.pv.buffer);
1080 }
1081 return result;
1082
1083 syntaxError:
1084 Tcl_ResetResult(interp);
1085 Tcl_AppendResult(interp, "syntax error in expression \"",
1086 infoPtr->originalExpr, "\"", (char *) NULL);
1087 result = TCL_ERROR;
1088 goto done;
1089
1090 illegalType:
1091 Tcl_AppendResult(interp, "can't use ", (badType == TYPE_DOUBLE) ?
1092 "floating-point value" : "non-numeric string",
1093 " as operand of \"", operatorStrings[operator], "\"",
1094 (char *) NULL);
1095 result = TCL_ERROR;
1096 goto done;
1097 }
1098 \f
1099 /*
1100 *--------------------------------------------------------------
1101 *
1102 * ExprMakeString --
1103 *
1104 * Convert a value from int or double representation to
1105 * a string.
1106 *
1107 * Results:
1108 * The information at *valuePtr gets converted to string
1109 * format, if it wasn't that way already.
1110 *
1111 * Side effects:
1112 * None.
1113 *
1114 *--------------------------------------------------------------
1115 */
1116
1117 static void
1118 ExprMakeString (
1119 register Value *valuePtr /* Value to be converted. */
1120 )
1121 {
1122 int shortfall;
1123
1124 shortfall = 150 - (valuePtr->pv.end - valuePtr->pv.buffer);
1125 if (shortfall > 0) {
1126 (*valuePtr->pv.expandProc)(&valuePtr->pv, shortfall);
1127 }
1128 if (valuePtr->type == TYPE_INT) {
1129 sprintf(valuePtr->pv.buffer, "%ld", valuePtr->intValue);
1130 } else if (valuePtr->type == TYPE_DOUBLE) {
1131 sprintf(valuePtr->pv.buffer, "%g", valuePtr->doubleValue);
1132 }
1133 valuePtr->type = TYPE_STRING;
1134 }
1135 \f
1136 /*
1137 *--------------------------------------------------------------
1138 *
1139 * ExprTopLevel --
1140 *
1141 * This procedure provides top-level functionality shared by
1142 * procedures like Tcl_ExprInt, Tcl_ExprDouble, etc.
1143 *
1144 * Results:
1145 * The result is a standard Tcl return value. If an error
1146 * occurs then an error message is left in interp->result.
1147 * The value of the expression is returned in *valuePtr, in
1148 * whatever form it ends up in (could be string or integer
1149 * or double). Caller may need to convert result. Caller
1150 * is also responsible for freeing string memory in *valuePtr,
1151 * if any was allocated.
1152 *
1153 * Side effects:
1154 * None.
1155 *
1156 *--------------------------------------------------------------
1157 */
1158
1159 static int
1160 ExprTopLevel (
1161 Tcl_Interp *interp, /* Context in which to evaluate the
1162 * expression. */
1163 char *string, /* Expression to evaluate. */
1164 Value *valuePtr /* Where to store result. Should
1165 * not be initialized by caller. */
1166 )
1167 {
1168 ExprInfo info;
1169 int result;
1170
1171 info.originalExpr = string;
1172 info.expr = string;
1173 valuePtr->pv.buffer = valuePtr->pv.next = valuePtr->staticSpace;
1174 valuePtr->pv.end = valuePtr->pv.buffer + STATIC_STRING_SPACE - 1;
1175 valuePtr->pv.expandProc = TclExpandParseValue;
1176 valuePtr->pv.clientData = (ClientData) NULL;
1177
1178 result = ExprGetValue(interp, &info, -1, valuePtr);
1179 if (result != TCL_OK) {
1180 return result;
1181 }
1182 if (info.token != END) {
1183 Tcl_AppendResult(interp, "syntax error in expression \"",
1184 string, "\"", (char *) NULL);
1185 return TCL_ERROR;
1186 }
1187 return TCL_OK;
1188 }
1189 \f
1190 /*
1191 *--------------------------------------------------------------
1192 *
1193 * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
1194 *
1195 * Procedures to evaluate an expression and return its value
1196 * in a particular form.
1197 *
1198 * Results:
1199 * Each of the procedures below returns a standard Tcl result.
1200 * If an error occurs then an error message is left in
1201 * interp->result. Otherwise the value of the expression,
1202 * in the appropriate form, is stored at *resultPtr. If
1203 * the expression had a result that was incompatible with the
1204 * desired form then an error is returned.
1205 *
1206 * Side effects:
1207 * None.
1208 *
1209 *--------------------------------------------------------------
1210 */
1211
1212 int
1213 Tcl_ExprLong (
1214 Tcl_Interp *interp, /* Context in which to evaluate the
1215 * expression. */
1216 char *string, /* Expression to evaluate. */
1217 long *ptr /* Where to store result. */
1218 )
1219 {
1220 Value value;
1221 int result;
1222
1223 result = ExprTopLevel(interp, string, &value);
1224 if (result == TCL_OK) {
1225 if (value.type == TYPE_INT) {
1226 *ptr = value.intValue;
1227 } else if (value.type == TYPE_DOUBLE) {
1228 *ptr = value.doubleValue;
1229 } else {
1230 interp->result = "expression didn't have numeric value";
1231 result = TCL_ERROR;
1232 }
1233 }
1234 if (value.pv.buffer != value.staticSpace) {
1235 ckfree(value.pv.buffer);
1236 }
1237 return result;
1238 }
1239
1240 int
1241 Tcl_ExprDouble (
1242 Tcl_Interp *interp, /* Context in which to evaluate the
1243 * expression. */
1244 char *string, /* Expression to evaluate. */
1245 double *ptr /* Where to store result. */
1246 )
1247 {
1248 Value value;
1249 int result;
1250
1251 result = ExprTopLevel(interp, string, &value);
1252 if (result == TCL_OK) {
1253 if (value.type == TYPE_INT) {
1254 *ptr = value.intValue;
1255 } else if (value.type == TYPE_DOUBLE) {
1256 *ptr = value.doubleValue;
1257 } else {
1258 interp->result = "expression didn't have numeric value";
1259 result = TCL_ERROR;
1260 }
1261 }
1262 if (value.pv.buffer != value.staticSpace) {
1263 ckfree(value.pv.buffer);
1264 }
1265 return result;
1266 }
1267
1268 int
1269 Tcl_ExprBoolean (
1270 Tcl_Interp *interp, /* Context in which to evaluate the
1271 * expression. */
1272 char *string, /* Expression to evaluate. */
1273 int *ptr /* Where to store 0/1 result. */
1274 )
1275 {
1276 Value value;
1277 int result;
1278
1279 result = ExprTopLevel(interp, string, &value);
1280 if (result == TCL_OK) {
1281 if (value.type == TYPE_INT) {
1282 *ptr = value.intValue != 0;
1283 } else if (value.type == TYPE_DOUBLE) {
1284 *ptr = value.doubleValue != 0.0;
1285 } else {
1286 interp->result = "expression didn't have numeric value";
1287 result = TCL_ERROR;
1288 }
1289 }
1290 if (value.pv.buffer != value.staticSpace) {
1291 ckfree(value.pv.buffer);
1292 }
1293 return result;
1294 }
1295 \f
1296 /*
1297 *--------------------------------------------------------------
1298 *
1299 * Tcl_ExprString --
1300 *
1301 * Evaluate an expression and return its value in string form.
1302 *
1303 * Results:
1304 * A standard Tcl result. If the result is TCL_OK, then the
1305 * interpreter's result is set to the string value of the
1306 * expression. If the result is TCL_OK, then interp->result
1307 * contains an error message.
1308 *
1309 * Side effects:
1310 * None.
1311 *
1312 *--------------------------------------------------------------
1313 */
1314
1315 int
1316 Tcl_ExprString (
1317 Tcl_Interp *interp, /* Context in which to evaluate the
1318 * expression. */
1319 char *string /* Expression to evaluate. */
1320 )
1321 {
1322 Value value;
1323 int result;
1324
1325 result = ExprTopLevel(interp, string, &value);
1326 if (result == TCL_OK) {
1327 if (value.type == TYPE_INT) {
1328 sprintf(interp->result, "%ld", value.intValue);
1329 } else if (value.type == TYPE_DOUBLE) {
1330 sprintf(interp->result, "%g", value.doubleValue);
1331 } else {
1332 if (value.pv.buffer != value.staticSpace) {
1333 interp->result = value.pv.buffer;
1334 interp->freeProc = (Tcl_FreeProc *) free;
1335 value.pv.buffer = value.staticSpace;
1336 } else {
1337 Tcl_SetResult(interp, value.pv.buffer, TCL_VOLATILE);
1338 }
1339 }
1340 }
1341 if (value.pv.buffer != value.staticSpace) {
1342 ckfree(value.pv.buffer);
1343 }
1344 return result;
1345 }
Impressum, Datenschutz