expr.y revision 62926
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 62926 2000-07-10 21:30:55Z 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> 1762926Sse#include <regex.h> 1831Salm 194Srgrimesenum valtype { 2012378Sjoerg integer, numeric_string, string 214Srgrimes} ; 2231Salm 234Srgrimesstruct val { 244Srgrimes enum valtype type; 254Srgrimes union { 264Srgrimes char *s; 2762926Sse quad_t i; 284Srgrimes } u; 2931Salm} ; 304Srgrimes 314Srgrimesstruct val *result; 324Srgrimesstruct val *op_or (); 334Srgrimesstruct val *op_and (); 344Srgrimesstruct val *op_eq (); 354Srgrimesstruct val *op_gt (); 364Srgrimesstruct val *op_lt (); 374Srgrimesstruct val *op_ge (); 384Srgrimesstruct val *op_le (); 394Srgrimesstruct val *op_ne (); 404Srgrimesstruct val *op_plus (); 414Srgrimesstruct val *op_minus (); 424Srgrimesstruct val *op_times (); 434Srgrimesstruct val *op_div (); 444Srgrimesstruct val *op_rem (); 454Srgrimesstruct val *op_colon (); 464Srgrimes 474Srgrimeschar **av; 484Srgrimes%} 494Srgrimes 504Srgrimes%union 514Srgrimes{ 524Srgrimes struct val *val; 534Srgrimes} 544Srgrimes 554Srgrimes%left <val> '|' 564Srgrimes%left <val> '&' 574Srgrimes%left <val> '=' '>' '<' GE LE NE 584Srgrimes%left <val> '+' '-' 594Srgrimes%left <val> '*' '/' '%' 604Srgrimes%left <val> ':' 614Srgrimes 624Srgrimes%token <val> TOKEN 634Srgrimes%type <val> start expr 644Srgrimes 654Srgrimes%% 664Srgrimes 674Srgrimesstart: expr { result = $$; } 684Srgrimes 694Srgrimesexpr: TOKEN 704Srgrimes | '(' expr ')' { $$ = $2; } 714Srgrimes | expr '|' expr { $$ = op_or ($1, $3); } 724Srgrimes | expr '&' expr { $$ = op_and ($1, $3); } 734Srgrimes | expr '=' expr { $$ = op_eq ($1, $3); } 744Srgrimes | expr '>' expr { $$ = op_gt ($1, $3); } 754Srgrimes | expr '<' expr { $$ = op_lt ($1, $3); } 764Srgrimes | expr GE expr { $$ = op_ge ($1, $3); } 774Srgrimes | expr LE expr { $$ = op_le ($1, $3); } 784Srgrimes | expr NE expr { $$ = op_ne ($1, $3); } 794Srgrimes | expr '+' expr { $$ = op_plus ($1, $3); } 804Srgrimes | expr '-' expr { $$ = op_minus ($1, $3); } 814Srgrimes | expr '*' expr { $$ = op_times ($1, $3); } 824Srgrimes | expr '/' expr { $$ = op_div ($1, $3); } 834Srgrimes | expr '%' expr { $$ = op_rem ($1, $3); } 844Srgrimes | expr ':' expr { $$ = op_colon ($1, $3); } 854Srgrimes ; 864Srgrimes 874Srgrimes 884Srgrimes%% 894Srgrimes 904Srgrimesstruct val * 914Srgrimesmake_integer (i) 9262926Ssequad_t i; 934Srgrimes{ 944Srgrimes struct val *vp; 954Srgrimes 964Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 974Srgrimes if (vp == NULL) { 9812378Sjoerg errx (2, "malloc() failed"); 994Srgrimes } 1004Srgrimes 1014Srgrimes vp->type = integer; 1024Srgrimes vp->u.i = i; 1034Srgrimes return vp; 1044Srgrimes} 1054Srgrimes 1064Srgrimesstruct val * 1074Srgrimesmake_str (s) 1084Srgrimeschar *s; 1094Srgrimes{ 1104Srgrimes struct val *vp; 1119909Sjoerg int i, isint; 1124Srgrimes 1134Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1144Srgrimes if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 11512378Sjoerg errx (2, "malloc() failed"); 1164Srgrimes } 1174Srgrimes 1189909Sjoerg for(i = 1, isint = isdigit(s[0]) || s[0] == '-'; 1199909Sjoerg isint && i < strlen(s); 1209909Sjoerg i++) 1219909Sjoerg { 1229909Sjoerg if(!isdigit(s[i])) 1239909Sjoerg isint = 0; 1249909Sjoerg } 1259909Sjoerg 12612378Sjoerg if (isint) 12712378Sjoerg vp->type = numeric_string; 12812378Sjoerg else 12912378Sjoerg vp->type = string; 1309909Sjoerg 1314Srgrimes return vp; 1324Srgrimes} 1334Srgrimes 1344Srgrimes 1354Srgrimesvoid 1364Srgrimesfree_value (vp) 1374Srgrimesstruct val *vp; 1384Srgrimes{ 13912378Sjoerg if (vp->type == string || vp->type == numeric_string) 1404Srgrimes free (vp->u.s); 1414Srgrimes} 1424Srgrimes 1434Srgrimes 14462926Ssequad_t 1454Srgrimesto_integer (vp) 1464Srgrimesstruct val *vp; 1474Srgrimes{ 14862926Sse quad_t i; 1494Srgrimes 1504Srgrimes if (vp->type == integer) 1514Srgrimes return 1; 1524Srgrimes 15312378Sjoerg if (vp->type == string) 15412378Sjoerg return 0; 1554Srgrimes 15612378Sjoerg /* vp->type == numeric_string, make it numeric */ 15762926Sse i = strtoq(vp->u.s, (char**)NULL, 10); 1584Srgrimes free (vp->u.s); 15912378Sjoerg vp->u.i = i; 1604Srgrimes vp->type = integer; 1614Srgrimes return 1; 1624Srgrimes} 1634Srgrimes 1644Srgrimesvoid 1654Srgrimesto_string (vp) 1664Srgrimesstruct val *vp; 1674Srgrimes{ 1684Srgrimes char *tmp; 1694Srgrimes 17012378Sjoerg if (vp->type == string || vp->type == numeric_string) 1714Srgrimes return; 1724Srgrimes 1734Srgrimes tmp = malloc (25); 1744Srgrimes if (tmp == NULL) { 17512378Sjoerg errx (2, "malloc() failed"); 1764Srgrimes } 1774Srgrimes 17862926Sse sprintf (tmp, "%qd", vp->u.i); 1794Srgrimes vp->type = string; 1804Srgrimes vp->u.s = tmp; 1814Srgrimes} 1824Srgrimes 1834Srgrimes 1844Srgrimesint 1854Srgrimesisstring (vp) 1864Srgrimesstruct val *vp; 1874Srgrimes{ 18812378Sjoerg /* only TRUE if this string is not a valid integer */ 1894Srgrimes return (vp->type == string); 1904Srgrimes} 1914Srgrimes 1924Srgrimes 1934Srgrimesint 1944Srgrimesyylex () 1954Srgrimes{ 1964Srgrimes char *p; 1974Srgrimes 1984Srgrimes if (*av == NULL) 1994Srgrimes return (0); 2004Srgrimes 2014Srgrimes p = *av++; 2024Srgrimes 2034Srgrimes if (strlen (p) == 1) { 2044Srgrimes if (strchr ("|&=<>+-*/%:()", *p)) 2054Srgrimes return (*p); 2064Srgrimes } else if (strlen (p) == 2 && p[1] == '=') { 2074Srgrimes switch (*p) { 2084Srgrimes case '>': return (GE); 2094Srgrimes case '<': return (LE); 2104Srgrimes case '!': return (NE); 2114Srgrimes } 2124Srgrimes } 2134Srgrimes 2144Srgrimes yylval.val = make_str (p); 2154Srgrimes return (TOKEN); 2164Srgrimes} 2174Srgrimes 2184Srgrimesint 2194Srgrimesis_zero_or_null (vp) 2204Srgrimesstruct val *vp; 2214Srgrimes{ 2224Srgrimes if (vp->type == integer) { 2234Srgrimes return (vp->u.i == 0); 2244Srgrimes } else { 225181Sconklin return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 2264Srgrimes } 2274Srgrimes /* NOTREACHED */ 2284Srgrimes} 2294Srgrimes 2307165Sjoergint yyparse (); 2317165Sjoerg 23212378Sjoergint 2334Srgrimesmain (argc, argv) 2344Srgrimesint argc; 2354Srgrimeschar **argv; 2364Srgrimes{ 237468Sjtc setlocale (LC_ALL, ""); 238468Sjtc 2394Srgrimes av = argv + 1; 2404Srgrimes 2414Srgrimes yyparse (); 2424Srgrimes 2434Srgrimes if (result->type == integer) 24462926Sse printf ("%qd\n", result->u.i); 2454Srgrimes else 2464Srgrimes printf ("%s\n", result->u.s); 2474Srgrimes 24812378Sjoerg return (is_zero_or_null (result)); 2494Srgrimes} 2504Srgrimes 2514Srgrimesint 2524Srgrimesyyerror (s) 2534Srgrimeschar *s; 2544Srgrimes{ 255295Sjtc errx (2, "syntax error"); 2564Srgrimes} 2574Srgrimes 2584Srgrimes 2594Srgrimesstruct val * 2604Srgrimesop_or (a, b) 2614Srgrimesstruct val *a, *b; 2624Srgrimes{ 2634Srgrimes if (is_zero_or_null (a)) { 2644Srgrimes free_value (a); 2654Srgrimes return (b); 2664Srgrimes } else { 2674Srgrimes free_value (b); 2684Srgrimes return (a); 2694Srgrimes } 2704Srgrimes} 2714Srgrimes 2724Srgrimesstruct val * 2734Srgrimesop_and (a, b) 2744Srgrimesstruct val *a, *b; 2754Srgrimes{ 2764Srgrimes if (is_zero_or_null (a) || is_zero_or_null (b)) { 2774Srgrimes free_value (a); 2784Srgrimes free_value (b); 27962926Sse return (make_integer ((quad_t)0)); 2804Srgrimes } else { 2814Srgrimes free_value (b); 2824Srgrimes return (a); 2834Srgrimes } 2844Srgrimes} 2854Srgrimes 2864Srgrimesstruct val * 2874Srgrimesop_eq (a, b) 2884Srgrimesstruct val *a, *b; 2894Srgrimes{ 2904Srgrimes struct val *r; 2914Srgrimes 2924Srgrimes if (isstring (a) || isstring (b)) { 2934Srgrimes to_string (a); 2944Srgrimes to_string (b); 29562926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0)); 2964Srgrimes } else { 29712378Sjoerg (void)to_integer(a); 29812378Sjoerg (void)to_integer(b); 29962926Sse r = make_integer ((quad_t)(a->u.i == b->u.i)); 3004Srgrimes } 3014Srgrimes 3024Srgrimes free_value (a); 3034Srgrimes free_value (b); 3044Srgrimes return r; 3054Srgrimes} 3064Srgrimes 3074Srgrimesstruct val * 3084Srgrimesop_gt (a, b) 3094Srgrimesstruct val *a, *b; 3104Srgrimes{ 3114Srgrimes struct val *r; 3124Srgrimes 3134Srgrimes if (isstring (a) || isstring (b)) { 3144Srgrimes to_string (a); 3154Srgrimes to_string (b); 31662926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0)); 3174Srgrimes } else { 31812378Sjoerg (void)to_integer(a); 31912378Sjoerg (void)to_integer(b); 32062926Sse r = make_integer ((quad_t)(a->u.i > b->u.i)); 3214Srgrimes } 3224Srgrimes 3234Srgrimes free_value (a); 3244Srgrimes free_value (b); 3254Srgrimes return r; 3264Srgrimes} 3274Srgrimes 3284Srgrimesstruct val * 3294Srgrimesop_lt (a, b) 3304Srgrimesstruct val *a, *b; 3314Srgrimes{ 3324Srgrimes struct val *r; 3334Srgrimes 3344Srgrimes if (isstring (a) || isstring (b)) { 3354Srgrimes to_string (a); 3364Srgrimes to_string (b); 33762926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0)); 3384Srgrimes } else { 33912378Sjoerg (void)to_integer(a); 34012378Sjoerg (void)to_integer(b); 34162926Sse r = make_integer ((quad_t)(a->u.i < b->u.i)); 3424Srgrimes } 3434Srgrimes 3444Srgrimes free_value (a); 3454Srgrimes free_value (b); 3464Srgrimes return r; 3474Srgrimes} 3484Srgrimes 3494Srgrimesstruct val * 3504Srgrimesop_ge (a, b) 3514Srgrimesstruct val *a, *b; 3524Srgrimes{ 3534Srgrimes struct val *r; 3544Srgrimes 3554Srgrimes if (isstring (a) || isstring (b)) { 3564Srgrimes to_string (a); 3574Srgrimes to_string (b); 35862926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0)); 3594Srgrimes } else { 36012378Sjoerg (void)to_integer(a); 36112378Sjoerg (void)to_integer(b); 36262926Sse r = make_integer ((quad_t)(a->u.i >= b->u.i)); 3634Srgrimes } 3644Srgrimes 3654Srgrimes free_value (a); 3664Srgrimes free_value (b); 3674Srgrimes return r; 3684Srgrimes} 3694Srgrimes 3704Srgrimesstruct val * 3714Srgrimesop_le (a, b) 3724Srgrimesstruct val *a, *b; 3734Srgrimes{ 3744Srgrimes struct val *r; 3754Srgrimes 3764Srgrimes if (isstring (a) || isstring (b)) { 3774Srgrimes to_string (a); 3784Srgrimes to_string (b); 37962926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0)); 3804Srgrimes } else { 38112378Sjoerg (void)to_integer(a); 38212378Sjoerg (void)to_integer(b); 38362926Sse r = make_integer ((quad_t)(a->u.i <= b->u.i)); 3844Srgrimes } 3854Srgrimes 3864Srgrimes free_value (a); 3874Srgrimes free_value (b); 3884Srgrimes return r; 3894Srgrimes} 3904Srgrimes 3914Srgrimesstruct val * 3924Srgrimesop_ne (a, b) 3934Srgrimesstruct val *a, *b; 3944Srgrimes{ 3954Srgrimes struct val *r; 3964Srgrimes 3974Srgrimes if (isstring (a) || isstring (b)) { 3984Srgrimes to_string (a); 3994Srgrimes to_string (b); 40062926Sse r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0)); 4014Srgrimes } else { 40212378Sjoerg (void)to_integer(a); 40312378Sjoerg (void)to_integer(b); 40462926Sse r = make_integer ((quad_t)(a->u.i != b->u.i)); 4054Srgrimes } 4064Srgrimes 4074Srgrimes free_value (a); 4084Srgrimes free_value (b); 4094Srgrimes return r; 4104Srgrimes} 4114Srgrimes 4124Srgrimesstruct val * 4134Srgrimesop_plus (a, b) 4144Srgrimesstruct val *a, *b; 4154Srgrimes{ 4164Srgrimes struct val *r; 4174Srgrimes 4184Srgrimes if (!to_integer (a) || !to_integer (b)) { 419295Sjtc errx (2, "non-numeric argument"); 4204Srgrimes } 4214Srgrimes 42262926Sse r = make_integer (/*(quad_t)*/(a->u.i + b->u.i)); 4234Srgrimes free_value (a); 4244Srgrimes free_value (b); 4254Srgrimes return r; 4264Srgrimes} 4274Srgrimes 4284Srgrimesstruct val * 4294Srgrimesop_minus (a, b) 4304Srgrimesstruct val *a, *b; 4314Srgrimes{ 4324Srgrimes struct val *r; 4334Srgrimes 4344Srgrimes if (!to_integer (a) || !to_integer (b)) { 435295Sjtc errx (2, "non-numeric argument"); 4364Srgrimes } 4374Srgrimes 43862926Sse r = make_integer (/*(quad_t)*/(a->u.i - b->u.i)); 4394Srgrimes free_value (a); 4404Srgrimes free_value (b); 4414Srgrimes return r; 4424Srgrimes} 4434Srgrimes 4444Srgrimesstruct val * 4454Srgrimesop_times (a, b) 4464Srgrimesstruct val *a, *b; 4474Srgrimes{ 4484Srgrimes struct val *r; 4494Srgrimes 4504Srgrimes if (!to_integer (a) || !to_integer (b)) { 451295Sjtc errx (2, "non-numeric argument"); 4524Srgrimes } 4534Srgrimes 45462926Sse r = make_integer (/*(quad_t)*/(a->u.i * b->u.i)); 4554Srgrimes free_value (a); 4564Srgrimes free_value (b); 4574Srgrimes return (r); 4584Srgrimes} 4594Srgrimes 4604Srgrimesstruct val * 4614Srgrimesop_div (a, b) 4624Srgrimesstruct val *a, *b; 4634Srgrimes{ 4644Srgrimes struct val *r; 4654Srgrimes 4664Srgrimes if (!to_integer (a) || !to_integer (b)) { 467295Sjtc errx (2, "non-numeric argument"); 4684Srgrimes } 4694Srgrimes 4704Srgrimes if (b->u.i == 0) { 471295Sjtc errx (2, "division by zero"); 4724Srgrimes } 4734Srgrimes 47462926Sse r = make_integer (/*(quad_t)*/(a->u.i / b->u.i)); 4754Srgrimes free_value (a); 4764Srgrimes free_value (b); 4774Srgrimes return r; 4784Srgrimes} 4794Srgrimes 4804Srgrimesstruct val * 4814Srgrimesop_rem (a, b) 4824Srgrimesstruct val *a, *b; 4834Srgrimes{ 4844Srgrimes struct val *r; 4854Srgrimes 4864Srgrimes if (!to_integer (a) || !to_integer (b)) { 487295Sjtc errx (2, "non-numeric argument"); 4884Srgrimes } 4894Srgrimes 4904Srgrimes if (b->u.i == 0) { 491295Sjtc errx (2, "division by zero"); 4924Srgrimes } 4934Srgrimes 49462926Sse r = make_integer (/*(quad_t)*/(a->u.i % b->u.i)); 4954Srgrimes free_value (a); 4964Srgrimes free_value (b); 4974Srgrimes return r; 4984Srgrimes} 4994Srgrimes 5004Srgrimesstruct val * 5014Srgrimesop_colon (a, b) 5024Srgrimesstruct val *a, *b; 5034Srgrimes{ 50431Salm regex_t rp; 505468Sjtc regmatch_t rm[2]; 50631Salm char errbuf[256]; 50731Salm int eval; 508181Sconklin struct val *v; 5094Srgrimes 510181Sconklin /* coerce to both arguments to strings */ 511181Sconklin to_string(a); 512181Sconklin to_string(b); 513181Sconklin 51431Salm /* compile regular expression */ 515539Sjtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 51631Salm regerror (eval, &rp, errbuf, sizeof(errbuf)); 517295Sjtc errx (2, "%s", errbuf); 5184Srgrimes } 5194Srgrimes 52031Salm /* compare string against pattern */ 521539Sjtc /* remember that patterns are anchored to the beginning of the line */ 522539Sjtc if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { 52331Salm if (rm[1].rm_so >= 0) { 524295Sjtc *(a->u.s + rm[1].rm_eo) = '\0'; 52531Salm v = make_str (a->u.s + rm[1].rm_so); 52631Salm 5274Srgrimes } else { 52862926Sse v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so)); 5294Srgrimes } 5304Srgrimes } else { 531295Sjtc if (rp.re_nsub == 0) { 53262926Sse v = make_integer ((quad_t)0); 533295Sjtc } else { 534295Sjtc v = make_str (""); 535295Sjtc } 5364Srgrimes } 5374Srgrimes 53831Salm /* free arguments and pattern buffer */ 53931Salm free_value (a); 54031Salm free_value (b); 54131Salm regfree (&rp); 54231Salm 54331Salm return v; 5444Srgrimes} 545