15b81b6b3SRodney W. Grimes %{ 25b81b6b3SRodney W. Grimes /* Written by Pace Willisson (pace@blitz.com) 355c497bfSJ.T. Conklin * and placed in the public domain. 45b81b6b3SRodney W. Grimes * 555c497bfSJ.T. Conklin * Largely rewritten by J.T. Conklin (jtc@wimsey.com) 655c497bfSJ.T. Conklin * 72a456239SPeter Wemm * $FreeBSD$ 85b81b6b3SRodney W. Grimes */ 94cf61abaSJ.T. Conklin 1064867286SStefan Eßer #include <sys/types.h> 115b81b6b3SRodney W. Grimes #include <stdio.h> 125b81b6b3SRodney W. Grimes #include <stdlib.h> 135b81b6b3SRodney W. Grimes #include <string.h> 144cf61abaSJ.T. Conklin #include <locale.h> 155b81b6b3SRodney W. Grimes #include <ctype.h> 1655c497bfSJ.T. Conklin #include <err.h> 17915198b4SStefan Eßer #include <errno.h> 1864867286SStefan Eßer #include <regex.h> 19915198b4SStefan Eßer #include <limits.h> 205b81b6b3SRodney W. Grimes 215b81b6b3SRodney W. Grimes enum valtype { 22717252eaSJoerg Wunsch integer, numeric_string, string 235b81b6b3SRodney W. Grimes } ; 245b81b6b3SRodney W. Grimes 255b81b6b3SRodney W. Grimes struct val { 265b81b6b3SRodney W. Grimes enum valtype type; 275b81b6b3SRodney W. Grimes union { 285b81b6b3SRodney W. Grimes char *s; 2964867286SStefan Eßer quad_t i; 305b81b6b3SRodney W. Grimes } u; 315b81b6b3SRodney W. Grimes } ; 325b81b6b3SRodney W. Grimes 335b81b6b3SRodney W. Grimes struct val *result; 343d06e95dSKris Kennaway 357669d0fcSWarner Losh int chk_div(quad_t, quad_t); 367669d0fcSWarner Losh int chk_minus(quad_t, quad_t, quad_t); 377669d0fcSWarner Losh int chk_plus(quad_t, quad_t, quad_t); 387669d0fcSWarner Losh int chk_times(quad_t, quad_t, quad_t); 397669d0fcSWarner Losh void free_value(struct val *); 407669d0fcSWarner Losh int is_zero_or_null(struct val *); 417669d0fcSWarner Losh int isstring(struct val *); 427669d0fcSWarner Losh struct val *make_integer(quad_t); 437669d0fcSWarner Losh struct val *make_str(const char *); 447669d0fcSWarner Losh struct val *op_and(struct val *, struct val *); 457669d0fcSWarner Losh struct val *op_colon(struct val *, struct val *); 467669d0fcSWarner Losh struct val *op_div(struct val *, struct val *); 477669d0fcSWarner Losh struct val *op_eq(struct val *, struct val *); 487669d0fcSWarner Losh struct val *op_ge(struct val *, struct val *); 497669d0fcSWarner Losh struct val *op_gt(struct val *, struct val *); 507669d0fcSWarner Losh struct val *op_le(struct val *, struct val *); 517669d0fcSWarner Losh struct val *op_lt(struct val *, struct val *); 527669d0fcSWarner Losh struct val *op_minus(struct val *, struct val *); 537669d0fcSWarner Losh struct val *op_ne(struct val *, struct val *); 547669d0fcSWarner Losh struct val *op_or(struct val *, struct val *); 557669d0fcSWarner Losh struct val *op_plus(struct val *, struct val *); 567669d0fcSWarner Losh struct val *op_rem(struct val *, struct val *); 577669d0fcSWarner Losh struct val *op_times(struct val *, struct val *); 587669d0fcSWarner Losh quad_t to_integer(struct val *); 597669d0fcSWarner Losh void to_string(struct val *); 607669d0fcSWarner Losh int yyerror(const char *); 617669d0fcSWarner Losh int yylex(void); 627669d0fcSWarner Losh int yyparse(void); 635b81b6b3SRodney W. Grimes 645b81b6b3SRodney W. Grimes char **av; 655b81b6b3SRodney W. Grimes %} 665b81b6b3SRodney W. Grimes 675b81b6b3SRodney W. Grimes %union 685b81b6b3SRodney W. Grimes { 695b81b6b3SRodney W. Grimes struct val *val; 705b81b6b3SRodney W. Grimes } 715b81b6b3SRodney W. Grimes 725b81b6b3SRodney W. Grimes %left <val> '|' 735b81b6b3SRodney W. Grimes %left <val> '&' 745b81b6b3SRodney W. Grimes %left <val> '=' '>' '<' GE LE NE 755b81b6b3SRodney W. Grimes %left <val> '+' '-' 765b81b6b3SRodney W. Grimes %left <val> '*' '/' '%' 775b81b6b3SRodney W. Grimes %left <val> ':' 785b81b6b3SRodney W. Grimes 795b81b6b3SRodney W. Grimes %token <val> TOKEN 805b81b6b3SRodney W. Grimes %type <val> start expr 815b81b6b3SRodney W. Grimes 825b81b6b3SRodney W. Grimes %% 835b81b6b3SRodney W. Grimes 845b81b6b3SRodney W. Grimes start: expr { result = $$; } 855b81b6b3SRodney W. Grimes 865b81b6b3SRodney W. Grimes expr: TOKEN 875b81b6b3SRodney W. Grimes | '(' expr ')' { $$ = $2; } 885b81b6b3SRodney W. Grimes | expr '|' expr { $$ = op_or ($1, $3); } 895b81b6b3SRodney W. Grimes | expr '&' expr { $$ = op_and ($1, $3); } 905b81b6b3SRodney W. Grimes | expr '=' expr { $$ = op_eq ($1, $3); } 915b81b6b3SRodney W. Grimes | expr '>' expr { $$ = op_gt ($1, $3); } 925b81b6b3SRodney W. Grimes | expr '<' expr { $$ = op_lt ($1, $3); } 935b81b6b3SRodney W. Grimes | expr GE expr { $$ = op_ge ($1, $3); } 945b81b6b3SRodney W. Grimes | expr LE expr { $$ = op_le ($1, $3); } 955b81b6b3SRodney W. Grimes | expr NE expr { $$ = op_ne ($1, $3); } 965b81b6b3SRodney W. Grimes | expr '+' expr { $$ = op_plus ($1, $3); } 975b81b6b3SRodney W. Grimes | expr '-' expr { $$ = op_minus ($1, $3); } 985b81b6b3SRodney W. Grimes | expr '*' expr { $$ = op_times ($1, $3); } 995b81b6b3SRodney W. Grimes | expr '/' expr { $$ = op_div ($1, $3); } 1005b81b6b3SRodney W. Grimes | expr '%' expr { $$ = op_rem ($1, $3); } 1015b81b6b3SRodney W. Grimes | expr ':' expr { $$ = op_colon ($1, $3); } 1025b81b6b3SRodney W. Grimes ; 1035b81b6b3SRodney W. Grimes 1045b81b6b3SRodney W. Grimes 1055b81b6b3SRodney W. Grimes %% 1065b81b6b3SRodney W. Grimes 1075b81b6b3SRodney W. Grimes struct val * 1087669d0fcSWarner Losh make_integer(quad_t i) 1095b81b6b3SRodney W. Grimes { 1105b81b6b3SRodney W. Grimes struct val *vp; 1115b81b6b3SRodney W. Grimes 1125b81b6b3SRodney W. Grimes vp = (struct val *) malloc (sizeof (*vp)); 1135b81b6b3SRodney W. Grimes if (vp == NULL) { 114717252eaSJoerg Wunsch errx (2, "malloc() failed"); 1155b81b6b3SRodney W. Grimes } 1165b81b6b3SRodney W. Grimes 1175b81b6b3SRodney W. Grimes vp->type = integer; 1185b81b6b3SRodney W. Grimes vp->u.i = i; 1195b81b6b3SRodney W. Grimes return vp; 1205b81b6b3SRodney W. Grimes } 1215b81b6b3SRodney W. Grimes 1225b81b6b3SRodney W. Grimes struct val * 1237669d0fcSWarner Losh make_str(const char *s) 1245b81b6b3SRodney W. Grimes { 1255b81b6b3SRodney W. Grimes struct val *vp; 1263d06e95dSKris Kennaway size_t i; 1273d06e95dSKris Kennaway int isint; 1285b81b6b3SRodney W. Grimes 1295b81b6b3SRodney W. Grimes vp = (struct val *) malloc (sizeof (*vp)); 1305b81b6b3SRodney W. Grimes if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 131717252eaSJoerg Wunsch errx (2, "malloc() failed"); 1325b81b6b3SRodney W. Grimes } 1335b81b6b3SRodney W. Grimes 1342a353a9fSJoerg Wunsch for(i = 1, isint = isdigit(s[0]) || s[0] == '-'; 1352a353a9fSJoerg Wunsch isint && i < strlen(s); 1362a353a9fSJoerg Wunsch i++) 1372a353a9fSJoerg Wunsch { 1382a353a9fSJoerg Wunsch if(!isdigit(s[i])) 1392a353a9fSJoerg Wunsch isint = 0; 1402a353a9fSJoerg Wunsch } 1412a353a9fSJoerg Wunsch 1422a353a9fSJoerg Wunsch if (isint) 143717252eaSJoerg Wunsch vp->type = numeric_string; 144717252eaSJoerg Wunsch else 145717252eaSJoerg Wunsch vp->type = string; 1462a353a9fSJoerg Wunsch 1475b81b6b3SRodney W. Grimes return vp; 1485b81b6b3SRodney W. Grimes } 1495b81b6b3SRodney W. Grimes 1505b81b6b3SRodney W. Grimes 1515b81b6b3SRodney W. Grimes void 1527669d0fcSWarner Losh free_value(struct val *vp) 1535b81b6b3SRodney W. Grimes { 154717252eaSJoerg Wunsch if (vp->type == string || vp->type == numeric_string) 1555b81b6b3SRodney W. Grimes free (vp->u.s); 1565b81b6b3SRodney W. Grimes } 1575b81b6b3SRodney W. Grimes 1585b81b6b3SRodney W. Grimes 15964867286SStefan Eßer quad_t 1607669d0fcSWarner Losh to_integer(struct val *vp) 1615b81b6b3SRodney W. Grimes { 16264867286SStefan Eßer quad_t i; 1635b81b6b3SRodney W. Grimes 1645b81b6b3SRodney W. Grimes if (vp->type == integer) 1655b81b6b3SRodney W. Grimes return 1; 1665b81b6b3SRodney W. Grimes 167717252eaSJoerg Wunsch if (vp->type == string) 1685b81b6b3SRodney W. Grimes return 0; 1695b81b6b3SRodney W. Grimes 170717252eaSJoerg Wunsch /* vp->type == numeric_string, make it numeric */ 171915198b4SStefan Eßer errno = 0; 17264867286SStefan Eßer i = strtoq(vp->u.s, (char**)NULL, 10); 173915198b4SStefan Eßer if (errno != 0) { 174915198b4SStefan Eßer errx (2, "overflow"); 175915198b4SStefan Eßer } 1765b81b6b3SRodney W. Grimes free (vp->u.s); 1775b81b6b3SRodney W. Grimes vp->u.i = i; 178717252eaSJoerg Wunsch vp->type = integer; 1795b81b6b3SRodney W. Grimes return 1; 1805b81b6b3SRodney W. Grimes } 1815b81b6b3SRodney W. Grimes 1825b81b6b3SRodney W. Grimes void 1837669d0fcSWarner Losh to_string(struct val *vp) 1845b81b6b3SRodney W. Grimes { 1855b81b6b3SRodney W. Grimes char *tmp; 1865b81b6b3SRodney W. Grimes 187717252eaSJoerg Wunsch if (vp->type == string || vp->type == numeric_string) 1885b81b6b3SRodney W. Grimes return; 1895b81b6b3SRodney W. Grimes 1903d06e95dSKris Kennaway tmp = malloc ((size_t)25); 1915b81b6b3SRodney W. Grimes if (tmp == NULL) { 192717252eaSJoerg Wunsch errx (2, "malloc() failed"); 1935b81b6b3SRodney W. Grimes } 1945b81b6b3SRodney W. Grimes 1953d06e95dSKris Kennaway sprintf (tmp, "%lld", (long long)vp->u.i); 1965b81b6b3SRodney W. Grimes vp->type = string; 1975b81b6b3SRodney W. Grimes vp->u.s = tmp; 1985b81b6b3SRodney W. Grimes } 1995b81b6b3SRodney W. Grimes 2005b81b6b3SRodney W. Grimes 2015b81b6b3SRodney W. Grimes int 2027669d0fcSWarner Losh isstring(struct val *vp) 2035b81b6b3SRodney W. Grimes { 204717252eaSJoerg Wunsch /* only TRUE if this string is not a valid integer */ 2055b81b6b3SRodney W. Grimes return (vp->type == string); 2065b81b6b3SRodney W. Grimes } 2075b81b6b3SRodney W. Grimes 2085b81b6b3SRodney W. Grimes 2095b81b6b3SRodney W. Grimes int 2107669d0fcSWarner Losh yylex(void) 2115b81b6b3SRodney W. Grimes { 2125b81b6b3SRodney W. Grimes char *p; 2135b81b6b3SRodney W. Grimes 2145b81b6b3SRodney W. Grimes if (*av == NULL) 2155b81b6b3SRodney W. Grimes return (0); 2165b81b6b3SRodney W. Grimes 2175b81b6b3SRodney W. Grimes p = *av++; 2185b81b6b3SRodney W. Grimes 2195b81b6b3SRodney W. Grimes if (strlen (p) == 1) { 2205b81b6b3SRodney W. Grimes if (strchr ("|&=<>+-*/%:()", *p)) 2215b81b6b3SRodney W. Grimes return (*p); 2225b81b6b3SRodney W. Grimes } else if (strlen (p) == 2 && p[1] == '=') { 2235b81b6b3SRodney W. Grimes switch (*p) { 2245b81b6b3SRodney W. Grimes case '>': return (GE); 2255b81b6b3SRodney W. Grimes case '<': return (LE); 2265b81b6b3SRodney W. Grimes case '!': return (NE); 2275b81b6b3SRodney W. Grimes } 2285b81b6b3SRodney W. Grimes } 2295b81b6b3SRodney W. Grimes 2305b81b6b3SRodney W. Grimes yylval.val = make_str (p); 2315b81b6b3SRodney W. Grimes return (TOKEN); 2325b81b6b3SRodney W. Grimes } 2335b81b6b3SRodney W. Grimes 2345b81b6b3SRodney W. Grimes int 2357669d0fcSWarner Losh is_zero_or_null(struct val *vp) 2365b81b6b3SRodney W. Grimes { 2375b81b6b3SRodney W. Grimes if (vp->type == integer) { 2385b81b6b3SRodney W. Grimes return (vp->u.i == 0); 2395b81b6b3SRodney W. Grimes } else { 240c9fe00dcSJ.T. Conklin return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 2415b81b6b3SRodney W. Grimes } 2425b81b6b3SRodney W. Grimes /* NOTREACHED */ 2435b81b6b3SRodney W. Grimes } 2445b81b6b3SRodney W. Grimes 245717252eaSJoerg Wunsch int 2467669d0fcSWarner Losh main(int argc __unused, char *argv[]) 2475b81b6b3SRodney W. Grimes { 2484cf61abaSJ.T. Conklin setlocale (LC_ALL, ""); 2494cf61abaSJ.T. Conklin 2505b81b6b3SRodney W. Grimes av = argv + 1; 2515b81b6b3SRodney W. Grimes 2525b81b6b3SRodney W. Grimes yyparse (); 2535b81b6b3SRodney W. Grimes 2545b81b6b3SRodney W. Grimes if (result->type == integer) 2553d06e95dSKris Kennaway printf ("%lld\n", (long long)result->u.i); 2565b81b6b3SRodney W. Grimes else 2575b81b6b3SRodney W. Grimes printf ("%s\n", result->u.s); 2585b81b6b3SRodney W. Grimes 259717252eaSJoerg Wunsch return (is_zero_or_null (result)); 2605b81b6b3SRodney W. Grimes } 2615b81b6b3SRodney W. Grimes 2625b81b6b3SRodney W. Grimes int 2637669d0fcSWarner Losh yyerror(const char *s __unused) 2645b81b6b3SRodney W. Grimes { 26555c497bfSJ.T. Conklin errx (2, "syntax error"); 2665b81b6b3SRodney W. Grimes } 2675b81b6b3SRodney W. Grimes 2685b81b6b3SRodney W. Grimes 2695b81b6b3SRodney W. Grimes struct val * 2707669d0fcSWarner Losh op_or(struct val *a, struct val *b) 2715b81b6b3SRodney W. Grimes { 2725b81b6b3SRodney W. Grimes if (is_zero_or_null (a)) { 2735b81b6b3SRodney W. Grimes free_value (a); 2745b81b6b3SRodney W. Grimes return (b); 2755b81b6b3SRodney W. Grimes } else { 2765b81b6b3SRodney W. Grimes free_value (b); 2775b81b6b3SRodney W. Grimes return (a); 2785b81b6b3SRodney W. Grimes } 2795b81b6b3SRodney W. Grimes } 2805b81b6b3SRodney W. Grimes 2815b81b6b3SRodney W. Grimes struct val * 2827669d0fcSWarner Losh op_and(struct val *a, struct val *b) 2835b81b6b3SRodney W. Grimes { 2845b81b6b3SRodney W. Grimes if (is_zero_or_null (a) || is_zero_or_null (b)) { 2855b81b6b3SRodney W. Grimes free_value (a); 2865b81b6b3SRodney W. Grimes free_value (b); 28764867286SStefan Eßer return (make_integer ((quad_t)0)); 2885b81b6b3SRodney W. Grimes } else { 2895b81b6b3SRodney W. Grimes free_value (b); 2905b81b6b3SRodney W. Grimes return (a); 2915b81b6b3SRodney W. Grimes } 2925b81b6b3SRodney W. Grimes } 2935b81b6b3SRodney W. Grimes 2945b81b6b3SRodney W. Grimes struct val * 2957669d0fcSWarner Losh op_eq(struct val *a, struct val *b) 2965b81b6b3SRodney W. Grimes { 2975b81b6b3SRodney W. Grimes struct val *r; 2985b81b6b3SRodney W. Grimes 2995b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 3005b81b6b3SRodney W. Grimes to_string (a); 3015b81b6b3SRodney W. Grimes to_string (b); 30264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0)); 3035b81b6b3SRodney W. Grimes } else { 304717252eaSJoerg Wunsch (void)to_integer(a); 305717252eaSJoerg Wunsch (void)to_integer(b); 30664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i == b->u.i)); 3075b81b6b3SRodney W. Grimes } 3085b81b6b3SRodney W. Grimes 3095b81b6b3SRodney W. Grimes free_value (a); 3105b81b6b3SRodney W. Grimes free_value (b); 3115b81b6b3SRodney W. Grimes return r; 3125b81b6b3SRodney W. Grimes } 3135b81b6b3SRodney W. Grimes 3145b81b6b3SRodney W. Grimes struct val * 3157669d0fcSWarner Losh op_gt(struct val *a, struct val *b) 3165b81b6b3SRodney W. Grimes { 3175b81b6b3SRodney W. Grimes struct val *r; 3185b81b6b3SRodney W. Grimes 3195b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 3205b81b6b3SRodney W. Grimes to_string (a); 3215b81b6b3SRodney W. Grimes to_string (b); 32264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0)); 3235b81b6b3SRodney W. Grimes } else { 324717252eaSJoerg Wunsch (void)to_integer(a); 325717252eaSJoerg Wunsch (void)to_integer(b); 32664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i > b->u.i)); 3275b81b6b3SRodney W. Grimes } 3285b81b6b3SRodney W. Grimes 3295b81b6b3SRodney W. Grimes free_value (a); 3305b81b6b3SRodney W. Grimes free_value (b); 3315b81b6b3SRodney W. Grimes return r; 3325b81b6b3SRodney W. Grimes } 3335b81b6b3SRodney W. Grimes 3345b81b6b3SRodney W. Grimes struct val * 3357669d0fcSWarner Losh op_lt(struct val *a, struct val *b) 3365b81b6b3SRodney W. Grimes { 3375b81b6b3SRodney W. Grimes struct val *r; 3385b81b6b3SRodney W. Grimes 3395b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 3405b81b6b3SRodney W. Grimes to_string (a); 3415b81b6b3SRodney W. Grimes to_string (b); 34264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0)); 3435b81b6b3SRodney W. Grimes } else { 344717252eaSJoerg Wunsch (void)to_integer(a); 345717252eaSJoerg Wunsch (void)to_integer(b); 34664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i < b->u.i)); 3475b81b6b3SRodney W. Grimes } 3485b81b6b3SRodney W. Grimes 3495b81b6b3SRodney W. Grimes free_value (a); 3505b81b6b3SRodney W. Grimes free_value (b); 3515b81b6b3SRodney W. Grimes return r; 3525b81b6b3SRodney W. Grimes } 3535b81b6b3SRodney W. Grimes 3545b81b6b3SRodney W. Grimes struct val * 3557669d0fcSWarner Losh op_ge(struct val *a, struct val *b) 3565b81b6b3SRodney W. Grimes { 3575b81b6b3SRodney W. Grimes struct val *r; 3585b81b6b3SRodney W. Grimes 3595b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 3605b81b6b3SRodney W. Grimes to_string (a); 3615b81b6b3SRodney W. Grimes to_string (b); 36264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0)); 3635b81b6b3SRodney W. Grimes } else { 364717252eaSJoerg Wunsch (void)to_integer(a); 365717252eaSJoerg Wunsch (void)to_integer(b); 36664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i >= b->u.i)); 3675b81b6b3SRodney W. Grimes } 3685b81b6b3SRodney W. Grimes 3695b81b6b3SRodney W. Grimes free_value (a); 3705b81b6b3SRodney W. Grimes free_value (b); 3715b81b6b3SRodney W. Grimes return r; 3725b81b6b3SRodney W. Grimes } 3735b81b6b3SRodney W. Grimes 3745b81b6b3SRodney W. Grimes struct val * 3757669d0fcSWarner Losh op_le(struct val *a, struct val *b) 3765b81b6b3SRodney W. Grimes { 3775b81b6b3SRodney W. Grimes struct val *r; 3785b81b6b3SRodney W. Grimes 3795b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 3805b81b6b3SRodney W. Grimes to_string (a); 3815b81b6b3SRodney W. Grimes to_string (b); 38264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0)); 3835b81b6b3SRodney W. Grimes } else { 384717252eaSJoerg Wunsch (void)to_integer(a); 385717252eaSJoerg Wunsch (void)to_integer(b); 38664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i <= b->u.i)); 3875b81b6b3SRodney W. Grimes } 3885b81b6b3SRodney W. Grimes 3895b81b6b3SRodney W. Grimes free_value (a); 3905b81b6b3SRodney W. Grimes free_value (b); 3915b81b6b3SRodney W. Grimes return r; 3925b81b6b3SRodney W. Grimes } 3935b81b6b3SRodney W. Grimes 3945b81b6b3SRodney W. Grimes struct val * 3957669d0fcSWarner Losh op_ne(struct val *a, struct val *b) 3965b81b6b3SRodney W. Grimes { 3975b81b6b3SRodney W. Grimes struct val *r; 3985b81b6b3SRodney W. Grimes 3995b81b6b3SRodney W. Grimes if (isstring (a) || isstring (b)) { 4005b81b6b3SRodney W. Grimes to_string (a); 4015b81b6b3SRodney W. Grimes to_string (b); 40264867286SStefan Eßer r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0)); 4035b81b6b3SRodney W. Grimes } else { 404717252eaSJoerg Wunsch (void)to_integer(a); 405717252eaSJoerg Wunsch (void)to_integer(b); 40664867286SStefan Eßer r = make_integer ((quad_t)(a->u.i != b->u.i)); 4075b81b6b3SRodney W. Grimes } 4085b81b6b3SRodney W. Grimes 4095b81b6b3SRodney W. Grimes free_value (a); 4105b81b6b3SRodney W. Grimes free_value (b); 4115b81b6b3SRodney W. Grimes return r; 4125b81b6b3SRodney W. Grimes } 4135b81b6b3SRodney W. Grimes 414915198b4SStefan Eßer int 4157669d0fcSWarner Losh chk_plus(quad_t a, quad_t b, quad_t r) 416915198b4SStefan Eßer { 417915198b4SStefan Eßer /* sum of two positive numbers must be positive */ 418915198b4SStefan Eßer if (a > 0 && b > 0 && r <= 0) 419915198b4SStefan Eßer return 1; 420915198b4SStefan Eßer /* sum of two negative numbers must be negative */ 421915198b4SStefan Eßer if (a < 0 && b < 0 && r >= 0) 422915198b4SStefan Eßer return 1; 423915198b4SStefan Eßer /* all other cases are OK */ 424915198b4SStefan Eßer return 0; 425915198b4SStefan Eßer } 426915198b4SStefan Eßer 4275b81b6b3SRodney W. Grimes struct val * 4287669d0fcSWarner Losh op_plus(struct val *a, struct val *b) 4295b81b6b3SRodney W. Grimes { 4305b81b6b3SRodney W. Grimes struct val *r; 4315b81b6b3SRodney W. Grimes 4325b81b6b3SRodney W. Grimes if (!to_integer (a) || !to_integer (b)) { 43355c497bfSJ.T. Conklin errx (2, "non-numeric argument"); 4345b81b6b3SRodney W. Grimes } 4355b81b6b3SRodney W. Grimes 43664867286SStefan Eßer r = make_integer (/*(quad_t)*/(a->u.i + b->u.i)); 437915198b4SStefan Eßer if (chk_plus (a->u.i, b->u.i, r->u.i)) { 438915198b4SStefan Eßer errx (2, "overflow"); 439915198b4SStefan Eßer } 4405b81b6b3SRodney W. Grimes free_value (a); 4415b81b6b3SRodney W. Grimes free_value (b); 4425b81b6b3SRodney W. Grimes return r; 4435b81b6b3SRodney W. Grimes } 4445b81b6b3SRodney W. Grimes 445915198b4SStefan Eßer int 4467669d0fcSWarner Losh chk_minus(quad_t a, quad_t b, quad_t r) 447915198b4SStefan Eßer { 448915198b4SStefan Eßer /* special case subtraction of QUAD_MIN */ 449915198b4SStefan Eßer if (b == QUAD_MIN) { 450915198b4SStefan Eßer if (a >= 0) 451915198b4SStefan Eßer return 1; 452915198b4SStefan Eßer else 453915198b4SStefan Eßer return 0; 454915198b4SStefan Eßer } 455915198b4SStefan Eßer /* this is allowed for b != QUAD_MIN */ 456915198b4SStefan Eßer return chk_plus (a, -b, r); 457915198b4SStefan Eßer } 458915198b4SStefan Eßer 4595b81b6b3SRodney W. Grimes struct val * 4607669d0fcSWarner Losh op_minus(struct val *a, struct val *b) 4615b81b6b3SRodney W. Grimes { 4625b81b6b3SRodney W. Grimes struct val *r; 4635b81b6b3SRodney W. Grimes 4645b81b6b3SRodney W. Grimes if (!to_integer (a) || !to_integer (b)) { 46555c497bfSJ.T. Conklin errx (2, "non-numeric argument"); 4665b81b6b3SRodney W. Grimes } 4675b81b6b3SRodney W. Grimes 46864867286SStefan Eßer r = make_integer (/*(quad_t)*/(a->u.i - b->u.i)); 469915198b4SStefan Eßer if (chk_minus (a->u.i, b->u.i, r->u.i)) { 470915198b4SStefan Eßer errx (2, "overflow"); 471915198b4SStefan Eßer } 4725b81b6b3SRodney W. Grimes free_value (a); 4735b81b6b3SRodney W. Grimes free_value (b); 4745b81b6b3SRodney W. Grimes return r; 4755b81b6b3SRodney W. Grimes } 4765b81b6b3SRodney W. Grimes 477915198b4SStefan Eßer int 4787669d0fcSWarner Losh chk_times(quad_t a, quad_t b, quad_t r) 479915198b4SStefan Eßer { 480915198b4SStefan Eßer /* special case: first operand is 0, no overflow possible */ 481915198b4SStefan Eßer if (a == 0) 482915198b4SStefan Eßer return 0; 483915198b4SStefan Eßer /* cerify that result of division matches second operand */ 484915198b4SStefan Eßer if (r / a != b) 485915198b4SStefan Eßer return 1; 486915198b4SStefan Eßer return 0; 487915198b4SStefan Eßer } 488915198b4SStefan Eßer 4895b81b6b3SRodney W. Grimes struct val * 4907669d0fcSWarner Losh op_times(struct val *a, struct val *b) 4915b81b6b3SRodney W. Grimes { 4925b81b6b3SRodney W. Grimes struct val *r; 4935b81b6b3SRodney W. Grimes 4945b81b6b3SRodney W. Grimes if (!to_integer (a) || !to_integer (b)) { 49555c497bfSJ.T. Conklin errx (2, "non-numeric argument"); 4965b81b6b3SRodney W. Grimes } 4975b81b6b3SRodney W. Grimes 49864867286SStefan Eßer r = make_integer (/*(quad_t)*/(a->u.i * b->u.i)); 499915198b4SStefan Eßer if (chk_times (a->u.i, b->u.i, r->u.i)) { 500915198b4SStefan Eßer errx (2, "overflow"); 501915198b4SStefan Eßer } 5025b81b6b3SRodney W. Grimes free_value (a); 5035b81b6b3SRodney W. Grimes free_value (b); 5045b81b6b3SRodney W. Grimes return (r); 5055b81b6b3SRodney W. Grimes } 5065b81b6b3SRodney W. Grimes 507915198b4SStefan Eßer int 5087669d0fcSWarner Losh chk_div(quad_t a, quad_t b) 509915198b4SStefan Eßer { 510915198b4SStefan Eßer /* div by zero has been taken care of before */ 511915198b4SStefan Eßer /* only QUAD_MIN / -1 causes overflow */ 512915198b4SStefan Eßer if (a == QUAD_MIN && b == -1) 513915198b4SStefan Eßer return 1; 514915198b4SStefan Eßer /* everything else is OK */ 515915198b4SStefan Eßer return 0; 516915198b4SStefan Eßer } 517915198b4SStefan Eßer 5185b81b6b3SRodney W. Grimes struct val * 5197669d0fcSWarner Losh op_div(struct val *a, struct val *b) 5205b81b6b3SRodney W. Grimes { 5215b81b6b3SRodney W. Grimes struct val *r; 5225b81b6b3SRodney W. Grimes 5235b81b6b3SRodney W. Grimes if (!to_integer (a) || !to_integer (b)) { 52455c497bfSJ.T. Conklin errx (2, "non-numeric argument"); 5255b81b6b3SRodney W. Grimes } 5265b81b6b3SRodney W. Grimes 5275b81b6b3SRodney W. Grimes if (b->u.i == 0) { 52855c497bfSJ.T. Conklin errx (2, "division by zero"); 5295b81b6b3SRodney W. Grimes } 5305b81b6b3SRodney W. Grimes 53164867286SStefan Eßer r = make_integer (/*(quad_t)*/(a->u.i / b->u.i)); 5323d06e95dSKris Kennaway if (chk_div (a->u.i, b->u.i)) { 533915198b4SStefan Eßer errx (2, "overflow"); 534915198b4SStefan Eßer } 5355b81b6b3SRodney W. Grimes free_value (a); 5365b81b6b3SRodney W. Grimes free_value (b); 5375b81b6b3SRodney W. Grimes return r; 5385b81b6b3SRodney W. Grimes } 5395b81b6b3SRodney W. Grimes 5405b81b6b3SRodney W. Grimes struct val * 5417669d0fcSWarner Losh op_rem(struct val *a, struct val *b) 5425b81b6b3SRodney W. Grimes { 5435b81b6b3SRodney W. Grimes struct val *r; 5445b81b6b3SRodney W. Grimes 5455b81b6b3SRodney W. Grimes if (!to_integer (a) || !to_integer (b)) { 54655c497bfSJ.T. Conklin errx (2, "non-numeric argument"); 5475b81b6b3SRodney W. Grimes } 5485b81b6b3SRodney W. Grimes 5495b81b6b3SRodney W. Grimes if (b->u.i == 0) { 55055c497bfSJ.T. Conklin errx (2, "division by zero"); 5515b81b6b3SRodney W. Grimes } 5525b81b6b3SRodney W. Grimes 55364867286SStefan Eßer r = make_integer (/*(quad_t)*/(a->u.i % b->u.i)); 554915198b4SStefan Eßer /* chk_rem necessary ??? */ 5555b81b6b3SRodney W. Grimes free_value (a); 5565b81b6b3SRodney W. Grimes free_value (b); 5575b81b6b3SRodney W. Grimes return r; 5585b81b6b3SRodney W. Grimes } 5595b81b6b3SRodney W. Grimes 5605b81b6b3SRodney W. Grimes struct val * 5617669d0fcSWarner Losh op_colon(struct val *a, struct val *b) 5625b81b6b3SRodney W. Grimes { 5634ba5f298SAndrew Moore regex_t rp; 5644cf61abaSJ.T. Conklin regmatch_t rm[2]; 5654ba5f298SAndrew Moore char errbuf[256]; 5664ba5f298SAndrew Moore int eval; 5674ba5f298SAndrew Moore struct val *v; 568c9fe00dcSJ.T. Conklin 569c9fe00dcSJ.T. Conklin /* coerce to both arguments to strings */ 570c9fe00dcSJ.T. Conklin to_string(a); 571c9fe00dcSJ.T. Conklin to_string(b); 5725b81b6b3SRodney W. Grimes 5734ba5f298SAndrew Moore /* compile regular expression */ 5744a13ab7cSJ.T. Conklin if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 5754ba5f298SAndrew Moore regerror (eval, &rp, errbuf, sizeof(errbuf)); 57655c497bfSJ.T. Conklin errx (2, "%s", errbuf); 5775b81b6b3SRodney W. Grimes } 5784ba5f298SAndrew Moore 5794ba5f298SAndrew Moore /* compare string against pattern */ 5804a13ab7cSJ.T. Conklin /* remember that patterns are anchored to the beginning of the line */ 5813d06e95dSKris Kennaway if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) { 5824ba5f298SAndrew Moore if (rm[1].rm_so >= 0) { 58355c497bfSJ.T. Conklin *(a->u.s + rm[1].rm_eo) = '\0'; 5844ba5f298SAndrew Moore v = make_str (a->u.s + rm[1].rm_so); 5854ba5f298SAndrew Moore 5864ba5f298SAndrew Moore } else { 58764867286SStefan Eßer v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so)); 5884ba5f298SAndrew Moore } 5894ba5f298SAndrew Moore } else { 59055c497bfSJ.T. Conklin if (rp.re_nsub == 0) { 59164867286SStefan Eßer v = make_integer ((quad_t)0); 59255c497bfSJ.T. Conklin } else { 59355c497bfSJ.T. Conklin v = make_str (""); 59455c497bfSJ.T. Conklin } 5954ba5f298SAndrew Moore } 5964ba5f298SAndrew Moore 5974ba5f298SAndrew Moore /* free arguments and pattern buffer */ 5984ba5f298SAndrew Moore free_value (a); 5994ba5f298SAndrew Moore free_value (b); 6004ba5f298SAndrew Moore regfree (&rp); 6014ba5f298SAndrew Moore 6024ba5f298SAndrew Moore return v; 6034ba5f298SAndrew Moore } 604