expr.y revision 63755
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 63755 2000-07-22 10:59:36Z se $ 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; 344Srgrimesstruct val *op_or (); 354Srgrimesstruct val *op_and (); 364Srgrimesstruct val *op_eq (); 374Srgrimesstruct val *op_gt (); 384Srgrimesstruct val *op_lt (); 394Srgrimesstruct val *op_ge (); 404Srgrimesstruct val *op_le (); 414Srgrimesstruct val *op_ne (); 424Srgrimesstruct val *op_plus (); 434Srgrimesstruct val *op_minus (); 444Srgrimesstruct val *op_times (); 454Srgrimesstruct val *op_div (); 464Srgrimesstruct val *op_rem (); 474Srgrimesstruct val *op_colon (); 484Srgrimes 494Srgrimeschar **av; 504Srgrimes%} 514Srgrimes 524Srgrimes%union 534Srgrimes{ 544Srgrimes struct val *val; 554Srgrimes} 564Srgrimes 574Srgrimes%left <val> '|' 584Srgrimes%left <val> '&' 594Srgrimes%left <val> '=' '>' '<' GE LE NE 604Srgrimes%left <val> '+' '-' 614Srgrimes%left <val> '*' '/' '%' 624Srgrimes%left <val> ':' 634Srgrimes 644Srgrimes%token <val> TOKEN 654Srgrimes%type <val> start expr 664Srgrimes 674Srgrimes%% 684Srgrimes 694Srgrimesstart: expr { result = $$; } 704Srgrimes 714Srgrimesexpr: TOKEN 724Srgrimes | '(' expr ')' { $$ = $2; } 734Srgrimes | expr '|' expr { $$ = op_or ($1, $3); } 744Srgrimes | expr '&' expr { $$ = op_and ($1, $3); } 754Srgrimes | expr '=' expr { $$ = op_eq ($1, $3); } 764Srgrimes | expr '>' expr { $$ = op_gt ($1, $3); } 774Srgrimes | expr '<' expr { $$ = op_lt ($1, $3); } 784Srgrimes | expr GE expr { $$ = op_ge ($1, $3); } 794Srgrimes | expr LE expr { $$ = op_le ($1, $3); } 804Srgrimes | expr NE expr { $$ = op_ne ($1, $3); } 814Srgrimes | expr '+' expr { $$ = op_plus ($1, $3); } 824Srgrimes | expr '-' expr { $$ = op_minus ($1, $3); } 834Srgrimes | expr '*' expr { $$ = op_times ($1, $3); } 844Srgrimes | expr '/' expr { $$ = op_div ($1, $3); } 854Srgrimes | expr '%' expr { $$ = op_rem ($1, $3); } 864Srgrimes | expr ':' expr { $$ = op_colon ($1, $3); } 874Srgrimes ; 884Srgrimes 894Srgrimes 904Srgrimes%% 914Srgrimes 924Srgrimesstruct val * 934Srgrimesmake_integer (i) 9462926Ssequad_t i; 954Srgrimes{ 964Srgrimes struct val *vp; 974Srgrimes 984Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 994Srgrimes if (vp == NULL) { 10012378Sjoerg errx (2, "malloc() failed"); 1014Srgrimes } 1024Srgrimes 1034Srgrimes vp->type = integer; 1044Srgrimes vp->u.i = i; 1054Srgrimes return vp; 1064Srgrimes} 1074Srgrimes 1084Srgrimesstruct val * 1094Srgrimesmake_str (s) 1104Srgrimeschar *s; 1114Srgrimes{ 1124Srgrimes struct val *vp; 1139909Sjoerg int i, isint; 1144Srgrimes 1154Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1164Srgrimes if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 11712378Sjoerg errx (2, "malloc() failed"); 1184Srgrimes } 1194Srgrimes 1209909Sjoerg for(i = 1, isint = isdigit(s[0]) || s[0] == '-'; 1219909Sjoerg isint && i < strlen(s); 1229909Sjoerg i++) 1239909Sjoerg { 1249909Sjoerg if(!isdigit(s[i])) 1259909Sjoerg isint = 0; 1269909Sjoerg } 1279909Sjoerg 12812378Sjoerg if (isint) 12912378Sjoerg vp->type = numeric_string; 13012378Sjoerg else 13112378Sjoerg vp->type = string; 1329909Sjoerg 1334Srgrimes return vp; 1344Srgrimes} 1354Srgrimes 1364Srgrimes 1374Srgrimesvoid 1384Srgrimesfree_value (vp) 1394Srgrimesstruct val *vp; 1404Srgrimes{ 14112378Sjoerg if (vp->type == string || vp->type == numeric_string) 1424Srgrimes free (vp->u.s); 1434Srgrimes} 1444Srgrimes 1454Srgrimes 14662926Ssequad_t 1474Srgrimesto_integer (vp) 1484Srgrimesstruct val *vp; 1494Srgrimes{ 15062926Sse quad_t i; 1514Srgrimes 1524Srgrimes if (vp->type == integer) 1534Srgrimes return 1; 1544Srgrimes 15512378Sjoerg if (vp->type == string) 15612378Sjoerg return 0; 1574Srgrimes 15812378Sjoerg /* vp->type == numeric_string, make it numeric */ 15963755Sse errno = 0; 16062926Sse i = strtoq(vp->u.s, (char**)NULL, 10); 16163755Sse if (errno != 0) { 16263755Sse errx (2, "overflow"); 16363755Sse } 1644Srgrimes free (vp->u.s); 16512378Sjoerg vp->u.i = i; 1664Srgrimes vp->type = integer; 1674Srgrimes return 1; 1684Srgrimes} 1694Srgrimes 1704Srgrimesvoid 1714Srgrimesto_string (vp) 1724Srgrimesstruct val *vp; 1734Srgrimes{ 1744Srgrimes char *tmp; 1754Srgrimes 17612378Sjoerg if (vp->type == string || vp->type == numeric_string) 1774Srgrimes return; 1784Srgrimes 1794Srgrimes tmp = malloc (25); 1804Srgrimes if (tmp == NULL) { 18112378Sjoerg errx (2, "malloc() failed"); 1824Srgrimes } 1834Srgrimes 18462926Sse sprintf (tmp, "%qd", vp->u.i); 1854Srgrimes vp->type = string; 1864Srgrimes vp->u.s = tmp; 1874Srgrimes} 1884Srgrimes 1894Srgrimes 1904Srgrimesint 1914Srgrimesisstring (vp) 1924Srgrimesstruct val *vp; 1934Srgrimes{ 19412378Sjoerg /* only TRUE if this string is not a valid integer */ 1954Srgrimes return (vp->type == string); 1964Srgrimes} 1974Srgrimes 1984Srgrimes 1994Srgrimesint 2004Srgrimesyylex () 2014Srgrimes{ 2024Srgrimes char *p; 2034Srgrimes 2044Srgrimes if (*av == NULL) 2054Srgrimes return (0); 2064Srgrimes 2074Srgrimes p = *av++; 2084Srgrimes 2094Srgrimes if (strlen (p) == 1) { 2104Srgrimes if (strchr ("|&=<>+-*/%:()", *p)) 2114Srgrimes return (*p); 2124Srgrimes } else if (strlen (p) == 2 && p[1] == '=') { 2134Srgrimes switch (*p) { 2144Srgrimes case '>': return (GE); 2154Srgrimes case '<': return (LE); 2164Srgrimes case '!': return (NE); 2174Srgrimes } 2184Srgrimes } 2194Srgrimes 2204Srgrimes yylval.val = make_str (p); 2214Srgrimes return (TOKEN); 2224Srgrimes} 2234Srgrimes 2244Srgrimesint 2254Srgrimesis_zero_or_null (vp) 2264Srgrimesstruct val *vp; 2274Srgrimes{ 2284Srgrimes if (vp->type == integer) { 2294Srgrimes return (vp->u.i == 0); 2304Srgrimes } else { 231181Sconklin return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 2324Srgrimes } 2334Srgrimes /* NOTREACHED */ 2344Srgrimes} 2354Srgrimes 2367165Sjoergint yyparse (); 2377165Sjoerg 23812378Sjoergint 2394Srgrimesmain (argc, argv) 2404Srgrimesint argc; 2414Srgrimeschar **argv; 2424Srgrimes{ 243468Sjtc setlocale (LC_ALL, ""); 244468Sjtc 2454Srgrimes av = argv + 1; 2464Srgrimes 2474Srgrimes yyparse (); 2484Srgrimes 2494Srgrimes if (result->type == integer) 25062926Sse printf ("%qd\n", result->u.i); 2514Srgrimes else 2524Srgrimes printf ("%s\n", result->u.s); 2534Srgrimes 25412378Sjoerg return (is_zero_or_null (result)); 2554Srgrimes} 2564Srgrimes 2574Srgrimesint 2584Srgrimesyyerror (s) 2594Srgrimeschar *s; 2604Srgrimes{ 261295Sjtc errx (2, "syntax error"); 2624Srgrimes} 2634Srgrimes 2644Srgrimes 2654Srgrimesstruct val * 2664Srgrimesop_or (a, b) 2674Srgrimesstruct val *a, *b; 2684Srgrimes{ 2694Srgrimes if (is_zero_or_null (a)) { 2704Srgrimes free_value (a); 2714Srgrimes return (b); 2724Srgrimes } else { 2734Srgrimes free_value (b); 2744Srgrimes return (a); 2754Srgrimes } 2764Srgrimes} 2774Srgrimes 2784Srgrimesstruct val * 2794Srgrimesop_and (a, b) 2804Srgrimesstruct val *a, *b; 2814Srgrimes{ 2824Srgrimes if (is_zero_or_null (a) || is_zero_or_null (b)) { 2834Srgrimes free_value (a); 2844Srgrimes free_value (b); 28562926Sse return (make_integer ((quad_t)0)); 2864Srgrimes } else { 2874Srgrimes free_value (b); 2884Srgrimes return (a); 2894Srgrimes } 2904Srgrimes} 2914Srgrimes 2924Srgrimesstruct val * 2934Srgrimesop_eq (a, b) 2944Srgrimesstruct val *a, *b; 2954Srgrimes{ 2964Srgrimes struct val *r; 2974Srgrimes 2984Srgrimes if (isstring (a) || isstring (b)) { 2994Srgrimes to_string (a); 3004Srgrimes to_string (b); 30162926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0)); 3024Srgrimes } else { 30312378Sjoerg (void)to_integer(a); 30412378Sjoerg (void)to_integer(b); 30562926Sse r = make_integer ((quad_t)(a->u.i == b->u.i)); 3064Srgrimes } 3074Srgrimes 3084Srgrimes free_value (a); 3094Srgrimes free_value (b); 3104Srgrimes return r; 3114Srgrimes} 3124Srgrimes 3134Srgrimesstruct val * 3144Srgrimesop_gt (a, b) 3154Srgrimesstruct val *a, *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 * 3354Srgrimesop_lt (a, b) 3364Srgrimesstruct val *a, *b; 3374Srgrimes{ 3384Srgrimes struct val *r; 3394Srgrimes 3404Srgrimes if (isstring (a) || isstring (b)) { 3414Srgrimes to_string (a); 3424Srgrimes to_string (b); 34362926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0)); 3444Srgrimes } else { 34512378Sjoerg (void)to_integer(a); 34612378Sjoerg (void)to_integer(b); 34762926Sse r = make_integer ((quad_t)(a->u.i < b->u.i)); 3484Srgrimes } 3494Srgrimes 3504Srgrimes free_value (a); 3514Srgrimes free_value (b); 3524Srgrimes return r; 3534Srgrimes} 3544Srgrimes 3554Srgrimesstruct val * 3564Srgrimesop_ge (a, b) 3574Srgrimesstruct val *a, *b; 3584Srgrimes{ 3594Srgrimes struct val *r; 3604Srgrimes 3614Srgrimes if (isstring (a) || isstring (b)) { 3624Srgrimes to_string (a); 3634Srgrimes to_string (b); 36462926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0)); 3654Srgrimes } else { 36612378Sjoerg (void)to_integer(a); 36712378Sjoerg (void)to_integer(b); 36862926Sse r = make_integer ((quad_t)(a->u.i >= b->u.i)); 3694Srgrimes } 3704Srgrimes 3714Srgrimes free_value (a); 3724Srgrimes free_value (b); 3734Srgrimes return r; 3744Srgrimes} 3754Srgrimes 3764Srgrimesstruct val * 3774Srgrimesop_le (a, b) 3784Srgrimesstruct val *a, *b; 3794Srgrimes{ 3804Srgrimes struct val *r; 3814Srgrimes 3824Srgrimes if (isstring (a) || isstring (b)) { 3834Srgrimes to_string (a); 3844Srgrimes to_string (b); 38562926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0)); 3864Srgrimes } else { 38712378Sjoerg (void)to_integer(a); 38812378Sjoerg (void)to_integer(b); 38962926Sse r = make_integer ((quad_t)(a->u.i <= b->u.i)); 3904Srgrimes } 3914Srgrimes 3924Srgrimes free_value (a); 3934Srgrimes free_value (b); 3944Srgrimes return r; 3954Srgrimes} 3964Srgrimes 3974Srgrimesstruct val * 3984Srgrimesop_ne (a, b) 3994Srgrimesstruct val *a, *b; 4004Srgrimes{ 4014Srgrimes struct val *r; 4024Srgrimes 4034Srgrimes if (isstring (a) || isstring (b)) { 4044Srgrimes to_string (a); 4054Srgrimes to_string (b); 40662926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0)); 4074Srgrimes } else { 40812378Sjoerg (void)to_integer(a); 40912378Sjoerg (void)to_integer(b); 41062926Sse r = make_integer ((quad_t)(a->u.i != b->u.i)); 4114Srgrimes } 4124Srgrimes 4134Srgrimes free_value (a); 4144Srgrimes free_value (b); 4154Srgrimes return r; 4164Srgrimes} 4174Srgrimes 41863755Sseint 41963755Ssechk_plus (a, b, r) 42063755Ssequad_t a, b, r; 42163755Sse{ 42263755Sse /* sum of two positive numbers must be positive */ 42363755Sse if (a > 0 && b > 0 && r <= 0) 42463755Sse return 1; 42563755Sse /* sum of two negative numbers must be negative */ 42663755Sse if (a < 0 && b < 0 && r >= 0) 42763755Sse return 1; 42863755Sse /* all other cases are OK */ 42963755Sse return 0; 43063755Sse} 43163755Sse 4324Srgrimesstruct val * 4334Srgrimesop_plus (a, b) 4344Srgrimesstruct val *a, *b; 4354Srgrimes{ 4364Srgrimes struct val *r; 4374Srgrimes 4384Srgrimes if (!to_integer (a) || !to_integer (b)) { 439295Sjtc errx (2, "non-numeric argument"); 4404Srgrimes } 4414Srgrimes 44262926Sse r = make_integer (/*(quad_t)*/(a->u.i + b->u.i)); 44363755Sse if (chk_plus (a->u.i, b->u.i, r->u.i)) { 44463755Sse errx (2, "overflow"); 44563755Sse } 4464Srgrimes free_value (a); 4474Srgrimes free_value (b); 4484Srgrimes return r; 4494Srgrimes} 45063755Sse 45163755Sseint 45263755Ssechk_minus (a, b, r) 45363755Ssequad_t a, b, r; 45463755Sse{ 45563755Sse /* special case subtraction of QUAD_MIN */ 45663755Sse if (b == QUAD_MIN) { 45763755Sse if (a >= 0) 45863755Sse return 1; 45963755Sse else 46063755Sse return 0; 46163755Sse } 46263755Sse /* this is allowed for b != QUAD_MIN */ 46363755Sse return chk_plus (a, -b, r); 46463755Sse} 46563755Sse 4664Srgrimesstruct val * 4674Srgrimesop_minus (a, b) 4684Srgrimesstruct val *a, *b; 4694Srgrimes{ 4704Srgrimes struct val *r; 4714Srgrimes 4724Srgrimes if (!to_integer (a) || !to_integer (b)) { 473295Sjtc errx (2, "non-numeric argument"); 4744Srgrimes } 4754Srgrimes 47662926Sse r = make_integer (/*(quad_t)*/(a->u.i - b->u.i)); 47763755Sse if (chk_minus (a->u.i, b->u.i, r->u.i)) { 47863755Sse errx (2, "overflow"); 47963755Sse } 4804Srgrimes free_value (a); 4814Srgrimes free_value (b); 4824Srgrimes return r; 4834Srgrimes} 48463755Sse 48563755Sseint 48663755Ssechk_times (a, b, r) 48763755Ssequad_t a, b, r; 48863755Sse{ 48963755Sse /* special case: first operand is 0, no overflow possible */ 49063755Sse if (a == 0) 49163755Sse return 0; 49263755Sse /* cerify that result of division matches second operand */ 49363755Sse if (r / a != b) 49463755Sse return 1; 49563755Sse return 0; 49663755Sse} 49763755Sse 4984Srgrimesstruct val * 4994Srgrimesop_times (a, b) 5004Srgrimesstruct val *a, *b; 5014Srgrimes{ 5024Srgrimes struct val *r; 5034Srgrimes 5044Srgrimes if (!to_integer (a) || !to_integer (b)) { 505295Sjtc errx (2, "non-numeric argument"); 5064Srgrimes } 5074Srgrimes 50862926Sse r = make_integer (/*(quad_t)*/(a->u.i * b->u.i)); 50963755Sse if (chk_times (a->u.i, b->u.i, r->u.i)) { 51063755Sse errx (2, "overflow"); 51163755Sse } 5124Srgrimes free_value (a); 5134Srgrimes free_value (b); 5144Srgrimes return (r); 5154Srgrimes} 51663755Sse 51763755Sseint 51863755Ssechk_div (a, b, r) 51963755Ssequad_t a, b, r; 52063755Sse{ 52163755Sse /* div by zero has been taken care of before */ 52263755Sse /* only QUAD_MIN / -1 causes overflow */ 52363755Sse if (a == QUAD_MIN && b == -1) 52463755Sse return 1; 52563755Sse /* everything else is OK */ 52663755Sse return 0; 52763755Sse} 52863755Sse 5294Srgrimesstruct val * 5304Srgrimesop_div (a, b) 5314Srgrimesstruct val *a, *b; 5324Srgrimes{ 5334Srgrimes struct val *r; 5344Srgrimes 5354Srgrimes if (!to_integer (a) || !to_integer (b)) { 536295Sjtc errx (2, "non-numeric argument"); 5374Srgrimes } 5384Srgrimes 5394Srgrimes if (b->u.i == 0) { 540295Sjtc errx (2, "division by zero"); 5414Srgrimes } 5424Srgrimes 54362926Sse r = make_integer (/*(quad_t)*/(a->u.i / b->u.i)); 54463755Sse if (chk_div (a->u.i, b->u.i, r->u.i)) { 54563755Sse errx (2, "overflow"); 54663755Sse } 5474Srgrimes free_value (a); 5484Srgrimes free_value (b); 5494Srgrimes return r; 5504Srgrimes} 5514Srgrimes 5524Srgrimesstruct val * 5534Srgrimesop_rem (a, b) 5544Srgrimesstruct val *a, *b; 5554Srgrimes{ 5564Srgrimes struct val *r; 5574Srgrimes 5584Srgrimes if (!to_integer (a) || !to_integer (b)) { 559295Sjtc errx (2, "non-numeric argument"); 5604Srgrimes } 5614Srgrimes 5624Srgrimes if (b->u.i == 0) { 563295Sjtc errx (2, "division by zero"); 5644Srgrimes } 5654Srgrimes 56662926Sse r = make_integer (/*(quad_t)*/(a->u.i % b->u.i)); 56763755Sse /* chk_rem necessary ??? */ 5684Srgrimes free_value (a); 5694Srgrimes free_value (b); 5704Srgrimes return r; 5714Srgrimes} 5724Srgrimes 5734Srgrimesstruct val * 5744Srgrimesop_colon (a, b) 5754Srgrimesstruct val *a, *b; 5764Srgrimes{ 57731Salm regex_t rp; 578468Sjtc regmatch_t rm[2]; 57931Salm char errbuf[256]; 58031Salm int eval; 581181Sconklin struct val *v; 5824Srgrimes 583181Sconklin /* coerce to both arguments to strings */ 584181Sconklin to_string(a); 585181Sconklin to_string(b); 586181Sconklin 58731Salm /* compile regular expression */ 588539Sjtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 58931Salm regerror (eval, &rp, errbuf, sizeof(errbuf)); 590295Sjtc errx (2, "%s", errbuf); 5914Srgrimes } 5924Srgrimes 59331Salm /* compare string against pattern */ 594539Sjtc /* remember that patterns are anchored to the beginning of the line */ 595539Sjtc if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { 59631Salm if (rm[1].rm_so >= 0) { 597295Sjtc *(a->u.s + rm[1].rm_eo) = '\0'; 59831Salm v = make_str (a->u.s + rm[1].rm_so); 59931Salm 6004Srgrimes } else { 60162926Sse v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so)); 6024Srgrimes } 6034Srgrimes } else { 604295Sjtc if (rp.re_nsub == 0) { 60562926Sse v = make_integer ((quad_t)0); 606295Sjtc } else { 607295Sjtc v = make_str (""); 608295Sjtc } 6094Srgrimes } 6104Srgrimes 61131Salm /* free arguments and pattern buffer */ 61231Salm free_value (a); 61331Salm free_value (b); 61431Salm regfree (&rp); 61531Salm 61631Salm return v; 6174Srgrimes} 618