Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtksh/tcl/tclExpr.c
1810 views
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 (c) 1987-1994 The Regents of the University of California.
11
* Copyright (c) 1994 Sun Microsystems, Inc.
12
*
13
* See the file "license.terms" for information on usage and redistribution
14
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15
*
16
* SCCS: @(#) tclExpr.c 1.92 96/09/06 13:22:44
17
*/
18
19
#include "tclInt.h"
20
#ifdef NO_FLOAT_H
21
# include "../compat/float.h"
22
#else
23
# include <float.h>
24
#endif
25
#ifndef TCL_NO_MATH
26
#include <math.h>
27
#endif
28
29
/*
30
* The stuff below is a bit of a hack so that this file can be used
31
* in environments that include no UNIX, i.e. no errno. Just define
32
* errno here.
33
*/
34
35
#ifndef TCL_GENERIC_ONLY
36
#include "tclPort.h"
37
#else
38
#define NO_ERRNO_H
39
#endif
40
41
#ifdef NO_ERRNO_H
42
int errno;
43
#define EDOM 33
44
#define ERANGE 34
45
#endif
46
47
/*
48
* The data structure below is used to describe an expression value,
49
* which can be either an integer (the usual case), a double-precision
50
* floating-point value, or a string. A given number has only one
51
* value at a time.
52
*/
53
54
#define STATIC_STRING_SPACE 150
55
56
typedef struct {
57
long intValue; /* Integer value, if any. */
58
double doubleValue; /* Floating-point value, if any. */
59
ParseValue pv; /* Used to hold a string value, if any. */
60
char staticSpace[STATIC_STRING_SPACE];
61
/* Storage for small strings; large ones
62
* are malloc-ed. */
63
int type; /* Type of value: TYPE_INT, TYPE_DOUBLE,
64
* or TYPE_STRING. */
65
} Value;
66
67
/*
68
* Valid values for type:
69
*/
70
71
#define TYPE_INT 0
72
#define TYPE_DOUBLE 1
73
#define TYPE_STRING 2
74
75
/*
76
* The data structure below describes the state of parsing an expression.
77
* It's passed among the routines in this module.
78
*/
79
80
typedef struct {
81
char *originalExpr; /* The entire expression, as originally
82
* passed to Tcl_ExprString et al. */
83
char *expr; /* Position to the next character to be
84
* scanned from the expression string. */
85
int token; /* Type of the last token to be parsed from
86
* expr. See below for definitions.
87
* Corresponds to the characters just
88
* before expr. */
89
} ExprInfo;
90
91
/*
92
* The token types are defined below. In addition, there is a table
93
* associating a precedence with each operator. The order of types
94
* is important. Consult the code before changing it.
95
*/
96
97
#define VALUE 0
98
#define OPEN_PAREN 1
99
#define CLOSE_PAREN 2
100
#define COMMA 3
101
#define END 4
102
#define UNKNOWN 5
103
104
/*
105
* Binary operators:
106
*/
107
108
#define MULT 8
109
#define DIVIDE 9
110
#define MOD 10
111
#define PLUS 11
112
#define MINUS 12
113
#define LEFT_SHIFT 13
114
#define RIGHT_SHIFT 14
115
#define LESS 15
116
#define GREATER 16
117
#define LEQ 17
118
#define GEQ 18
119
#define EQUAL 19
120
#define NEQ 20
121
#define BIT_AND 21
122
#define BIT_XOR 22
123
#define BIT_OR 23
124
#define AND 24
125
#define OR 25
126
#define QUESTY 26
127
#define COLON 27
128
129
/*
130
* Unary operators:
131
*/
132
133
#define UNARY_MINUS 28
134
#define UNARY_PLUS 29
135
#define NOT 30
136
#define BIT_NOT 31
137
138
/*
139
* Precedence table. The values for non-operator token types are ignored.
140
*/
141
142
static int precTable[] = {
143
0, 0, 0, 0, 0, 0, 0, 0,
144
12, 12, 12, /* MULT, DIVIDE, MOD */
145
11, 11, /* PLUS, MINUS */
146
10, 10, /* LEFT_SHIFT, RIGHT_SHIFT */
147
9, 9, 9, 9, /* LESS, GREATER, LEQ, GEQ */
148
8, 8, /* EQUAL, NEQ */
149
7, /* BIT_AND */
150
6, /* BIT_XOR */
151
5, /* BIT_OR */
152
4, /* AND */
153
3, /* OR */
154
2, /* QUESTY */
155
1, /* COLON */
156
13, 13, 13, 13 /* UNARY_MINUS, UNARY_PLUS, NOT,
157
* BIT_NOT */
158
};
159
160
/*
161
* Mapping from operator numbers to strings; used for error messages.
162
*/
163
164
static char *operatorStrings[] = {
165
"VALUE", "(", ")", ",", "END", "UNKNOWN", "6", "7",
166
"*", "/", "%", "+", "-", "<<", ">>", "<", ">", "<=",
167
">=", "==", "!=", "&", "^", "|", "&&", "||", "?", ":",
168
"-", "+", "!", "~"
169
};
170
171
/*
172
* The following slight modification to DBL_MAX is needed because of
173
* a compiler bug on Sprite (4/15/93).
174
*/
175
176
#ifdef sprite
177
#undef DBL_MAX
178
#define DBL_MAX 1.797693134862316e+307
179
#endif
180
181
/*
182
* Macros for testing floating-point values for certain special
183
* cases. Test for not-a-number by comparing a value against
184
* itself; test for infinity by comparing against the largest
185
* floating-point value.
186
*/
187
188
#define IS_NAN(v) ((v) != (v))
189
#ifdef DBL_MAX
190
# define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
191
#else
192
# define IS_INF(v) 0
193
#endif
194
195
/*
196
* The following global variable is use to signal matherr that Tcl
197
* is responsible for the arithmetic, so errors can be handled in a
198
* fashion appropriate for Tcl. Zero means no Tcl math is in
199
* progress; non-zero means Tcl is doing math.
200
*/
201
202
int tcl_MathInProgress = 0;
203
204
/*
205
* The variable below serves no useful purpose except to generate
206
* a reference to matherr, so that the Tcl version of matherr is
207
* linked in rather than the system version. Without this reference
208
* the need for matherr won't be discovered during linking until after
209
* libtcl.a has been processed, so Tcl's version won't be used.
210
*/
211
212
#ifdef NEED_MATHERR
213
214
extern int matherr();
215
int (*tclMatherrPtr)() = matherr;
216
217
#endif
218
219
/*
220
* Declarations for local procedures to this file:
221
*/
222
223
static int ExprAbsFunc _ANSI_ARGS_((ClientData clientData,
224
Tcl_Interp *interp, Tcl_Value *args,
225
Tcl_Value *resultPtr));
226
static int ExprBinaryFunc _ANSI_ARGS_((ClientData clientData,
227
Tcl_Interp *interp, Tcl_Value *args,
228
Tcl_Value *resultPtr));
229
static int ExprDoubleFunc _ANSI_ARGS_((ClientData clientData,
230
Tcl_Interp *interp, Tcl_Value *args,
231
Tcl_Value *resultPtr));
232
static int ExprGetValue _ANSI_ARGS_((Tcl_Interp *interp,
233
ExprInfo *infoPtr, int prec, Value *valuePtr));
234
static int ExprIntFunc _ANSI_ARGS_((ClientData clientData,
235
Tcl_Interp *interp, Tcl_Value *args,
236
Tcl_Value *resultPtr));
237
static int ExprLex _ANSI_ARGS_((Tcl_Interp *interp,
238
ExprInfo *infoPtr, Value *valuePtr));
239
static int ExprLooksLikeInt _ANSI_ARGS_((char *p));
240
static void ExprMakeString _ANSI_ARGS_((Tcl_Interp *interp,
241
Value *valuePtr));
242
static int ExprMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
243
ExprInfo *infoPtr, Value *valuePtr));
244
static int ExprParseString _ANSI_ARGS_((Tcl_Interp *interp,
245
char *string, Value *valuePtr));
246
static int ExprRoundFunc _ANSI_ARGS_((ClientData clientData,
247
Tcl_Interp *interp, Tcl_Value *args,
248
Tcl_Value *resultPtr));
249
static int ExprTopLevel _ANSI_ARGS_((Tcl_Interp *interp,
250
char *string, Value *valuePtr));
251
static int ExprUnaryFunc _ANSI_ARGS_((ClientData clientData,
252
Tcl_Interp *interp, Tcl_Value *args,
253
Tcl_Value *resultPtr));
254
255
#ifndef TCL_NO_MATH
256
#if _WIN32
257
static double local_floor(double x) { return floor(x); }
258
#undef floor
259
#define floor local_floor
260
#endif
261
#endif
262
263
/*
264
* Built-in math functions:
265
*/
266
267
typedef struct {
268
char *name; /* Name of function. */
269
int numArgs; /* Number of arguments for function. */
270
Tcl_ValueType argTypes[MAX_MATH_ARGS];
271
/* Acceptable types for each argument. */
272
Tcl_MathProc *proc; /* Procedure that implements this function. */
273
ClientData clientData; /* Additional argument to pass to the function
274
* when invoking it. */
275
} BuiltinFunc;
276
277
static BuiltinFunc funcTable[] = {
278
#ifndef TCL_NO_MATH
279
{"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
280
{"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
281
{"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
282
{"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
283
{"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
284
{"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
285
{"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
286
{"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
287
{"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
288
{"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
289
{"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
290
{"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
291
{"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
292
{"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
293
{"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
294
{"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
295
{"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
296
{"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
297
{"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
298
#endif
299
{"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
300
{"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
301
{"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
302
{"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
303
304
{0},
305
};
306
307
/*
308
*--------------------------------------------------------------
309
*
310
* ExprParseString --
311
*
312
* Given a string (such as one coming from command or variable
313
* substitution), make a Value based on the string. The value
314
* will be a floating-point or integer, if possible, or else it
315
* will just be a copy of the string.
316
*
317
* Results:
318
* TCL_OK is returned under normal circumstances, and TCL_ERROR
319
* is returned if a floating-point overflow or underflow occurred
320
* while reading in a number. The value at *valuePtr is modified
321
* to hold a number, if possible.
322
*
323
* Side effects:
324
* None.
325
*
326
*--------------------------------------------------------------
327
*/
328
329
static int
330
ExprParseString(interp, string, valuePtr)
331
Tcl_Interp *interp; /* Where to store error message. */
332
char *string; /* String to turn into value. */
333
Value *valuePtr; /* Where to store value information.
334
* Caller must have initialized pv field. */
335
{
336
char *term, *p, *start;
337
338
if (*string != 0) {
339
if (ExprLooksLikeInt(string)) {
340
valuePtr->type = TYPE_INT;
341
errno = 0;
342
343
/*
344
* Note: use strtoul instead of strtol for integer conversions
345
* to allow full-size unsigned numbers, but don't depend on
346
* strtoul to handle sign characters; it won't in some
347
* implementations.
348
*/
349
350
for (p = string; isspace(UCHAR(*p)); p++) {
351
/* Empty loop body. */
352
}
353
if (*p == '-') {
354
start = p+1;
355
valuePtr->intValue = -((int)strtoul(start, &term, 0));
356
} else if (*p == '+') {
357
start = p+1;
358
valuePtr->intValue = strtoul(start, &term, 0);
359
} else {
360
start = p;
361
valuePtr->intValue = strtoul(start, &term, 0);
362
}
363
if (*term == 0) {
364
if (errno == ERANGE) {
365
/*
366
* This procedure is sometimes called with string in
367
* interp->result, so we have to clear the result before
368
* logging an error message.
369
*/
370
371
Tcl_ResetResult(interp);
372
interp->result = "integer value too large to represent";
373
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
374
interp->result, (char *) NULL);
375
return TCL_ERROR;
376
} else {
377
return TCL_OK;
378
}
379
}
380
} else {
381
errno = 0;
382
valuePtr->doubleValue = strtod(string, &term);
383
if ((term != string) && (*term == 0)) {
384
if (errno != 0) {
385
Tcl_ResetResult(interp);
386
TclExprFloatError(interp, valuePtr->doubleValue);
387
return TCL_ERROR;
388
}
389
valuePtr->type = TYPE_DOUBLE;
390
return TCL_OK;
391
}
392
}
393
}
394
395
/*
396
* Not a valid number. Save a string value (but don't do anything
397
* if it's already the value).
398
*/
399
400
valuePtr->type = TYPE_STRING;
401
if (string != valuePtr->pv.buffer) {
402
int length, shortfall;
403
404
length = strlen(string);
405
valuePtr->pv.next = valuePtr->pv.buffer;
406
shortfall = length - (valuePtr->pv.end - valuePtr->pv.buffer);
407
if (shortfall > 0) {
408
(*valuePtr->pv.expandProc)(&valuePtr->pv, shortfall);
409
}
410
strcpy(valuePtr->pv.buffer, string);
411
}
412
return TCL_OK;
413
}
414
415
/*
416
*----------------------------------------------------------------------
417
*
418
* ExprLex --
419
*
420
* Lexical analyzer for expression parser: parses a single value,
421
* operator, or other syntactic element from an expression string.
422
*
423
* Results:
424
* TCL_OK is returned unless an error occurred while doing lexical
425
* analysis or executing an embedded command. In that case a
426
* standard Tcl error is returned, using interp->result to hold
427
* an error message. In the event of a successful return, the token
428
* and field in infoPtr is updated to refer to the next symbol in
429
* the expression string, and the expr field is advanced past that
430
* token; if the token is a value, then the value is stored at
431
* valuePtr.
432
*
433
* Side effects:
434
* None.
435
*
436
*----------------------------------------------------------------------
437
*/
438
439
static int
440
ExprLex(interp, infoPtr, valuePtr)
441
Tcl_Interp *interp; /* Interpreter to use for error
442
* reporting. */
443
register ExprInfo *infoPtr; /* Describes the state of the parse. */
444
register Value *valuePtr; /* Where to store value, if that is
445
* what's parsed from string. Caller
446
* must have initialized pv field
447
* correctly. */
448
{
449
register char *p;
450
char *var, *term;
451
int result;
452
453
p = infoPtr->expr;
454
while (isspace(UCHAR(*p))) {
455
p++;
456
}
457
if (*p == 0) {
458
infoPtr->token = END;
459
infoPtr->expr = p;
460
return TCL_OK;
461
}
462
463
/*
464
* First try to parse the token as an integer or floating-point number.
465
* Don't want to check for a number if the first character is "+"
466
* or "-". If we do, we might treat a binary operator as unary by
467
* mistake, which will eventually cause a syntax error.
468
*/
469
470
if ((*p != '+') && (*p != '-')) {
471
if (ExprLooksLikeInt(p)) {
472
errno = 0;
473
valuePtr->intValue = strtoul(p, &term, 0);
474
if (errno == ERANGE) {
475
interp->result = "integer value too large to represent";
476
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
477
interp->result, (char *) NULL);
478
return TCL_ERROR;
479
}
480
infoPtr->token = VALUE;
481
infoPtr->expr = term;
482
valuePtr->type = TYPE_INT;
483
return TCL_OK;
484
} else {
485
errno = 0;
486
valuePtr->doubleValue = strtod(p, &term);
487
if (term != p) {
488
if (errno != 0) {
489
TclExprFloatError(interp, valuePtr->doubleValue);
490
return TCL_ERROR;
491
}
492
infoPtr->token = VALUE;
493
infoPtr->expr = term;
494
valuePtr->type = TYPE_DOUBLE;
495
return TCL_OK;
496
}
497
}
498
}
499
500
infoPtr->expr = p+1;
501
switch (*p) {
502
case '$':
503
504
/*
505
* Variable. Fetch its value, then see if it makes sense
506
* as an integer or floating-point number.
507
*/
508
509
infoPtr->token = VALUE;
510
var = Tcl_ParseVar(interp, p, &infoPtr->expr);
511
if (var == NULL) {
512
return TCL_ERROR;
513
}
514
Tcl_ResetResult(interp);
515
if (((Interp *) interp)->noEval) {
516
valuePtr->type = TYPE_INT;
517
valuePtr->intValue = 0;
518
return TCL_OK;
519
}
520
return ExprParseString(interp, var, valuePtr);
521
522
case '[':
523
infoPtr->token = VALUE;
524
((Interp *) interp)->evalFlags = TCL_BRACKET_TERM;
525
result = Tcl_Eval(interp, p+1);
526
infoPtr->expr = ((Interp *) interp)->termPtr;
527
if (result != TCL_OK) {
528
return result;
529
}
530
infoPtr->expr++;
531
if (((Interp *) interp)->noEval) {
532
valuePtr->type = TYPE_INT;
533
valuePtr->intValue = 0;
534
Tcl_ResetResult(interp);
535
return TCL_OK;
536
}
537
result = ExprParseString(interp, interp->result, valuePtr);
538
if (result != TCL_OK) {
539
return result;
540
}
541
Tcl_ResetResult(interp);
542
return TCL_OK;
543
544
case '"':
545
infoPtr->token = VALUE;
546
result = TclParseQuotes(interp, infoPtr->expr, '"', 0,
547
&infoPtr->expr, &valuePtr->pv);
548
if (result != TCL_OK) {
549
return result;
550
}
551
Tcl_ResetResult(interp);
552
return ExprParseString(interp, valuePtr->pv.buffer, valuePtr);
553
554
case '{':
555
infoPtr->token = VALUE;
556
result = TclParseBraces(interp, infoPtr->expr, &infoPtr->expr,
557
&valuePtr->pv);
558
if (result != TCL_OK) {
559
return result;
560
}
561
Tcl_ResetResult(interp);
562
return ExprParseString(interp, valuePtr->pv.buffer, valuePtr);
563
564
case '(':
565
infoPtr->token = OPEN_PAREN;
566
return TCL_OK;
567
568
case ')':
569
infoPtr->token = CLOSE_PAREN;
570
return TCL_OK;
571
572
case ',':
573
infoPtr->token = COMMA;
574
return TCL_OK;
575
576
case '*':
577
infoPtr->token = MULT;
578
return TCL_OK;
579
580
case '/':
581
infoPtr->token = DIVIDE;
582
return TCL_OK;
583
584
case '%':
585
infoPtr->token = MOD;
586
return TCL_OK;
587
588
case '+':
589
infoPtr->token = PLUS;
590
return TCL_OK;
591
592
case '-':
593
infoPtr->token = MINUS;
594
return TCL_OK;
595
596
case '?':
597
infoPtr->token = QUESTY;
598
return TCL_OK;
599
600
case ':':
601
infoPtr->token = COLON;
602
return TCL_OK;
603
604
case '<':
605
switch (p[1]) {
606
case '<':
607
infoPtr->expr = p+2;
608
infoPtr->token = LEFT_SHIFT;
609
break;
610
case '=':
611
infoPtr->expr = p+2;
612
infoPtr->token = LEQ;
613
break;
614
default:
615
infoPtr->token = LESS;
616
break;
617
}
618
return TCL_OK;
619
620
case '>':
621
switch (p[1]) {
622
case '>':
623
infoPtr->expr = p+2;
624
infoPtr->token = RIGHT_SHIFT;
625
break;
626
case '=':
627
infoPtr->expr = p+2;
628
infoPtr->token = GEQ;
629
break;
630
default:
631
infoPtr->token = GREATER;
632
break;
633
}
634
return TCL_OK;
635
636
case '=':
637
if (p[1] == '=') {
638
infoPtr->expr = p+2;
639
infoPtr->token = EQUAL;
640
} else {
641
infoPtr->token = UNKNOWN;
642
}
643
return TCL_OK;
644
645
case '!':
646
if (p[1] == '=') {
647
infoPtr->expr = p+2;
648
infoPtr->token = NEQ;
649
} else {
650
infoPtr->token = NOT;
651
}
652
return TCL_OK;
653
654
case '&':
655
if (p[1] == '&') {
656
infoPtr->expr = p+2;
657
infoPtr->token = AND;
658
} else {
659
infoPtr->token = BIT_AND;
660
}
661
return TCL_OK;
662
663
case '^':
664
infoPtr->token = BIT_XOR;
665
return TCL_OK;
666
667
case '|':
668
if (p[1] == '|') {
669
infoPtr->expr = p+2;
670
infoPtr->token = OR;
671
} else {
672
infoPtr->token = BIT_OR;
673
}
674
return TCL_OK;
675
676
case '~':
677
infoPtr->token = BIT_NOT;
678
return TCL_OK;
679
680
default:
681
if (isalpha(UCHAR(*p))) {
682
infoPtr->expr = p;
683
return ExprMathFunc(interp, infoPtr, valuePtr);
684
}
685
infoPtr->expr = p+1;
686
infoPtr->token = UNKNOWN;
687
return TCL_OK;
688
}
689
}
690
691
/*
692
*----------------------------------------------------------------------
693
*
694
* ExprGetValue --
695
*
696
* Parse a "value" from the remainder of the expression in infoPtr.
697
*
698
* Results:
699
* Normally TCL_OK is returned. The value of the expression is
700
* returned in *valuePtr. If an error occurred, then interp->result
701
* contains an error message and TCL_ERROR is returned.
702
* InfoPtr->token will be left pointing to the token AFTER the
703
* expression, and infoPtr->expr will point to the character just
704
* after the terminating token.
705
*
706
* Side effects:
707
* None.
708
*
709
*----------------------------------------------------------------------
710
*/
711
712
static int
713
ExprGetValue(interp, infoPtr, prec, valuePtr)
714
Tcl_Interp *interp; /* Interpreter to use for error
715
* reporting. */
716
register ExprInfo *infoPtr; /* Describes the state of the parse
717
* just before the value (i.e. ExprLex
718
* will be called to get first token
719
* of value). */
720
int prec; /* Treat any un-parenthesized operator
721
* with precedence <= this as the end
722
* of the expression. */
723
Value *valuePtr; /* Where to store the value of the
724
* expression. Caller must have
725
* initialized pv field. */
726
{
727
Interp *iPtr = (Interp *) interp;
728
Value value2; /* Second operand for current
729
* operator. */
730
int operator; /* Current operator (either unary
731
* or binary). */
732
int badType; /* Type of offending argument; used
733
* for error messages. */
734
int gotOp; /* Non-zero means already lexed the
735
* operator (while picking up value
736
* for unary operator). Don't lex
737
* again. */
738
int result;
739
740
/*
741
* There are two phases to this procedure. First, pick off an initial
742
* value. Then, parse (binary operator, value) pairs until done.
743
*/
744
745
gotOp = 0;
746
value2.pv.buffer = value2.pv.next = value2.staticSpace;
747
value2.pv.end = value2.pv.buffer + STATIC_STRING_SPACE - 1;
748
value2.pv.expandProc = TclExpandParseValue;
749
value2.pv.clientData = (ClientData) NULL;
750
result = ExprLex(interp, infoPtr, valuePtr);
751
if (result != TCL_OK) {
752
goto done;
753
}
754
if (infoPtr->token == OPEN_PAREN) {
755
756
/*
757
* Parenthesized sub-expression.
758
*/
759
760
result = ExprGetValue(interp, infoPtr, -1, valuePtr);
761
if (result != TCL_OK) {
762
goto done;
763
}
764
if (infoPtr->token != CLOSE_PAREN) {
765
Tcl_AppendResult(interp, "unmatched parentheses in expression \"",
766
infoPtr->originalExpr, "\"", (char *) NULL);
767
result = TCL_ERROR;
768
goto done;
769
}
770
} else {
771
if (infoPtr->token == MINUS) {
772
infoPtr->token = UNARY_MINUS;
773
}
774
if (infoPtr->token == PLUS) {
775
infoPtr->token = UNARY_PLUS;
776
}
777
if (infoPtr->token >= UNARY_MINUS) {
778
779
/*
780
* Process unary operators.
781
*/
782
783
operator = infoPtr->token;
784
result = ExprGetValue(interp, infoPtr, precTable[infoPtr->token],
785
valuePtr);
786
if (result != TCL_OK) {
787
goto done;
788
}
789
if (!iPtr->noEval) {
790
switch (operator) {
791
case UNARY_MINUS:
792
if (valuePtr->type == TYPE_INT) {
793
valuePtr->intValue = -valuePtr->intValue;
794
} else if (valuePtr->type == TYPE_DOUBLE){
795
valuePtr->doubleValue = -valuePtr->doubleValue;
796
} else {
797
badType = valuePtr->type;
798
goto illegalType;
799
}
800
break;
801
case UNARY_PLUS:
802
if ((valuePtr->type != TYPE_INT)
803
&& (valuePtr->type != TYPE_DOUBLE)) {
804
badType = valuePtr->type;
805
goto illegalType;
806
}
807
break;
808
case NOT:
809
if (valuePtr->type == TYPE_INT) {
810
valuePtr->intValue = !valuePtr->intValue;
811
} else if (valuePtr->type == TYPE_DOUBLE) {
812
/*
813
* Theoretically, should be able to use
814
* "!valuePtr->intValue", but apparently some
815
* compilers can't handle it.
816
*/
817
if (valuePtr->doubleValue == 0.0) {
818
valuePtr->intValue = 1;
819
} else {
820
valuePtr->intValue = 0;
821
}
822
valuePtr->type = TYPE_INT;
823
} else {
824
badType = valuePtr->type;
825
goto illegalType;
826
}
827
break;
828
case BIT_NOT:
829
if (valuePtr->type == TYPE_INT) {
830
valuePtr->intValue = ~valuePtr->intValue;
831
} else {
832
badType = valuePtr->type;
833
goto illegalType;
834
}
835
break;
836
}
837
}
838
gotOp = 1;
839
} else if (infoPtr->token != VALUE) {
840
goto syntaxError;
841
}
842
}
843
844
/*
845
* Got the first operand. Now fetch (operator, operand) pairs.
846
*/
847
848
if (!gotOp) {
849
result = ExprLex(interp, infoPtr, &value2);
850
if (result != TCL_OK) {
851
goto done;
852
}
853
}
854
while (1) {
855
operator = infoPtr->token;
856
value2.pv.next = value2.pv.buffer;
857
if ((operator < MULT) || (operator >= UNARY_MINUS)) {
858
if ((operator == END) || (operator == CLOSE_PAREN)
859
|| (operator == COMMA)) {
860
result = TCL_OK;
861
goto done;
862
} else {
863
goto syntaxError;
864
}
865
}
866
if (precTable[operator] <= prec) {
867
result = TCL_OK;
868
goto done;
869
}
870
871
/*
872
* If we're doing an AND or OR and the first operand already
873
* determines the result, don't execute anything in the
874
* second operand: just parse. Same style for ?: pairs.
875
*/
876
877
if ((operator == AND) || (operator == OR) || (operator == QUESTY)) {
878
if (valuePtr->type == TYPE_DOUBLE) {
879
valuePtr->intValue = valuePtr->doubleValue != 0;
880
valuePtr->type = TYPE_INT;
881
} else if (valuePtr->type == TYPE_STRING) {
882
if (!iPtr->noEval) {
883
badType = TYPE_STRING;
884
goto illegalType;
885
}
886
887
/*
888
* Must set valuePtr->intValue to avoid referencing
889
* uninitialized memory in the "if" below; the actual
890
* value doesn't matter, since it will be ignored.
891
*/
892
893
valuePtr->intValue = 0;
894
}
895
if (((operator == AND) && !valuePtr->intValue)
896
|| ((operator == OR) && valuePtr->intValue)) {
897
iPtr->noEval++;
898
result = ExprGetValue(interp, infoPtr, precTable[operator],
899
&value2);
900
iPtr->noEval--;
901
if (result != TCL_OK) {
902
goto done;
903
}
904
if (operator == OR) {
905
valuePtr->intValue = 1;
906
}
907
continue;
908
} else if (operator == QUESTY) {
909
/*
910
* Special note: ?: operators must associate right to
911
* left. To make this happen, use a precedence one lower
912
* than QUESTY when calling ExprGetValue recursively.
913
*/
914
915
if (valuePtr->intValue != 0) {
916
valuePtr->pv.next = valuePtr->pv.buffer;
917
result = ExprGetValue(interp, infoPtr,
918
precTable[QUESTY] - 1, valuePtr);
919
if (result != TCL_OK) {
920
goto done;
921
}
922
if (infoPtr->token != COLON) {
923
goto syntaxError;
924
}
925
value2.pv.next = value2.pv.buffer;
926
iPtr->noEval++;
927
result = ExprGetValue(interp, infoPtr,
928
precTable[QUESTY] - 1, &value2);
929
iPtr->noEval--;
930
} else {
931
iPtr->noEval++;
932
result = ExprGetValue(interp, infoPtr,
933
precTable[QUESTY] - 1, &value2);
934
iPtr->noEval--;
935
if (result != TCL_OK) {
936
goto done;
937
}
938
if (infoPtr->token != COLON) {
939
goto syntaxError;
940
}
941
valuePtr->pv.next = valuePtr->pv.buffer;
942
result = ExprGetValue(interp, infoPtr,
943
precTable[QUESTY] - 1, valuePtr);
944
if (result != TCL_OK) {
945
goto done;
946
}
947
}
948
continue;
949
} else {
950
result = ExprGetValue(interp, infoPtr, precTable[operator],
951
&value2);
952
}
953
} else {
954
result = ExprGetValue(interp, infoPtr, precTable[operator],
955
&value2);
956
}
957
if (result != TCL_OK) {
958
goto done;
959
}
960
if ((infoPtr->token < MULT) && (infoPtr->token != VALUE)
961
&& (infoPtr->token != END) && (infoPtr->token != COMMA)
962
&& (infoPtr->token != CLOSE_PAREN)) {
963
goto syntaxError;
964
}
965
966
if (iPtr->noEval) {
967
continue;
968
}
969
970
/*
971
* At this point we've got two values and an operator. Check
972
* to make sure that the particular data types are appropriate
973
* for the particular operator, and perform type conversion
974
* if necessary.
975
*/
976
977
switch (operator) {
978
979
/*
980
* For the operators below, no strings are allowed and
981
* ints get converted to floats if necessary.
982
*/
983
984
case MULT: case DIVIDE: case PLUS: case MINUS:
985
if ((valuePtr->type == TYPE_STRING)
986
|| (value2.type == TYPE_STRING)) {
987
badType = TYPE_STRING;
988
goto illegalType;
989
}
990
if (valuePtr->type == TYPE_DOUBLE) {
991
if (value2.type == TYPE_INT) {
992
value2.doubleValue = value2.intValue;
993
value2.type = TYPE_DOUBLE;
994
}
995
} else if (value2.type == TYPE_DOUBLE) {
996
if (valuePtr->type == TYPE_INT) {
997
valuePtr->doubleValue = valuePtr->intValue;
998
valuePtr->type = TYPE_DOUBLE;
999
}
1000
}
1001
break;
1002
1003
/*
1004
* For the operators below, only integers are allowed.
1005
*/
1006
1007
case MOD: case LEFT_SHIFT: case RIGHT_SHIFT:
1008
case BIT_AND: case BIT_XOR: case BIT_OR:
1009
if (valuePtr->type != TYPE_INT) {
1010
badType = valuePtr->type;
1011
goto illegalType;
1012
} else if (value2.type != TYPE_INT) {
1013
badType = value2.type;
1014
goto illegalType;
1015
}
1016
break;
1017
1018
/*
1019
* For the operators below, any type is allowed but the
1020
* two operands must have the same type. Convert integers
1021
* to floats and either to strings, if necessary.
1022
*/
1023
1024
case LESS: case GREATER: case LEQ: case GEQ:
1025
case EQUAL: case NEQ:
1026
if (valuePtr->type == TYPE_STRING) {
1027
if (value2.type != TYPE_STRING) {
1028
ExprMakeString(interp, &value2);
1029
}
1030
} else if (value2.type == TYPE_STRING) {
1031
if (valuePtr->type != TYPE_STRING) {
1032
ExprMakeString(interp, valuePtr);
1033
}
1034
} else if (valuePtr->type == TYPE_DOUBLE) {
1035
if (value2.type == TYPE_INT) {
1036
value2.doubleValue = value2.intValue;
1037
value2.type = TYPE_DOUBLE;
1038
}
1039
} else if (value2.type == TYPE_DOUBLE) {
1040
if (valuePtr->type == TYPE_INT) {
1041
valuePtr->doubleValue = valuePtr->intValue;
1042
valuePtr->type = TYPE_DOUBLE;
1043
}
1044
}
1045
break;
1046
1047
/*
1048
* For the operators below, no strings are allowed, but
1049
* no int->double conversions are performed.
1050
*/
1051
1052
case AND: case OR:
1053
if (valuePtr->type == TYPE_STRING) {
1054
badType = valuePtr->type;
1055
goto illegalType;
1056
}
1057
if (value2.type == TYPE_STRING) {
1058
badType = value2.type;
1059
goto illegalType;
1060
}
1061
break;
1062
1063
/*
1064
* For the operators below, type and conversions are
1065
* irrelevant: they're handled elsewhere.
1066
*/
1067
1068
case QUESTY: case COLON:
1069
break;
1070
1071
/*
1072
* Any other operator is an error.
1073
*/
1074
1075
default:
1076
interp->result = "unknown operator in expression";
1077
result = TCL_ERROR;
1078
goto done;
1079
}
1080
1081
/*
1082
* Carry out the function of the specified operator.
1083
*/
1084
1085
switch (operator) {
1086
case MULT:
1087
if (valuePtr->type == TYPE_INT) {
1088
valuePtr->intValue = valuePtr->intValue * value2.intValue;
1089
} else {
1090
valuePtr->doubleValue *= value2.doubleValue;
1091
}
1092
break;
1093
case DIVIDE:
1094
case MOD:
1095
if (valuePtr->type == TYPE_INT) {
1096
long divisor, quot, rem;
1097
int negative;
1098
1099
if (value2.intValue == 0) {
1100
divideByZero:
1101
interp->result = "divide by zero";
1102
Tcl_SetErrorCode(interp, "ARITH", "DIVZERO",
1103
interp->result, (char *) NULL);
1104
result = TCL_ERROR;
1105
goto done;
1106
}
1107
1108
/*
1109
* The code below is tricky because C doesn't guarantee
1110
* much about the properties of the quotient or
1111
* remainder, but Tcl does: the remainder always has
1112
* the same sign as the divisor and a smaller absolute
1113
* value.
1114
*/
1115
1116
divisor = value2.intValue;
1117
negative = 0;
1118
if (divisor < 0) {
1119
divisor = -divisor;
1120
valuePtr->intValue = -valuePtr->intValue;
1121
negative = 1;
1122
}
1123
quot = valuePtr->intValue / divisor;
1124
rem = valuePtr->intValue % divisor;
1125
if (rem < 0) {
1126
rem += divisor;
1127
quot -= 1;
1128
}
1129
if (negative) {
1130
rem = -rem;
1131
}
1132
valuePtr->intValue = (operator == DIVIDE) ? quot : rem;
1133
} else {
1134
if (value2.doubleValue == 0.0) {
1135
goto divideByZero;
1136
}
1137
valuePtr->doubleValue /= value2.doubleValue;
1138
}
1139
break;
1140
case PLUS:
1141
if (valuePtr->type == TYPE_INT) {
1142
valuePtr->intValue = valuePtr->intValue + value2.intValue;
1143
} else {
1144
valuePtr->doubleValue += value2.doubleValue;
1145
}
1146
break;
1147
case MINUS:
1148
if (valuePtr->type == TYPE_INT) {
1149
valuePtr->intValue = valuePtr->intValue - value2.intValue;
1150
} else {
1151
valuePtr->doubleValue -= value2.doubleValue;
1152
}
1153
break;
1154
case LEFT_SHIFT:
1155
valuePtr->intValue <<= value2.intValue;
1156
break;
1157
case RIGHT_SHIFT:
1158
/*
1159
* The following code is a bit tricky: it ensures that
1160
* right shifts propagate the sign bit even on machines
1161
* where ">>" won't do it by default.
1162
*/
1163
1164
if (valuePtr->intValue < 0) {
1165
valuePtr->intValue =
1166
~((~valuePtr->intValue) >> value2.intValue);
1167
} else {
1168
valuePtr->intValue >>= value2.intValue;
1169
}
1170
break;
1171
case LESS:
1172
if (valuePtr->type == TYPE_INT) {
1173
valuePtr->intValue =
1174
valuePtr->intValue < value2.intValue;
1175
} else if (valuePtr->type == TYPE_DOUBLE) {
1176
valuePtr->intValue =
1177
valuePtr->doubleValue < value2.doubleValue;
1178
} else {
1179
valuePtr->intValue =
1180
strcmp(valuePtr->pv.buffer, value2.pv.buffer) < 0;
1181
}
1182
valuePtr->type = TYPE_INT;
1183
break;
1184
case GREATER:
1185
if (valuePtr->type == TYPE_INT) {
1186
valuePtr->intValue =
1187
valuePtr->intValue > value2.intValue;
1188
} else if (valuePtr->type == TYPE_DOUBLE) {
1189
valuePtr->intValue =
1190
valuePtr->doubleValue > value2.doubleValue;
1191
} else {
1192
valuePtr->intValue =
1193
strcmp(valuePtr->pv.buffer, value2.pv.buffer) > 0;
1194
}
1195
valuePtr->type = TYPE_INT;
1196
break;
1197
case LEQ:
1198
if (valuePtr->type == TYPE_INT) {
1199
valuePtr->intValue =
1200
valuePtr->intValue <= value2.intValue;
1201
} else if (valuePtr->type == TYPE_DOUBLE) {
1202
valuePtr->intValue =
1203
valuePtr->doubleValue <= value2.doubleValue;
1204
} else {
1205
valuePtr->intValue =
1206
strcmp(valuePtr->pv.buffer, value2.pv.buffer) <= 0;
1207
}
1208
valuePtr->type = TYPE_INT;
1209
break;
1210
case GEQ:
1211
if (valuePtr->type == TYPE_INT) {
1212
valuePtr->intValue =
1213
valuePtr->intValue >= value2.intValue;
1214
} else if (valuePtr->type == TYPE_DOUBLE) {
1215
valuePtr->intValue =
1216
valuePtr->doubleValue >= value2.doubleValue;
1217
} else {
1218
valuePtr->intValue =
1219
strcmp(valuePtr->pv.buffer, value2.pv.buffer) >= 0;
1220
}
1221
valuePtr->type = TYPE_INT;
1222
break;
1223
case EQUAL:
1224
if (valuePtr->type == TYPE_INT) {
1225
valuePtr->intValue =
1226
valuePtr->intValue == value2.intValue;
1227
} else if (valuePtr->type == TYPE_DOUBLE) {
1228
valuePtr->intValue =
1229
valuePtr->doubleValue == value2.doubleValue;
1230
} else {
1231
valuePtr->intValue =
1232
strcmp(valuePtr->pv.buffer, value2.pv.buffer) == 0;
1233
}
1234
valuePtr->type = TYPE_INT;
1235
break;
1236
case NEQ:
1237
if (valuePtr->type == TYPE_INT) {
1238
valuePtr->intValue =
1239
valuePtr->intValue != value2.intValue;
1240
} else if (valuePtr->type == TYPE_DOUBLE) {
1241
valuePtr->intValue =
1242
valuePtr->doubleValue != value2.doubleValue;
1243
} else {
1244
valuePtr->intValue =
1245
strcmp(valuePtr->pv.buffer, value2.pv.buffer) != 0;
1246
}
1247
valuePtr->type = TYPE_INT;
1248
break;
1249
case BIT_AND:
1250
valuePtr->intValue &= value2.intValue;
1251
break;
1252
case BIT_XOR:
1253
valuePtr->intValue ^= value2.intValue;
1254
break;
1255
case BIT_OR:
1256
valuePtr->intValue |= value2.intValue;
1257
break;
1258
1259
/*
1260
* For AND and OR, we know that the first value has already
1261
* been converted to an integer. Thus we need only consider
1262
* the possibility of int vs. double for the second value.
1263
*/
1264
1265
case AND:
1266
if (value2.type == TYPE_DOUBLE) {
1267
value2.intValue = value2.doubleValue != 0;
1268
value2.type = TYPE_INT;
1269
}
1270
valuePtr->intValue = valuePtr->intValue && value2.intValue;
1271
break;
1272
case OR:
1273
if (value2.type == TYPE_DOUBLE) {
1274
value2.intValue = value2.doubleValue != 0;
1275
value2.type = TYPE_INT;
1276
}
1277
valuePtr->intValue = valuePtr->intValue || value2.intValue;
1278
break;
1279
1280
case COLON:
1281
interp->result = "can't have : operator without ? first";
1282
result = TCL_ERROR;
1283
goto done;
1284
}
1285
}
1286
1287
done:
1288
if (value2.pv.buffer != value2.staticSpace) {
1289
ckfree(value2.pv.buffer);
1290
}
1291
return result;
1292
1293
syntaxError:
1294
Tcl_AppendResult(interp, "syntax error in expression \"",
1295
infoPtr->originalExpr, "\"", (char *) NULL);
1296
result = TCL_ERROR;
1297
goto done;
1298
1299
illegalType:
1300
Tcl_AppendResult(interp, "can't use ", (badType == TYPE_DOUBLE) ?
1301
"floating-point value" : "non-numeric string",
1302
" as operand of \"", operatorStrings[operator], "\"",
1303
(char *) NULL);
1304
result = TCL_ERROR;
1305
goto done;
1306
}
1307
1308
/*
1309
*--------------------------------------------------------------
1310
*
1311
* ExprMakeString --
1312
*
1313
* Convert a value from int or double representation to
1314
* a string.
1315
*
1316
* Results:
1317
* The information at *valuePtr gets converted to string
1318
* format, if it wasn't that way already.
1319
*
1320
* Side effects:
1321
* None.
1322
*
1323
*--------------------------------------------------------------
1324
*/
1325
1326
static void
1327
ExprMakeString(interp, valuePtr)
1328
Tcl_Interp *interp; /* Interpreter to use for precision
1329
* information. */
1330
register Value *valuePtr; /* Value to be converted. */
1331
{
1332
int shortfall;
1333
1334
shortfall = 150 - (valuePtr->pv.end - valuePtr->pv.buffer);
1335
if (shortfall > 0) {
1336
(*valuePtr->pv.expandProc)(&valuePtr->pv, shortfall);
1337
}
1338
if (valuePtr->type == TYPE_INT) {
1339
sprintf(valuePtr->pv.buffer, "%ld", valuePtr->intValue);
1340
} else if (valuePtr->type == TYPE_DOUBLE) {
1341
Tcl_PrintDouble(interp, valuePtr->doubleValue, valuePtr->pv.buffer);
1342
}
1343
valuePtr->type = TYPE_STRING;
1344
}
1345
1346
/*
1347
*--------------------------------------------------------------
1348
*
1349
* ExprTopLevel --
1350
*
1351
* This procedure provides top-level functionality shared by
1352
* procedures like Tcl_ExprInt, Tcl_ExprDouble, etc.
1353
*
1354
* Results:
1355
* The result is a standard Tcl return value. If an error
1356
* occurs then an error message is left in interp->result.
1357
* The value of the expression is returned in *valuePtr, in
1358
* whatever form it ends up in (could be string or integer
1359
* or double). Caller may need to convert result. Caller
1360
* is also responsible for freeing string memory in *valuePtr,
1361
* if any was allocated.
1362
*
1363
* Side effects:
1364
* None.
1365
*
1366
*--------------------------------------------------------------
1367
*/
1368
1369
static int
1370
ExprTopLevel(interp, string, valuePtr)
1371
Tcl_Interp *interp; /* Context in which to evaluate the
1372
* expression. */
1373
char *string; /* Expression to evaluate. */
1374
Value *valuePtr; /* Where to store result. Should
1375
* not be initialized by caller. */
1376
{
1377
ExprInfo info;
1378
int result;
1379
1380
/*
1381
* Create the math functions the first time an expression is
1382
* evaluated.
1383
*/
1384
1385
if (!(((Interp *) interp)->flags & EXPR_INITIALIZED)) {
1386
BuiltinFunc *funcPtr;
1387
1388
((Interp *) interp)->flags |= EXPR_INITIALIZED;
1389
for (funcPtr = funcTable; funcPtr->name != NULL;
1390
funcPtr++) {
1391
Tcl_CreateMathFunc(interp, funcPtr->name, funcPtr->numArgs,
1392
funcPtr->argTypes, funcPtr->proc, funcPtr->clientData);
1393
}
1394
}
1395
1396
info.originalExpr = string;
1397
info.expr = string;
1398
valuePtr->pv.buffer = valuePtr->pv.next = valuePtr->staticSpace;
1399
valuePtr->pv.end = valuePtr->pv.buffer + STATIC_STRING_SPACE - 1;
1400
valuePtr->pv.expandProc = TclExpandParseValue;
1401
valuePtr->pv.clientData = (ClientData) NULL;
1402
1403
result = ExprGetValue(interp, &info, -1, valuePtr);
1404
if (result != TCL_OK) {
1405
return result;
1406
}
1407
if (info.token != END) {
1408
Tcl_AppendResult(interp, "syntax error in expression \"",
1409
string, "\"", (char *) NULL);
1410
return TCL_ERROR;
1411
}
1412
if ((valuePtr->type == TYPE_DOUBLE) && (IS_NAN(valuePtr->doubleValue)
1413
|| IS_INF(valuePtr->doubleValue))) {
1414
/*
1415
* IEEE floating-point error.
1416
*/
1417
1418
TclExprFloatError(interp, valuePtr->doubleValue);
1419
return TCL_ERROR;
1420
}
1421
return TCL_OK;
1422
}
1423
1424
/*
1425
*--------------------------------------------------------------
1426
*
1427
* Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
1428
*
1429
* Procedures to evaluate an expression and return its value
1430
* in a particular form.
1431
*
1432
* Results:
1433
* Each of the procedures below returns a standard Tcl result.
1434
* If an error occurs then an error message is left in
1435
* interp->result. Otherwise the value of the expression,
1436
* in the appropriate form, is stored at *resultPtr. If
1437
* the expression had a result that was incompatible with the
1438
* desired form then an error is returned.
1439
*
1440
* Side effects:
1441
* None.
1442
*
1443
*--------------------------------------------------------------
1444
*/
1445
1446
int
1447
Tcl_ExprLong(interp, string, ptr)
1448
Tcl_Interp *interp; /* Context in which to evaluate the
1449
* expression. */
1450
char *string; /* Expression to evaluate. */
1451
long *ptr; /* Where to store result. */
1452
{
1453
Value value;
1454
int result;
1455
1456
result = ExprTopLevel(interp, string, &value);
1457
if (result == TCL_OK) {
1458
if (value.type == TYPE_INT) {
1459
*ptr = value.intValue;
1460
} else if (value.type == TYPE_DOUBLE) {
1461
*ptr = (long) value.doubleValue;
1462
} else {
1463
interp->result = "expression didn't have numeric value";
1464
result = TCL_ERROR;
1465
}
1466
}
1467
if (value.pv.buffer != value.staticSpace) {
1468
ckfree(value.pv.buffer);
1469
}
1470
return result;
1471
}
1472
1473
int
1474
Tcl_ExprDouble(interp, string, ptr)
1475
Tcl_Interp *interp; /* Context in which to evaluate the
1476
* expression. */
1477
char *string; /* Expression to evaluate. */
1478
double *ptr; /* Where to store result. */
1479
{
1480
Value value;
1481
int result;
1482
1483
result = ExprTopLevel(interp, string, &value);
1484
if (result == TCL_OK) {
1485
if (value.type == TYPE_INT) {
1486
*ptr = value.intValue;
1487
} else if (value.type == TYPE_DOUBLE) {
1488
*ptr = value.doubleValue;
1489
} else {
1490
interp->result = "expression didn't have numeric value";
1491
result = TCL_ERROR;
1492
}
1493
}
1494
if (value.pv.buffer != value.staticSpace) {
1495
ckfree(value.pv.buffer);
1496
}
1497
return result;
1498
}
1499
1500
int
1501
Tcl_ExprBoolean(interp, string, ptr)
1502
Tcl_Interp *interp; /* Context in which to evaluate the
1503
* expression. */
1504
char *string; /* Expression to evaluate. */
1505
int *ptr; /* Where to store 0/1 result. */
1506
{
1507
Value value;
1508
int result;
1509
1510
result = ExprTopLevel(interp, string, &value);
1511
if (result == TCL_OK) {
1512
if (value.type == TYPE_INT) {
1513
*ptr = value.intValue != 0;
1514
} else if (value.type == TYPE_DOUBLE) {
1515
*ptr = value.doubleValue != 0.0;
1516
} else {
1517
result = Tcl_GetBoolean(interp, value.pv.buffer, ptr);
1518
}
1519
}
1520
if (value.pv.buffer != value.staticSpace) {
1521
ckfree(value.pv.buffer);
1522
}
1523
return result;
1524
}
1525
1526
/*
1527
*--------------------------------------------------------------
1528
*
1529
* Tcl_ExprString --
1530
*
1531
* Evaluate an expression and return its value in string form.
1532
*
1533
* Results:
1534
* A standard Tcl result. If the result is TCL_OK, then the
1535
* interpreter's result is set to the string value of the
1536
* expression. If the result is TCL_OK, then interp->result
1537
* contains an error message.
1538
*
1539
* Side effects:
1540
* None.
1541
*
1542
*--------------------------------------------------------------
1543
*/
1544
1545
int
1546
Tcl_ExprString(interp, string)
1547
Tcl_Interp *interp; /* Context in which to evaluate the
1548
* expression. */
1549
char *string; /* Expression to evaluate. */
1550
{
1551
Value value;
1552
int result;
1553
1554
result = ExprTopLevel(interp, string, &value);
1555
if (result == TCL_OK) {
1556
if (value.type == TYPE_INT) {
1557
sprintf(interp->result, "%ld", value.intValue);
1558
} else if (value.type == TYPE_DOUBLE) {
1559
Tcl_PrintDouble(interp, value.doubleValue, interp->result);
1560
} else {
1561
if (value.pv.buffer != value.staticSpace) {
1562
interp->result = value.pv.buffer;
1563
interp->freeProc = TCL_DYNAMIC;
1564
value.pv.buffer = value.staticSpace;
1565
} else {
1566
Tcl_SetResult(interp, value.pv.buffer, TCL_VOLATILE);
1567
}
1568
}
1569
}
1570
if (value.pv.buffer != value.staticSpace) {
1571
ckfree(value.pv.buffer);
1572
}
1573
return result;
1574
}
1575
1576
/*
1577
*----------------------------------------------------------------------
1578
*
1579
* Tcl_CreateMathFunc --
1580
*
1581
* Creates a new math function for expressions in a given
1582
* interpreter.
1583
*
1584
* Results:
1585
* None.
1586
*
1587
* Side effects:
1588
* The function defined by "name" is created; if such a function
1589
* already existed then its definition is overriden.
1590
*
1591
*----------------------------------------------------------------------
1592
*/
1593
1594
void
1595
Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
1596
Tcl_Interp *interp; /* Interpreter in which function is
1597
* to be available. */
1598
char *name; /* Name of function (e.g. "sin"). */
1599
int numArgs; /* Nnumber of arguments required by
1600
* function. */
1601
Tcl_ValueType *argTypes; /* Array of types acceptable for
1602
* each argument. */
1603
Tcl_MathProc *proc; /* Procedure that implements the
1604
* math function. */
1605
ClientData clientData; /* Additional value to pass to the
1606
* function. */
1607
{
1608
Interp *iPtr = (Interp *) interp;
1609
Tcl_HashEntry *hPtr;
1610
MathFunc *mathFuncPtr;
1611
int new, i;
1612
1613
hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
1614
if (new) {
1615
Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
1616
}
1617
mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
1618
if (numArgs > MAX_MATH_ARGS) {
1619
numArgs = MAX_MATH_ARGS;
1620
}
1621
mathFuncPtr->numArgs = numArgs;
1622
for (i = 0; i < numArgs; i++) {
1623
mathFuncPtr->argTypes[i] = argTypes[i];
1624
}
1625
mathFuncPtr->proc = proc;
1626
mathFuncPtr->clientData = clientData;
1627
}
1628
1629
/*
1630
*----------------------------------------------------------------------
1631
*
1632
* ExprMathFunc --
1633
*
1634
* This procedure is invoked to parse a math function from an
1635
* expression string, carry out the function, and return the
1636
* value computed.
1637
*
1638
* Results:
1639
* TCL_OK is returned if all went well and the function's value
1640
* was computed successfully. If an error occurred, TCL_ERROR
1641
* is returned and an error message is left in interp->result.
1642
* After a successful return infoPtr has been updated to refer
1643
* to the character just after the function call, the token is
1644
* set to VALUE, and the value is stored in valuePtr.
1645
*
1646
* Side effects:
1647
* Embedded commands could have arbitrary side-effects.
1648
*
1649
*----------------------------------------------------------------------
1650
*/
1651
1652
static int
1653
ExprMathFunc(interp, infoPtr, valuePtr)
1654
Tcl_Interp *interp; /* Interpreter to use for error
1655
* reporting. */
1656
register ExprInfo *infoPtr; /* Describes the state of the parse.
1657
* infoPtr->expr must point to the
1658
* first character of the function's
1659
* name. */
1660
register Value *valuePtr; /* Where to store value, if that is
1661
* what's parsed from string. Caller
1662
* must have initialized pv field
1663
* correctly. */
1664
{
1665
Interp *iPtr = (Interp *) interp;
1666
MathFunc *mathFuncPtr; /* Info about math function. */
1667
Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
1668
Tcl_Value funcResult; /* Result of function call. */
1669
Tcl_HashEntry *hPtr;
1670
char *p, *funcName, savedChar;
1671
int i, result;
1672
1673
/*
1674
* Find the end of the math function's name and lookup the MathFunc
1675
* record for the function.
1676
*/
1677
1678
p = funcName = infoPtr->expr;
1679
while (isalnum(UCHAR(*p)) || (*p == '_')) {
1680
p++;
1681
}
1682
infoPtr->expr = p;
1683
result = ExprLex(interp, infoPtr, valuePtr);
1684
if (result != TCL_OK) {
1685
return TCL_ERROR;
1686
}
1687
if (infoPtr->token != OPEN_PAREN) {
1688
goto syntaxError;
1689
}
1690
savedChar = *p;
1691
*p = 0;
1692
hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
1693
if (hPtr == NULL) {
1694
Tcl_AppendResult(interp, "unknown math function \"", funcName,
1695
"\"", (char *) NULL);
1696
*p = savedChar;
1697
return TCL_ERROR;
1698
}
1699
*p = savedChar;
1700
mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
1701
1702
/*
1703
* Scan off the arguments for the function, if there are any.
1704
*/
1705
1706
if (mathFuncPtr->numArgs == 0) {
1707
result = ExprLex(interp, infoPtr, valuePtr);
1708
if ((result != TCL_OK) || (infoPtr->token != CLOSE_PAREN)) {
1709
goto syntaxError;
1710
}
1711
} else {
1712
for (i = 0; ; i++) {
1713
valuePtr->pv.next = valuePtr->pv.buffer;
1714
result = ExprGetValue(interp, infoPtr, -1, valuePtr);
1715
if (result != TCL_OK) {
1716
return result;
1717
}
1718
if (valuePtr->type == TYPE_STRING) {
1719
interp->result =
1720
"argument to math function didn't have numeric value";
1721
return TCL_ERROR;
1722
}
1723
1724
/*
1725
* Copy the value to the argument record, converting it if
1726
* necessary.
1727
*/
1728
1729
if (valuePtr->type == TYPE_INT) {
1730
if (mathFuncPtr->argTypes[i] == TCL_DOUBLE) {
1731
args[i].type = TCL_DOUBLE;
1732
args[i].doubleValue = valuePtr->intValue;
1733
} else {
1734
args[i].type = TCL_INT;
1735
args[i].intValue = valuePtr->intValue;
1736
}
1737
} else {
1738
if (mathFuncPtr->argTypes[i] == TCL_INT) {
1739
args[i].type = TCL_INT;
1740
args[i].intValue = (long) valuePtr->doubleValue;
1741
} else {
1742
args[i].type = TCL_DOUBLE;
1743
args[i].doubleValue = valuePtr->doubleValue;
1744
}
1745
}
1746
1747
/*
1748
* Check for a comma separator between arguments or a close-paren
1749
* to end the argument list.
1750
*/
1751
1752
if (i == (mathFuncPtr->numArgs-1)) {
1753
if (infoPtr->token == CLOSE_PAREN) {
1754
break;
1755
}
1756
if (infoPtr->token == COMMA) {
1757
interp->result = "too many arguments for math function";
1758
return TCL_ERROR;
1759
} else {
1760
goto syntaxError;
1761
}
1762
}
1763
if (infoPtr->token != COMMA) {
1764
if (infoPtr->token == CLOSE_PAREN) {
1765
interp->result = "too few arguments for math function";
1766
return TCL_ERROR;
1767
} else {
1768
goto syntaxError;
1769
}
1770
}
1771
}
1772
}
1773
if (iPtr->noEval) {
1774
valuePtr->type = TYPE_INT;
1775
valuePtr->intValue = 0;
1776
infoPtr->token = VALUE;
1777
return TCL_OK;
1778
}
1779
1780
/*
1781
* Invoke the function and copy its result back into valuePtr.
1782
*/
1783
1784
tcl_MathInProgress++;
1785
result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
1786
&funcResult);
1787
tcl_MathInProgress--;
1788
if (result != TCL_OK) {
1789
return result;
1790
}
1791
if (funcResult.type == TCL_INT) {
1792
valuePtr->type = TYPE_INT;
1793
valuePtr->intValue = funcResult.intValue;
1794
} else {
1795
valuePtr->type = TYPE_DOUBLE;
1796
valuePtr->doubleValue = funcResult.doubleValue;
1797
}
1798
infoPtr->token = VALUE;
1799
return TCL_OK;
1800
1801
syntaxError:
1802
Tcl_AppendResult(interp, "syntax error in expression \"",
1803
infoPtr->originalExpr, "\"", (char *) NULL);
1804
return TCL_ERROR;
1805
}
1806
1807
/*
1808
*----------------------------------------------------------------------
1809
*
1810
* TclExprFloatError --
1811
*
1812
* This procedure is called when an error occurs during a
1813
* floating-point operation. It reads errno and sets
1814
* interp->result accordingly.
1815
*
1816
* Results:
1817
* Interp->result is set to hold an error message.
1818
*
1819
* Side effects:
1820
* None.
1821
*
1822
*----------------------------------------------------------------------
1823
*/
1824
1825
void
1826
TclExprFloatError(interp, value)
1827
Tcl_Interp *interp; /* Where to store error message. */
1828
double value; /* Value returned after error; used to
1829
* distinguish underflows from overflows. */
1830
{
1831
char buf[20];
1832
1833
if ((errno == EDOM) || (value != value)) {
1834
interp->result = "domain error: argument not in valid range";
1835
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", interp->result,
1836
(char *) NULL);
1837
} else if ((errno == ERANGE) || IS_INF(value)) {
1838
if (value == 0.0) {
1839
interp->result = "floating-point value too small to represent";
1840
Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", interp->result,
1841
(char *) NULL);
1842
} else {
1843
interp->result = "floating-point value too large to represent";
1844
Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", interp->result,
1845
(char *) NULL);
1846
}
1847
} else {
1848
sprintf(buf, "%d", errno);
1849
Tcl_AppendResult(interp, "unknown floating-point error, ",
1850
"errno = ", buf, (char *) NULL);
1851
Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", interp->result,
1852
(char *) NULL);
1853
}
1854
}
1855
1856
/*
1857
*----------------------------------------------------------------------
1858
*
1859
* Math Functions --
1860
*
1861
* This page contains the procedures that implement all of the
1862
* built-in math functions for expressions.
1863
*
1864
* Results:
1865
* Each procedure returns TCL_OK if it succeeds and places result
1866
* information at *resultPtr. If it fails it returns TCL_ERROR
1867
* and leaves an error message in interp->result.
1868
*
1869
* Side effects:
1870
* None.
1871
*
1872
*----------------------------------------------------------------------
1873
*/
1874
1875
static int
1876
ExprUnaryFunc(clientData, interp, args, resultPtr)
1877
ClientData clientData; /* Contains address of procedure that
1878
* takes one double argument and
1879
* returns a double result. */
1880
Tcl_Interp *interp;
1881
Tcl_Value *args;
1882
Tcl_Value *resultPtr;
1883
{
1884
double (*func) _ANSI_ARGS_((double)) = (double (*)_ANSI_ARGS_((double))) clientData;
1885
1886
errno = 0;
1887
resultPtr->type = TCL_DOUBLE;
1888
resultPtr->doubleValue = (*func)(args[0].doubleValue);
1889
if (errno != 0) {
1890
TclExprFloatError(interp, resultPtr->doubleValue);
1891
return TCL_ERROR;
1892
}
1893
return TCL_OK;
1894
}
1895
1896
static int
1897
ExprBinaryFunc(clientData, interp, args, resultPtr)
1898
ClientData clientData; /* Contains address of procedure that
1899
* takes two double arguments and
1900
* returns a double result. */
1901
Tcl_Interp *interp;
1902
Tcl_Value *args;
1903
Tcl_Value *resultPtr;
1904
{
1905
double (*func) _ANSI_ARGS_((double, double))
1906
= (double (*)_ANSI_ARGS_((double, double))) clientData;
1907
1908
errno = 0;
1909
resultPtr->type = TCL_DOUBLE;
1910
resultPtr->doubleValue = (*func)(args[0].doubleValue, args[1].doubleValue);
1911
if (errno != 0) {
1912
TclExprFloatError(interp, resultPtr->doubleValue);
1913
return TCL_ERROR;
1914
}
1915
return TCL_OK;
1916
}
1917
1918
/* ARGSUSED */
1919
static int
1920
ExprAbsFunc(clientData, interp, args, resultPtr)
1921
ClientData clientData;
1922
Tcl_Interp *interp;
1923
Tcl_Value *args;
1924
Tcl_Value *resultPtr;
1925
{
1926
resultPtr->type = TCL_DOUBLE;
1927
if (args[0].type == TCL_DOUBLE) {
1928
resultPtr->type = TCL_DOUBLE;
1929
if (args[0].doubleValue < 0) {
1930
resultPtr->doubleValue = -args[0].doubleValue;
1931
} else {
1932
resultPtr->doubleValue = args[0].doubleValue;
1933
}
1934
} else {
1935
resultPtr->type = TCL_INT;
1936
if (args[0].intValue < 0) {
1937
resultPtr->intValue = -args[0].intValue;
1938
if (resultPtr->intValue < 0) {
1939
interp->result = "integer value too large to represent";
1940
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", interp->result,
1941
(char *) NULL);
1942
return TCL_ERROR;
1943
}
1944
} else {
1945
resultPtr->intValue = args[0].intValue;
1946
}
1947
}
1948
return TCL_OK;
1949
}
1950
1951
/* ARGSUSED */
1952
static int
1953
ExprDoubleFunc(clientData, interp, args, resultPtr)
1954
ClientData clientData;
1955
Tcl_Interp *interp;
1956
Tcl_Value *args;
1957
Tcl_Value *resultPtr;
1958
{
1959
resultPtr->type = TCL_DOUBLE;
1960
if (args[0].type == TCL_DOUBLE) {
1961
resultPtr->doubleValue = args[0].doubleValue;
1962
} else {
1963
resultPtr->doubleValue = args[0].intValue;
1964
}
1965
return TCL_OK;
1966
}
1967
1968
/* ARGSUSED */
1969
static int
1970
ExprIntFunc(clientData, interp, args, resultPtr)
1971
ClientData clientData;
1972
Tcl_Interp *interp;
1973
Tcl_Value *args;
1974
Tcl_Value *resultPtr;
1975
{
1976
resultPtr->type = TCL_INT;
1977
if (args[0].type == TCL_INT) {
1978
resultPtr->intValue = args[0].intValue;
1979
} else {
1980
if (args[0].doubleValue < 0) {
1981
if (args[0].doubleValue < (double) (long) LONG_MIN) {
1982
tooLarge:
1983
interp->result = "integer value too large to represent";
1984
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
1985
interp->result, (char *) NULL);
1986
return TCL_ERROR;
1987
}
1988
} else {
1989
if (args[0].doubleValue > (double) LONG_MAX) {
1990
goto tooLarge;
1991
}
1992
}
1993
resultPtr->intValue = (long) args[0].doubleValue;
1994
}
1995
return TCL_OK;
1996
}
1997
1998
/* ARGSUSED */
1999
static int
2000
ExprRoundFunc(clientData, interp, args, resultPtr)
2001
ClientData clientData;
2002
Tcl_Interp *interp;
2003
Tcl_Value *args;
2004
Tcl_Value *resultPtr;
2005
{
2006
resultPtr->type = TCL_INT;
2007
if (args[0].type == TCL_INT) {
2008
resultPtr->intValue = args[0].intValue;
2009
} else {
2010
if (args[0].doubleValue < 0) {
2011
if (args[0].doubleValue <= (((double) (long) LONG_MIN) - 0.5)) {
2012
tooLarge:
2013
interp->result = "integer value too large to represent";
2014
Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
2015
interp->result, (char *) NULL);
2016
return TCL_ERROR;
2017
}
2018
resultPtr->intValue = (long) (args[0].doubleValue - 0.5);
2019
} else {
2020
if (args[0].doubleValue >= (((double) LONG_MAX + 0.5))) {
2021
goto tooLarge;
2022
}
2023
resultPtr->intValue = (long) (args[0].doubleValue + 0.5);
2024
}
2025
}
2026
return TCL_OK;
2027
}
2028
2029
/*
2030
*----------------------------------------------------------------------
2031
*
2032
* ExprLooksLikeInt --
2033
*
2034
* This procedure decides whether the leading characters of a
2035
* string look like an integer or something else (such as a
2036
* floating-point number or string).
2037
*
2038
* Results:
2039
* The return value is 1 if the leading characters of p look
2040
* like a valid Tcl integer. If they look like a floating-point
2041
* number (e.g. "e01" or "2.4"), or if they don't look like a
2042
* number at all, then 0 is returned.
2043
*
2044
* Side effects:
2045
* None.
2046
*
2047
*----------------------------------------------------------------------
2048
*/
2049
2050
static int
2051
ExprLooksLikeInt(p)
2052
char *p; /* Pointer to string. */
2053
{
2054
while (isspace(UCHAR(*p))) {
2055
p++;
2056
}
2057
if ((*p == '+') || (*p == '-')) {
2058
p++;
2059
}
2060
if (!isdigit(UCHAR(*p))) {
2061
return 0;
2062
}
2063
p++;
2064
while (isdigit(UCHAR(*p))) {
2065
p++;
2066
}
2067
if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
2068
return 1;
2069
}
2070
return 0;
2071
}
2072
2073