diff options
Diffstat (limited to 'coreutils/expr.c')
-rw-r--r-- | coreutils/expr.c | 406 |
1 files changed, 195 insertions, 211 deletions
diff --git a/coreutils/expr.c b/coreutils/expr.c index 0a1baa1..e7fdc5f 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c @@ -37,11 +37,13 @@ typedef enum valtype TYPE; #if ENABLE_EXPR_MATH_SUPPORT_64 typedef int64_t arith_t; + #define PF_REZ "ll" #define PF_REZ_TYPE (long long) #define STRTOL(s, e, b) strtoll(s, e, b) #else typedef long arith_t; + #define PF_REZ "l" #define PF_REZ_TYPE (long) #define STRTOL(s, e, b) strtol(s, e, b) @@ -49,8 +51,8 @@ typedef long arith_t; /* A value is.... */ struct valinfo { - TYPE type; /* Which kind. */ - union { /* The value itself. */ + TYPE type; /* Which kind. */ + union { /* The value itself. */ arith_t i; char *s; } u; @@ -60,17 +62,17 @@ typedef struct valinfo VALUE; /* The arguments given to the program, minus the program name. */ static char **args; -static VALUE *docolon (VALUE *sv, VALUE *pv); -static VALUE *eval (void); -static VALUE *int_value (arith_t i); -static VALUE *str_value (char *s); -static int nextarg (char *str); -static int null (VALUE *v); -static int toarith (VALUE *v); -static void freev (VALUE *v); -static void tostring (VALUE *v); - -int expr_main (int argc, char **argv) +static VALUE *docolon(VALUE * sv, VALUE * pv); +static VALUE *eval(void); +static VALUE *int_value(arith_t i); +static VALUE *str_value(char *s); +static int nextarg(char *str); +static int null(VALUE * v); +static int toarith(VALUE * v); +static void freev(VALUE * v); +static void tostring(VALUE * v); + +int expr_main(int argc, char **argv) { VALUE *v; @@ -80,25 +82,25 @@ int expr_main (int argc, char **argv) args = argv + 1; - v = eval (); + v = eval(); if (*args) - bb_error_msg_and_die ("syntax error"); + bb_error_msg_and_die("syntax error"); if (v->type == integer) - printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); + bb_printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); else - puts (v->u.s); + puts(v->u.s); - exit (null (v)); + exit(null(v)); } /* Return a VALUE for I. */ -static VALUE *int_value (arith_t i) +static VALUE *int_value(arith_t i) { VALUE *v; - v = xmalloc (sizeof(VALUE)); + v = xmalloc(sizeof(VALUE)); v->type = integer; v->u.i = i; return v; @@ -106,7 +108,7 @@ static VALUE *int_value (arith_t i) /* Return a VALUE for S. */ -static VALUE *str_value (char *s) +static VALUE *str_value(char *s) { VALUE *v; @@ -118,28 +120,26 @@ static VALUE *str_value (char *s) /* Free VALUE V, including structure components. */ -static void freev (VALUE *v) +static void freev(VALUE * v) { if (v->type == string) - free (v->u.s); - free (v); + free(v->u.s); + free(v); } /* Return nonzero if V is a null-string or zero-number. */ -static int null (VALUE *v) +static int null(VALUE * v) { - switch (v->type) { - case integer: - return v->u.i == 0; - default: /* string: */ - return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; - } + if (v->type == integer) + return v->u.i == 0; + else /* string: */ + return v->u.s[0] == '\0' || strcmp(v->u.s, "0") == 0; } /* Coerce V to a string value (can't fail). */ -static void tostring (VALUE *v) +static void tostring(VALUE * v) { if (v->type == integer) { v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i); @@ -149,9 +149,9 @@ static void tostring (VALUE *v) /* Coerce V to an integer value. Return 1 on success, 0 on failure. */ -static int toarith (VALUE *v) +static int toarith(VALUE * v) { - if(v->type == string) { + if (v->type == string) { arith_t i; char *e; @@ -160,7 +160,7 @@ static int toarith (VALUE *v) i = STRTOL(v->u.s, &e, 10); if ((v->u.s == e) || *e) return 0; - free (v->u.s); + free(v->u.s); v->u.i = i; v->type = integer; } @@ -170,221 +170,207 @@ static int toarith (VALUE *v) /* Return nonzero if the next token matches STR exactly. STR must not be NULL. */ -static int -nextarg (char *str) +static int nextarg(char *str) { if (*args == NULL) return 0; - return strcmp (*args, str) == 0; + return strcmp(*args, str) == 0; } /* The comparison operator handling functions. */ -static int cmp_common (VALUE *l, VALUE *r, int op) +static int cmp_common(VALUE * l, VALUE * r, int op) { int cmpval; if (l->type == string || r->type == string) { - tostring (l); - tostring (r); - cmpval = strcmp (l->u.s, r->u.s); - } - else + tostring(l); + tostring(r); + cmpval = strcmp(l->u.s, r->u.s); + } else cmpval = l->u.i - r->u.i; - switch(op) { - case '<': - return cmpval < 0; - case ('L'+'E'): - return cmpval <= 0; - case '=': - return cmpval == 0; - case '!': - return cmpval != 0; - case '>': - return cmpval > 0; - default: /* >= */ - return cmpval >= 0; - } + if (op == '<') + return cmpval < 0; + else if (op == ('L' + 'E')) + return cmpval <= 0; + else if (op == '=') + return cmpval == 0; + else if (op == '!') + return cmpval != 0; + else if (op == '>') + return cmpval > 0; + else /* >= */ + return cmpval >= 0; } /* The arithmetic operator handling functions. */ -static arith_t arithmetic_common (VALUE *l, VALUE *r, int op) +static arith_t arithmetic_common(VALUE * l, VALUE * r, int op) { - arith_t li, ri; - - if (!toarith (l) || !toarith (r)) - bb_error_msg_and_die ("non-numeric argument"); - li = l->u.i; - ri = r->u.i; - if((op == '/' || op == '%') && ri == 0) - bb_error_msg_and_die ( "division by zero"); - switch(op) { - case '+': + arith_t li, ri; + + if (!toarith(l) || !toarith(r)) + bb_error_msg_and_die("non-numeric argument"); + li = l->u.i; + ri = r->u.i; + if ((op == '/' || op == '%') && ri == 0) + bb_error_msg_and_die("division by zero"); + if (op == '+') return li + ri; - case '-': + else if (op == '-') return li - ri; - case '*': + else if (op == '*') return li * ri; - case '/': + else if (op == '/') return li / ri; - default: + else return li % ri; - } } /* Do the : operator. SV is the VALUE for the lhs (the string), PV is the VALUE for the rhs (the pattern). */ -static VALUE *docolon (VALUE *sv, VALUE *pv) +static VALUE *docolon(VALUE * sv, VALUE * pv) { VALUE *v; regex_t re_buffer; const int NMATCH = 2; regmatch_t re_regs[NMATCH]; - tostring (sv); - tostring (pv); + tostring(sv); + tostring(pv); if (pv->u.s[0] == '^') { - fprintf (stderr, "\ + fprintf(stderr, "\ warning: unportable BRE: `%s': using `^' as the first character\n\ -of a basic regular expression is not portable; it is being ignored", - pv->u.s); +of a basic regular expression is not portable; it is being ignored", pv->u.s); } - memset (&re_buffer, 0, sizeof (re_buffer)); - memset (re_regs, 0, sizeof (*re_regs)); - if( regcomp (&re_buffer, pv->u.s, 0) != 0 ) + memset(&re_buffer, 0, sizeof(re_buffer)); + memset(re_regs, 0, sizeof(*re_regs)); + if (regcomp(&re_buffer, pv->u.s, 0) != 0) bb_error_msg_and_die("Invalid regular expression"); /* expr uses an anchored pattern match, so check that there was a * match and that the match starts at offset 0. */ - if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && - re_regs[0].rm_so == 0) { + if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH && + re_regs[0].rm_so == 0) { /* Were \(...\) used? */ if (re_buffer.re_nsub > 0) { sv->u.s[re_regs[1].rm_eo] = '\0'; - v = str_value (sv->u.s + re_regs[1].rm_so); - } - else - v = int_value (re_regs[0].rm_eo); - } - else { + v = str_value(sv->u.s + re_regs[1].rm_so); + } else + v = int_value(re_regs[0].rm_eo); + } else { /* Match failed -- return the right kind of null. */ if (re_buffer.re_nsub > 0) - v = str_value (""); + v = str_value(""); else - v = int_value (0); + v = int_value(0); } return v; } /* Handle bare operands and ( expr ) syntax. */ -static VALUE *eval7 (void) +static VALUE *eval7(void) { VALUE *v; if (!*args) - bb_error_msg_and_die ( "syntax error"); + bb_error_msg_and_die("syntax error"); - if (nextarg ("(")) { + if (nextarg("(")) { args++; - v = eval (); - if (!nextarg (")")) - bb_error_msg_and_die ( "syntax error"); - args++; - return v; - } + v = eval(); + if (!nextarg(")")) + bb_error_msg_and_die("syntax error"); + args++; + return v; + } - if (nextarg (")")) - bb_error_msg_and_die ( "syntax error"); + if (nextarg(")")) + bb_error_msg_and_die("syntax error"); - return str_value (*args++); + return str_value(*args++); } /* Handle match, substr, index, length, and quote keywords. */ -static VALUE *eval6 (void) +static VALUE *eval6(void) { VALUE *l, *r, *v, *i1, *i2; - if (nextarg ("quote")) { + if (nextarg("quote")) { args++; if (!*args) - bb_error_msg_and_die ( "syntax error"); - return str_value (*args++); - } - else if (nextarg ("length")) { + bb_error_msg_and_die("syntax error"); + return str_value(*args++); + } else if (nextarg("length")) { args++; - r = eval6 (); - tostring (r); - v = int_value (strlen (r->u.s)); - freev (r); + r = eval6(); + tostring(r); + v = int_value(strlen(r->u.s)); + freev(r); return v; - } - else if (nextarg ("match")) { + } else if (nextarg("match")) { args++; - l = eval6 (); - r = eval6 (); - v = docolon (l, r); - freev (l); - freev (r); + l = eval6(); + r = eval6(); + v = docolon(l, r); + freev(l); + freev(r); return v; - } - else if (nextarg ("index")) { + } else if (nextarg("index")) { args++; - l = eval6 (); - r = eval6 (); - tostring (l); - tostring (r); - v = int_value (strcspn (l->u.s, r->u.s) + 1); - if (v->u.i == (arith_t) strlen (l->u.s) + 1) + l = eval6(); + r = eval6(); + tostring(l); + tostring(r); + v = int_value(strcspn(l->u.s, r->u.s) + 1); + if (v->u.i == (arith_t) strlen(l->u.s) + 1) v->u.i = 0; - freev (l); - freev (r); + freev(l); + freev(r); return v; - } - else if (nextarg ("substr")) { + } else if (nextarg("substr")) { args++; - l = eval6 (); - i1 = eval6 (); - i2 = eval6 (); - tostring (l); - if (!toarith (i1) || !toarith (i2) - || i1->u.i > (arith_t) strlen (l->u.s) + l = eval6(); + i1 = eval6(); + i2 = eval6(); + tostring(l); + if (!toarith(i1) || !toarith(i2) + || i1->u.i > (arith_t) strlen(l->u.s) || i1->u.i <= 0 || i2->u.i <= 0) - v = str_value (""); + v = str_value(""); else { - v = xmalloc (sizeof(VALUE)); + v = xmalloc(sizeof(VALUE)); v->type = string; v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i); } - freev (l); - freev (i1); - freev (i2); + freev(l); + freev(i1); + freev(i2); return v; - } - else - return eval7 (); + } else + return eval7(); } /* Handle : operator (pattern matching). Calls docolon to do the real work. */ -static VALUE *eval5 (void) +static VALUE *eval5(void) { VALUE *l, *r, *v; - l = eval6 (); - while (nextarg (":")) { + l = eval6(); + while (nextarg(":")) { args++; - r = eval6 (); - v = docolon (l, r); - freev (l); - freev (r); + r = eval6(); + v = docolon(l, r); + freev(l); + freev(r); l = v; } return l; @@ -392,128 +378,126 @@ static VALUE *eval5 (void) /* Handle *, /, % operators. */ -static VALUE *eval4 (void) +static VALUE *eval4(void) { VALUE *l, *r; int op; arith_t val; - l = eval5 (); + l = eval5(); while (1) { - if (nextarg ("*")) + if (nextarg("*")) op = '*'; - else if (nextarg ("/")) + else if (nextarg("/")) op = '/'; - else if (nextarg ("%")) + else if (nextarg("%")) op = '%'; else return l; args++; - r = eval5 (); - val = arithmetic_common (l, r, op); - freev (l); - freev (r); - l = int_value (val); + r = eval5(); + val = arithmetic_common(l, r, op); + freev(l); + freev(r); + l = int_value(val); } } /* Handle +, - operators. */ -static VALUE *eval3 (void) +static VALUE *eval3(void) { VALUE *l, *r; int op; arith_t val; - l = eval4 (); + l = eval4(); while (1) { - if (nextarg ("+")) + if (nextarg("+")) op = '+'; - else if (nextarg ("-")) + else if (nextarg("-")) op = '-'; else return l; args++; - r = eval4 (); - val = arithmetic_common (l, r, op); - freev (l); - freev (r); - l = int_value (val); + r = eval4(); + val = arithmetic_common(l, r, op); + freev(l); + freev(r); + l = int_value(val); } } /* Handle comparisons. */ -static VALUE *eval2 (void) +static VALUE *eval2(void) { VALUE *l, *r; int op; arith_t val; - l = eval3 (); + l = eval3(); while (1) { - if (nextarg ("<")) + if (nextarg("<")) op = '<'; - else if (nextarg ("<=")) - op = 'L'+'E'; - else if (nextarg ("=") || nextarg ("==")) + else if (nextarg("<=")) + op = 'L' + 'E'; + else if (nextarg("=") || nextarg("==")) op = '='; - else if (nextarg ("!=")) + else if (nextarg("!=")) op = '!'; - else if (nextarg (">=")) - op = 'G'+'E'; - else if (nextarg (">")) + else if (nextarg(">=")) + op = 'G' + 'E'; + else if (nextarg(">")) op = '>'; else return l; args++; - r = eval3 (); - toarith (l); - toarith (r); - val = cmp_common (l, r, op); - freev (l); - freev (r); - l = int_value (val); + r = eval3(); + toarith(l); + toarith(r); + val = cmp_common(l, r, op); + freev(l); + freev(r); + l = int_value(val); } } /* Handle &. */ -static VALUE *eval1 (void) +static VALUE *eval1(void) { VALUE *l, *r; - l = eval2 (); - while (nextarg ("&")) { + l = eval2(); + while (nextarg("&")) { args++; - r = eval2 (); - if (null (l) || null (r)) { - freev (l); - freev (r); - l = int_value (0); - } - else - freev (r); + r = eval2(); + if (null(l) || null(r)) { + freev(l); + freev(r); + l = int_value(0); + } else + freev(r); } return l; } /* Handle |. */ -static VALUE *eval (void) +static VALUE *eval(void) { VALUE *l, *r; - l = eval1 (); - while (nextarg ("|")) { + l = eval1(); + while (nextarg("|")) { args++; - r = eval1 (); - if (null (l)) { - freev (l); + r = eval1(); + if (null(l)) { + freev(l); l = r; - } - else - freev (r); + } else + freev(r); } return l; } |