PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/expr/expr.y

https://bitbucket.org/cooljeanius/dragonflybsd
Happy | 617 lines | 519 code | 98 blank | 0 comment | 0 complexity | f647f6dfd68fb52dfc499cf081d33833 MD5 | raw file
  1. %{
  2. /* Written by Pace Willisson (pace@blitz.com)
  3. * and placed in the public domain.
  4. *
  5. * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
  6. *
  7. * $FreeBSD: src/bin/expr/expr.y,v 1.14.2.3 2001/08/01 02:37:46 obrien Exp $
  8. * $DragonFly: src/bin/expr/expr.y,v 1.6 2005/11/06 11:44:02 swildner Exp $
  9. */
  10. #include <sys/types.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <locale.h>
  15. #include <ctype.h>
  16. #include <err.h>
  17. #include <errno.h>
  18. #include <regex.h>
  19. #include <limits.h>
  20. enum valtype {
  21. integer, numeric_string, string
  22. } ;
  23. struct val {
  24. enum valtype type;
  25. union {
  26. char *s;
  27. quad_t i;
  28. } u;
  29. } ;
  30. struct val *result;
  31. int chk_div (quad_t, quad_t);
  32. int chk_minus (quad_t, quad_t, quad_t);
  33. int chk_plus (quad_t, quad_t, quad_t);
  34. int chk_times (quad_t, quad_t, quad_t);
  35. void free_value (struct val *);
  36. int is_zero_or_null (struct val *);
  37. int isstring (struct val *);
  38. int main (int, char **);
  39. struct val *make_integer (quad_t);
  40. struct val *make_str (const char *);
  41. struct val *op_and (struct val *, struct val *);
  42. struct val *op_colon (struct val *, struct val *);
  43. struct val *op_div (struct val *, struct val *);
  44. struct val *op_eq (struct val *, struct val *);
  45. struct val *op_ge (struct val *, struct val *);
  46. struct val *op_gt (struct val *, struct val *);
  47. struct val *op_le (struct val *, struct val *);
  48. struct val *op_lt (struct val *, struct val *);
  49. struct val *op_minus (struct val *, struct val *);
  50. struct val *op_ne (struct val *, struct val *);
  51. struct val *op_or (struct val *, struct val *);
  52. struct val *op_plus (struct val *, struct val *);
  53. struct val *op_rem (struct val *, struct val *);
  54. struct val *op_times (struct val *, struct val *);
  55. quad_t to_integer (struct val *);
  56. void to_string (struct val *);
  57. int yyerror (const char *);
  58. int yylex (void);
  59. char **av;
  60. %}
  61. %union
  62. {
  63. struct val *val;
  64. }
  65. %left <val> '|'
  66. %left <val> '&'
  67. %left <val> '=' '>' '<' GE LE NE
  68. %left <val> '+' '-'
  69. %left <val> '*' '/' '%'
  70. %left <val> ':'
  71. %token <val> TOKEN
  72. %type <val> start expr
  73. %%
  74. start: expr { result = $$; }
  75. expr: TOKEN
  76. | '(' expr ')' { $$ = $2; }
  77. | expr '|' expr { $$ = op_or ($1, $3); }
  78. | expr '&' expr { $$ = op_and ($1, $3); }
  79. | expr '=' expr { $$ = op_eq ($1, $3); }
  80. | expr '>' expr { $$ = op_gt ($1, $3); }
  81. | expr '<' expr { $$ = op_lt ($1, $3); }
  82. | expr GE expr { $$ = op_ge ($1, $3); }
  83. | expr LE expr { $$ = op_le ($1, $3); }
  84. | expr NE expr { $$ = op_ne ($1, $3); }
  85. | expr '+' expr { $$ = op_plus ($1, $3); }
  86. | expr '-' expr { $$ = op_minus ($1, $3); }
  87. | expr '*' expr { $$ = op_times ($1, $3); }
  88. | expr '/' expr { $$ = op_div ($1, $3); }
  89. | expr '%' expr { $$ = op_rem ($1, $3); }
  90. | expr ':' expr { $$ = op_colon ($1, $3); }
  91. ;
  92. %%
  93. struct val *
  94. make_integer(quad_t i)
  95. {
  96. struct val *vp;
  97. vp = (struct val *) malloc (sizeof (*vp));
  98. if (vp == NULL) {
  99. errx (2, "malloc() failed");
  100. }
  101. vp->type = integer;
  102. vp->u.i = i;
  103. return vp;
  104. }
  105. struct val *
  106. make_str(const char *s)
  107. {
  108. struct val *vp;
  109. size_t i;
  110. int isint;
  111. vp = (struct val *) malloc (sizeof (*vp));
  112. if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
  113. errx (2, "malloc() failed");
  114. }
  115. for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
  116. isint && i < strlen(s);
  117. i++)
  118. {
  119. if(!isdigit(s[i]))
  120. isint = 0;
  121. }
  122. if (isint)
  123. vp->type = numeric_string;
  124. else
  125. vp->type = string;
  126. return vp;
  127. }
  128. void
  129. free_value(struct val *vp)
  130. {
  131. if (vp->type == string || vp->type == numeric_string)
  132. free (vp->u.s);
  133. }
  134. quad_t
  135. to_integer(struct val *vp)
  136. {
  137. quad_t i;
  138. if (vp->type == integer)
  139. return 1;
  140. if (vp->type == string)
  141. return 0;
  142. /* vp->type == numeric_string, make it numeric */
  143. errno = 0;
  144. i = strtoll(vp->u.s, NULL, 10);
  145. if (errno != 0) {
  146. errx (2, "overflow");
  147. }
  148. free (vp->u.s);
  149. vp->u.i = i;
  150. vp->type = integer;
  151. return 1;
  152. }
  153. void
  154. to_string(struct val *vp)
  155. {
  156. char *tmp;
  157. if (vp->type == string || vp->type == numeric_string)
  158. return;
  159. tmp = malloc ((size_t)25);
  160. if (tmp == NULL) {
  161. errx (2, "malloc() failed");
  162. }
  163. sprintf (tmp, "%lld", (long long)vp->u.i);
  164. vp->type = string;
  165. vp->u.s = tmp;
  166. }
  167. int
  168. isstring(struct val *vp)
  169. {
  170. /* only TRUE if this string is not a valid integer */
  171. return (vp->type == string);
  172. }
  173. int
  174. yylex(void)
  175. {
  176. char *p;
  177. if (*av == NULL)
  178. return (0);
  179. p = *av++;
  180. if (strlen (p) == 1) {
  181. if (strchr ("|&=<>+-*/%:()", *p))
  182. return (*p);
  183. } else if (strlen (p) == 2 && p[1] == '=') {
  184. switch (*p) {
  185. case '>': return (GE);
  186. case '<': return (LE);
  187. case '!': return (NE);
  188. }
  189. }
  190. yylval.val = make_str (p);
  191. return (TOKEN);
  192. }
  193. int
  194. is_zero_or_null(struct val *vp)
  195. {
  196. if (vp->type == integer) {
  197. return (vp->u.i == 0);
  198. } else {
  199. return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
  200. }
  201. /* NOTREACHED */
  202. }
  203. static void
  204. usage(void)
  205. {
  206. fprintf(stderr,
  207. "usage: expr expression\n");
  208. exit(EXIT_FAILURE);
  209. }
  210. int
  211. main (int argc, char **argv)
  212. {
  213. setlocale (LC_ALL, "");
  214. if (argc > 1 && strcmp(argv[1], "--"))
  215. av = argv + 1;
  216. else if (argc > 2)
  217. av = argv + 2;
  218. else
  219. usage();
  220. yyparse ();
  221. if (result->type == integer)
  222. printf ("%lld\n", (long long)result->u.i);
  223. else
  224. printf ("%s\n", result->u.s);
  225. return (is_zero_or_null (result));
  226. }
  227. int
  228. yyerror(const char *s __unused)
  229. {
  230. errx (2, "syntax error");
  231. }
  232. struct val *
  233. op_or(struct val *a, struct val *b)
  234. {
  235. if (is_zero_or_null (a)) {
  236. free_value (a);
  237. return (b);
  238. } else {
  239. free_value (b);
  240. return (a);
  241. }
  242. }
  243. struct val *
  244. op_and(struct val *a, struct val *b)
  245. {
  246. if (is_zero_or_null (a) || is_zero_or_null (b)) {
  247. free_value (a);
  248. free_value (b);
  249. return (make_integer ((quad_t)0));
  250. } else {
  251. free_value (b);
  252. return (a);
  253. }
  254. }
  255. struct val *
  256. op_eq(struct val *a, struct val *b)
  257. {
  258. struct val *r;
  259. if (isstring (a) || isstring (b)) {
  260. to_string (a);
  261. to_string (b);
  262. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
  263. } else {
  264. to_integer(a);
  265. to_integer(b);
  266. r = make_integer ((quad_t)(a->u.i == b->u.i));
  267. }
  268. free_value (a);
  269. free_value (b);
  270. return r;
  271. }
  272. struct val *
  273. op_gt(struct val *a, struct val *b)
  274. {
  275. struct val *r;
  276. if (isstring (a) || isstring (b)) {
  277. to_string (a);
  278. to_string (b);
  279. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
  280. } else {
  281. to_integer(a);
  282. to_integer(b);
  283. r = make_integer ((quad_t)(a->u.i > b->u.i));
  284. }
  285. free_value (a);
  286. free_value (b);
  287. return r;
  288. }
  289. struct val *
  290. op_lt(struct val *a, struct val *b)
  291. {
  292. struct val *r;
  293. if (isstring (a) || isstring (b)) {
  294. to_string (a);
  295. to_string (b);
  296. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
  297. } else {
  298. to_integer(a);
  299. to_integer(b);
  300. r = make_integer ((quad_t)(a->u.i < b->u.i));
  301. }
  302. free_value (a);
  303. free_value (b);
  304. return r;
  305. }
  306. struct val *
  307. op_ge(struct val *a, struct val *b)
  308. {
  309. struct val *r;
  310. if (isstring (a) || isstring (b)) {
  311. to_string (a);
  312. to_string (b);
  313. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
  314. } else {
  315. to_integer(a);
  316. to_integer(b);
  317. r = make_integer ((quad_t)(a->u.i >= b->u.i));
  318. }
  319. free_value (a);
  320. free_value (b);
  321. return r;
  322. }
  323. struct val *
  324. op_le(struct val *a, struct val *b)
  325. {
  326. struct val *r;
  327. if (isstring (a) || isstring (b)) {
  328. to_string (a);
  329. to_string (b);
  330. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
  331. } else {
  332. to_integer(a);
  333. to_integer(b);
  334. r = make_integer ((quad_t)(a->u.i <= b->u.i));
  335. }
  336. free_value (a);
  337. free_value (b);
  338. return r;
  339. }
  340. struct val *
  341. op_ne(struct val *a, struct val *b)
  342. {
  343. struct val *r;
  344. if (isstring (a) || isstring (b)) {
  345. to_string (a);
  346. to_string (b);
  347. r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
  348. } else {
  349. to_integer(a);
  350. to_integer(b);
  351. r = make_integer ((quad_t)(a->u.i != b->u.i));
  352. }
  353. free_value (a);
  354. free_value (b);
  355. return r;
  356. }
  357. int
  358. chk_plus(quad_t a, quad_t b, quad_t r)
  359. {
  360. /* sum of two positive numbers must be positive */
  361. if (a > 0 && b > 0 && r <= 0)
  362. return 1;
  363. /* sum of two negative numbers must be negative */
  364. if (a < 0 && b < 0 && r >= 0)
  365. return 1;
  366. /* all other cases are OK */
  367. return 0;
  368. }
  369. struct val *
  370. op_plus(struct val *a, struct val *b)
  371. {
  372. struct val *r;
  373. if (!to_integer (a) || !to_integer (b)) {
  374. errx (2, "non-numeric argument");
  375. }
  376. r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
  377. if (chk_plus (a->u.i, b->u.i, r->u.i)) {
  378. errx (2, "overflow");
  379. }
  380. free_value (a);
  381. free_value (b);
  382. return r;
  383. }
  384. int
  385. chk_minus(quad_t a, quad_t b, quad_t r)
  386. {
  387. /* special case subtraction of QUAD_MIN */
  388. if (b == QUAD_MIN) {
  389. if (a >= 0)
  390. return 1;
  391. else
  392. return 0;
  393. }
  394. /* this is allowed for b != QUAD_MIN */
  395. return chk_plus (a, -b, r);
  396. }
  397. struct val *
  398. op_minus(struct val *a, struct val *b)
  399. {
  400. struct val *r;
  401. if (!to_integer (a) || !to_integer (b)) {
  402. errx (2, "non-numeric argument");
  403. }
  404. r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
  405. if (chk_minus (a->u.i, b->u.i, r->u.i)) {
  406. errx (2, "overflow");
  407. }
  408. free_value (a);
  409. free_value (b);
  410. return r;
  411. }
  412. int
  413. chk_times(quad_t a, quad_t b, quad_t r)
  414. {
  415. /* special case: first operand is 0, no overflow possible */
  416. if (a == 0)
  417. return 0;
  418. /* cerify that result of division matches second operand */
  419. if (r / a != b)
  420. return 1;
  421. return 0;
  422. }
  423. struct val *
  424. op_times(struct val *a, struct val *b)
  425. {
  426. struct val *r;
  427. if (!to_integer (a) || !to_integer (b)) {
  428. errx (2, "non-numeric argument");
  429. }
  430. r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
  431. if (chk_times (a->u.i, b->u.i, r->u.i)) {
  432. errx (2, "overflow");
  433. }
  434. free_value (a);
  435. free_value (b);
  436. return (r);
  437. }
  438. int
  439. chk_div(quad_t a, quad_t b)
  440. {
  441. /* div by zero has been taken care of before */
  442. /* only QUAD_MIN / -1 causes overflow */
  443. if (a == QUAD_MIN && b == -1)
  444. return 1;
  445. /* everything else is OK */
  446. return 0;
  447. }
  448. struct val *
  449. op_div(struct val *a, struct val *b)
  450. {
  451. struct val *r;
  452. if (!to_integer (a) || !to_integer (b)) {
  453. errx (2, "non-numeric argument");
  454. }
  455. if (b->u.i == 0) {
  456. errx (2, "division by zero");
  457. }
  458. r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
  459. if (chk_div (a->u.i, b->u.i)) {
  460. errx (2, "overflow");
  461. }
  462. free_value (a);
  463. free_value (b);
  464. return r;
  465. }
  466. struct val *
  467. op_rem(struct val *a, struct val *b)
  468. {
  469. struct val *r;
  470. if (!to_integer (a) || !to_integer (b)) {
  471. errx (2, "non-numeric argument");
  472. }
  473. if (b->u.i == 0) {
  474. errx (2, "division by zero");
  475. }
  476. r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
  477. /* chk_rem necessary ??? */
  478. free_value (a);
  479. free_value (b);
  480. return r;
  481. }
  482. struct val *
  483. op_colon(struct val *a, struct val *b)
  484. {
  485. regex_t rp;
  486. regmatch_t rm[2];
  487. char errbuf[256];
  488. int eval;
  489. struct val *v;
  490. /* coerce to both arguments to strings */
  491. to_string(a);
  492. to_string(b);
  493. /* compile regular expression */
  494. if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
  495. regerror (eval, &rp, errbuf, sizeof(errbuf));
  496. errx (2, "%s", errbuf);
  497. }
  498. /* compare string against pattern */
  499. /* remember that patterns are anchored to the beginning of the line */
  500. if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
  501. if (rm[1].rm_so >= 0) {
  502. *(a->u.s + rm[1].rm_eo) = '\0';
  503. v = make_str (a->u.s + rm[1].rm_so);
  504. } else {
  505. v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
  506. }
  507. } else {
  508. if (rp.re_nsub == 0) {
  509. v = make_integer ((quad_t)0);
  510. } else {
  511. v = make_str ("");
  512. }
  513. }
  514. /* free arguments and pattern buffer */
  515. free_value (a);
  516. free_value (b);
  517. regfree (&rp);
  518. return v;
  519. }