expr.y revision 92979
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 92979 2002-03-22 20:18:26Z wollman $ 84Srgrimes */ 9468Sjtc 1062926Sse#include <sys/types.h> 1192979Swollman 1292979Swollman#include <ctype.h> 1392979Swollman#include <err.h> 1492979Swollman#include <errno.h> 1592979Swollman#include <inttypes.h> 1692979Swollman#include <limits.h> 1792979Swollman#include <locale.h> 184Srgrimes#include <stdio.h> 194Srgrimes#include <stdlib.h> 204Srgrimes#include <string.h> 2162926Sse#include <regex.h> 2292979Swollman#include <unistd.h> 2331Salm 2492979Swollman/* 2592979Swollman * POSIX specifies a specific error code for syntax errors. We exit 2692979Swollman * with this code for all errors. 2792979Swollman */ 2892979Swollman#define ERR_EXIT 2 2992979Swollman 304Srgrimesenum valtype { 3112378Sjoerg integer, numeric_string, string 324Srgrimes} ; 3331Salm 344Srgrimesstruct val { 354Srgrimes enum valtype type; 364Srgrimes union { 374Srgrimes char *s; 3892979Swollman intmax_t i; 394Srgrimes } u; 4031Salm} ; 414Srgrimes 424Srgrimesstruct val *result; 434Srgrimes 4492979Swollmanint chk_div(intmax_t, intmax_t); 4592979Swollmanint chk_minus(intmax_t, intmax_t, intmax_t); 4692979Swollmanint chk_plus(intmax_t, intmax_t, intmax_t); 4792979Swollmanint chk_times(intmax_t, intmax_t, intmax_t); 4890109Simpvoid free_value(struct val *); 4990109Simpint is_zero_or_null(struct val *); 5090109Simpint isstring(struct val *); 5192979Swollmanstruct val *make_integer(intmax_t); 5290109Simpstruct val *make_str(const char *); 5390109Simpstruct val *op_and(struct val *, struct val *); 5490109Simpstruct val *op_colon(struct val *, struct val *); 5590109Simpstruct val *op_div(struct val *, struct val *); 5690109Simpstruct val *op_eq(struct val *, struct val *); 5790109Simpstruct val *op_ge(struct val *, struct val *); 5890109Simpstruct val *op_gt(struct val *, struct val *); 5990109Simpstruct val *op_le(struct val *, struct val *); 6090109Simpstruct val *op_lt(struct val *, struct val *); 6190109Simpstruct val *op_minus(struct val *, struct val *); 6290109Simpstruct val *op_ne(struct val *, struct val *); 6390109Simpstruct val *op_or(struct val *, struct val *); 6490109Simpstruct val *op_plus(struct val *, struct val *); 6590109Simpstruct val *op_rem(struct val *, struct val *); 6690109Simpstruct val *op_times(struct val *, struct val *); 6792979Swollmanintmax_t to_integer(struct val *); 6890109Simpvoid to_string(struct val *); 6990109Simpint yyerror(const char *); 7090109Simpint yylex(void); 7190109Simpint yyparse(void); 7277244Skris 734Srgrimeschar **av; 744Srgrimes%} 754Srgrimes 764Srgrimes%union 774Srgrimes{ 784Srgrimes struct val *val; 794Srgrimes} 804Srgrimes 814Srgrimes%left <val> '|' 824Srgrimes%left <val> '&' 834Srgrimes%left <val> '=' '>' '<' GE LE NE 844Srgrimes%left <val> '+' '-' 854Srgrimes%left <val> '*' '/' '%' 864Srgrimes%left <val> ':' 874Srgrimes 884Srgrimes%token <val> TOKEN 894Srgrimes%type <val> start expr 904Srgrimes 914Srgrimes%% 924Srgrimes 934Srgrimesstart: expr { result = $$; } 944Srgrimes 954Srgrimesexpr: TOKEN 964Srgrimes | '(' expr ')' { $$ = $2; } 974Srgrimes | expr '|' expr { $$ = op_or ($1, $3); } 984Srgrimes | expr '&' expr { $$ = op_and ($1, $3); } 994Srgrimes | expr '=' expr { $$ = op_eq ($1, $3); } 1004Srgrimes | expr '>' expr { $$ = op_gt ($1, $3); } 1014Srgrimes | expr '<' expr { $$ = op_lt ($1, $3); } 1024Srgrimes | expr GE expr { $$ = op_ge ($1, $3); } 1034Srgrimes | expr LE expr { $$ = op_le ($1, $3); } 1044Srgrimes | expr NE expr { $$ = op_ne ($1, $3); } 1054Srgrimes | expr '+' expr { $$ = op_plus ($1, $3); } 1064Srgrimes | expr '-' expr { $$ = op_minus ($1, $3); } 1074Srgrimes | expr '*' expr { $$ = op_times ($1, $3); } 1084Srgrimes | expr '/' expr { $$ = op_div ($1, $3); } 1094Srgrimes | expr '%' expr { $$ = op_rem ($1, $3); } 1104Srgrimes | expr ':' expr { $$ = op_colon ($1, $3); } 1114Srgrimes ; 1124Srgrimes 1134Srgrimes 1144Srgrimes%% 1154Srgrimes 1164Srgrimesstruct val * 11792979Swollmanmake_integer(intmax_t i) 1184Srgrimes{ 1194Srgrimes struct val *vp; 1204Srgrimes 1214Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1224Srgrimes if (vp == NULL) { 12392979Swollman errx(ERR_EXIT, "malloc() failed"); 1244Srgrimes } 1254Srgrimes 1264Srgrimes vp->type = integer; 1274Srgrimes vp->u.i = i; 1284Srgrimes return vp; 1294Srgrimes} 1304Srgrimes 1314Srgrimesstruct val * 13290109Simpmake_str(const char *s) 1334Srgrimes{ 1344Srgrimes struct val *vp; 13592979Swollman char *ep; 1364Srgrimes 1374Srgrimes vp = (struct val *) malloc (sizeof (*vp)); 1384Srgrimes if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { 13992979Swollman errx(ERR_EXIT, "malloc() failed"); 1404Srgrimes } 1414Srgrimes 14292979Swollman /* 14392979Swollman * Previously we tried to scan the string to see if it ``looked like'' 14492979Swollman * an integer (erroneously, as it happened). Let strtoimax() do the 14592979Swollman * dirty work. We could cache the value, except that we are using 14692979Swollman * a union and need to preserve the original string form until we 14792979Swollman * are certain that it is not needed. 14892979Swollman * 14992979Swollman * IEEE Std.1003.1-2001 says: 15092979Swollman * /integer/ An argument consisting only of an (optional) unary minus 15192979Swollman * followed by digits. 15292979Swollman * 15392979Swollman * This means that arguments which consist of digits followed by 15492979Swollman * non-digits MUST NOT be considered integers. strtoimax() will 15592979Swollman * figure this out for us. 15692979Swollman */ 15792979Swollman (void)strtoimax(s, &ep, 10); 1589909Sjoerg 15992979Swollman if (*ep != '\0') 16092979Swollman vp->type = string; 16192979Swollman else 16212378Sjoerg vp->type = numeric_string; 1639909Sjoerg 1644Srgrimes return vp; 1654Srgrimes} 1664Srgrimes 1674Srgrimes 1684Srgrimesvoid 16990109Simpfree_value(struct val *vp) 1704Srgrimes{ 17112378Sjoerg if (vp->type == string || vp->type == numeric_string) 1724Srgrimes free (vp->u.s); 1734Srgrimes} 1744Srgrimes 1754Srgrimes 17692979Swollmanintmax_t 17790109Simpto_integer(struct val *vp) 1784Srgrimes{ 17992979Swollman intmax_t i; 1804Srgrimes 1814Srgrimes if (vp->type == integer) 1824Srgrimes return 1; 1834Srgrimes 18412378Sjoerg if (vp->type == string) 18512378Sjoerg return 0; 1864Srgrimes 18712378Sjoerg /* vp->type == numeric_string, make it numeric */ 18863755Sse errno = 0; 18992979Swollman i = strtoimax(vp->u.s, (char **)NULL, 10); 19092979Swollman if (errno == ERANGE) 19192979Swollman err(ERR_EXIT, NULL); 19292979Swollman 1934Srgrimes free (vp->u.s); 19412378Sjoerg vp->u.i = i; 1954Srgrimes vp->type = integer; 1964Srgrimes return 1; 1974Srgrimes} 1984Srgrimes 1994Srgrimesvoid 20090109Simpto_string(struct val *vp) 2014Srgrimes{ 2024Srgrimes char *tmp; 2034Srgrimes 20412378Sjoerg if (vp->type == string || vp->type == numeric_string) 2054Srgrimes return; 2064Srgrimes 20792979Swollman /* 20892979Swollman * log_10(x) ~= 0.3 * log_2(x). Rounding up gives the number 20992979Swollman * of digits; add one each for the sign and terminating null 21092979Swollman * character, respectively. 21192979Swollman */ 21292979Swollman#define NDIGITS(x) (3 * (sizeof(x) * CHAR_BIT) / 10 + 1 + 1 + 1) 21392979Swollman tmp = malloc(NDIGITS(vp->u.i)); 21492979Swollman if (tmp == NULL) 21592979Swollman errx(ERR_EXIT, "malloc() failed"); 2164Srgrimes 21792979Swollman sprintf(tmp, "%jd", vp->u.i); 2184Srgrimes vp->type = string; 2194Srgrimes vp->u.s = tmp; 2204Srgrimes} 2214Srgrimes 2224Srgrimes 2234Srgrimesint 22490109Simpisstring(struct val *vp) 2254Srgrimes{ 22612378Sjoerg /* only TRUE if this string is not a valid integer */ 2274Srgrimes return (vp->type == string); 2284Srgrimes} 2294Srgrimes 2304Srgrimes 2314Srgrimesint 23290109Simpyylex(void) 2334Srgrimes{ 2344Srgrimes char *p; 2354Srgrimes 2364Srgrimes if (*av == NULL) 2374Srgrimes return (0); 2384Srgrimes 2394Srgrimes p = *av++; 2404Srgrimes 2414Srgrimes if (strlen (p) == 1) { 2424Srgrimes if (strchr ("|&=<>+-*/%:()", *p)) 2434Srgrimes return (*p); 2444Srgrimes } else if (strlen (p) == 2 && p[1] == '=') { 2454Srgrimes switch (*p) { 2464Srgrimes case '>': return (GE); 2474Srgrimes case '<': return (LE); 2484Srgrimes case '!': return (NE); 2494Srgrimes } 2504Srgrimes } 2514Srgrimes 2524Srgrimes yylval.val = make_str (p); 2534Srgrimes return (TOKEN); 2544Srgrimes} 2554Srgrimes 2564Srgrimesint 25790109Simpis_zero_or_null(struct val *vp) 2584Srgrimes{ 2594Srgrimes if (vp->type == integer) { 2604Srgrimes return (vp->u.i == 0); 2614Srgrimes } else { 262181Sconklin return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); 2634Srgrimes } 2644Srgrimes /* NOTREACHED */ 2654Srgrimes} 2664Srgrimes 26712378Sjoergint 26892979Swollmanmain(int argc, char *argv[]) 2694Srgrimes{ 27092979Swollman int c; 27192979Swollman 272468Sjtc setlocale (LC_ALL, ""); 27392979Swollman while ((c = getopt(argc, argv, "")) != -1) 27492979Swollman switch (c) { 27592979Swollman default: 27692979Swollman fprintf(stderr, "usage: expr [--] expression\n"); 27792979Swollman exit(ERR_EXIT); 27892979Swollman } 279468Sjtc 28092979Swollman av = argv + optind; 2814Srgrimes 28292979Swollman yyparse(); 2834Srgrimes 2844Srgrimes if (result->type == integer) 28592979Swollman printf("%jd\n", result->u.i); 2864Srgrimes else 28792979Swollman printf("%s\n", result->u.s); 2884Srgrimes 28992979Swollman return (is_zero_or_null(result)); 2904Srgrimes} 2914Srgrimes 2924Srgrimesint 29390109Simpyyerror(const char *s __unused) 2944Srgrimes{ 29592979Swollman errx(ERR_EXIT, "syntax error"); 2964Srgrimes} 2974Srgrimes 2984Srgrimes 2994Srgrimesstruct val * 30090109Simpop_or(struct val *a, struct val *b) 3014Srgrimes{ 3024Srgrimes if (is_zero_or_null (a)) { 3034Srgrimes free_value (a); 3044Srgrimes return (b); 3054Srgrimes } else { 3064Srgrimes free_value (b); 3074Srgrimes return (a); 3084Srgrimes } 3094Srgrimes} 3104Srgrimes 3114Srgrimesstruct val * 31290109Simpop_and(struct val *a, struct val *b) 3134Srgrimes{ 3144Srgrimes if (is_zero_or_null (a) || is_zero_or_null (b)) { 3154Srgrimes free_value (a); 3164Srgrimes free_value (b); 31792979Swollman return (make_integer ((intmax_t)0)); 3184Srgrimes } else { 3194Srgrimes free_value (b); 3204Srgrimes return (a); 3214Srgrimes } 3224Srgrimes} 3234Srgrimes 3244Srgrimesstruct val * 32590109Simpop_eq(struct val *a, struct val *b) 3264Srgrimes{ 3274Srgrimes struct val *r; 3284Srgrimes 3294Srgrimes if (isstring (a) || isstring (b)) { 3304Srgrimes to_string (a); 3314Srgrimes to_string (b); 33292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) == 0)); 3334Srgrimes } else { 33412378Sjoerg (void)to_integer(a); 33512378Sjoerg (void)to_integer(b); 33692979Swollman r = make_integer ((intmax_t)(a->u.i == b->u.i)); 3374Srgrimes } 3384Srgrimes 3394Srgrimes free_value (a); 3404Srgrimes free_value (b); 3414Srgrimes return r; 3424Srgrimes} 3434Srgrimes 3444Srgrimesstruct val * 34590109Simpop_gt(struct val *a, struct val *b) 3464Srgrimes{ 3474Srgrimes struct val *r; 3484Srgrimes 3494Srgrimes if (isstring (a) || isstring (b)) { 3504Srgrimes to_string (a); 3514Srgrimes to_string (b); 35292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) > 0)); 3534Srgrimes } else { 35412378Sjoerg (void)to_integer(a); 35512378Sjoerg (void)to_integer(b); 35692979Swollman r = make_integer ((intmax_t)(a->u.i > b->u.i)); 3574Srgrimes } 3584Srgrimes 3594Srgrimes free_value (a); 3604Srgrimes free_value (b); 3614Srgrimes return r; 3624Srgrimes} 3634Srgrimes 3644Srgrimesstruct val * 36590109Simpop_lt(struct val *a, struct val *b) 3664Srgrimes{ 3674Srgrimes struct val *r; 3684Srgrimes 3694Srgrimes if (isstring (a) || isstring (b)) { 3704Srgrimes to_string (a); 3714Srgrimes to_string (b); 37292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) < 0)); 3734Srgrimes } else { 37412378Sjoerg (void)to_integer(a); 37512378Sjoerg (void)to_integer(b); 37692979Swollman r = make_integer ((intmax_t)(a->u.i < b->u.i)); 3774Srgrimes } 3784Srgrimes 3794Srgrimes free_value (a); 3804Srgrimes free_value (b); 3814Srgrimes return r; 3824Srgrimes} 3834Srgrimes 3844Srgrimesstruct val * 38590109Simpop_ge(struct val *a, struct val *b) 3864Srgrimes{ 3874Srgrimes struct val *r; 3884Srgrimes 3894Srgrimes if (isstring (a) || isstring (b)) { 3904Srgrimes to_string (a); 3914Srgrimes to_string (b); 39292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) >= 0)); 3934Srgrimes } else { 39412378Sjoerg (void)to_integer(a); 39512378Sjoerg (void)to_integer(b); 39692979Swollman r = make_integer ((intmax_t)(a->u.i >= b->u.i)); 3974Srgrimes } 3984Srgrimes 3994Srgrimes free_value (a); 4004Srgrimes free_value (b); 4014Srgrimes return r; 4024Srgrimes} 4034Srgrimes 4044Srgrimesstruct val * 40590109Simpop_le(struct val *a, struct val *b) 4064Srgrimes{ 4074Srgrimes struct val *r; 4084Srgrimes 4094Srgrimes if (isstring (a) || isstring (b)) { 4104Srgrimes to_string (a); 4114Srgrimes to_string (b); 41292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) <= 0)); 4134Srgrimes } else { 41412378Sjoerg (void)to_integer(a); 41512378Sjoerg (void)to_integer(b); 41692979Swollman r = make_integer ((intmax_t)(a->u.i <= b->u.i)); 4174Srgrimes } 4184Srgrimes 4194Srgrimes free_value (a); 4204Srgrimes free_value (b); 4214Srgrimes return r; 4224Srgrimes} 4234Srgrimes 4244Srgrimesstruct val * 42590109Simpop_ne(struct val *a, struct val *b) 4264Srgrimes{ 4274Srgrimes struct val *r; 4284Srgrimes 4294Srgrimes if (isstring (a) || isstring (b)) { 4304Srgrimes to_string (a); 4314Srgrimes to_string (b); 43292979Swollman r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) != 0)); 4334Srgrimes } else { 43412378Sjoerg (void)to_integer(a); 43512378Sjoerg (void)to_integer(b); 43692979Swollman r = make_integer ((intmax_t)(a->u.i != b->u.i)); 4374Srgrimes } 4384Srgrimes 4394Srgrimes free_value (a); 4404Srgrimes free_value (b); 4414Srgrimes return r; 4424Srgrimes} 4434Srgrimes 44463755Sseint 44592979Swollmanchk_plus(intmax_t a, intmax_t b, intmax_t r) 44663755Sse{ 44763755Sse /* sum of two positive numbers must be positive */ 44863755Sse if (a > 0 && b > 0 && r <= 0) 44963755Sse return 1; 45063755Sse /* sum of two negative numbers must be negative */ 45163755Sse if (a < 0 && b < 0 && r >= 0) 45263755Sse return 1; 45363755Sse /* all other cases are OK */ 45463755Sse return 0; 45563755Sse} 45663755Sse 4574Srgrimesstruct val * 45890109Simpop_plus(struct val *a, struct val *b) 4594Srgrimes{ 4604Srgrimes struct val *r; 4614Srgrimes 4624Srgrimes if (!to_integer (a) || !to_integer (b)) { 46392979Swollman errx(ERR_EXIT, "non-numeric argument"); 4644Srgrimes } 4654Srgrimes 46692979Swollman r = make_integer (/*(intmax_t)*/(a->u.i + b->u.i)); 46763755Sse if (chk_plus (a->u.i, b->u.i, r->u.i)) { 46892979Swollman errx(ERR_EXIT, "overflow"); 46963755Sse } 4704Srgrimes free_value (a); 4714Srgrimes free_value (b); 4724Srgrimes return r; 4734Srgrimes} 47463755Sse 47563755Sseint 47692979Swollmanchk_minus(intmax_t a, intmax_t b, intmax_t r) 47763755Sse{ 47892979Swollman /* special case subtraction of INTMAX_MIN */ 47992979Swollman if (b == INTMAX_MIN) { 48063755Sse if (a >= 0) 48163755Sse return 1; 48263755Sse else 48363755Sse return 0; 48463755Sse } 48592979Swollman /* this is allowed for b != INTMAX_MIN */ 48663755Sse return chk_plus (a, -b, r); 48763755Sse} 48863755Sse 4894Srgrimesstruct val * 49090109Simpop_minus(struct val *a, struct val *b) 4914Srgrimes{ 4924Srgrimes struct val *r; 4934Srgrimes 4944Srgrimes if (!to_integer (a) || !to_integer (b)) { 49592979Swollman errx(ERR_EXIT, "non-numeric argument"); 4964Srgrimes } 4974Srgrimes 49892979Swollman r = make_integer (/*(intmax_t)*/(a->u.i - b->u.i)); 49963755Sse if (chk_minus (a->u.i, b->u.i, r->u.i)) { 50092979Swollman errx(ERR_EXIT, "overflow"); 50163755Sse } 5024Srgrimes free_value (a); 5034Srgrimes free_value (b); 5044Srgrimes return r; 5054Srgrimes} 50663755Sse 50763755Sseint 50892979Swollmanchk_times(intmax_t a, intmax_t b, intmax_t r) 50963755Sse{ 51063755Sse /* special case: first operand is 0, no overflow possible */ 51163755Sse if (a == 0) 51263755Sse return 0; 51363755Sse /* cerify that result of division matches second operand */ 51463755Sse if (r / a != b) 51563755Sse return 1; 51663755Sse return 0; 51763755Sse} 51863755Sse 5194Srgrimesstruct val * 52090109Simpop_times(struct val *a, struct val *b) 5214Srgrimes{ 5224Srgrimes struct val *r; 5234Srgrimes 5244Srgrimes if (!to_integer (a) || !to_integer (b)) { 52592979Swollman errx(ERR_EXIT, "non-numeric argument"); 5264Srgrimes } 5274Srgrimes 52892979Swollman r = make_integer (/*(intmax_t)*/(a->u.i * b->u.i)); 52963755Sse if (chk_times (a->u.i, b->u.i, r->u.i)) { 53092979Swollman errx(ERR_EXIT, "overflow"); 53163755Sse } 5324Srgrimes free_value (a); 5334Srgrimes free_value (b); 5344Srgrimes return (r); 5354Srgrimes} 53663755Sse 53763755Sseint 53892979Swollmanchk_div(intmax_t a, intmax_t b) 53963755Sse{ 54063755Sse /* div by zero has been taken care of before */ 54192979Swollman /* only INTMAX_MIN / -1 causes overflow */ 54292979Swollman if (a == INTMAX_MIN && b == -1) 54363755Sse return 1; 54463755Sse /* everything else is OK */ 54563755Sse return 0; 54663755Sse} 54763755Sse 5484Srgrimesstruct val * 54990109Simpop_div(struct val *a, struct val *b) 5504Srgrimes{ 5514Srgrimes struct val *r; 5524Srgrimes 5534Srgrimes if (!to_integer (a) || !to_integer (b)) { 55492979Swollman errx(ERR_EXIT, "non-numeric argument"); 5554Srgrimes } 5564Srgrimes 5574Srgrimes if (b->u.i == 0) { 55892979Swollman errx(ERR_EXIT, "division by zero"); 5594Srgrimes } 5604Srgrimes 56192979Swollman r = make_integer (/*(intmax_t)*/(a->u.i / b->u.i)); 56277244Skris if (chk_div (a->u.i, b->u.i)) { 56392979Swollman errx(ERR_EXIT, "overflow"); 56463755Sse } 5654Srgrimes free_value (a); 5664Srgrimes free_value (b); 5674Srgrimes return r; 5684Srgrimes} 5694Srgrimes 5704Srgrimesstruct val * 57190109Simpop_rem(struct val *a, struct val *b) 5724Srgrimes{ 5734Srgrimes struct val *r; 5744Srgrimes 5754Srgrimes if (!to_integer (a) || !to_integer (b)) { 57692979Swollman errx(ERR_EXIT, "non-numeric argument"); 5774Srgrimes } 5784Srgrimes 5794Srgrimes if (b->u.i == 0) { 58092979Swollman errx(ERR_EXIT, "division by zero"); 5814Srgrimes } 5824Srgrimes 58392979Swollman r = make_integer (/*(intmax_t)*/(a->u.i % b->u.i)); 58463755Sse /* chk_rem necessary ??? */ 5854Srgrimes free_value (a); 5864Srgrimes free_value (b); 5874Srgrimes return r; 5884Srgrimes} 5894Srgrimes 5904Srgrimesstruct val * 59190109Simpop_colon(struct val *a, struct val *b) 5924Srgrimes{ 59331Salm regex_t rp; 594468Sjtc regmatch_t rm[2]; 59531Salm char errbuf[256]; 59631Salm int eval; 597181Sconklin struct val *v; 5984Srgrimes 599181Sconklin /* coerce to both arguments to strings */ 600181Sconklin to_string(a); 601181Sconklin to_string(b); 602181Sconklin 60331Salm /* compile regular expression */ 604539Sjtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { 60531Salm regerror (eval, &rp, errbuf, sizeof(errbuf)); 60692979Swollman errx(ERR_EXIT, "%s", errbuf); 6074Srgrimes } 6084Srgrimes 60931Salm /* compare string against pattern */ 610539Sjtc /* remember that patterns are anchored to the beginning of the line */ 61177244Skris if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) { 61231Salm if (rm[1].rm_so >= 0) { 613295Sjtc *(a->u.s + rm[1].rm_eo) = '\0'; 61431Salm v = make_str (a->u.s + rm[1].rm_so); 61531Salm 6164Srgrimes } else { 61792979Swollman v = make_integer ((intmax_t)(rm[0].rm_eo - rm[0].rm_so)); 6184Srgrimes } 6194Srgrimes } else { 620295Sjtc if (rp.re_nsub == 0) { 62192979Swollman v = make_integer ((intmax_t)0); 622295Sjtc } else { 623295Sjtc v = make_str (""); 624295Sjtc } 6254Srgrimes } 6264Srgrimes 62731Salm /* free arguments and pattern buffer */ 62831Salm free_value (a); 62931Salm free_value (b); 63031Salm regfree (&rp); 63131Salm 63231Salm return v; 6334Srgrimes} 634