expr.y revision 90109
14Srgrimes%{ 24Srgrimes/* Written by Pace Willisson (pace@blitz.com) 3295Sjtc * and placed in the public domain. 44Srgrimes * 5295Sjtc * Largely rewritten by J.T. Conklin (jtc@wimsey.com) 6295Sjtc * 750471Speter * $FreeBSD: head/bin/expr/expr.y 90109 2002-02-02 06:36:49Z imp $ 84Srgrimes */ 9468Sjtc 1062926Sse#include <sys/types.h> 114Srgrimes#include <stdio.h> 124Srgrimes#include <stdlib.h> 134Srgrimes#include <string.h> 14468Sjtc#include <locale.h> 154Srgrimes#include <ctype.h> 16295Sjtc#include <err.h> 1763755Sse#include <errno.h> 1862926Sse#include <regex.h> 1963755Sse#include <limits.h> 2031Salm 214Srgrimesenum valtype { 2212378Sjoerg integer, numeric_string, string 234Srgrimes} ; 2431Salm 254Srgrimesstruct val { 264Srgrimes enum valtype type; 274Srgrimes union { 284Srgrimes char *s; 2962926Sse quad_t i; 304Srgrimes } u; 3131Salm} ; 324Srgrimes 334Srgrimesstruct val *result; 344Srgrimes 3590109Simpint chk_div(quad_t, quad_t); 3690109Simpint chk_minus(quad_t, quad_t, quad_t); 3790109Simpint chk_plus(quad_t, quad_t, quad_t); 3890109Simpint chk_times(quad_t, quad_t, quad_t); 3990109Simpvoid free_value(struct val *); 4090109Simpint is_zero_or_null(struct val *); 4190109Simpint isstring(struct val *); 4290109Simpstruct val *make_integer(quad_t); 4390109Simpstruct val *make_str(const char *); 4490109Simpstruct val *op_and(struct val *, struct val *); 4590109Simpstruct val *op_colon(struct val *, struct val *); 4690109Simpstruct val *op_div(struct val *, struct val *); 4790109Simpstruct val *op_eq(struct val *, struct val *); 4890109Simpstruct val *op_ge(struct val *, struct val *); 4990109Simpstruct val *op_gt(struct val *, struct val *); 5090109Simpstruct val *op_le(struct val *, struct val *); 5190109Simpstruct val *op_lt(struct val *, struct val *); 5290109Simpstruct val *op_minus(struct val *, struct val *); 5390109Simpstruct val *op_ne(struct val *, struct val *); 5490109Simpstruct val *op_or(struct val *, struct val *); 5590109Simpstruct val *op_plus(struct val *, struct val *); 5690109Simpstruct val *op_rem(struct val *, struct val *); 5790109Simpstruct val *op_times(struct val *, struct val *); 5890109Simpquad_t to_integer(struct val *); 5990109Simpvoid to_string(struct val *); 6090109Simpint yyerror(const char *); 6190109Simpint yylex(void); 6290109Simpint yyparse(void); 6377244Skris 644Srgrimeschar **av; 654Srgrimes%} 664Srgrimes 674Srgrimes%union 684Srgrimes{ 694Srgrimes struct val *val; 704Srgrimes} 714Srgrimes 724Srgrimes%left <val> '|' 734Srgrimes%left <val> '&' 744Srgrimes%left <val> '=' '>' '<' GE LE NE 754Srgrimes%left <val> '+' '-' 764Srgrimes%left <val> '*' '/' '%' 774Srgrimes%left <val> ':' 784Srgrimes 794Srgrimes%token <val> TOKEN 804Srgrimes%type <val> start expr 814Srgrimes 824Srgrimes%% 834Srgrimes 844Srgrimesstart: expr { result = $$; } 854Srgrimes 864Srgrimesexpr: TOKEN 874Srgrimes | '(' expr ')' { $$ = $2; } 884Srgrimes | expr '|' expr { $$ = op_or ($1, $3); } 894Srgrimes | expr '&' expr { $$ = op_and ($1, $3); } 904Srgrimes | expr '=' expr { $$ = op_eq ($1, $3); } 914Srgrimes | expr '>' expr { $$ = op_gt ($1, $3); } 924Srgrimes | expr '<' expr { $$ = op_lt ($1, $3); } 934Srgrimes | expr GE expr { $$ = op_ge ($1, $3); } 944Srgrimes | expr LE expr { $$ = op_le ($1, $3); } 954Srgrimes | expr NE expr { $$ = op_ne ($1, $3); } 964Srgrimes | expr '+' expr { $$ = op_plus ($1, $3); } 974Srgrimes | expr '-' expr { $$ = op_minus ($1, $3); } 984Srgrimes | expr '*' expr { $$ = op_times ($1, $3); } 994Srgrimes | expr '/' expr { $$ = op_div ($1, $3); } 1004Srgrimes | expr '%' expr { $$ = op_rem ($1, $3); } 1014Srgrimes | expr ':' expr { $$ = op_colon ($1, $3); } 1024Srgrimes ; 1034Srgrimes 1044Srgrimes 1054Srgrimes%% 1064Srgrimes 1074Srgrimesstruct val * 10890109Simpmake_integer(quad_t i) 1094Srgrimes{ 1104Srgrimes struct val *vp; 1114Srgrimes 1124Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1134Srgrimes if (vp == NULL) { 11412378Sjoerg errx (2, "malloc() failed"); 1154Srgrimes } 1164Srgrimes 1174Srgrimes vp->type = integer; 1184Srgrimes vp->u.i = i; 1194Srgrimes return vp; 1204Srgrimes} 1214Srgrimes 1224Srgrimesstruct val * 12390109Simpmake_str(const char *s) 1244Srgrimes{ 1254Srgrimes struct val *vp; 12677244Skris size_t i; 12777244Skris int isint; 1284Srgrimes 1294Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1304Srgrimes if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 13112378Sjoerg errx (2, "malloc() failed"); 1324Srgrimes } 1334Srgrimes 1349909Sjoerg for(i = 1, isint = isdigit(s[0]) || s[0] == '-'; 1359909Sjoerg isint && i < strlen(s); 1369909Sjoerg i++) 1379909Sjoerg { 1389909Sjoerg if(!isdigit(s[i])) 1399909Sjoerg isint = 0; 1409909Sjoerg } 1419909Sjoerg 14212378Sjoerg if (isint) 14312378Sjoerg vp->type = numeric_string; 14412378Sjoerg else 14512378Sjoerg vp->type = string; 1469909Sjoerg 1474Srgrimes return vp; 1484Srgrimes} 1494Srgrimes 1504Srgrimes 1514Srgrimesvoid 15290109Simpfree_value(struct val *vp) 1534Srgrimes{ 15412378Sjoerg if (vp->type == string || vp->type == numeric_string) 1554Srgrimes free (vp->u.s); 1564Srgrimes} 1574Srgrimes 1584Srgrimes 15962926Ssequad_t 16090109Simpto_integer(struct val *vp) 1614Srgrimes{ 16262926Sse quad_t i; 1634Srgrimes 1644Srgrimes if (vp->type == integer) 1654Srgrimes return 1; 1664Srgrimes 16712378Sjoerg if (vp->type == string) 16812378Sjoerg return 0; 1694Srgrimes 17012378Sjoerg /* vp->type == numeric_string, make it numeric */ 17163755Sse errno = 0; 17262926Sse i = strtoq(vp->u.s, (char**)NULL, 10); 17363755Sse if (errno != 0) { 17463755Sse errx (2, "overflow"); 17563755Sse } 1764Srgrimes free (vp->u.s); 17712378Sjoerg vp->u.i = i; 1784Srgrimes vp->type = integer; 1794Srgrimes return 1; 1804Srgrimes} 1814Srgrimes 1824Srgrimesvoid 18390109Simpto_string(struct val *vp) 1844Srgrimes{ 1854Srgrimes char *tmp; 1864Srgrimes 18712378Sjoerg if (vp->type == string || vp->type == numeric_string) 1884Srgrimes return; 1894Srgrimes 19077244Skris tmp = malloc ((size_t)25); 1914Srgrimes if (tmp == NULL) { 19212378Sjoerg errx (2, "malloc() failed"); 1934Srgrimes } 1944Srgrimes 19577244Skris sprintf (tmp, "%lld", (long long)vp->u.i); 1964Srgrimes vp->type = string; 1974Srgrimes vp->u.s = tmp; 1984Srgrimes} 1994Srgrimes 2004Srgrimes 2014Srgrimesint 20290109Simpisstring(struct val *vp) 2034Srgrimes{ 20412378Sjoerg /* only TRUE if this string is not a valid integer */ 2054Srgrimes return (vp->type == string); 2064Srgrimes} 2074Srgrimes 2084Srgrimes 2094Srgrimesint 21090109Simpyylex(void) 2114Srgrimes{ 2124Srgrimes char *p; 2134Srgrimes 2144Srgrimes if (*av == NULL) 2154Srgrimes return (0); 2164Srgrimes 2174Srgrimes p = *av++; 2184Srgrimes 2194Srgrimes if (strlen (p) == 1) { 2204Srgrimes if (strchr ("|&=<>+-*/%:()", *p)) 2214Srgrimes return (*p); 2224Srgrimes } else if (strlen (p) == 2 && p[1] == '=') { 2234Srgrimes switch (*p) { 2244Srgrimes case '>': return (GE); 2254Srgrimes case '<': return (LE); 2264Srgrimes case '!': return (NE); 2274Srgrimes } 2284Srgrimes } 2294Srgrimes 2304Srgrimes yylval.val = make_str (p); 2314Srgrimes return (TOKEN); 2324Srgrimes} 2334Srgrimes 2344Srgrimesint 23590109Simpis_zero_or_null(struct val *vp) 2364Srgrimes{ 2374Srgrimes if (vp->type == integer) { 2384Srgrimes return (vp->u.i == 0); 2394Srgrimes } else { 240181Sconklin return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 2414Srgrimes } 2424Srgrimes /* NOTREACHED */ 2434Srgrimes} 2444Srgrimes 24512378Sjoergint 24690109Simpmain(int argc __unused, char *argv[]) 2474Srgrimes{ 248468Sjtc setlocale (LC_ALL, ""); 249468Sjtc 2504Srgrimes av = argv + 1; 2514Srgrimes 2524Srgrimes yyparse (); 2534Srgrimes 2544Srgrimes if (result->type == integer) 25577244Skris printf ("%lld\n", (long long)result->u.i); 2564Srgrimes else 2574Srgrimes printf ("%s\n", result->u.s); 2584Srgrimes 25912378Sjoerg return (is_zero_or_null (result)); 2604Srgrimes} 2614Srgrimes 2624Srgrimesint 26390109Simpyyerror(const char *s __unused) 2644Srgrimes{ 265295Sjtc errx (2, "syntax error"); 2664Srgrimes} 2674Srgrimes 2684Srgrimes 2694Srgrimesstruct val * 27090109Simpop_or(struct val *a, struct val *b) 2714Srgrimes{ 2724Srgrimes if (is_zero_or_null (a)) { 2734Srgrimes free_value (a); 2744Srgrimes return (b); 2754Srgrimes } else { 2764Srgrimes free_value (b); 2774Srgrimes return (a); 2784Srgrimes } 2794Srgrimes} 2804Srgrimes 2814Srgrimesstruct val * 28290109Simpop_and(struct val *a, struct val *b) 2834Srgrimes{ 2844Srgrimes if (is_zero_or_null (a) || is_zero_or_null (b)) { 2854Srgrimes free_value (a); 2864Srgrimes free_value (b); 28762926Sse return (make_integer ((quad_t)0)); 2884Srgrimes } else { 2894Srgrimes free_value (b); 2904Srgrimes return (a); 2914Srgrimes } 2924Srgrimes} 2934Srgrimes 2944Srgrimesstruct val * 29590109Simpop_eq(struct val *a, struct val *b) 2964Srgrimes{ 2974Srgrimes struct val *r; 2984Srgrimes 2994Srgrimes if (isstring (a) || isstring (b)) { 3004Srgrimes to_string (a); 3014Srgrimes to_string (b); 30262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0)); 3034Srgrimes } else { 30412378Sjoerg (void)to_integer(a); 30512378Sjoerg (void)to_integer(b); 30662926Sse r = make_integer ((quad_t)(a->u.i == b->u.i)); 3074Srgrimes } 3084Srgrimes 3094Srgrimes free_value (a); 3104Srgrimes free_value (b); 3114Srgrimes return r; 3124Srgrimes} 3134Srgrimes 3144Srgrimesstruct val * 31590109Simpop_gt(struct val *a, struct val *b) 3164Srgrimes{ 3174Srgrimes struct val *r; 3184Srgrimes 3194Srgrimes if (isstring (a) || isstring (b)) { 3204Srgrimes to_string (a); 3214Srgrimes to_string (b); 32262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0)); 3234Srgrimes } else { 32412378Sjoerg (void)to_integer(a); 32512378Sjoerg (void)to_integer(b); 32662926Sse r = make_integer ((quad_t)(a->u.i > b->u.i)); 3274Srgrimes } 3284Srgrimes 3294Srgrimes free_value (a); 3304Srgrimes free_value (b); 3314Srgrimes return r; 3324Srgrimes} 3334Srgrimes 3344Srgrimesstruct val * 33590109Simpop_lt(struct val *a, struct val *b) 3364Srgrimes{ 3374Srgrimes struct val *r; 3384Srgrimes 3394Srgrimes if (isstring (a) || isstring (b)) { 3404Srgrimes to_string (a); 3414Srgrimes to_string (b); 34262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0)); 3434Srgrimes } else { 34412378Sjoerg (void)to_integer(a); 34512378Sjoerg (void)to_integer(b); 34662926Sse r = make_integer ((quad_t)(a->u.i < b->u.i)); 3474Srgrimes } 3484Srgrimes 3494Srgrimes free_value (a); 3504Srgrimes free_value (b); 3514Srgrimes return r; 3524Srgrimes} 3534Srgrimes 3544Srgrimesstruct val * 35590109Simpop_ge(struct val *a, struct val *b) 3564Srgrimes{ 3574Srgrimes struct val *r; 3584Srgrimes 3594Srgrimes if (isstring (a) || isstring (b)) { 3604Srgrimes to_string (a); 3614Srgrimes to_string (b); 36262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0)); 3634Srgrimes } else { 36412378Sjoerg (void)to_integer(a); 36512378Sjoerg (void)to_integer(b); 36662926Sse r = make_integer ((quad_t)(a->u.i >= b->u.i)); 3674Srgrimes } 3684Srgrimes 3694Srgrimes free_value (a); 3704Srgrimes free_value (b); 3714Srgrimes return r; 3724Srgrimes} 3734Srgrimes 3744Srgrimesstruct val * 37590109Simpop_le(struct val *a, struct val *b) 3764Srgrimes{ 3774Srgrimes struct val *r; 3784Srgrimes 3794Srgrimes if (isstring (a) || isstring (b)) { 3804Srgrimes to_string (a); 3814Srgrimes to_string (b); 38262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0)); 3834Srgrimes } else { 38412378Sjoerg (void)to_integer(a); 38512378Sjoerg (void)to_integer(b); 38662926Sse r = make_integer ((quad_t)(a->u.i <= b->u.i)); 3874Srgrimes } 3884Srgrimes 3894Srgrimes free_value (a); 3904Srgrimes free_value (b); 3914Srgrimes return r; 3924Srgrimes} 3934Srgrimes 3944Srgrimesstruct val * 39590109Simpop_ne(struct val *a, struct val *b) 3964Srgrimes{ 3974Srgrimes struct val *r; 3984Srgrimes 3994Srgrimes if (isstring (a) || isstring (b)) { 4004Srgrimes to_string (a); 4014Srgrimes to_string (b); 40262926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0)); 4034Srgrimes } else { 40412378Sjoerg (void)to_integer(a); 40512378Sjoerg (void)to_integer(b); 40662926Sse r = make_integer ((quad_t)(a->u.i != b->u.i)); 4074Srgrimes } 4084Srgrimes 4094Srgrimes free_value (a); 4104Srgrimes free_value (b); 4114Srgrimes return r; 4124Srgrimes} 4134Srgrimes 41463755Sseint 41590109Simpchk_plus(quad_t a, quad_t b, quad_t r) 41663755Sse{ 41763755Sse /* sum of two positive numbers must be positive */ 41863755Sse if (a > 0 && b > 0 && r <= 0) 41963755Sse return 1; 42063755Sse /* sum of two negative numbers must be negative */ 42163755Sse if (a < 0 && b < 0 && r >= 0) 42263755Sse return 1; 42363755Sse /* all other cases are OK */ 42463755Sse return 0; 42563755Sse} 42663755Sse 4274Srgrimesstruct val * 42890109Simpop_plus(struct val *a, struct val *b) 4294Srgrimes{ 4304Srgrimes struct val *r; 4314Srgrimes 4324Srgrimes if (!to_integer (a) || !to_integer (b)) { 433295Sjtc errx (2, "non-numeric argument"); 4344Srgrimes } 4354Srgrimes 43662926Sse r = make_integer (/*(quad_t)*/(a->u.i + b->u.i)); 43763755Sse if (chk_plus (a->u.i, b->u.i, r->u.i)) { 43863755Sse errx (2, "overflow"); 43963755Sse } 4404Srgrimes free_value (a); 4414Srgrimes free_value (b); 4424Srgrimes return r; 4434Srgrimes} 44463755Sse 44563755Sseint 44690109Simpchk_minus(quad_t a, quad_t b, quad_t r) 44763755Sse{ 44863755Sse /* special case subtraction of QUAD_MIN */ 44963755Sse if (b == QUAD_MIN) { 45063755Sse if (a >= 0) 45163755Sse return 1; 45263755Sse else 45363755Sse return 0; 45463755Sse } 45563755Sse /* this is allowed for b != QUAD_MIN */ 45663755Sse return chk_plus (a, -b, r); 45763755Sse} 45863755Sse 4594Srgrimesstruct val * 46090109Simpop_minus(struct val *a, struct val *b) 4614Srgrimes{ 4624Srgrimes struct val *r; 4634Srgrimes 4644Srgrimes if (!to_integer (a) || !to_integer (b)) { 465295Sjtc errx (2, "non-numeric argument"); 4664Srgrimes } 4674Srgrimes 46862926Sse r = make_integer (/*(quad_t)*/(a->u.i - b->u.i)); 46963755Sse if (chk_minus (a->u.i, b->u.i, r->u.i)) { 47063755Sse errx (2, "overflow"); 47163755Sse } 4724Srgrimes free_value (a); 4734Srgrimes free_value (b); 4744Srgrimes return r; 4754Srgrimes} 47663755Sse 47763755Sseint 47890109Simpchk_times(quad_t a, quad_t b, quad_t r) 47963755Sse{ 48063755Sse /* special case: first operand is 0, no overflow possible */ 48163755Sse if (a == 0) 48263755Sse return 0; 48363755Sse /* cerify that result of division matches second operand */ 48463755Sse if (r / a != b) 48563755Sse return 1; 48663755Sse return 0; 48763755Sse} 48863755Sse 4894Srgrimesstruct val * 49090109Simpop_times(struct val *a, struct val *b) 4914Srgrimes{ 4924Srgrimes struct val *r; 4934Srgrimes 4944Srgrimes if (!to_integer (a) || !to_integer (b)) { 495295Sjtc errx (2, "non-numeric argument"); 4964Srgrimes } 4974Srgrimes 49862926Sse r = make_integer (/*(quad_t)*/(a->u.i * b->u.i)); 49963755Sse if (chk_times (a->u.i, b->u.i, r->u.i)) { 50063755Sse errx (2, "overflow"); 50163755Sse } 5024Srgrimes free_value (a); 5034Srgrimes free_value (b); 5044Srgrimes return (r); 5054Srgrimes} 50663755Sse 50763755Sseint 50890109Simpchk_div(quad_t a, quad_t b) 50963755Sse{ 51063755Sse /* div by zero has been taken care of before */ 51163755Sse /* only QUAD_MIN / -1 causes overflow */ 51263755Sse if (a == QUAD_MIN && b == -1) 51363755Sse return 1; 51463755Sse /* everything else is OK */ 51563755Sse return 0; 51663755Sse} 51763755Sse 5184Srgrimesstruct val * 51990109Simpop_div(struct val *a, struct val *b) 5204Srgrimes{ 5214Srgrimes struct val *r; 5224Srgrimes 5234Srgrimes if (!to_integer (a) || !to_integer (b)) { 524295Sjtc errx (2, "non-numeric argument"); 5254Srgrimes } 5264Srgrimes 5274Srgrimes if (b->u.i == 0) { 528295Sjtc errx (2, "division by zero"); 5294Srgrimes } 5304Srgrimes 53162926Sse r = make_integer (/*(quad_t)*/(a->u.i / b->u.i)); 53277244Skris if (chk_div (a->u.i, b->u.i)) { 53363755Sse errx (2, "overflow"); 53463755Sse } 5354Srgrimes free_value (a); 5364Srgrimes free_value (b); 5374Srgrimes return r; 5384Srgrimes} 5394Srgrimes 5404Srgrimesstruct val * 54190109Simpop_rem(struct val *a, struct val *b) 5424Srgrimes{ 5434Srgrimes struct val *r; 5444Srgrimes 5454Srgrimes if (!to_integer (a) || !to_integer (b)) { 546295Sjtc errx (2, "non-numeric argument"); 5474Srgrimes } 5484Srgrimes 5494Srgrimes if (b->u.i == 0) { 550295Sjtc errx (2, "division by zero"); 5514Srgrimes } 5524Srgrimes 55362926Sse r = make_integer (/*(quad_t)*/(a->u.i % b->u.i)); 55463755Sse /* chk_rem necessary ??? */ 5554Srgrimes free_value (a); 5564Srgrimes free_value (b); 5574Srgrimes return r; 5584Srgrimes} 5594Srgrimes 5604Srgrimesstruct val * 56190109Simpop_colon(struct val *a, struct val *b) 5624Srgrimes{ 56331Salm regex_t rp; 564468Sjtc regmatch_t rm[2]; 56531Salm char errbuf[256]; 56631Salm int eval; 567181Sconklin struct val *v; 5684Srgrimes 569181Sconklin /* coerce to both arguments to strings */ 570181Sconklin to_string(a); 571181Sconklin to_string(b); 572181Sconklin 57331Salm /* compile regular expression */ 574539Sjtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 57531Salm regerror (eval, &rp, errbuf, sizeof(errbuf)); 576295Sjtc errx (2, "%s", errbuf); 5774Srgrimes } 5784Srgrimes 57931Salm /* compare string against pattern */ 580539Sjtc /* remember that patterns are anchored to the beginning of the line */ 58177244Skris if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) { 58231Salm if (rm[1].rm_so >= 0) { 583295Sjtc *(a->u.s + rm[1].rm_eo) = '\0'; 58431Salm v = make_str (a->u.s + rm[1].rm_so); 58531Salm 5864Srgrimes } else { 58762926Sse v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so)); 5884Srgrimes } 5894Srgrimes } else { 590295Sjtc if (rp.re_nsub == 0) { 59162926Sse v = make_integer ((quad_t)0); 592295Sjtc } else { 593295Sjtc v = make_str (""); 594295Sjtc } 5954Srgrimes } 5964Srgrimes 59731Salm /* free arguments and pattern buffer */ 59831Salm free_value (a); 59931Salm free_value (b); 60031Salm regfree (&rp); 60131Salm 60231Salm return v; 6034Srgrimes} 604