3
0

math.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. /*
  2. * Arithmetic code ripped out of ash shell for code sharing.
  3. *
  4. * This code is derived from software contributed to Berkeley by
  5. * Kenneth Almquist.
  6. *
  7. * Original BSD copyright notice is retained at the end of this file.
  8. *
  9. * Copyright (c) 1989, 1991, 1993, 1994
  10. * The Regents of the University of California. All rights reserved.
  11. *
  12. * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
  13. * was re-ported from NetBSD and debianized.
  14. *
  15. * rewrite arith.y to micro stack based cryptic algorithm by
  16. * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
  17. *
  18. * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
  19. * dynamic variables.
  20. *
  21. * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
  22. * used in busybox and size optimizations,
  23. * rewrote arith (see notes to this), added locale support,
  24. * rewrote dynamic variables.
  25. *
  26. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  27. */
  28. /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
  29. *
  30. * Permission is hereby granted, free of charge, to any person obtaining
  31. * a copy of this software and associated documentation files (the
  32. * "Software"), to deal in the Software without restriction, including
  33. * without limitation the rights to use, copy, modify, merge, publish,
  34. * distribute, sublicense, and/or sell copies of the Software, and to
  35. * permit persons to whom the Software is furnished to do so, subject to
  36. * the following conditions:
  37. *
  38. * The above copyright notice and this permission notice shall be
  39. * included in all copies or substantial portions of the Software.
  40. *
  41. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  42. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  43. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  44. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  45. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  46. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  47. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. */
  49. /* This is my infix parser/evaluator. It is optimized for size, intended
  50. * as a replacement for yacc-based parsers. However, it may well be faster
  51. * than a comparable parser written in yacc. The supported operators are
  52. * listed in #defines below. Parens, order of operations, and error handling
  53. * are supported. This code is thread safe. The exact expression format should
  54. * be that which POSIX specifies for shells.
  55. *
  56. * The code uses a simple two-stack algorithm. See
  57. * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
  58. * for a detailed explanation of the infix-to-postfix algorithm on which
  59. * this is based (this code differs in that it applies operators immediately
  60. * to the stack instead of adding them to a queue to end up with an
  61. * expression).
  62. */
  63. /*
  64. * Aug 24, 2001 Manuel Novoa III
  65. *
  66. * Reduced the generated code size by about 30% (i386) and fixed several bugs.
  67. *
  68. * 1) In arith_apply():
  69. * a) Cached values of *numptr and &(numptr[-1]).
  70. * b) Removed redundant test for zero denominator.
  71. *
  72. * 2) In arith():
  73. * a) Eliminated redundant code for processing operator tokens by moving
  74. * to a table-based implementation. Also folded handling of parens
  75. * into the table.
  76. * b) Combined all 3 loops which called arith_apply to reduce generated
  77. * code size at the cost of speed.
  78. *
  79. * 3) The following expressions were treated as valid by the original code:
  80. * 1() , 0! , 1 ( *3 ) .
  81. * These bugs have been fixed by internally enclosing the expression in
  82. * parens and then checking that all binary ops and right parens are
  83. * preceded by a valid expression (NUM_TOKEN).
  84. *
  85. * Note: It may be desirable to replace Aaron's test for whitespace with
  86. * ctype's isspace() if it is used by another busybox applet or if additional
  87. * whitespace chars should be considered. Look below the "#include"s for a
  88. * precompiler test.
  89. */
  90. /*
  91. * Aug 26, 2001 Manuel Novoa III
  92. *
  93. * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
  94. *
  95. * Merge in Aaron's comments previously posted to the busybox list,
  96. * modified slightly to take account of my changes to the code.
  97. */
  98. /*
  99. * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
  100. *
  101. * - allow access to variable,
  102. * use recursive value indirection: c="2*2"; a="c"; echo $((a+=2)) produce 6
  103. * - implement assign syntax (VAR=expr, +=, *= etc)
  104. * - implement exponentiation (** operator)
  105. * - implement comma separated - expr, expr
  106. * - implement ++expr --expr expr++ expr--
  107. * - implement expr ? expr : expr (but second expr is always calculated)
  108. * - allow hexadecimal and octal numbers
  109. * - restore lost XOR operator
  110. * - protect $((num num)) as true zero expr (Manuel's error)
  111. * - always use special isspace(), see comment from bash ;-)
  112. */
  113. #include "libbb.h"
  114. #include "math.h"
  115. #if 1
  116. # define dbg(...) ((void)0)
  117. #else
  118. # define dbg(...) bb_error_msg(__VA_ARGS__)
  119. #endif
  120. typedef unsigned char operator;
  121. /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
  122. * precedence, and 3 high bits are an ID unique across operators of that
  123. * precedence. The ID portion is so that multiple operators can have the
  124. * same precedence, ensuring that the leftmost one is evaluated first.
  125. * Consider * and /
  126. */
  127. #define tok_decl(prec,id) (((id)<<5) | (prec))
  128. #define ID_SHIFT 5
  129. #define PREC(op) ((op) & 0x1f)
  130. #define PREC_LPAREN 0
  131. #define TOK_LPAREN tok_decl(0,0)
  132. /* Precedence value of RPAREN is used only to distinguish it from LPAREN */
  133. #define TOK_RPAREN tok_decl(1,1)
  134. #define TOK_COMMA tok_decl(1,0)
  135. /* All assignments are right associative and have the same precedence,
  136. * but there are 11 of them, which doesn't fit into 3 bits for unique id.
  137. * Abusing another precedence level:
  138. */
  139. #define PREC_ASSIGN1 2
  140. #define TOK_ASSIGN tok_decl(2,0)
  141. #define TOK_AND_ASSIGN tok_decl(2,1)
  142. #define TOK_OR_ASSIGN tok_decl(2,2)
  143. #define TOK_XOR_ASSIGN tok_decl(2,3)
  144. #define TOK_ADD_ASSIGN tok_decl(2,4)
  145. #define TOK_SUB_ASSIGN tok_decl(2,5)
  146. #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
  147. #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
  148. #define PREC_ASSIGN2 3
  149. #define TOK_MUL_ASSIGN tok_decl(3,0)
  150. /* "/" and "/=" ops have the same id bits */
  151. #define DIV_ID1 1
  152. #define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1)
  153. #define TOK_REM_ASSIGN tok_decl(3,2)
  154. #define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0)
  155. /* Ternary conditional operator is right associative too */
  156. /*
  157. * bash documentation says that precedence order is:
  158. * ...
  159. * expr ? expr1 : expr2
  160. * = *= /= %= += -= <<= >>= &= ^= |=
  161. * exprA , exprB
  162. * What it omits is that expr1 is parsed as if parenthesized
  163. * (this matches the rules of ?: in C language):
  164. * "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4"
  165. * "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error)
  166. */
  167. #define TOK_CONDITIONAL tok_decl(4,0)
  168. #define TOK_CONDITIONAL_SEP tok_decl(4,1)
  169. #define TOK_OR tok_decl(5,0)
  170. #define TOK_AND tok_decl(6,0)
  171. #define TOK_BOR tok_decl(7,0)
  172. #define TOK_BXOR tok_decl(8,0)
  173. #define TOK_BAND tok_decl(9,0)
  174. #define TOK_EQ tok_decl(10,0)
  175. #define TOK_NE tok_decl(10,1)
  176. #define TOK_LT tok_decl(11,0)
  177. #define TOK_GT tok_decl(11,1)
  178. #define TOK_GE tok_decl(11,2)
  179. #define TOK_LE tok_decl(11,3)
  180. #define TOK_LSHIFT tok_decl(12,0)
  181. #define TOK_RSHIFT tok_decl(12,1)
  182. #define TOK_ADD tok_decl(13,0)
  183. #define TOK_SUB tok_decl(13,1)
  184. #define TOK_MUL tok_decl(14,0)
  185. #define TOK_DIV tok_decl(14,DIV_ID1)
  186. #define TOK_REM tok_decl(14,2)
  187. /* Exponent is right associative */
  188. #define TOK_EXPONENT tok_decl(15,1)
  189. /* Unary operators */
  190. #define UNARYPREC 16
  191. #define TOK_BNOT tok_decl(UNARYPREC,0)
  192. #define TOK_NOT tok_decl(UNARYPREC,1)
  193. #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
  194. #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
  195. #define PREC_PRE (UNARYPREC+2)
  196. #define TOK_PRE_INC tok_decl(PREC_PRE,0)
  197. #define TOK_PRE_DEC tok_decl(PREC_PRE,1)
  198. #define PREC_POST (UNARYPREC+3)
  199. #define TOK_POST_INC tok_decl(PREC_POST,0)
  200. #define TOK_POST_DEC tok_decl(PREC_POST,1)
  201. /* TOK_VALUE marks a number, name, name++/name--, or (EXPR):
  202. * IOW: something which can be used as the left side of a binary op.
  203. * Since it's never pushed to opstack, its precedence does not matter.
  204. */
  205. #define TOK_VALUE tok_decl(PREC_POST,2)
  206. static int
  207. is_assign_op(operator op)
  208. {
  209. operator prec = PREC(op);
  210. return prec == PREC_ASSIGN1
  211. || prec == PREC_ASSIGN2
  212. || prec == PREC_PRE
  213. || prec == PREC_POST;
  214. }
  215. static int
  216. is_right_associative(operator prec)
  217. {
  218. return prec == PREC(TOK_ASSIGN)
  219. || prec == PREC(TOK_EXPONENT)
  220. || prec == PREC(TOK_CONDITIONAL);
  221. }
  222. typedef struct {
  223. arith_t val;
  224. const char *var_name;
  225. } var_or_num_t;
  226. #define VALID_NAME(name) (name)
  227. #define NOT_NAME(name) (!(name))
  228. typedef struct remembered_name {
  229. struct remembered_name *next;
  230. const char *var_name;
  231. } remembered_name;
  232. static ALWAYS_INLINE int isalnum_(int c)
  233. {
  234. return (isalnum(c) || c == '_');
  235. }
  236. static arith_t
  237. evaluate_string(arith_state_t *math_state, const char *expr);
  238. static arith_t
  239. arith_lookup_val(arith_state_t *math_state, const char *name, char *endname)
  240. {
  241. char c;
  242. const char *p;
  243. c = *endname;
  244. *endname = '\0';
  245. p = math_state->lookupvar(name);
  246. *endname = c;
  247. if (p) {
  248. arith_t val;
  249. size_t len = endname - name;
  250. remembered_name *cur;
  251. remembered_name remember;
  252. /* did we already see this name?
  253. * testcase: a=b; b=a; echo $((a))
  254. */
  255. for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
  256. if (strncmp(cur->var_name, name, len) == 0
  257. && !isalnum_(cur->var_name[len])
  258. ) {
  259. /* yes */
  260. math_state->errmsg = "expression recursion loop detected";
  261. return -1;
  262. }
  263. }
  264. /* push current var name */
  265. remember.var_name = name;
  266. remember.next = math_state->list_of_recursed_names;
  267. math_state->list_of_recursed_names = &remember;
  268. /* recursively evaluate p as expression */
  269. /* this sets math_state->errmsg on error */
  270. val = evaluate_string(math_state, p);
  271. /* pop current var name */
  272. math_state->list_of_recursed_names = remember.next;
  273. return val;
  274. }
  275. /* treat undefined var as 0 */
  276. return 0;
  277. }
  278. /* "Applying" a token means performing it on the top elements on the integer
  279. * stack. For an unary operator it will only change the top element,
  280. * a binary operator will pop two arguments and push the result,
  281. * the ternary ?: op will pop three arguments and push the result.
  282. */
  283. static NOINLINE const char*
  284. arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr)
  285. {
  286. #define NUMSTACKPTR (*numstackptr)
  287. var_or_num_t *top_of_stack;
  288. arith_t rez;
  289. /* There is no operator that can work without arguments */
  290. if (NUMSTACKPTR == numstack)
  291. goto syntax_err;
  292. top_of_stack = NUMSTACKPTR - 1;
  293. if (op == TOK_CONDITIONAL_SEP) {
  294. /* "expr1 ? expr2 : expr3" operation */
  295. var_or_num_t *expr1 = &top_of_stack[-2];
  296. NUMSTACKPTR = expr1 + 1;
  297. if (expr1 < numstack) /* Example: $((2:3)) */
  298. return "malformed ?: operator";
  299. if (expr1->val != 0) /* select expr2 or expr3 */
  300. top_of_stack--;
  301. rez = top_of_stack->val;
  302. top_of_stack = expr1;
  303. goto ret_rez;
  304. }
  305. if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */
  306. return "malformed ?: operator";
  307. rez = top_of_stack->val;
  308. if (op == TOK_UMINUS)
  309. rez = -rez;
  310. else if (op == TOK_NOT)
  311. rez = !rez;
  312. else if (op == TOK_BNOT)
  313. rez = ~rez;
  314. else if (op == TOK_POST_INC || op == TOK_PRE_INC)
  315. rez++;
  316. else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
  317. rez--;
  318. else /*if (op != TOK_UPLUS) - always true, we drop TOK_UPLUS earlier */ {
  319. /* Binary operators */
  320. arith_t right_side_val;
  321. if (top_of_stack == numstack) /* have two arguments? */
  322. goto syntax_err; /* no */
  323. /* Pop numstack */
  324. NUMSTACKPTR = top_of_stack; /* this decrements NUMSTACKPTR */
  325. if (math_state->evaluation_disabled) {
  326. dbg("binary op %02x skipped", op);
  327. return NULL;
  328. /* bash 5.2.12 does not execute "2/0" in disabled
  329. * branches of ?: (and thus does not complain),
  330. * but complains about negative exp: "2**-1".
  331. * I don't think we need to emulate that.
  332. */
  333. }
  334. top_of_stack--; /* now points to left side */
  335. right_side_val = rez;
  336. rez = top_of_stack->val;
  337. if (op == TOK_BOR || op == TOK_OR_ASSIGN)
  338. rez |= right_side_val;
  339. else if (op == TOK_OR)
  340. rez = right_side_val || rez;
  341. else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
  342. rez &= right_side_val;
  343. else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
  344. rez ^= right_side_val;
  345. else if (op == TOK_AND)
  346. rez = rez && right_side_val;
  347. else if (op == TOK_EQ)
  348. rez = (rez == right_side_val);
  349. else if (op == TOK_NE)
  350. rez = (rez != right_side_val);
  351. else if (op == TOK_GE)
  352. rez = (rez >= right_side_val);
  353. else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
  354. rez >>= right_side_val;
  355. else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
  356. rez <<= right_side_val;
  357. else if (op == TOK_GT)
  358. rez = (rez > right_side_val);
  359. else if (op == TOK_LT)
  360. rez = (rez < right_side_val);
  361. else if (op == TOK_LE)
  362. rez = (rez <= right_side_val);
  363. else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
  364. rez *= right_side_val;
  365. else if (op == TOK_ADD || op == TOK_ADD_ASSIGN)
  366. rez += right_side_val;
  367. else if (op == TOK_SUB || op == TOK_SUB_ASSIGN)
  368. rez -= right_side_val;
  369. else if (op == TOK_ASSIGN || op == TOK_COMMA)
  370. rez = right_side_val;
  371. else if (op == TOK_EXPONENT) {
  372. arith_t c;
  373. if (right_side_val < 0)
  374. return "exponent less than 0";
  375. c = 1;
  376. while (right_side_val != 0) {
  377. if ((right_side_val & 1) == 0) {
  378. /* this if() block is not necessary for correctness,
  379. * but otherwise echo $((3**999999999999999999))
  380. * takes a VERY LONG time
  381. * (and it's not interruptible by ^C)
  382. */
  383. rez *= rez;
  384. right_side_val >>= 1;
  385. }
  386. c *= rez;
  387. right_side_val--;
  388. }
  389. rez = c;
  390. }
  391. else /*if (op == TOK_DIV || op == TOK_DIV_ASSIGN
  392. || op == TOK_REM || op == TOK_REM_ASSIGN) - always true */
  393. {
  394. if (right_side_val == 0)
  395. return "divide by zero";
  396. /*
  397. * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))'
  398. *
  399. * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1
  400. * and thus is not representable.
  401. * Some CPUs segfault trying such op.
  402. * Others overflow MAX_POSITIVE_INT+1 to
  403. * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000).
  404. * Make sure to at least not SEGV here:
  405. */
  406. if (right_side_val == -1
  407. && (rez << 1) == 0 /* MAX_NEGATIVE_INT or 0 */
  408. ) {
  409. right_side_val = 1;
  410. }
  411. if (op & (DIV_ID1 << ID_SHIFT)) /* DIV or DIV_ASSIGN? */
  412. rez /= right_side_val;
  413. else
  414. rez %= right_side_val;
  415. }
  416. }
  417. if (math_state->evaluation_disabled) {
  418. dbg("unary op %02x skipped", op);
  419. return NULL;
  420. }
  421. if (is_assign_op(op)) {
  422. char buf[sizeof(arith_t)*3 + 2];
  423. if (NOT_NAME(top_of_stack->var_name)) {
  424. /* Hmm, 1=2 ? */
  425. goto syntax_err;
  426. }
  427. /* Save to shell variable */
  428. sprintf(buf, ARITH_FMT, rez);
  429. {
  430. char *e = (char*)endofname(top_of_stack->var_name);
  431. char c = *e;
  432. *e = '\0';
  433. math_state->setvar(top_of_stack->var_name, buf);
  434. *e = c;
  435. }
  436. /* VAR++ or VAR--? */
  437. if (PREC(op) == PREC_POST) {
  438. /* Do not store new value to stack (keep old value) */
  439. goto ret_NULL;
  440. }
  441. }
  442. ret_rez:
  443. top_of_stack->val = rez;
  444. ret_NULL:
  445. /* Erase var name, it is just a number now */
  446. top_of_stack->var_name = NULL;
  447. return NULL;
  448. syntax_err:
  449. return "arithmetic syntax error";
  450. #undef NUMSTACKPTR
  451. }
  452. /* longest must be first */
  453. static const char op_tokens[] ALIGN1 = {
  454. '<','<','=',0, TOK_LSHIFT_ASSIGN,
  455. '>','>','=',0, TOK_RSHIFT_ASSIGN,
  456. '<','<', 0, TOK_LSHIFT,
  457. '>','>', 0, TOK_RSHIFT,
  458. '|','|', 0, TOK_OR,
  459. '&','&', 0, TOK_AND,
  460. '!','=', 0, TOK_NE,
  461. '<','=', 0, TOK_LE,
  462. '>','=', 0, TOK_GE,
  463. '=','=', 0, TOK_EQ,
  464. '|','=', 0, TOK_OR_ASSIGN,
  465. '&','=', 0, TOK_AND_ASSIGN,
  466. '*','=', 0, TOK_MUL_ASSIGN,
  467. '/','=', 0, TOK_DIV_ASSIGN,
  468. '%','=', 0, TOK_REM_ASSIGN,
  469. '+','=', 0, TOK_ADD_ASSIGN,
  470. '-','=', 0, TOK_SUB_ASSIGN,
  471. '-','-', 0, TOK_POST_DEC,
  472. '^','=', 0, TOK_XOR_ASSIGN,
  473. '+','+', 0, TOK_POST_INC,
  474. '*','*', 0, TOK_EXPONENT,
  475. '!', 0, TOK_NOT,
  476. '<', 0, TOK_LT,
  477. '>', 0, TOK_GT,
  478. '=', 0, TOK_ASSIGN,
  479. '|', 0, TOK_BOR,
  480. '&', 0, TOK_BAND,
  481. '*', 0, TOK_MUL,
  482. '/', 0, TOK_DIV,
  483. '%', 0, TOK_REM,
  484. '+', 0, TOK_ADD,
  485. '-', 0, TOK_SUB,
  486. '^', 0, TOK_BXOR,
  487. '~', 0, TOK_BNOT,
  488. ',', 0, TOK_COMMA,
  489. '?', 0, TOK_CONDITIONAL,
  490. ':', 0, TOK_CONDITIONAL_SEP,
  491. ')', 0, TOK_RPAREN,
  492. '(', 0, TOK_LPAREN,
  493. 0
  494. };
  495. #define END_POINTER (&op_tokens[sizeof(op_tokens)-1])
  496. #if ENABLE_FEATURE_SH_MATH_BASE
  497. static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base)
  498. {
  499. arith_t n = 0;
  500. const char *start = nptr;
  501. for (;;) {
  502. unsigned digit = (unsigned)*nptr - '0';
  503. if (digit >= 10 /* not 0..9 */
  504. && digit <= 'z' - '0' /* reject e.g. $((64#~)) */
  505. ) {
  506. /* current char is one of :;<=>?@A..Z[\]^_`a..z */
  507. /* in bases up to 36, case does not matter for a-z,
  508. * map @A..Z and `a..z to 9..35: */
  509. digit = (unsigned)(*nptr | 0x20) - ('a' - 10);
  510. if (base > 36 && *nptr <= '_') {
  511. /* base > 36: A-Z,@,_ are 36-61,62,63 */
  512. if (*nptr == '_')
  513. digit = 63;
  514. else if (*nptr == '@')
  515. digit = 62;
  516. else if (digit < 36) /* A-Z */
  517. digit += 36 - 10;
  518. else
  519. break; /* error: one of [\]^ */
  520. }
  521. //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit);
  522. if (digit < 10) /* reject e.g. $((36#@)) */
  523. break;
  524. }
  525. if (digit >= base)
  526. break;
  527. /* bash does not check for overflows */
  528. n = n * base + digit;
  529. nptr++;
  530. }
  531. *endptr = (char*)nptr;
  532. /* "64#" and "64#+1" used to be valid expressions, but bash 5.2.15
  533. * no longer allow such, detect this:
  534. */
  535. // NB: bash allows $((0x)), this is probably a bug...
  536. if (nptr == start)
  537. *endptr = NULL; /* there weren't any digits, bad */
  538. return n;
  539. }
  540. static arith_t strto_arith_t(const char *nptr, char **endptr)
  541. {
  542. /* NB: we do not use strtoull here to be bash-compatible:
  543. * $((99999999999999999999)) is 7766279631452241919
  544. * (the 64-bit truncated value).
  545. */
  546. unsigned base;
  547. /* nptr[0] is '0'..'9' here */
  548. base = nptr[0] - '0';
  549. if (base == 0) { /* nptr[0] is '0' */
  550. base = 8;
  551. if ((nptr[1] | 0x20) == 'x') {
  552. base = 16;
  553. nptr += 2;
  554. }
  555. // NB: bash allows $((0x)), this is probably a bug...
  556. return parse_with_base(nptr, endptr, base);
  557. }
  558. /* base is 1..9 here */
  559. if (nptr[1] == '#') {
  560. if (base > 1)
  561. return parse_with_base(nptr + 2, endptr, base);
  562. /* else: "1#NN", bash says "invalid arithmetic base" */
  563. }
  564. if (isdigit(nptr[1]) && nptr[2] == '#') {
  565. base = 10 * base + (nptr[1] - '0');
  566. /* base is at least 10 here */
  567. if (base <= 64)
  568. return parse_with_base(nptr + 3, endptr, base);
  569. /* else: bash says "invalid arithmetic base" */
  570. }
  571. return parse_with_base(nptr, endptr, 10);
  572. }
  573. #else /* !ENABLE_FEATURE_SH_MATH_BASE */
  574. # if ENABLE_FEATURE_SH_MATH_64
  575. # define strto_arith_t(nptr, endptr) strtoull(nptr, endptr, 0)
  576. # else
  577. # define strto_arith_t(nptr, endptr) strtoul(nptr, endptr, 0)
  578. # endif
  579. #endif
  580. static arith_t
  581. evaluate_string(arith_state_t *math_state, const char *expr)
  582. {
  583. /* Stack of integers/names */
  584. var_or_num_t *numstack, *numstackptr;
  585. /* Stack of operator tokens */
  586. operator *opstack, *opstackptr;
  587. /* To detect whether we are after a "value": */
  588. operator lasttok;
  589. /* To insert implicit () in ?: ternary op: */
  590. operator insert_op = 0xff;
  591. unsigned ternary_level = 0;
  592. const char *errmsg;
  593. const char *start_expr = expr = skip_whitespace(expr);
  594. {
  595. unsigned expr_len = strlen(expr);
  596. /* If LOTS of whitespace, do not blow up the estimation */
  597. const char *p = expr;
  598. while (*p) {
  599. /* in a run of whitespace, count only 1st char */
  600. if (isspace(*p)) {
  601. while (p++, isspace(*p))
  602. expr_len--;
  603. } else {
  604. p++;
  605. }
  606. }
  607. dbg("expr:'%s' expr_len:%u", expr, expr_len);
  608. /* expr_len deep opstack is needed. Think "------------7".
  609. * Only "?" operator temporarily needs two opstack slots
  610. * (IOW: more than one slot), but its second slot (LPAREN)
  611. * is popped off when ":" is reached.
  612. */
  613. expr_len++; /* +1 for 1st LPAREN. See what $((1?)) pushes to opstack */
  614. opstackptr = opstack = alloca(expr_len * sizeof(opstack[0]));
  615. /* There can be no more than (expr_len/2 + 1)
  616. * integers/names in any given correct or incorrect expression.
  617. * (modulo "09", "0v" cases where 2 chars are 2 ints/names,
  618. * but we have code to detect that early)
  619. */
  620. expr_len = (expr_len / 2)
  621. + 1 /* "1+2" has two nums, 2 = len/2+1, NOT len/2 */;
  622. numstackptr = numstack = alloca(expr_len * sizeof(numstack[0]));
  623. }
  624. /* Start with a left paren */
  625. dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack));
  626. *opstackptr++ = lasttok = TOK_LPAREN;
  627. while (1) {
  628. const char *p;
  629. operator op;
  630. operator prec;
  631. expr = skip_whitespace(expr);
  632. if (*expr == '\0') {
  633. if (expr == start_expr) {
  634. /* Null expression */
  635. return 0;
  636. }
  637. /* This is only reached after all tokens have been extracted from the
  638. * input stream. If there are still tokens on the operator stack, they
  639. * are to be applied in order. At the end, there should be a final
  640. * result on the integer stack */
  641. if (expr != END_POINTER) {
  642. /* If we haven't done so already,
  643. * append a closing right paren
  644. * and let the loop process it */
  645. expr = END_POINTER;
  646. op = TOK_RPAREN;
  647. goto tok_found1;
  648. }
  649. /* At this point, we're done with the expression */
  650. if (numstackptr != numstack + 1) {
  651. /* if there is not exactly one result, it's bad */
  652. /* Example: $((1 2)) */
  653. goto syntax_err;
  654. }
  655. return numstack->val;
  656. }
  657. p = endofname(expr);
  658. if (p != expr) {
  659. /* Name */
  660. if (!math_state->evaluation_disabled) {
  661. numstackptr->var_name = expr;
  662. dbg("[%d] var:'%.*s'", (int)(numstackptr - numstack), (int)(p - expr), expr);
  663. expr = skip_whitespace(p);
  664. /* If it is not followed by "=" operator... */
  665. if (expr[0] != '=' /* not "=..." */
  666. || expr[1] == '=' /* or "==..." */
  667. ) {
  668. /* Evaluate variable to value */
  669. arith_t val = arith_lookup_val(math_state, numstackptr->var_name, (char*)p);
  670. if (math_state->errmsg)
  671. return val; /* -1 */
  672. numstackptr->val = val;
  673. }
  674. } else {
  675. dbg("[%d] var:IGNORED", (int)(numstackptr - numstack));
  676. expr = p;
  677. numstackptr->var_name = NULL; /* not needed, paranoia */
  678. numstackptr->val = 0; /* not needed, paranoia */
  679. }
  680. push_value:
  681. numstackptr++;
  682. lasttok = TOK_VALUE;
  683. continue;
  684. }
  685. if (isdigit(*expr)) {
  686. /* Number */
  687. char *end;
  688. numstackptr->var_name = NULL;
  689. /* code is smaller compared to using &expr here: */
  690. numstackptr->val = strto_arith_t(expr, &end);
  691. expr = end;
  692. dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val);
  693. if (!expr) /* example: $((10#)) */
  694. goto syntax_err;
  695. /* A number can't be followed by another number, or a variable name.
  696. * We'd catch this later anyway, but this would require numstack[]
  697. * to be ~twice as deep to handle strings where _every_ char is
  698. * a new number or name.
  699. * Examples: "09" is two numbers, "0v" is number and name.
  700. */
  701. if (isalnum(*expr) || *expr == '_')
  702. goto syntax_err;
  703. goto push_value;
  704. }
  705. /* Should be an operator */
  706. /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized
  707. * only if XYZ is a variable name, not a number or EXPR. IOW:
  708. * "a+++v" is a++ + v.
  709. * "(a)+++7" is ( a ) + + + 7.
  710. * "7+++v" is 7 + ++v, not 7++ + v.
  711. * "--7" is - - 7, not --7.
  712. * "++++a" is + + ++a, not ++ ++a.
  713. */
  714. if ((expr[0] == '+' || expr[0] == '-')
  715. && (expr[1] == expr[0])
  716. ) {
  717. if (numstackptr == numstack || NOT_NAME(numstackptr[-1].var_name)) {
  718. /* not a VAR++ */
  719. char next = skip_whitespace(expr + 2)[0];
  720. if (!(isalpha(next) || next == '_')) {
  721. /* not a ++VAR */
  722. op = (expr[0] == '+' ? TOK_ADD : TOK_SUB);
  723. expr++;
  724. goto tok_found1;
  725. }
  726. }
  727. }
  728. p = op_tokens;
  729. while (1) {
  730. /* Compare expr to current op_tokens[] element */
  731. const char *e = expr;
  732. while (1) {
  733. if (*p == '\0') {
  734. /* Match: operator is found */
  735. expr = e;
  736. goto tok_found;
  737. }
  738. if (*p != *e)
  739. break;
  740. p++;
  741. e++;
  742. }
  743. /* No match, go to next element of op_tokens[] */
  744. while (*p)
  745. p++;
  746. p += 2; /* skip NUL and TOK_foo bytes */
  747. if (*p == '\0') {
  748. /* No next element, operator not found */
  749. //math_state->syntax_error_at = expr;
  750. goto syntax_err;
  751. }
  752. }
  753. /* NB: expr now points past the operator */
  754. tok_found:
  755. op = p[1]; /* fetch TOK_foo value */
  756. /* Special rule for "? EXPR :"
  757. * "EXPR in the middle of ? : is parsed as if parenthesized"
  758. * (this quirk originates in C grammar, I think).
  759. */
  760. if (op == TOK_CONDITIONAL) {
  761. insert_op = TOK_LPAREN;
  762. dbg("insert_op=%02x", insert_op);
  763. }
  764. if (op == TOK_CONDITIONAL_SEP) {
  765. insert_op = op;
  766. op = TOK_RPAREN;
  767. dbg("insert_op=%02x op=%02x", insert_op, op);
  768. }
  769. tok_found1:
  770. /* NAME++ is a "value" (something suitable for a binop) */
  771. if (PREC(lasttok) == PREC_POST)
  772. lasttok = TOK_VALUE;
  773. /* Plus and minus are binary (not unary) _only_ if the last
  774. * token was a "value". Think about it. It makes sense.
  775. */
  776. if (lasttok != TOK_VALUE) {
  777. switch (op) {
  778. case TOK_ADD:
  779. //op = TOK_UPLUS;
  780. //break;
  781. /* Unary plus does nothing, do not even push it to opstack */
  782. continue;
  783. case TOK_SUB:
  784. op = TOK_UMINUS;
  785. break;
  786. case TOK_POST_INC:
  787. op = TOK_PRE_INC;
  788. break;
  789. case TOK_POST_DEC:
  790. op = TOK_PRE_DEC;
  791. break;
  792. }
  793. }
  794. /* We don't want an unary operator to cause recursive descent on the
  795. * stack, because there can be many in a row and it could cause an
  796. * operator to be evaluated before its argument is pushed onto the
  797. * integer stack.
  798. * But for binary operators, "apply" everything on the operator
  799. * stack until we find an operator with a lesser priority than the
  800. * one we have just extracted. If op is right-associative,
  801. * then stop "applying" on the equal priority too.
  802. * Left paren will never be "applied" in this way.
  803. */
  804. prec = PREC(op);
  805. if (prec != PREC_LPAREN && prec < UNARYPREC) {
  806. /* Binary, ternary or RPAREN */
  807. if (lasttok != TOK_VALUE) {
  808. /* Must be preceded by a value.
  809. * $((2 2 + * 3)) would be accepted without this.
  810. */
  811. goto syntax_err;
  812. }
  813. /* if op is RPAREN:
  814. * while opstack is not empty:
  815. * pop prev_op
  816. * if prev_op is LPAREN (finished evaluating (EXPR)):
  817. * goto N
  818. * evaluate prev_op on top of numstack
  819. * BUG (unpaired RPAREN)
  820. * else (op is not RPAREN):
  821. * while opstack is not empty:
  822. * pop prev_op
  823. * if can't evaluate prev_op (it is lower precedence than op):
  824. * push prev_op back
  825. * goto C
  826. * evaluate prev_op on top of numstack
  827. * C:if op is "?": check result, set disable flag if needed
  828. * push op
  829. * N:loop to parse the rest of string
  830. */
  831. while (opstackptr != opstack) {
  832. operator prev_op = *--opstackptr;
  833. if (op == TOK_RPAREN) {
  834. if (prev_op == TOK_LPAREN) {
  835. /* Erase var name: for example, (VAR) = 1 is not valid */
  836. numstackptr[-1].var_name = NULL;
  837. /* (EXPR) is a "value": next operator directly after
  838. * close paren should be considered binary
  839. */
  840. lasttok = TOK_VALUE;
  841. goto next;
  842. }
  843. /* Not (y), but ...x~y). Fall through to evaluate x~y */
  844. } else {
  845. operator prev_prec = PREC(prev_op);
  846. fix_assignment_prec(prec);
  847. fix_assignment_prec(prev_prec);
  848. if (prev_prec < prec
  849. || (prev_prec == prec && is_right_associative(prec))
  850. ) {
  851. /* ...x~y@. push @ on opstack */
  852. opstackptr++; /* undo removal of ~ op */
  853. goto check_cond;
  854. }
  855. /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */
  856. }
  857. dbg("arith_apply(prev_op:%02x, numstack:%d)", prev_op, (int)(numstackptr - numstack));
  858. errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
  859. if (errmsg)
  860. goto err_with_custom_msg;
  861. dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[-1].val, numstackptr[-1].var_name);
  862. if (prev_op == TOK_CONDITIONAL_SEP) {
  863. /* We just executed ":" */
  864. /* Remove "?" from opstack too, not just ":" */
  865. opstackptr--;
  866. if (*opstackptr != TOK_CONDITIONAL) {
  867. /* Example: $((1,2:3)) */
  868. errmsg = "malformed ?: operator";
  869. goto err_with_custom_msg;
  870. }
  871. /* Example: a=1?2:3,a. We just executed ":".
  872. * Prevent assignment from being still disabled.
  873. */
  874. if (ternary_level == math_state->evaluation_disabled) {
  875. math_state->evaluation_disabled = 0;
  876. dbg("':' executed: evaluation_disabled=CLEAR");
  877. }
  878. ternary_level--;
  879. }
  880. } /* while (opstack not empty) */
  881. if (op == TOK_RPAREN) /* unpaired RPAREN? */
  882. goto syntax_err;
  883. check_cond:
  884. if (op == TOK_CONDITIONAL) {
  885. /* We just now evaluated EXPR before "?".
  886. * Should we disable evaluation now?
  887. */
  888. ternary_level++;
  889. if (numstackptr[-1].val == 0 && !math_state->evaluation_disabled) {
  890. math_state->evaluation_disabled = ternary_level;
  891. dbg("'?' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
  892. }
  893. }
  894. } /* if */
  895. /* else: LPAREN or UNARY: push it on opstack */
  896. /* Push this operator to opstack */
  897. dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op);
  898. *opstackptr++ = lasttok = op;
  899. next:
  900. if (insert_op != 0xff) {
  901. op = insert_op;
  902. insert_op = 0xff;
  903. dbg("inserting %02x", op);
  904. if (op == TOK_CONDITIONAL_SEP) {
  905. /* The next token is ":". Toggle "do not evaluate" state */
  906. if (!math_state->evaluation_disabled) {
  907. math_state->evaluation_disabled = ternary_level;
  908. dbg("':' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
  909. } else if (ternary_level == math_state->evaluation_disabled) {
  910. math_state->evaluation_disabled = 0;
  911. dbg("':' entered: evaluation_disabled=CLEAR");
  912. } /* else: ternary_level > evaluation_disabled && evaluation_disabled != 0 */
  913. /* We are in nested "?:" while in outer "?:" disabled branch */
  914. /* do_nothing */
  915. }
  916. goto tok_found1;
  917. }
  918. } /* while (1) */
  919. syntax_err:
  920. errmsg = "arithmetic syntax error";
  921. err_with_custom_msg:
  922. math_state->errmsg = errmsg;
  923. return -1;
  924. }
  925. arith_t FAST_FUNC
  926. arith(arith_state_t *math_state, const char *expr)
  927. {
  928. math_state->evaluation_disabled = 0;
  929. math_state->errmsg = NULL;
  930. math_state->list_of_recursed_names = NULL;
  931. return evaluate_string(math_state, expr);
  932. }
  933. /*
  934. * Copyright (c) 1989, 1991, 1993, 1994
  935. * The Regents of the University of California. All rights reserved.
  936. *
  937. * This code is derived from software contributed to Berkeley by
  938. * Kenneth Almquist.
  939. *
  940. * Redistribution and use in source and binary forms, with or without
  941. * modification, are permitted provided that the following conditions
  942. * are met:
  943. * 1. Redistributions of source code must retain the above copyright
  944. * notice, this list of conditions and the following disclaimer.
  945. * 2. Redistributions in binary form must reproduce the above copyright
  946. * notice, this list of conditions and the following disclaimer in the
  947. * documentation and/or other materials provided with the distribution.
  948. * 3. Neither the name of the University nor the names of its contributors
  949. * may be used to endorse or promote products derived from this software
  950. * without specific prior written permission.
  951. *
  952. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
  953. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  954. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  955. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  956. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  957. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  958. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  959. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  960. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  961. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  962. * SUCH DAMAGE.
  963. */