1 /* @(#)strexpr.c 1.31 18/07/16 Copyright 2016-2018 J. Schilling */
2 #include <schily/mconfig.h>
3 static UConst char sccsid[] =
4 "@(#)strexpr.c 1.31 18/07/16 Copyright 2016-2018 J. Schilling";
5 #ifdef DO_DOL_PAREN
6 /*
7 * Arithmetic expansion
8 *
9 * Copyright (c) 2016-2018 J. Schilling
10 */
11 /*
12 * The contents of this file are subject to the terms of the
13 * Common Development and Distribution License, Version 1.0 only
14 * (the "License"). You may not use this file except in compliance
15 * with the License.
16 *
17 * See the file CDDL.Schily.txt in this distribution for details.
18 * A copy of the CDDL is also available via the Internet at
19 * http://www.opensource.org/licenses/cddl1.txt
20 *
21 * When distributing Covered Code, include this CDDL HEADER in each
22 * file and include the License file CDDL.Schily.txt from this distribution.
23 */
24
25 #include "defs.h"
26
27 #ifdef STREX_DEBUG
28 #define ARITH_DEBUG
29 #else
30 #ifdef PROTOTYPES
31 #ifdef __problem__ /* Varadic macros have been introduced with C99 */
32 #define fprintf(...)
33 #endif
34 #else
35 #define fprintf()
36 #endif
37 #endif
38
39 struct expr {
40 unsigned char *expr;
41 unsigned char *subexpr;
42 unsigned char *tokenp;
43 struct namnod *var;
44 int token;
45 int unop;
46 int precedence;
47 int flags;
48 Intmax_t val;
49 };
50
51 #define EX_OP 1 /* Looking for an operator */
52 #define EX_NOEVAL 2 /* Parse but do not evaluate */
53
54 #define LOCAL static
55
56 LOCAL const char nolvalue[] = "lvalue required";
57 LOCAL const char badexpr[] = "bad expression";
58 LOCAL jmp_buf exprsyntax;
59
60
61 Intmax_t strexpr __PR((unsigned char *arg, int *errp));
62 #ifdef NEED_PEEKTOK
63 LOCAL int peektok __PR((struct expr *ep));
64 #endif
65 LOCAL int exprtok __PR((struct expr *ep));
66 LOCAL Intmax_t expreval __PR((struct expr *ep,
67 int precedence));
68 LOCAL Intmax_t unary __PR((struct expr *ep, Intmax_t v,
69 int op));
70 LOCAL int getop __PR((struct expr *ep));
71 LOCAL UIntmax_t number __PR((struct expr *ep,
72 unsigned char *str,
73 unsigned char **endptr));
74 LOCAL void efailed __PR((unsigned char *s1,
75 const char *s2));
76 #ifdef ARITH_DEBUG
77 LOCAL char *tokname __PR((int t));
78 #endif
79
80 /*
81 * Token definitions for the parser
82 */
83 #define TK_NONE 0
84 #define TK_EOF 1 /* End of string seen */
85 #define TK_ADD 2 /* + */
86 #define TK_SUB 3 /* - */
87 #define TK_MULT 4 /* * */
88 #define TK_DIV 5 /* / */
89 #define TK_MOD 6 /* % */
90 #define TK_LSHIFT 7 /* << */
91 #define TK_RSHIFT 8 /* >> */
92 #define TK_LT 9 /* < */
93 #define TK_GT 10 /* > */
94 #define TK_LE 11 /* <= */
95 #define TK_GE 12 /* >= */
96 #define TK_EQUAL 13 /* == */
97 #define TK_NEQUAL 14 /* != */
98 #define TK_BAND 15 /* & */
99 #define TK_BXOR 16 /* ^ */
100 #define TK_BOR 17 /* | */
101 #define TK_LAND 18 /* && */
102 #define TK_LOR 19 /* || */
103 #define TK_QUEST 20 /* ? */
104 #define TK_COLON 21 /* : */
105 #define TK_ASSIGN 22 /* = */
106 #define TK_PLUSASN 23 /* += */
107 #define TK_MINUSASN 24 /* -= */
108 #define TK_MULTASN 25 /* *= */
109 #define TK_DIVASN 26 /* /= */
110 #define TK_MODASN 27 /* %= */
111 #define TK_LSHIFTASN 28 /* <<= */
112 #define TK_RSHIFTASN 29 /* >>= */
113 #define TK_BANDASN 30 /* &= */
114 #define TK_BXORASN 31 /* ^= */
115 #define TK_BORASN 32 /* |= */
116 #define TK_PLUSPLUS 33 /* ++ */
117 #define TK_MINUSMINUS 34 /* -- */
118 #define TK_UPLUS 35 /* + */
119 #define TK_UMINUS 36 /* - */
120 #define TK_BNOT 37 /* ~ */
121 #define TK_LNOT 38 /* ! */
122 #define TK_OPAREN 39 /* ( */
123 #define TK_CLPAREN 40 /* ) */
124 #define TK_COMMA 41 /* , */
125 #define TK_END 42 /* op-delimiter */
126 #define TK_NUM 43 /* numerical value */
127 #define TK_VAR 44 /* variable name */
128 #define TK_ERROR 45 /* No token found */
129
130 #define TK_ISBINARYOP ((t) >= TK_ADD && (t) <= TK_LOR)
131 #define TK_ISASSIGN(t) ((t) >= TK_ASSIGN && (t) <= TK_BORASN)
132 #define TK_ISUNARYOP(t) ((t) >= TK_PLUSPLUS && (t) <= TK_LNOT)
133
134 /*
135 * Precedence values, lower numbers yield higher precedence.
136 */
137 #define PR_PRIMARY 0 /* var, (), ! ~ ++ -- */
138 #define PR_MULT 1 /* * / % */
139 #define PR_ADD 2 /* + - */
140 #define PR_SHIFT 3 /* << >> */
141 #define PR_COMPARE 4 /* < > <= >= */
142 #define PR_EQUAL 5 /* == != */
143 #define PR_BAND 6 /* & */
144 #define PR_BXOR 7 /* ^ */
145 #define PR_BOR 8 /* | */
146 #define PR_LAND 9 /* && */
147 #define PR_LOR 10 /* || */
148 #define PR_QUEST 11 /* ? */
149 #define PR_ASSIGN 12 /* = += -= *= /= %= <<= >>= &= ^= |= */
150 #define PR_COMMA 13 /* , */
151 #define PR_MAXPREC 13
152
153 /*
154 * Operators, longer strings need to be before shorter sub-strings.
155 */
156 LOCAL struct ops {
157 char name[4];
158 char nlen;
159 char val;
160 char precedence;
161 } ops[] = {
162 { "++", 2, TK_PLUSPLUS, PR_PRIMARY, },
163 { "--", 2, TK_MINUSMINUS, PR_PRIMARY, },
164 { "==", 2, TK_EQUAL, PR_EQUAL, },
165 { "!=", 2, TK_NEQUAL, PR_EQUAL, },
166 { "+=", 2, TK_PLUSASN, PR_ASSIGN, },
167 { "-=", 2, TK_MINUSASN, PR_ASSIGN, },
168 { "*=", 2, TK_MULTASN, PR_ASSIGN, },
169 { "/=", 2, TK_DIVASN, PR_ASSIGN, },
170 { "%=", 2, TK_MODASN, PR_ASSIGN, },
171 { "<<=", 3, TK_LSHIFTASN, PR_ASSIGN, },
172 { ">>=", 3, TK_RSHIFTASN, PR_ASSIGN, },
173 { "&=", 2, TK_BANDASN, PR_ASSIGN, },
174 { "^=", 2, TK_BXORASN, PR_ASSIGN, },
175 { "|=", 2, TK_BORASN, PR_ASSIGN, },
176 { "=", 1, TK_ASSIGN, PR_ASSIGN, },
177 { "&&", 2, TK_LAND, PR_LAND, },
178 { "||", 2, TK_LOR, PR_LOR, },
179 { "+", 1, TK_ADD, PR_ADD, },
180 { "-", 1, TK_SUB, PR_ADD, },
181 { "*", 1, TK_MULT, PR_MULT, },
182 { "/", 1, TK_DIV, PR_MULT, },
183 { "%", 1, TK_MOD, PR_MULT, },
184 { "<<", 2, TK_LSHIFT, PR_SHIFT, },
185 { ">>", 2, TK_RSHIFT, PR_SHIFT, },
186 { "&", 1, TK_BAND, PR_BAND, },
187 { "^", 1, TK_BXOR, PR_BXOR, },
188 { "|", 1, TK_BOR, PR_BOR, },
189 { "<=", 2, TK_LE, PR_COMPARE, },
190 { ">=", 2, TK_GE, PR_COMPARE, },
191 { "<", 1, TK_LT, PR_COMPARE, },
192 { ">", 1, TK_GT, PR_COMPARE, },
193 { "~", 1, TK_BNOT, PR_PRIMARY, },
194 { "!", 1, TK_LNOT, PR_PRIMARY, },
195 { "(", 1, TK_OPAREN, PR_PRIMARY, },
196 { ")", 1, TK_CLPAREN, PR_PRIMARY, },
197 { "?", 1, TK_QUEST, PR_QUEST, },
198 { ":", 1, TK_COLON, PR_QUEST, },
199 { ",", 1, TK_COMMA, PR_COMMA, },
200 { "", 1, TK_EOF, PR_PRIMARY, },
201 { "", 0, TK_END, PR_PRIMARY, }
202 };
203
204 /*
205 * Returns the result.
206 */
207 Intmax_t
strexpr(arg,errp)208 strexpr(arg, errp)
209 unsigned char *arg;
210 int *errp;
211 {
212 struct expr exp;
213 Intmax_t ret;
214
215 #ifdef ARITH_DEBUG
216 fprintf(stderr, "strexpr('%s')\n", arg);
217 #endif
218 memset(&exp, 0, sizeof (exp));
219 exp.expr = exp.subexpr = exp.tokenp = arg;
220
221 *errp = 0;
222 if (setjmp(exprsyntax)) {
223 *errp = ERROR;
224 return (0); /* Does not matter */
225 }
226 exprtok(&exp);
227 ret = expreval(&exp, PR_MAXPREC);
228 return (ret);
229 }
230
231 #ifdef NEED_PEEKTOK
232 LOCAL int
peektok(ep)233 peektok(ep)
234 struct expr *ep;
235 {
236 struct expr exp;
237
238 exp = *ep;
239 exp.flags = EX_OP | EX_NOEVAL;
240 return (exprtok(&exp));
241 }
242 #endif
243
244 /*
245 * Returns the next token.
246 * If the next token is a variable or a constant, then the variable is put
247 * into ep->val.
248 */
249 LOCAL int
exprtok(ep)250 exprtok(ep)
251 struct expr *ep;
252 {
253 int flag = ep->flags;
254 int tok = getop(ep); /* get token */
255
256 if ((flag & EX_OP) == 0 &&
257 (tok == TK_ADD || tok == TK_SUB ||
258 TK_ISUNARYOP(tok))) {
259 exprtok(ep);
260 if (ep->token == TK_OPAREN) {
261 exprtok(ep);
262 expreval(ep, PR_PRIMARY);
263 }
264 ep->val = unary(ep, ep->val, tok);
265 return (tok);
266 }
267 if (tok == TK_NUM) {
268 UIntmax_t i;
269 unsigned char *np;
270
271 i = number(ep, ep->tokenp, &np);
272 if (alphanum(*np)) {
273 efailed(ep->expr, badnum);
274 }
275 ep->val = unary(ep, i, ep->unop);
276 ep->var = NULL;
277 ep->tokenp = np;
278
279 } else if (tok == TK_VAR) {
280 UIntptr_t b = relstak();
281 unsigned char *np = ep->tokenp;
282 struct namnod *n;
283 int c;
284 UIntmax_t i = 0;
285 int neg = 0;
286 unsigned char *otokenp;
287 int otoken;
288 int xtok;
289
290 while ((c = *np++) != '\0') {
291 if (!alphanum(c))
292 break;
293 GROWSTAKTOP();
294 pushstak(c);
295 }
296 GROWSTAKTOP();
297 zerostak();
298 staktop = absstak(b);
299 ep->tokenp = --np;
300 n = lookup(staktop);
301 np = NULL;
302 if (n->namval == NULL) {
303 ep->val = i;
304 } else if (*n->namval == '\0') {
305 ep->val = i;
306 } else {
307 unsigned char *nv = n->namval;
308
309 if (*nv == '-') {
310 neg++;
311 nv++;
312 }
313 i = number(ep, nv, &np);
314 /*
315 * Avoid the need to check *np later as it is
316 * invalidated by unary().
317 */
318 if (*np == '\0')
319 np = NULL;
320 }
321 ep->var = n;
322 ep->val = unary(ep, neg?-i:i, ep->unop);
323 otokenp = ep->tokenp;
324 otoken = ep->token;
325 xtok = getop(ep);
326
327 if (xtok != TK_ASSIGN && np)
328 efailed(ep->expr, badnum);
329
330 if ((flags & setflg) && xtok != TK_ASSIGN && n->namval == NULL)
331 efailed(n->namid, unset);
332 if (xtok == TK_PLUSPLUS || xtok == TK_MINUSMINUS) {
333 unary(ep, ep->val, xtok);
334 ep->token = otoken;
335 } else {
336 ep->tokenp = otokenp;
337 ep->token = otoken;
338 }
339 }
340 return (tok);
341 }
342
343 /*
344 * Returns the result.
345 *
346 * We start with the first token already read.
347 * The first call to exprtok() for this reason either returns the operator
348 * or TK_EOF.
349 */
350 LOCAL Intmax_t
expreval(ep,precedence)351 expreval(ep, precedence)
352 struct expr *ep;
353 int precedence;
354 {
355 Intmax_t v;
356 struct namnod *n;
357 int tok;
358 int ntok = TK_NONE;
359 int prec;
360 int nprec;
361 unsigned char *otokenp;
362 int otoken;
363
364 if ((tok = ep->token) == TK_OPAREN) {
365 exprtok(ep);
366 expreval(ep, PR_PRIMARY);
367 ep->var = NULL;
368 } else if (tok > TK_EOF &&
369 tok < TK_NUM &&
370 tok != TK_CLPAREN) {
371 efailed(ep->expr, synmsg);
372 }
373 v = ep->val;
374 n = ep->var;
375 otokenp = ep->tokenp;
376 otoken = ep->token;
377 ep->flags |= EX_OP;
378 tok = exprtok(ep); /* get next token (operator) */
379 prec = ep->precedence;
380
381 if (precedence == PR_QUEST && tok == TK_COMMA && prec > precedence) {
382 ep->token = tok;
383 return (ep->val);
384 }
385 /*
386 * If there is no next token, then we return the previous value.
387 */
388 if (tok == TK_EOF ||
389 ((tok == TK_CLPAREN) && ep->precedence == PR_PRIMARY) ||
390 ((tok == TK_COLON) && ep->precedence == PR_QUEST)) {
391 if (tok == TK_COLON) {
392 ep->tokenp = otokenp;
393 ep->token = otoken;
394 }
395 return (ep->val);
396 }
397
398 /*
399 * Check whether we need at least one additional argument.
400 * This is the case with normal binary operators, with
401 * the conditional operator and with the assignment operators.
402 * The "second value" may be "(".
403 */
404 if ((tok >= TK_ADD && tok <= TK_BORASN) || tok == TK_COMMA) {
405 int oflags = ep->flags;
406
407 if ((tok == TK_LAND || tok == TK_QUEST) && v == 0)
408 ep->flags |= EX_NOEVAL;
409 if ((tok == TK_LOR) && v != 0)
410 ep->flags |= EX_NOEVAL;
411 ntok = exprtok(ep);
412 ep->flags = oflags;
413 }
414
415 do {
416 int otok = tok;
417
418 if (ntok == TK_EOF) {
419 efailed(ep->expr, "missing token");
420 }
421 if (ntok == TK_OPAREN || tok == TK_QUEST) {
422 int oflags = ep->flags;
423
424 if ((tok == TK_LAND || tok == TK_QUEST) && v == 0)
425 ep->flags |= EX_NOEVAL;
426 if ((tok == TK_LOR) && v != 0)
427 ep->flags |= EX_NOEVAL;
428 if (ntok == TK_OPAREN) {
429 exprtok(ep);
430 expreval(ep, PR_PRIMARY);
431 } else {
432 expreval(ep, PR_QUEST);
433 }
434 ep->flags = oflags;
435 }
436 otokenp = ep->tokenp;
437 otoken = ep->token;
438 ep->flags |= EX_OP;
439 ntok = exprtok(ep); /* Check for next operator */
440 nprec = ep->precedence;
441
442 /*
443 * XXX expreval() rekursiv wenn "ntok" h�here Prezedenz hat.
444 */
445 if (ntok != TK_EOF &&
446 ((prec > ep->precedence) ||
447 TK_ISASSIGN(ntok))) {
448 int oflags = ep->flags;
449
450 if ((tok == TK_LAND || tok == TK_QUEST) && v == 0)
451 ep->flags |= EX_NOEVAL;
452 if ((tok == TK_LOR) && v != 0)
453 ep->flags |= EX_NOEVAL;
454 if (otoken != TK_COLON) {
455 ep->tokenp = otokenp;
456 ep->token = otoken;
457 }
458 expreval(ep, ep->precedence);
459 ep->flags = oflags;
460 ntok = ep->token;
461 nprec = ep->precedence;
462 tok = otok;
463 }
464
465 if (n == NULL && TK_ISASSIGN(tok)) {
466 efailed(ep->expr, nolvalue);
467 }
468 if (ep->flags & EX_NOEVAL) {
469 if (tok == TK_QUEST)
470 goto quest;
471 goto noeval;
472 }
473 switch (tok) {
474 case TK_DIV:
475 case TK_DIVASN:
476 case TK_MOD:
477 case TK_MODASN:
478 if (ep->val == 0) {
479 efailed(ep->expr, divzero);
480 ep->val = 1;
481 }
482 }
483 switch (tok) {
484
485 case TK_PLUSASN:
486 case TK_ADD: ep->val = v + ep->val;
487 break;
488 case TK_MINUSASN:
489 case TK_SUB: ep->val = v - ep->val;
490 break;
491 case TK_MULTASN:
492 case TK_MULT: ep->val = v * ep->val;
493 break;
494 case TK_DIVASN:
495 case TK_DIV: ep->val = v / ep->val;
496 break;
497 case TK_MODASN:
498 case TK_MOD: ep->val = v % ep->val;
499 break;
500 case TK_LSHIFTASN:
501 case TK_LSHIFT: ep->val = v << ep->val;
502 break;
503 case TK_RSHIFTASN:
504 case TK_RSHIFT: ep->val = v >> ep->val;
505 break;
506 case TK_LT: ep->val = v < ep->val;
507 break;
508 case TK_GT: ep->val = v > ep->val;
509 break;
510 case TK_LE: ep->val = v <= ep->val;
511 break;
512 case TK_GE: ep->val = v >= ep->val;
513 break;
514 case TK_EQUAL: ep->val = v == ep->val;
515 break;
516 case TK_NEQUAL: ep->val = v != ep->val;
517 break;
518 case TK_BANDASN:
519 case TK_BAND: ep->val = v & ep->val;
520 break;
521 case TK_BXORASN:
522 case TK_BXOR: ep->val = v ^ ep->val;
523 break;
524 case TK_BORASN:
525 case TK_BOR: ep->val = v | ep->val;
526 break;
527 case TK_LAND: ep->val = v && ep->val;
528 break;
529 case TK_LOR: ep->val = v || ep->val;
530 break;
531
532 quest:
533 case TK_QUEST: {
534 int oflags = ep->flags;
535 Intmax_t oval = ep->val;
536
537 if (v)
538 ep->flags |= EX_NOEVAL;
539 exprtok(ep);
540 expreval(ep, PR_QUEST);
541 ep->flags = oflags;
542 if (ntok == TK_COLON) {
543 nprec = PR_MAXPREC +1;
544 }
545 ntok = ep->token;
546 if (ntok == TK_COMMA) {
547 ep->token = TK_NONE;
548 return (expreval(ep,
549 PR_MAXPREC));
550 }
551 if (v)
552 ep->val = oval;
553 }
554 if (ep->flags & EX_NOEVAL)
555 goto noeval;
556 break;
557
558 case TK_COLON:
559 efailed(ep->expr, synmsg);
560 break;
561
562 }
563 if (TK_ISASSIGN(tok)) {
564 assign(n, &numbuf[slltos(ep->val)]);
565 }
566 noeval:
567 /*
568 * "precedence" is the precedence we have been called with.
569 * Comparing only works with non-primary expressions, so
570 * if this call was because of an expression in parenthesis
571 * we may not leave here.
572 */
573 if (precedence > PR_PRIMARY && precedence < nprec) {
574 return (ep->val);
575 }
576
577 tok = ntok;
578 prec = ep->precedence;
579 v = ep->val;
580 if (tok != TK_EOF && tok != TK_CLPAREN && tok != TK_COLON) {
581 ntok = exprtok(ep);
582 } else if (tok == TK_COLON) {
583 ep->tokenp = otokenp;
584 ep->token = otoken;
585 }
586 } while (tok != TK_EOF && tok != TK_CLPAREN && tok != TK_COLON);
587
588 return (ep->val);
589 }
590
591 LOCAL Intmax_t
unary(ep,v,op)592 unary(ep, v, op)
593 struct expr *ep;
594 Intmax_t v;
595 int op;
596 {
597 if (op == TK_PLUSPLUS || op == TK_MINUSMINUS) {
598 if (ep->var == NULL) {
599 efailed(ep->expr, nolvalue);
600 return (0);
601 }
602 if ((ep->flags & EX_NOEVAL) == 0) {
603 assign(ep->var,
604 &numbuf[slltos(op == TK_PLUSPLUS ? ++v:--v)]);
605 }
606 ep->var = NULL;
607 return (v);
608 }
609 switch (op) {
610
611 case 0:
612 case TK_ADD:
613 case TK_UPLUS: return (v);
614 case TK_SUB:
615 case TK_UMINUS: return (-v);
616 case TK_BNOT: return (~v);
617 case TK_LNOT: return (!v);
618
619 default: efailed(ep->expr, badexpr);
620 return (0);
621 }
622 }
623
624 /*
625 * Returns next operator token.
626 * If the next token is a variable or a constant, then a primary operator in
627 * front of the variable/number is returned as a combined token.
628 */
629 LOCAL int
getop(ep)630 getop(ep)
631 struct expr *ep;
632 {
633 int i;
634 int c;
635 int val = 0;
636 unsigned char *p = ep->tokenp;
637
638 ep->unop = 0;
639 again:
640 while (c = *p++, white(c))
641 ;
642 --p;
643 if (digit(c)) {
644 if (val == TK_PLUSPLUS || val == TK_MINUSMINUS) {
645 efailed(ep->expr, nolvalue);
646 return (ep->token = val);
647 }
648
649 ep->tokenp = p;
650 ep->precedence = PR_PRIMARY;
651 ep->flags &= ~EX_OP;
652
653 ep->unop = val;
654 return (ep->token = TK_NUM);
655 } else if (letter(c)) {
656 ep->tokenp = p;
657 ep->precedence = PR_PRIMARY;
658 ep->flags &= ~EX_OP;
659
660 ep->unop = val;
661 return (ep->token = TK_VAR);
662 } else {
663 if (val)
664 return (ep->token = val);
665 for (i = 0; ops[i].val != TK_END; i++) {
666 if (strncmp(C p, ops[i].name, ops[i].nlen) == 0) {
667 val = ops[i].val;
668
669 if (val != TK_EOF)
670 p += ops[i].nlen;
671
672 if (val == TK_COMMA) {
673 #ifdef __needed__
674 /*
675 * A comma without a space before only
676 * may appear inside international
677 * floating point numbers.
678 */
679 if (ep->subexpr == ep->tokenp)
680 break;
681 #endif
682 ep->subexpr = ep->tokenp;
683 } else if ((ep->flags & EX_OP) == 0 &&
684 (val == TK_ADD || val == TK_SUB ||
685 TK_ISUNARYOP(val))) {
686 ep->tokenp = p;
687 ep->precedence = ops[i].precedence;
688 goto again;
689 }
690 ep->flags &= ~EX_OP;
691 ep->tokenp = p;
692 ep->precedence = ops[i].precedence;
693 return (ep->token = val);
694 }
695 }
696 }
697 efailed(ep->expr, badexpr);
698 ep->flags &= ~EX_OP;
699 return (ep->token = TK_ERROR);
700 }
701
702 LOCAL UIntmax_t
number(ep,str,endptr)703 number(ep, str, endptr)
704 struct expr *ep;
705 unsigned char *str;
706 unsigned char **endptr;
707 {
708 UIntmax_t i;
709
710 #ifdef HAVE_STRTOULL
711 i = strtoull(C str, CP endptr, 0);
712 #else
713 *endptr = UC astoull(C str, &i);
714 #endif
715 return (i);
716 }
717
718 static void
efailed(s1,s2)719 efailed(s1, s2)
720 unsigned char *s1;
721 const char *s2;
722 {
723 failed_real(ERROR, s1, s2, NULL);
724 longjmp(exprsyntax, 1);
725 }
726
727 #ifdef ARITH_DEBUG
728 LOCAL char *
tokname(t)729 tokname(t)
730 int t;
731 {
732 int i;
733
734 /*
735 * First check for the values that are missing in our table:
736 */
737 switch (t) {
738
739 case 0: return ("UNINTIALIZED");
740 case TK_UPLUS: return ("unary +");
741 case TK_UMINUS: return ("unary -");
742 case TK_EOF: return ("EOF");
743 case TK_END: return ("ENDE DER LISTE");
744 case TK_NUM: return ("NUMBER");
745 case TK_VAR: return ("VARIABLE");
746 case TK_ERROR: return ("ERROR");
747 }
748
749 /*
750 * Now search the table:
751 */
752 for (i = 0; ops[i].val != TK_END; i++) {
753 if (ops[i].val == t)
754 return (ops[i].name);
755 }
756
757 /*
758 * Any other value:
759 */
760 return ("???");
761 }
762 #endif
763 #endif /* DO_DOL_PAREN */
764