3
0

expr.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini expr implementation for busybox
  4. *
  5. * based on GNU expr Mike Parker.
  6. * Copyright (C) 86, 1991-1997, 1999 Free Software Foundation, Inc.
  7. *
  8. * Busybox modifications
  9. * Copyright (c) 2000 Edward Betts <edward@debian.org>.
  10. * Aug 2003 Vladimir Oleynik - reduced 464 bytes.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25. *
  26. */
  27. /* This program evaluates expressions. Each token (operator, operand,
  28. * parenthesis) of the expression must be a separate argument. The
  29. * parser used is a reasonably general one, though any incarnation of
  30. * it is language-specific. It is especially nice for expressions.
  31. *
  32. * No parse tree is needed; a new node is evaluated immediately.
  33. * One function can handle multiple operators all of equal precedence,
  34. * provided they all associate ((x op x) op x). */
  35. /* no getopt needed */
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <regex.h>
  40. #include <sys/types.h>
  41. #include <errno.h>
  42. #include "busybox.h"
  43. /* The kinds of value we can have. */
  44. enum valtype {
  45. integer,
  46. string
  47. };
  48. typedef enum valtype TYPE;
  49. /* A value is.... */
  50. struct valinfo {
  51. TYPE type; /* Which kind. */
  52. union { /* The value itself. */
  53. int i;
  54. char *s;
  55. } u;
  56. };
  57. typedef struct valinfo VALUE;
  58. /* The arguments given to the program, minus the program name. */
  59. static char **args;
  60. static VALUE *docolon (VALUE *sv, VALUE *pv);
  61. static VALUE *eval (void);
  62. static VALUE *int_value (int i);
  63. static VALUE *str_value (char *s);
  64. static int nextarg (char *str);
  65. static int null (VALUE *v);
  66. static int toarith (VALUE *v);
  67. static void freev (VALUE *v);
  68. static void tostring (VALUE *v);
  69. int expr_main (int argc, char **argv)
  70. {
  71. VALUE *v;
  72. if (argc == 1) {
  73. bb_error_msg_and_die("too few arguments");
  74. }
  75. args = argv + 1;
  76. v = eval ();
  77. if (*args)
  78. bb_error_msg_and_die ("syntax error");
  79. if (v->type == integer)
  80. printf ("%d\n", v->u.i);
  81. else
  82. puts (v->u.s);
  83. exit (null (v));
  84. }
  85. /* Return a VALUE for I. */
  86. static VALUE *int_value (int i)
  87. {
  88. VALUE *v;
  89. v = xmalloc (sizeof(VALUE));
  90. v->type = integer;
  91. v->u.i = i;
  92. return v;
  93. }
  94. /* Return a VALUE for S. */
  95. static VALUE *str_value (char *s)
  96. {
  97. VALUE *v;
  98. v = xmalloc (sizeof(VALUE));
  99. v->type = string;
  100. v->u.s = bb_xstrdup (s);
  101. return v;
  102. }
  103. /* Free VALUE V, including structure components. */
  104. static void freev (VALUE *v)
  105. {
  106. if (v->type == string)
  107. free (v->u.s);
  108. free (v);
  109. }
  110. /* Return nonzero if V is a null-string or zero-number. */
  111. static int null (VALUE *v)
  112. {
  113. switch (v->type) {
  114. case integer:
  115. return v->u.i == 0;
  116. default: /* string: */
  117. return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
  118. }
  119. }
  120. /* Coerce V to a string value (can't fail). */
  121. static void tostring (VALUE *v)
  122. {
  123. if (v->type == integer) {
  124. bb_xasprintf (&(v->u.s), "%d", v->u.i);
  125. v->type = string;
  126. }
  127. }
  128. /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
  129. static int toarith (VALUE *v)
  130. {
  131. if(v->type == string) {
  132. int i;
  133. char *e;
  134. /* Don't interpret the empty string as an integer. */
  135. /* Currently does not worry about overflow or int/long differences. */
  136. i = (int) strtol(v->u.s, &e, 10);
  137. if ((v->u.s == e) || *e)
  138. return 0;
  139. free (v->u.s);
  140. v->u.i = i;
  141. v->type = integer;
  142. }
  143. return 1;
  144. }
  145. /* Return nonzero if the next token matches STR exactly.
  146. STR must not be NULL. */
  147. static int
  148. nextarg (char *str)
  149. {
  150. if (*args == NULL)
  151. return 0;
  152. return strcmp (*args, str) == 0;
  153. }
  154. /* The comparison operator handling functions. */
  155. static int cmp_common (VALUE *l, VALUE *r, int op)
  156. {
  157. int cmpval;
  158. if (l->type == string || r->type == string) {
  159. tostring (l);
  160. tostring (r);
  161. cmpval = strcmp (l->u.s, r->u.s);
  162. }
  163. else
  164. cmpval = l->u.i - r->u.i;
  165. switch(op) {
  166. case '<':
  167. return cmpval < 0;
  168. case ('L'+'E'):
  169. return cmpval <= 0;
  170. case '=':
  171. return cmpval == 0;
  172. case '!':
  173. return cmpval != 0;
  174. case '>':
  175. return cmpval > 0;
  176. default: /* >= */
  177. return cmpval >= 0;
  178. }
  179. }
  180. /* The arithmetic operator handling functions. */
  181. static int arithmetic_common (VALUE *l, VALUE *r, int op)
  182. {
  183. int li, ri;
  184. if (!toarith (l) || !toarith (r))
  185. bb_error_msg_and_die ("non-numeric argument");
  186. li = l->u.i;
  187. ri = r->u.i;
  188. if((op == '/' || op == '%') && ri == 0)
  189. bb_error_msg_and_die ( "division by zero");
  190. switch(op) {
  191. case '+':
  192. return li + ri;
  193. case '-':
  194. return li - ri;
  195. case '*':
  196. return li * ri;
  197. case '/':
  198. return li / ri;
  199. default:
  200. return li % ri;
  201. }
  202. }
  203. /* Do the : operator.
  204. SV is the VALUE for the lhs (the string),
  205. PV is the VALUE for the rhs (the pattern). */
  206. static VALUE *docolon (VALUE *sv, VALUE *pv)
  207. {
  208. VALUE *v;
  209. regex_t re_buffer;
  210. const int NMATCH = 2;
  211. regmatch_t re_regs[NMATCH];
  212. tostring (sv);
  213. tostring (pv);
  214. if (pv->u.s[0] == '^') {
  215. fprintf (stderr, "\
  216. warning: unportable BRE: `%s': using `^' as the first character\n\
  217. of a basic regular expression is not portable; it is being ignored",
  218. pv->u.s);
  219. }
  220. memset (&re_buffer, 0, sizeof (re_buffer));
  221. memset (re_regs, 0, sizeof (*re_regs));
  222. if( regcomp (&re_buffer, pv->u.s, 0) != 0 )
  223. bb_error_msg_and_die("Invalid regular expression");
  224. /* expr uses an anchored pattern match, so check that there was a
  225. * match and that the match starts at offset 0. */
  226. if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
  227. re_regs[0].rm_so == 0) {
  228. /* Were \(...\) used? */
  229. if (re_buffer.re_nsub > 0) {
  230. sv->u.s[re_regs[1].rm_eo] = '\0';
  231. v = str_value (sv->u.s + re_regs[1].rm_so);
  232. }
  233. else
  234. v = int_value (re_regs[0].rm_eo);
  235. }
  236. else {
  237. /* Match failed -- return the right kind of null. */
  238. if (re_buffer.re_nsub > 0)
  239. v = str_value ("");
  240. else
  241. v = int_value (0);
  242. }
  243. return v;
  244. }
  245. /* Handle bare operands and ( expr ) syntax. */
  246. static VALUE *eval7 (void)
  247. {
  248. VALUE *v;
  249. if (!*args)
  250. bb_error_msg_and_die ( "syntax error");
  251. if (nextarg ("(")) {
  252. args++;
  253. v = eval ();
  254. if (!nextarg (")"))
  255. bb_error_msg_and_die ( "syntax error");
  256. args++;
  257. return v;
  258. }
  259. if (nextarg (")"))
  260. bb_error_msg_and_die ( "syntax error");
  261. return str_value (*args++);
  262. }
  263. /* Handle match, substr, index, length, and quote keywords. */
  264. static VALUE *eval6 (void)
  265. {
  266. VALUE *l, *r, *v, *i1, *i2;
  267. if (nextarg ("quote")) {
  268. args++;
  269. if (!*args)
  270. bb_error_msg_and_die ( "syntax error");
  271. return str_value (*args++);
  272. }
  273. else if (nextarg ("length")) {
  274. args++;
  275. r = eval6 ();
  276. tostring (r);
  277. v = int_value (strlen (r->u.s));
  278. freev (r);
  279. return v;
  280. }
  281. else if (nextarg ("match")) {
  282. args++;
  283. l = eval6 ();
  284. r = eval6 ();
  285. v = docolon (l, r);
  286. freev (l);
  287. freev (r);
  288. return v;
  289. }
  290. else if (nextarg ("index")) {
  291. args++;
  292. l = eval6 ();
  293. r = eval6 ();
  294. tostring (l);
  295. tostring (r);
  296. v = int_value (strcspn (l->u.s, r->u.s) + 1);
  297. if (v->u.i == (int) strlen (l->u.s) + 1)
  298. v->u.i = 0;
  299. freev (l);
  300. freev (r);
  301. return v;
  302. }
  303. else if (nextarg ("substr")) {
  304. args++;
  305. l = eval6 ();
  306. i1 = eval6 ();
  307. i2 = eval6 ();
  308. tostring (l);
  309. if (!toarith (i1) || !toarith (i2)
  310. || i1->u.i > (int) strlen (l->u.s)
  311. || i1->u.i <= 0 || i2->u.i <= 0)
  312. v = str_value ("");
  313. else {
  314. v = xmalloc (sizeof(VALUE));
  315. v->type = string;
  316. v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
  317. }
  318. freev (l);
  319. freev (i1);
  320. freev (i2);
  321. return v;
  322. }
  323. else
  324. return eval7 ();
  325. }
  326. /* Handle : operator (pattern matching).
  327. Calls docolon to do the real work. */
  328. static VALUE *eval5 (void)
  329. {
  330. VALUE *l, *r, *v;
  331. l = eval6 ();
  332. while (nextarg (":")) {
  333. args++;
  334. r = eval6 ();
  335. v = docolon (l, r);
  336. freev (l);
  337. freev (r);
  338. l = v;
  339. }
  340. return l;
  341. }
  342. /* Handle *, /, % operators. */
  343. static VALUE *eval4 (void)
  344. {
  345. VALUE *l, *r;
  346. int op, val;
  347. l = eval5 ();
  348. while (1) {
  349. if (nextarg ("*"))
  350. op = '*';
  351. else if (nextarg ("/"))
  352. op = '/';
  353. else if (nextarg ("%"))
  354. op = '%';
  355. else
  356. return l;
  357. args++;
  358. r = eval5 ();
  359. val = arithmetic_common (l, r, op);
  360. freev (l);
  361. freev (r);
  362. l = int_value (val);
  363. }
  364. }
  365. /* Handle +, - operators. */
  366. static VALUE *eval3 (void)
  367. {
  368. VALUE *l, *r;
  369. int op, val;
  370. l = eval4 ();
  371. while (1) {
  372. if (nextarg ("+"))
  373. op = '+';
  374. else if (nextarg ("-"))
  375. op = '-';
  376. else
  377. return l;
  378. args++;
  379. r = eval4 ();
  380. val = arithmetic_common (l, r, op);
  381. freev (l);
  382. freev (r);
  383. l = int_value (val);
  384. }
  385. }
  386. /* Handle comparisons. */
  387. static VALUE *eval2 (void)
  388. {
  389. VALUE *l, *r;
  390. int op, val;
  391. l = eval3 ();
  392. while (1) {
  393. if (nextarg ("<"))
  394. op = '<';
  395. else if (nextarg ("<="))
  396. op = 'L'+'E';
  397. else if (nextarg ("=") || nextarg ("=="))
  398. op = '=';
  399. else if (nextarg ("!="))
  400. op = '!';
  401. else if (nextarg (">="))
  402. op = 'G'+'E';
  403. else if (nextarg (">"))
  404. op = '>';
  405. else
  406. return l;
  407. args++;
  408. r = eval3 ();
  409. toarith (l);
  410. toarith (r);
  411. val = cmp_common (l, r, op);
  412. freev (l);
  413. freev (r);
  414. l = int_value (val);
  415. }
  416. }
  417. /* Handle &. */
  418. static VALUE *eval1 (void)
  419. {
  420. VALUE *l, *r;
  421. l = eval2 ();
  422. while (nextarg ("&")) {
  423. args++;
  424. r = eval2 ();
  425. if (null (l) || null (r)) {
  426. freev (l);
  427. freev (r);
  428. l = int_value (0);
  429. }
  430. else
  431. freev (r);
  432. }
  433. return l;
  434. }
  435. /* Handle |. */
  436. static VALUE *eval (void)
  437. {
  438. VALUE *l, *r;
  439. l = eval1 ();
  440. while (nextarg ("|")) {
  441. args++;
  442. r = eval1 ();
  443. if (null (l)) {
  444. freev (l);
  445. l = r;
  446. }
  447. else
  448. freev (r);
  449. }
  450. return l;
  451. }