1 /* Yash: yet another shell */
2 /* arith.c: arithmetic expansion */
3 /* (C) 2007-2019 magicant */
4 
5 /* This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 
19 #include "common.h"
20 #include "arith.h"
21 #include <assert.h>
22 #include <errno.h>
23 #include <float.h>
24 #include <limits.h>
25 #include <locale.h>
26 #include <math.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <wchar.h>
31 #include <sys/types.h>
32 #include <wctype.h>
33 #include "option.h"
34 #include "strbuf.h"
35 #include "util.h"
36 #include "variable.h"
37 
38 
39 typedef struct word_T {
40     const wchar_t *contents;
41     size_t length;
42 } word_T;
43 
44 typedef enum valuetype_T {
45     VT_INVALID, VT_LONG, VT_DOUBLE, VT_VAR,
46 } valuetype_T;
47 typedef struct value_T {
48     valuetype_T type;
49     union {
50 	long longvalue;
51 	double doublevalue;
52 	word_T varvalue;
53     } value;
54 } value_T;
55 #define v_long   value.longvalue
56 #define v_double value.doublevalue
57 #define v_var    value.varvalue
58 
59 typedef enum atokentype_T {
60     TT_NULL, TT_INVALID,
61     /* symbols */
62     TT_LPAREN, TT_RPAREN, TT_TILDE, TT_EXCL, TT_PERCENT,
63     TT_PLUS, TT_MINUS, TT_PLUSPLUS, TT_MINUSMINUS, TT_ASTER, TT_SLASH,
64     TT_LESS, TT_GREATER, TT_LESSLESS, TT_GREATERGREATER,
65     TT_LESSEQUAL, TT_GREATEREQUAL, TT_EQUALEQUAL, TT_EXCLEQUAL,
66     TT_AMP, TT_AMPAMP, TT_HAT, TT_PIPE, TT_PIPEPIPE, TT_QUESTION, TT_COLON,
67     TT_EQUAL, TT_PLUSEQUAL, TT_MINUSEQUAL, TT_ASTEREQUAL, TT_SLASHEQUAL,
68     TT_PERCENTEQUAL, TT_LESSLESSEQUAL, TT_GREATERGREATEREQUAL,
69     TT_AMPEQUAL, TT_HATEQUAL, TT_PIPEEQUAL,
70     /* numbers */
71     TT_NUMBER,
72     /* identifiers */
73     TT_IDENTIFIER,
74 } atokentype_T;
75 typedef struct atoken_T {
76     atokentype_T type;
77     word_T word;  /* valid only for numbers and identifiers */
78 } atoken_T;
79 
80 typedef struct evalinfo_T {
81     const wchar_t *exp;  /* expression to parse and calculate */
82     size_t index;        /* index of next token */
83     atoken_T atoken;     /* current token */
84     bool parseonly;      /* only parse the expression: don't calculate */
85     bool error;          /* true if there is an error */
86     char *savelocale;    /* original LC_NUMERIC locale */
87 } evalinfo_T;
88 
89 static void evaluate(
90 	const wchar_t *exp, value_T *result, evalinfo_T *info, bool coerce)
91     __attribute__((nonnull));
92 static void parse_assignment(evalinfo_T *info, value_T *result)
93     __attribute__((nonnull));
94 static bool do_assignment(const word_T *word, const value_T *value)
95     __attribute__((nonnull));
96 static wchar_t *value_to_string(const value_T *value)
97     __attribute__((nonnull,malloc,warn_unused_result));
98 static bool do_binary_calculation(
99 	evalinfo_T *info, atokentype_T ttype,
100 	value_T *lhs, value_T *rhs, value_T *result)
101     __attribute__((nonnull));
102 static long do_long_calculation1(atokentype_T ttype, long v1, long v2);
103 static long do_long_calculation2(atokentype_T ttype, long v1, long v2);
104 static double do_double_calculation(atokentype_T ttype, double v1, double v2);
105 static long do_double_comparison(atokentype_T ttype, double v1, double v2);
106 static void parse_conditional(evalinfo_T *info, value_T *result)
107     __attribute__((nonnull));
108 static void parse_logical_or(evalinfo_T *info, value_T *result)
109     __attribute__((nonnull));
110 static void parse_logical_and(evalinfo_T *info, value_T *result)
111     __attribute__((nonnull));
112 static void parse_inclusive_or(evalinfo_T *info, value_T *result)
113     __attribute__((nonnull));
114 static void parse_exclusive_or(evalinfo_T *info, value_T *result)
115     __attribute__((nonnull));
116 static void parse_and(evalinfo_T *info, value_T *result)
117     __attribute__((nonnull));
118 static void parse_equality(evalinfo_T *info, value_T *result)
119     __attribute__((nonnull));
120 static void parse_relational(evalinfo_T *info, value_T *result)
121     __attribute__((nonnull));
122 static void parse_shift(evalinfo_T *info, value_T *result)
123     __attribute__((nonnull));
124 static void parse_additive(evalinfo_T *info, value_T *result)
125     __attribute__((nonnull));
126 static void parse_multiplicative(evalinfo_T *info, value_T *result)
127     __attribute__((nonnull));
128 static void parse_prefix(evalinfo_T *info, value_T *result)
129     __attribute__((nonnull));
130 static void parse_postfix(evalinfo_T *info, value_T *result)
131     __attribute__((nonnull));
132 static void do_increment_or_decrement(atokentype_T ttype, value_T *value)
133     __attribute__((nonnull));
134 static void parse_primary(evalinfo_T *info, value_T *result)
135     __attribute__((nonnull));
136 static void parse_as_number(evalinfo_T *info, value_T *result)
137     __attribute__((nonnull));
138 static void coerce_number(evalinfo_T *info, value_T *value)
139     __attribute__((nonnull));
140 static void coerce_integer(evalinfo_T *info, value_T *value)
141     __attribute__((nonnull));
142 static valuetype_T coerce_type(evalinfo_T *info,
143 	value_T *value1, value_T *value2)
144     __attribute__((nonnull));
145 static void next_token(evalinfo_T *info)
146     __attribute__((nonnull));
147 static bool fail_if_will_divide_by_zero(
148 	atokentype_T op, const value_T *rhs, evalinfo_T *info, value_T *result)
149     __attribute__((nonnull));
150 
151 
152 /* Evaluates the specified string as an arithmetic expression.
153  * The argument string is freed in this function.
154  * The result is converted into a string and returned as a newly-malloced
155  * string. On error, an error message is printed to the standard error and NULL
156  * is returned. */
evaluate_arithmetic(wchar_t * exp)157 wchar_t *evaluate_arithmetic(wchar_t *exp)
158 {
159     value_T result;
160     evalinfo_T info;
161 
162     evaluate(exp, &result, &info, posixly_correct);
163 
164     wchar_t *resultstr;
165     if (info.error) {
166 	resultstr = NULL;
167     } else if (info.atoken.type == TT_NULL) {
168 	resultstr = value_to_string(&result);
169     } else {
170 	if (info.atoken.type != TT_INVALID)
171 	    xerror(0, Ngt("arithmetic: invalid syntax"));
172 	resultstr = NULL;
173     }
174     free(exp);
175     return resultstr;
176 }
177 
178 /* Evaluates the specified string as an arithmetic expression.
179  * The argument string is freed in this function.
180  * The expression must yield a valid integer value, which is assigned to
181  * `*valuep'. Otherwise, an error message is printed.
182  * Returns true iff successful. */
evaluate_index(wchar_t * exp,ssize_t * valuep)183 bool evaluate_index(wchar_t *exp, ssize_t *valuep)
184 {
185     value_T result;
186     evalinfo_T info;
187 
188     evaluate(exp, &result, &info, true);
189 
190     bool ok;
191     if (info.error) {
192 	ok = false;
193     } else if (info.atoken.type == TT_NULL) {
194 	if (result.type == VT_LONG) {
195 #if LONG_MAX > SSIZE_MAX
196 	    if (result.v_long > (long) SSIZE_MAX)
197 		*valuep = SSIZE_MAX;
198 	    else
199 #endif
200 #if LONG_MIN < -SSIZE_MAX
201 	    if (result.v_long < (long) -SSIZE_MAX)
202 		*valuep = -SSIZE_MAX;
203 	    else
204 #endif
205 		*valuep = (ssize_t) result.v_long;
206 	    ok = true;
207 	} else {
208 	    xerror(0, Ngt("the index is not an integer"));
209 	    ok = false;
210 	}
211     } else {
212 	if (info.atoken.type != TT_INVALID)
213 	    xerror(0, Ngt("arithmetic: invalid syntax"));
214 	ok = false;
215     }
216     free(exp);
217     return ok;
218 }
219 
evaluate(const wchar_t * exp,value_T * result,evalinfo_T * info,bool coerce)220 void evaluate(
221 	const wchar_t *exp, value_T *result, evalinfo_T *info, bool coerce)
222 {
223     info->exp = exp;
224     info->index = 0;
225     info->parseonly = false;
226     info->error = false;
227     info->savelocale = xstrdup(setlocale(LC_NUMERIC, NULL));
228 
229     next_token(info);
230     parse_assignment(info, result);
231     if (coerce)
232 	coerce_number(info, result);
233 
234     free(info->savelocale);
235 }
236 
237 /* Parses an assignment expression.
238  *   AssignmentExp := ConditionalExp
239  *                  | ConditionalExp AssignmentOperator AssignmentExp */
parse_assignment(evalinfo_T * info,value_T * result)240 void parse_assignment(evalinfo_T *info, value_T *result)
241 {
242     parse_conditional(info, result);
243 
244     atokentype_T ttype = info->atoken.type;
245     switch (ttype) {
246 	case TT_EQUAL:          case TT_PLUSEQUAL:   case TT_MINUSEQUAL:
247 	case TT_ASTEREQUAL:     case TT_SLASHEQUAL:  case TT_PERCENTEQUAL:
248 	case TT_LESSLESSEQUAL:  case TT_GREATERGREATEREQUAL:
249 	case TT_AMPEQUAL:       case TT_HATEQUAL:    case TT_PIPEEQUAL:
250 	    {
251 		value_T rhs;
252 		next_token(info);
253 		parse_assignment(info, &rhs);
254 		if (result->type == VT_VAR) {
255 		    word_T saveword = result->v_var;
256 		    if (!do_binary_calculation(
257 				info, ttype, result, &rhs, result))
258 			break;
259 		    if (!do_assignment(&saveword, result))
260 			info->error = true, result->type = VT_INVALID;
261 		} else if (result->type != VT_INVALID) {
262 		    /* TRANSLATORS: This error message is shown when the target
263 		     * of an assignment is not a variable. */
264 		    xerror(0, Ngt("arithmetic: cannot assign to a number"));
265 		    info->error = true;
266 		    result->type = VT_INVALID;
267 		}
268 		break;
269 	    }
270 	default:
271 	    break;
272     }
273 }
274 
275 /* Assigns the specified `value' to the variable specified by `word'.
276  * Returns false on error. */
do_assignment(const word_T * word,const value_T * value)277 bool do_assignment(const word_T *word, const value_T *value)
278 {
279     wchar_t *vstr = value_to_string(value);
280     if (vstr == NULL)
281 	return false;
282 
283     wchar_t name[word->length + 1];
284     wmemcpy(name, word->contents, word->length);
285     name[word->length] = L'\0';
286     return set_variable(name, vstr, SCOPE_GLOBAL, false);
287 }
288 
289 /* Converts `value' to a newly-malloced wide string.
290  * Returns NULL on error. */
value_to_string(const value_T * value)291 wchar_t *value_to_string(const value_T *value)
292 {
293     switch (value->type) {
294 	case VT_INVALID:
295 	    return NULL;
296 	case VT_LONG:
297 	    return malloc_wprintf(L"%ld", value->v_long);
298 	case VT_DOUBLE:
299 	    return malloc_wprintf(L"%.*g", DBL_DIG, value->v_double);
300 	case VT_VAR:
301 	    {
302 		wchar_t name[value->v_var.length + 1];
303 		wmemcpy(name, value->v_var.contents, value->v_var.length);
304 		name[value->v_var.length] = L'\0';
305 		const wchar_t *var = getvar(name);
306 		if (var != NULL)
307 		    return xwcsdup(var);
308 		if (shopt_unset)
309 		    return malloc_wprintf(L"%ld", 0L);
310 		xerror(0, Ngt("arithmetic: parameter `%ls' is not set"), name);
311 		return NULL;
312 	    }
313     }
314     assert(false);
315 }
316 
317 /* Applies the binary operation defined by token `ttype' to operands `lhs' and
318  * `rhs'. The operands may be modified as a result of coercion. The result is
319  * assigned to `*result' unless there is an error.
320  * Returns true iff successful. */
do_binary_calculation(evalinfo_T * info,atokentype_T ttype,value_T * lhs,value_T * rhs,value_T * result)321 bool do_binary_calculation(
322 	evalinfo_T *info, atokentype_T ttype,
323 	value_T *lhs, value_T *rhs, value_T *result)
324 {
325     switch (ttype) {
326 	case TT_ASTER:  case TT_ASTEREQUAL:
327 	case TT_SLASH:  case TT_SLASHEQUAL:
328 	case TT_PERCENT:  case TT_PERCENTEQUAL:
329 	case TT_PLUS:  case TT_PLUSEQUAL:
330 	case TT_MINUS:  case TT_MINUSEQUAL:
331 	    result->type = coerce_type(info, lhs, rhs);
332 	    if (fail_if_will_divide_by_zero(ttype, rhs, info, result))
333 		return false;
334 	    switch (result->type) {
335 		case VT_LONG:
336 		    result->v_long = do_long_calculation1(
337 			    ttype, lhs->v_long, rhs->v_long);
338 		    break;
339 		case VT_DOUBLE:
340 		    result->v_double = do_double_calculation(
341 			    ttype, lhs->v_double, rhs->v_double);
342 		    break;
343 		case VT_VAR:
344 		    assert(false);
345 		case VT_INVALID:
346 		    break;
347 	    }
348 	    break;
349 	case TT_LESSLESS:  case TT_LESSLESSEQUAL:
350 	case TT_GREATERGREATER:  case TT_GREATERGREATEREQUAL:
351 	case TT_AMP:  case TT_AMPEQUAL:
352 	case TT_HAT:  case TT_HATEQUAL:
353 	case TT_PIPE:  case TT_PIPEEQUAL:
354 	    coerce_integer(info, lhs);
355 	    coerce_integer(info, rhs);
356 	    if (lhs->type == VT_LONG && rhs->type == VT_LONG) {
357 		result->type = VT_LONG;
358 		result->v_long =
359 		    do_long_calculation2(ttype, lhs->v_long, rhs->v_long);
360 	    } else {
361 		result->type = VT_INVALID;
362 	    }
363 	    break;
364 	case TT_EQUAL:
365 	    *result = *rhs;
366 	    break;
367 	default:
368 	    assert(false);
369     }
370     return true;
371 }
372 
373 /* Does unary or binary long calculation according to the specified operator
374  * token. Division by zero is not allowed. */
do_long_calculation1(atokentype_T ttype,long v1,long v2)375 long do_long_calculation1(atokentype_T ttype, long v1, long v2)
376 {
377     switch (ttype) {
378 	case TT_PLUS:  case TT_PLUSEQUAL:
379 	    return v1 + v2;
380 	case TT_MINUS:  case TT_MINUSEQUAL:
381 	    return v1 - v2;
382 	case TT_ASTER:  case TT_ASTEREQUAL:
383 	    return v1 * v2;
384 	case TT_SLASH:  case TT_SLASHEQUAL:
385 	    return v1 / v2;
386 	case TT_PERCENT:  case TT_PERCENTEQUAL:
387 	    return v1 % v2;
388 	default:
389 	    assert(false);
390     }
391 }
392 
393 /* Does unary or binary long calculation according to the specified operator
394  * token. */
do_long_calculation2(atokentype_T ttype,long v1,long v2)395 long do_long_calculation2(atokentype_T ttype, long v1, long v2)
396 {
397     switch (ttype) {
398 	case TT_LESSLESS:  case TT_LESSLESSEQUAL:
399 	    return v1 << v2;
400 	case TT_GREATERGREATER:  case TT_GREATERGREATEREQUAL:
401 	    return v1 >> v2;
402 	case TT_LESS:
403 	    return v1 < v2;
404 	case TT_LESSEQUAL:
405 	    return v1 <= v2;
406 	case TT_GREATER:
407 	    return v1 > v2;
408 	case TT_GREATEREQUAL:
409 	    return v1 >= v2;
410 	case TT_EQUALEQUAL:
411 	    return v1 == v2;
412 	case TT_EXCLEQUAL:
413 	    return v1 != v2;
414 	case TT_AMP:  case TT_AMPEQUAL:
415 	    return v1 & v2;
416 	case TT_HAT:  case TT_HATEQUAL:
417 	    return v1 ^ v2;
418 	case TT_PIPE:  case TT_PIPEEQUAL:
419 	    return v1 | v2;
420 	default:
421 	    assert(false);
422     }
423 }
424 
425 /* Does unary or binary double calculation according to the specified operator
426  * token. */
do_double_calculation(atokentype_T ttype,double v1,double v2)427 double do_double_calculation(atokentype_T ttype, double v1, double v2)
428 {
429     switch (ttype) {
430 	case TT_PLUS:  case TT_PLUSEQUAL:
431 	    return v1 + v2;
432 	case TT_MINUS:  case TT_MINUSEQUAL:
433 	    return v1 - v2;
434 	case TT_ASTER:  case TT_ASTEREQUAL:
435 	    return v1 * v2;
436 	case TT_SLASH:  case TT_SLASHEQUAL:
437 	    return v1 / v2;
438 	case TT_PERCENT:  case TT_PERCENTEQUAL:
439 	    return fmod(v1, v2);
440 	default:
441 	    assert(false);
442     }
443 }
444 
445 /* Does double comparison according to the specified operator token. */
do_double_comparison(atokentype_T ttype,double v1,double v2)446 long do_double_comparison(atokentype_T ttype, double v1, double v2)
447 {
448     switch (ttype) {
449 	case TT_LESS:
450 	    return v1 < v2;
451 	case TT_LESSEQUAL:
452 	    return v1 <= v2;
453 	case TT_GREATER:
454 	    return v1 > v2;
455 	case TT_GREATEREQUAL:
456 	    return v1 >= v2;
457 	case TT_EQUALEQUAL:
458 	    return v1 == v2;
459 	case TT_EXCLEQUAL:
460 	    return v1 != v2;
461 	default:
462 	    assert(false);
463     }
464 }
465 
466 /* Parses a conditional expression.
467  *   ConditionalExp := LogicalOrExp
468  *                   | LogicalOrExp "?" AssignmentExp ":" ConditionalExp */
parse_conditional(evalinfo_T * info,value_T * result)469 void parse_conditional(evalinfo_T *info, value_T *result)
470 {
471     bool saveparseonly = info->parseonly;
472 
473     for (;;) {
474 	value_T dummy;
475 	value_T *result2;
476 
477 	result2 = info->parseonly ? &dummy : result;
478 	parse_logical_or(info, result2);
479 	if (info->atoken.type != TT_QUESTION)
480 	    break;
481 
482 	bool cond, valid = true;
483 
484 	coerce_number(info, result2);
485 	next_token(info);
486 	switch (result2->type) {
487 	    case VT_INVALID:  valid = false, cond = true;   break;
488 	    case VT_LONG:     cond = result2->v_long;       break;
489 	    case VT_DOUBLE:   cond = result2->v_double;     break;
490 	    default:          assert(false);
491 	}
492 
493 	bool saveparseonly2 = info->parseonly || !valid;
494 	info->parseonly = saveparseonly2 || !cond;
495 
496 	result2 = info->parseonly ? &dummy : result;
497 	parse_assignment(info, result2);
498 	if (info->atoken.type != TT_COLON) {
499 	    xerror(0, Ngt("arithmetic: `%ls' is missing"), L":");
500 	    info->error = true;
501 	    result->type = VT_INVALID;
502 	    break;
503 	}
504 
505 	next_token(info);
506 	info->parseonly = saveparseonly2 || cond;
507     }
508 
509     info->parseonly = saveparseonly;
510     if (info->parseonly)
511 	result->type = VT_INVALID;
512 }
513 
514 /* Parses a logical OR expression.
515  *   LogicalOrExp := LogicalAndExp | LogicalOrExp "||" LogicalAndExp */
parse_logical_or(evalinfo_T * info,value_T * result)516 void parse_logical_or(evalinfo_T *info, value_T *result)
517 {
518     bool saveparseonly = info->parseonly;
519 
520     parse_logical_and(info, result);
521     while (info->atoken.type == TT_PIPEPIPE) {
522 	bool value, valid = true;
523 
524 	coerce_number(info, result);
525 	next_token(info);
526 	switch (result->type) {
527 	    case VT_INVALID: valid = false, value = true;  break;
528 	    case VT_LONG:    value = result->v_long;       break;
529 	    case VT_DOUBLE:  value = result->v_double;     break;
530 	    default:         assert(false);
531 	}
532 
533 	info->parseonly |= value;
534 	parse_logical_and(info, result);
535 	coerce_number(info, result);
536 	if (!value) switch (result->type) {
537 	    case VT_INVALID: valid = false;             break;
538 	    case VT_LONG:    value = result->v_long;    break;
539 	    case VT_DOUBLE:  value = result->v_double;  break;
540 	    default:         assert(false);
541 	}
542 	if (valid)
543 	    result->type = VT_LONG, result->v_long = value;
544 	else
545 	    result->type = VT_INVALID;
546     }
547     info->parseonly = saveparseonly;
548 }
549 
550 /* Parses a logical AND expression.
551  *   LogicalAndExp := InclusiveOrExp | LogicalAndExp "&&" InclusiveOrExp */
parse_logical_and(evalinfo_T * info,value_T * result)552 void parse_logical_and(evalinfo_T *info, value_T *result)
553 {
554     bool saveparseonly = info->parseonly;
555 
556     parse_inclusive_or(info, result);
557     while (info->atoken.type == TT_AMPAMP) {
558 	bool value, valid = true;
559 
560 	coerce_number(info, result);
561 	next_token(info);
562 	switch (result->type) {
563 	    case VT_INVALID: valid = false, value = false;  break;
564 	    case VT_LONG:    value = result->v_long;        break;
565 	    case VT_DOUBLE:  value = result->v_double;      break;
566 	    default:         assert(false);
567 	}
568 
569 	info->parseonly |= !value;
570 	parse_inclusive_or(info, result);
571 	coerce_number(info, result);
572 	if (value) switch (result->type) {
573 	    case VT_INVALID: valid = false;             break;
574 	    case VT_LONG:    value = result->v_long;    break;
575 	    case VT_DOUBLE:  value = result->v_double;  break;
576 	    default:         assert(false);
577 	}
578 	if (valid)
579 	    result->type = VT_LONG, result->v_long = value;
580 	else
581 	    result->type = VT_INVALID;
582     }
583     info->parseonly = saveparseonly;
584 }
585 
586 /* Parses an inclusive OR expression.
587  *   InclusiveOrExp := ExclusiveOrExp | InclusiveOrExp "|" ExclusiveOrExp */
parse_inclusive_or(evalinfo_T * info,value_T * result)588 void parse_inclusive_or(evalinfo_T *info, value_T *result)
589 {
590     parse_exclusive_or(info, result);
591     for (;;) {
592 	atokentype_T ttype = info->atoken.type;
593 	value_T rhs;
594 	switch (ttype) {
595 	    case TT_PIPE:
596 		next_token(info);
597 		parse_exclusive_or(info, &rhs);
598 		do_binary_calculation(info, TT_PIPE, result, &rhs, result);
599 		break;
600 	    default:
601 		return;
602 	}
603     }
604 }
605 
606 /* Parses an exclusive OR expression.
607  *   ExclusiveOrExp := AndExp | ExclusiveOrExp "^" AndExp */
parse_exclusive_or(evalinfo_T * info,value_T * result)608 void parse_exclusive_or(evalinfo_T *info, value_T *result)
609 {
610     parse_and(info, result);
611     for (;;) {
612 	atokentype_T ttype = info->atoken.type;
613 	value_T rhs;
614 	switch (ttype) {
615 	    case TT_HAT:
616 		next_token(info);
617 		parse_and(info, &rhs);
618 		do_binary_calculation(info, TT_HAT, result, &rhs, result);
619 		break;
620 	    default:
621 		return;
622 	}
623     }
624 }
625 
626 /* Parses an AND expression.
627  *   AndExp := EqualityExp | AndExp "&" EqualityExp */
parse_and(evalinfo_T * info,value_T * result)628 void parse_and(evalinfo_T *info, value_T *result)
629 {
630     parse_equality(info, result);
631     for (;;) {
632 	atokentype_T ttype = info->atoken.type;
633 	value_T rhs;
634 	switch (ttype) {
635 	    case TT_AMP:
636 		next_token(info);
637 		parse_equality(info, &rhs);
638 		do_binary_calculation(info, TT_AMP, result, &rhs, result);
639 		break;
640 	    default:
641 		return;
642 	}
643     }
644 }
645 
646 /* Parses an equality expression.
647  *   EqualityExp := RelationalExp
648  *                | EqualityExp "==" RelationalExp
649  *                | EqualityExp "!=" RelationalExp */
parse_equality(evalinfo_T * info,value_T * result)650 void parse_equality(evalinfo_T *info, value_T *result)
651 {
652     parse_relational(info, result);
653     for (;;) {
654 	atokentype_T ttype = info->atoken.type;
655 	value_T rhs;
656 	switch (ttype) {
657 	    case TT_EQUALEQUAL:
658 	    case TT_EXCLEQUAL:
659 		next_token(info);
660 		parse_relational(info, &rhs);
661 		switch (coerce_type(info, result, &rhs)) {
662 		    case VT_LONG:
663 			result->v_long = do_long_calculation2(ttype,
664 				result->v_long, rhs.v_long);
665 			break;
666 		    case VT_DOUBLE:
667 			result->v_long = do_double_comparison(ttype,
668 				result->v_double, rhs.v_double);
669 			result->type = VT_LONG;
670 			break;
671 		    case VT_INVALID:
672 			result->type = VT_INVALID;
673 			break;
674 		    case VT_VAR:
675 			assert(false);
676 		}
677 		break;
678 	    default:
679 		return;
680 	}
681     }
682 }
683 
684 /* Parses a relational expression.
685  *   RelationalExp := ShiftExp
686  *                  | RelationalExp "<" ShiftExp
687  *                  | RelationalExp ">" ShiftExp
688  *                  | RelationalExp "<=" ShiftExp
689  *                  | RelationalExp ">=" ShiftExp */
parse_relational(evalinfo_T * info,value_T * result)690 void parse_relational(evalinfo_T *info, value_T *result)
691 {
692     parse_shift(info, result);
693     for (;;) {
694 	atokentype_T ttype = info->atoken.type;
695 	value_T rhs;
696 	switch (ttype) {
697 	    case TT_LESS:
698 	    case TT_LESSEQUAL:
699 	    case TT_GREATER:
700 	    case TT_GREATEREQUAL:
701 		next_token(info);
702 		parse_shift(info, &rhs);
703 		switch (coerce_type(info, result, &rhs)) {
704 		    case VT_LONG:
705 			result->v_long = do_long_calculation2(ttype,
706 				result->v_long, rhs.v_long);
707 			break;
708 		    case VT_DOUBLE:
709 			result->v_long = do_double_comparison(ttype,
710 				result->v_double, rhs.v_double);
711 			result->type = VT_LONG;
712 			break;
713 		    case VT_INVALID:
714 			result->type = VT_INVALID;
715 			break;
716 		    case VT_VAR:
717 			assert(false);
718 		}
719 		break;
720 	    default:
721 		return;
722 	}
723     }
724 }
725 
726 /* Parses a shift expression.
727  *   ShiftExp := AdditiveExp
728  *             | ShiftExp "<<" AdditiveExp | ShiftExp ">>" AdditiveExp */
parse_shift(evalinfo_T * info,value_T * result)729 void parse_shift(evalinfo_T *info, value_T *result)
730 {
731     parse_additive(info, result);
732     for (;;) {
733 	atokentype_T ttype = info->atoken.type;
734 	value_T rhs;
735 	switch (ttype) {
736 	    case TT_LESSLESS:
737 	    case TT_GREATERGREATER:
738 		next_token(info);
739 		parse_additive(info, &rhs);
740 		do_binary_calculation(info, ttype, result, &rhs, result);
741 		break;
742 	    default:
743 		return;
744 	}
745     }
746 }
747 
748 /* Parses an additive expression.
749  *   AdditiveExp := MultiplicativeExp
750  *                | AdditiveExp "+" MultiplicativeExp
751  *                | AdditiveExp "-" MultiplicativeExp */
parse_additive(evalinfo_T * info,value_T * result)752 void parse_additive(evalinfo_T *info, value_T *result)
753 {
754     parse_multiplicative(info, result);
755     for (;;) {
756 	atokentype_T ttype = info->atoken.type;
757 	value_T rhs;
758 	switch (ttype) {
759 	    case TT_PLUS:
760 	    case TT_MINUS:
761 		next_token(info);
762 		parse_multiplicative(info, &rhs);
763 		do_binary_calculation(info, ttype, result, &rhs, result);
764 		break;
765 	    default:
766 		return;
767 	}
768     }
769 }
770 
771 /* Parses a multiplicative expression.
772  *   MultiplicativeExp := PrefixExp
773  *                      | MultiplicativeExp "*" PrefixExp
774  *                      | MultiplicativeExp "/" PrefixExp
775  *                      | MultiplicativeExp "%" PrefixExp */
parse_multiplicative(evalinfo_T * info,value_T * result)776 void parse_multiplicative(evalinfo_T *info, value_T *result)
777 {
778     parse_prefix(info, result);
779     for (;;) {
780 	atokentype_T ttype = info->atoken.type;
781 	value_T rhs;
782 	switch (ttype) {
783 	    case TT_ASTER:
784 	    case TT_SLASH:
785 	    case TT_PERCENT:
786 		next_token(info);
787 		parse_prefix(info, &rhs);
788 		do_binary_calculation(info, ttype, result, &rhs, result);
789 		break;
790 	    default:
791 		return;
792 	}
793     }
794 }
795 
796 /* Parses a prefix expression.
797  *   PrefixExp := PostfixExp
798  *              | "++" PrefixExp | "--" PrefixExp
799  *              | "+" PrefixExp | "-" PrefixExp
800  *              | "~" PrefixExp | "!" PrefixExp */
parse_prefix(evalinfo_T * info,value_T * result)801 void parse_prefix(evalinfo_T *info, value_T *result)
802 {
803     atokentype_T ttype = info->atoken.type;
804     switch (ttype) {
805 	case TT_PLUSPLUS:
806 	case TT_MINUSMINUS:
807 	    next_token(info);
808 	    parse_prefix(info, result);
809 	    if (posixly_correct) {
810 		xerror(0, Ngt("arithmetic: operator `%ls' is not supported"),
811 			(ttype == TT_PLUSPLUS) ? L"++" : L"--");
812 		info->error = true;
813 		result->type = VT_INVALID;
814 	    } else if (result->type == VT_VAR) {
815 		word_T saveword = result->v_var;
816 		coerce_number(info, result);
817 		do_increment_or_decrement(ttype, result);
818 		if (!do_assignment(&saveword, result))
819 		    info->error = true, result->type = VT_INVALID;
820 	    } else if (result->type != VT_INVALID) {
821 		/* TRANSLATORS: This error message is shown when the operand of
822 		 * the "++" or "--" operator is not a variable. */
823 		xerror(0, Ngt("arithmetic: operator `%ls' requires a variable"),
824 			(info->atoken.type == TT_PLUSPLUS) ? L"++" : L"--");
825 		info->error = true;
826 		result->type = VT_INVALID;
827 	    }
828 	    break;
829 	case TT_PLUS:
830 	case TT_MINUS:
831 	    next_token(info);
832 	    parse_prefix(info, result);
833 	    coerce_number(info, result);
834 	    if (ttype == TT_MINUS) {
835 		switch (result->type) {
836 		case VT_LONG:     result->v_long = -result->v_long;      break;
837 		case VT_DOUBLE:   result->v_double = -result->v_double;  break;
838 		case VT_INVALID:  break;
839 		default:          assert(false);
840 		}
841 	    }
842 	    break;
843 	case TT_TILDE:
844 	    next_token(info);
845 	    parse_prefix(info, result);
846 	    coerce_integer(info, result);
847 	    if (result->type == VT_LONG)
848 		result->v_long = ~result->v_long;
849 	    break;
850 	case TT_EXCL:
851 	    next_token(info);
852 	    parse_prefix(info, result);
853 	    coerce_number(info, result);
854 	    switch (result->type) {
855 		case VT_LONG:
856 		    result->v_long = !result->v_long;
857 		    break;
858 		case VT_DOUBLE:
859 		    result->type = VT_LONG;
860 		    result->v_long = !result->v_double;
861 		    break;
862 		case VT_INVALID:
863 		    break;
864 		default:
865 		    assert(false);
866 	    }
867 	    break;
868 	default:
869 	    parse_postfix(info, result);
870 	    break;
871     }
872 }
873 
874 /* Parses a postfix expression.
875  *   PostfixExp := PrimaryExp
876  *               | PostfixExp "++" | PostfixExp "--" */
parse_postfix(evalinfo_T * info,value_T * result)877 void parse_postfix(evalinfo_T *info, value_T *result)
878 {
879     parse_primary(info, result);
880     for (;;) {
881 	switch (info->atoken.type) {
882 	    case TT_PLUSPLUS:
883 	    case TT_MINUSMINUS:
884 		if (posixly_correct) {
885 		    xerror(0,
886 			    Ngt("arithmetic: operator `%ls' is not supported"),
887 			    (info->atoken.type == TT_PLUSPLUS) ? L"++" : L"--");
888 		    info->error = true;
889 		    result->type = VT_INVALID;
890 		} else if (result->type == VT_VAR) {
891 		    word_T saveword = result->v_var;
892 		    coerce_number(info, result);
893 		    value_T value = *result;
894 		    do_increment_or_decrement(info->atoken.type, &value);
895 		    if (!do_assignment(&saveword, &value)) {
896 			info->error = true;
897 			result->type = VT_INVALID;
898 		    }
899 		} else if (result->type != VT_INVALID) {
900 		    xerror(0, Ngt("arithmetic: "
901 				"operator `%ls' requires a variable"),
902 			    (info->atoken.type == TT_PLUSPLUS) ? L"++" : L"--");
903 		    info->error = true;
904 		    result->type = VT_INVALID;
905 		}
906 		next_token(info);
907 		break;
908 	    default:
909 		return;
910 	}
911     }
912 }
913 
914 /* Increment or decrement the specified value.
915  * `ttype' must be either TT_PLUSPLUS or TT_MINUSMINUS and the `value' must be
916  * `coerce_number'ed. */
do_increment_or_decrement(atokentype_T ttype,value_T * value)917 void do_increment_or_decrement(atokentype_T ttype, value_T *value)
918 {
919     if (ttype == TT_PLUSPLUS) {
920 	switch (value->type) {
921 	    case VT_LONG:    value->v_long++;    break;
922 	    case VT_DOUBLE:  value->v_double++;  break;
923 	    case VT_INVALID: break;
924 	    default:         assert(false);
925 	}
926     } else {
927 	switch (value->type) {
928 	    case VT_LONG:    value->v_long--;    break;
929 	    case VT_DOUBLE:  value->v_double--;  break;
930 	    case VT_INVALID: break;
931 	    default:         assert(false);
932 	}
933     }
934 }
935 
936 /* Parses a primary expression.
937  *   PrimaryExp := "(" AssignmentExp ")" | Number | Identifier */
parse_primary(evalinfo_T * info,value_T * result)938 void parse_primary(evalinfo_T *info, value_T *result)
939 {
940     switch (info->atoken.type) {
941 	case TT_LPAREN:
942 	    next_token(info);
943 	    parse_assignment(info, result);
944 	    if (info->atoken.type == TT_RPAREN) {
945 		next_token(info);
946 	    } else {
947 		xerror(0, Ngt("arithmetic: `%ls' is missing"), L")");
948 		info->error = true;
949 		result->type = VT_INVALID;
950 	    }
951 	    break;
952 	case TT_NUMBER:
953 	    parse_as_number(info, result);
954 	    next_token(info);
955 	    break;
956 	case TT_IDENTIFIER:
957 	    result->type = VT_VAR;
958 	    result->v_var = info->atoken.word;
959 	    next_token(info);
960 	    break;
961 	default:
962 	    xerror(0, Ngt("arithmetic: a value is missing"));
963 	    info->error = true;
964 	    result->type = VT_INVALID;
965 	    break;
966     }
967     if (info->parseonly)
968 	result->type = VT_INVALID;
969 }
970 
971 /* Parses the current word as a number literal. */
parse_as_number(evalinfo_T * info,value_T * result)972 void parse_as_number(evalinfo_T *info, value_T *result)
973 {
974     word_T *word = &info->atoken.word;
975     wchar_t wordstr[word->length + 1];
976     wcsncpy(wordstr, word->contents, word->length);
977     wordstr[word->length] = L'\0';
978 
979     long longresult;
980     if (xwcstol(wordstr, 0, &longresult)) {
981 	result->type = VT_LONG;
982 	result->v_long = longresult;
983 	return;
984     }
985     if (!posixly_correct) {
986 	double doubleresult;
987 	wchar_t *end;
988 	setlocale(LC_NUMERIC, "C");
989 	errno = 0;
990 	doubleresult = wcstod(wordstr, &end);
991 	bool ok = (errno == 0 && *end == L'\0');
992 	setlocale(LC_NUMERIC, info->savelocale);
993 	if (ok) {
994 	    result->type = VT_DOUBLE;
995 	    result->v_double = doubleresult;
996 	    return;
997 	}
998     }
999     xerror(0, Ngt("arithmetic: `%ls' is not a valid number"), wordstr);
1000     info->error = true;
1001     result->type = VT_INVALID;
1002 }
1003 
1004 /* If the value is of the VT_VAR type, change it into VT_LONG/VT_DOUBLE.
1005  * If the variable specified by the value is unset, it is assumed 0.
1006  * On parse error, false is returned and the value is unspecified. */
coerce_number(evalinfo_T * info,value_T * value)1007 void coerce_number(evalinfo_T *info, value_T *value)
1008 {
1009     if (value->type != VT_VAR)
1010 	return;
1011 
1012     const wchar_t *varvalue;
1013     {
1014 	word_T *name = &value->v_var;
1015 	wchar_t namestr[name->length + 1];
1016 	wmemcpy(namestr, name->contents, name->length);
1017 	namestr[name->length] = L'\0';
1018 	varvalue = getvar(namestr);
1019 
1020 	if (varvalue == NULL && !shopt_unset) {
1021 	    xerror(0, Ngt("arithmetic: parameter `%ls' is not set"), namestr);
1022 	    info->error = true;
1023 	    value->type = VT_INVALID;
1024 	    return;
1025 	}
1026     }
1027     if (varvalue == NULL || varvalue[0] == L'\0') {
1028 	value->type = VT_LONG;
1029 	value->v_long = 0;
1030 	return;
1031     }
1032 
1033     long longresult;
1034     if (xwcstol(varvalue, 0, &longresult)) {
1035 	value->type = VT_LONG;
1036 	value->v_long = longresult;
1037 	return;
1038     }
1039     if (!posixly_correct) {
1040 	double doubleresult;
1041 	wchar_t *end;
1042 	errno = 0;
1043 	doubleresult = wcstod(varvalue, &end);
1044 	if (errno == 0 && *end == L'\0') {
1045 	    value->type = VT_DOUBLE;
1046 	    value->v_double = doubleresult;
1047 	    return;
1048 	}
1049     }
1050     xerror(0, Ngt("arithmetic: `%ls' is not a valid number"), varvalue);
1051     info->error = true;
1052     value->type = VT_INVALID;
1053     return;
1054 }
1055 
1056 /* Does `coerce_number' and if the result is of VT_DOUBLE, converts into
1057  * VT_LONG. */
coerce_integer(evalinfo_T * info,value_T * value)1058 void coerce_integer(evalinfo_T *info, value_T *value)
1059 {
1060     coerce_number(info, value);
1061     if (value->type == VT_DOUBLE) {
1062 	value->type = VT_LONG;
1063 	value->v_long = (long) value->v_double;
1064     }
1065 }
1066 
1067 /* Unifies the types of the numeric values.
1068  * First, the given values are `coerce_number'ed.
1069  * Then, if one of the values is of VT_LONG and the other is of VT_DOUBLE, the
1070  * VT_LONG value is converted into VT_DOUBLE.
1071  * If the both values are of VT_LONG, VT_LONG is returned without conversion.
1072  * If either value is of VT_DOUBLE and the other is not VT_INVALID, VT_DOUBLE
1073  * is returned after conversion. If either value is VT_INVALID, the return
1074  * value is VT_INVALID. This function never returns VT_VAR. */
coerce_type(evalinfo_T * info,value_T * value1,value_T * value2)1075 valuetype_T coerce_type(evalinfo_T *info, value_T *value1, value_T *value2)
1076 {
1077     coerce_number(info, value1);
1078     coerce_number(info, value2);
1079     if (value1->type == value2->type)
1080 	return value1->type;
1081     if (value1->type == VT_INVALID || value2->type == VT_INVALID)
1082 	return VT_INVALID;
1083     assert(value1->type == VT_LONG || value1->type == VT_DOUBLE);
1084     assert(value2->type == VT_LONG || value2->type == VT_DOUBLE);
1085 
1086     value_T *value_to_coerce = (value1->type == VT_LONG) ? value1 : value2;
1087     value_to_coerce->type = VT_DOUBLE;
1088     value_to_coerce->v_double = (double) value_to_coerce->v_long;
1089     return VT_DOUBLE;
1090 }
1091 
1092 /* Moves to the next token.
1093  * The contents of `*info' is updated.
1094  * If there is no more token, `info->index' indicates the terminating null char
1095  * and a TT_NULL token is returned. On error, TT_INVALID is returned. */
next_token(evalinfo_T * info)1096 void next_token(evalinfo_T *info)
1097 {
1098     /* skip spaces */
1099     while (iswspace(info->exp[info->index]))
1100 	info->index++;
1101 
1102     wchar_t c = info->exp[info->index];
1103     switch (c) {
1104 	case L'\0':
1105 	    info->atoken.type = TT_NULL;
1106 	    return;
1107 	case L'(':
1108 	    info->atoken.type = TT_LPAREN;
1109 	    info->index++;
1110 	    break;
1111 	case L')':
1112 	    info->atoken.type = TT_RPAREN;
1113 	    info->index++;
1114 	    break;
1115 	case L'~':
1116 	    info->atoken.type = TT_TILDE;
1117 	    info->index++;
1118 	    break;
1119 	case L'!':
1120 	    switch (info->exp[info->index + 1]) {
1121 		case L'=':
1122 		    info->atoken.type = TT_EXCLEQUAL;
1123 		    info->index += 2;
1124 		    break;
1125 		default:
1126 		    info->atoken.type = TT_EXCL;
1127 		    info->index += 1;
1128 		    break;
1129 	    }
1130 	    break;
1131 	case L'%':
1132 	    switch (info->exp[info->index + 1]) {
1133 		case L'=':
1134 		    info->atoken.type = TT_PERCENTEQUAL;
1135 		    info->index += 2;
1136 		    break;
1137 		default:
1138 		    info->atoken.type = TT_PERCENT;
1139 		    info->index += 1;
1140 		    break;
1141 	    }
1142 	    break;
1143 	case L'+':
1144 	    switch (info->exp[info->index + 1]) {
1145 		case L'+':
1146 		    info->atoken.type = TT_PLUSPLUS;
1147 		    info->index += 2;
1148 		    break;
1149 		case L'=':
1150 		    info->atoken.type = TT_PLUSEQUAL;
1151 		    info->index += 2;
1152 		    break;
1153 		default:
1154 		    info->atoken.type = TT_PLUS;
1155 		    info->index += 1;
1156 		    break;
1157 	    }
1158 	    break;
1159 	case L'-':
1160 	    switch (info->exp[info->index + 1]) {
1161 		case L'-':
1162 		    info->atoken.type = TT_MINUSMINUS;
1163 		    info->index += 2;
1164 		    break;
1165 		case L'=':
1166 		    info->atoken.type = TT_MINUSEQUAL;
1167 		    info->index += 2;
1168 		    break;
1169 		default:
1170 		    info->atoken.type = TT_MINUS;
1171 		    info->index += 1;
1172 		    break;
1173 	    }
1174 	    break;
1175 	case L'*':
1176 	    switch (info->exp[info->index + 1]) {
1177 		case L'=':
1178 		    info->atoken.type = TT_ASTEREQUAL;
1179 		    info->index += 2;
1180 		    break;
1181 		default:
1182 		    info->atoken.type = TT_ASTER;
1183 		    info->index += 1;
1184 		    break;
1185 	    }
1186 	    break;
1187 	case L'/':
1188 	    switch (info->exp[info->index + 1]) {
1189 		case L'=':
1190 		    info->atoken.type = TT_SLASHEQUAL;
1191 		    info->index += 2;
1192 		    break;
1193 		default:
1194 		    info->atoken.type = TT_SLASH;
1195 		    info->index += 1;
1196 		    break;
1197 	    }
1198 	    break;
1199 	case L'<':
1200 	    {
1201 		info->index++;
1202 		bool twin = info->exp[info->index] == L'<';
1203 		if (twin)
1204 		    info->index++;
1205 		bool equal = info->exp[info->index] == L'=';
1206 		if (equal)
1207 		    info->index++;
1208 		info->atoken.type = twin
1209 		    ? equal ? TT_LESSLESSEQUAL : TT_LESSLESS
1210 		    : equal ? TT_LESSEQUAL : TT_LESS;
1211 	    }
1212 	    break;
1213 	case L'>':
1214 	    {
1215 		info->index++;
1216 		bool twin = info->exp[info->index] == L'>';
1217 		if (twin)
1218 		    info->index++;
1219 		bool equal = info->exp[info->index] == L'=';
1220 		if (equal)
1221 		    info->index++;
1222 		info->atoken.type = twin
1223 		    ? equal ? TT_GREATERGREATEREQUAL : TT_GREATERGREATER
1224 		    : equal ? TT_GREATEREQUAL : TT_GREATER;
1225 	    }
1226 	    break;
1227 	case L'=':
1228 	    switch (info->exp[info->index + 1]) {
1229 		case L'=':
1230 		    info->atoken.type = TT_EQUALEQUAL;
1231 		    info->index += 2;
1232 		    break;
1233 		default:
1234 		    info->atoken.type = TT_EQUAL;
1235 		    info->index += 1;
1236 		    break;
1237 	    }
1238 	    break;
1239 	case L'&':
1240 	    switch (info->exp[info->index + 1]) {
1241 		case L'&':
1242 		    info->atoken.type = TT_AMPAMP;
1243 		    info->index += 2;
1244 		    break;
1245 		case L'=':
1246 		    info->atoken.type = TT_AMPEQUAL;
1247 		    info->index += 2;
1248 		    break;
1249 		default:
1250 		    info->atoken.type = TT_AMP;
1251 		    info->index += 1;
1252 		    break;
1253 	    }
1254 	    break;
1255 	case L'|':
1256 	    switch (info->exp[info->index + 1]) {
1257 		case L'|':
1258 		    info->atoken.type = TT_PIPEPIPE;
1259 		    info->index += 2;
1260 		    break;
1261 		case L'=':
1262 		    info->atoken.type = TT_PIPEEQUAL;
1263 		    info->index += 2;
1264 		    break;
1265 		default:
1266 		    info->atoken.type = TT_PIPE;
1267 		    info->index += 1;
1268 		    break;
1269 	    }
1270 	    break;
1271 	case L'^':
1272 	    switch (info->exp[info->index + 1]) {
1273 		case L'=':
1274 		    info->atoken.type = TT_HATEQUAL;
1275 		    info->index += 2;
1276 		    break;
1277 		default:
1278 		    info->atoken.type = TT_HAT;
1279 		    info->index += 1;
1280 		    break;
1281 	    }
1282 	    break;
1283 	case L'?':
1284 	    info->atoken.type = TT_QUESTION;
1285 	    info->index++;
1286 	    break;
1287 	case L':':
1288 	    info->atoken.type = TT_COLON;
1289 	    info->index++;
1290 	    break;
1291 	case L'_':
1292 	    goto parse_identifier;
1293 	default:
1294 	    assert(!iswspace(c));
1295 	    if (c == L'.' || iswdigit(c)) {
1296 		/* number */
1297 		size_t startindex = info->index;
1298 parse_num:
1299 		do
1300 		    c = info->exp[++info->index];
1301 		while (c == L'.' || iswalnum(c));
1302 		if (c == L'+' || c == L'-') {
1303 		    c = info->exp[info->index - 1];
1304 		    if (c == L'E' || c == L'e')
1305 			goto parse_num;
1306 		}
1307 		info->atoken.type = TT_NUMBER;
1308 		info->atoken.word.contents = &info->exp[startindex];
1309 		info->atoken.word.length = info->index - startindex;
1310 	    } else if (iswalpha(c)) {
1311 parse_identifier:;
1312 		size_t startindex = info->index;
1313 		do
1314 		    c = info->exp[++info->index];
1315 		while (c == L'_' || iswalnum(c));
1316 		info->atoken.type = TT_IDENTIFIER;
1317 		info->atoken.word.contents = &info->exp[startindex];
1318 		info->atoken.word.length = info->index - startindex;
1319 	    } else {
1320 		xerror(0, Ngt("arithmetic: `%lc' is not "
1321 			    "a valid number or operator"), (wint_t) c);
1322 		info->error = true;
1323 		info->atoken.type = TT_INVALID;
1324 	    }
1325 	    break;
1326     }
1327 }
1328 
1329 /* If `op' is a division operator and `rhs' is zero, then prints an error
1330  * message, sets `info->error' to true, sets `result->type' to VT_INVALID, and
1331  * returns true. Otherwise, just returns false.
1332  * `rhs->type' must not be VT_VAR. */
fail_if_will_divide_by_zero(atokentype_T op,const value_T * rhs,evalinfo_T * info,value_T * result)1333 bool fail_if_will_divide_by_zero(
1334 	atokentype_T op, const value_T *rhs, evalinfo_T *info, value_T *result)
1335 {
1336     switch (op) {
1337     case TT_SLASH:
1338     case TT_SLASHEQUAL:
1339     case TT_PERCENT:
1340     case TT_PERCENTEQUAL:
1341 	switch (rhs->type) {
1342 	case VT_LONG:
1343 	    if (rhs->v_long == 0)
1344 		goto fail;
1345 	    break;
1346 	case VT_DOUBLE:
1347 #if DOUBLE_DIVISION_BY_ZERO_ERROR
1348 	    if (rhs->v_double == 0.0)
1349 		goto fail;
1350 #endif
1351 	    break;
1352 	case VT_VAR:
1353 	    assert(false);
1354 	case VT_INVALID:
1355 	    break;
1356 	}
1357 	/* falls through */
1358     default:
1359 	return false;
1360     }
1361 
1362 fail:
1363     xerror(0, Ngt("arithmetic: division by zero"));
1364     info->error = true;
1365     result->type = VT_INVALID;
1366     return true;
1367 }
1368 
1369 /* vim: set ts=8 sts=4 sw=4 noet tw=80: */
1370