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