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