[BACK]Return to expr.y CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / bin / expr

Annotation of src/bin/expr/expr.y, Revision 1.14.2.1

1.1       cgd         1: %{
                      2: /* Written by Pace Willisson (pace@blitz.com)
1.11      jtc         3:  * and placed in the public domain.
1.2       cgd         4:  *
1.11      jtc         5:  * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
                      6:  *
1.12      jtc         7:  * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $
1.1       cgd         8:  */
1.12      jtc         9:
1.1       cgd        10: #include <stdio.h>
1.4       cgd        11: #include <stdlib.h>
                     12: #include <string.h>
1.12      jtc        13: #include <locale.h>
1.1       cgd        14: #include <ctype.h>
1.11      jtc        15: #include <err.h>
1.5       cgd        16:
1.4       cgd        17: enum valtype {
                     18:        integer, string
                     19: } ;
1.5       cgd        20:
1.1       cgd        21: struct val {
1.4       cgd        22:        enum valtype type;
                     23:        union {
                     24:                char *s;
                     25:                int   i;
                     26:        } u;
1.5       cgd        27: } ;
1.1       cgd        28:
                     29: struct val *result;
                     30: struct val *op_or ();
                     31: struct val *op_and ();
                     32: struct val *op_eq ();
                     33: struct val *op_gt ();
                     34: struct val *op_lt ();
                     35: struct val *op_ge ();
                     36: struct val *op_le ();
                     37: struct val *op_ne ();
                     38: struct val *op_plus ();
                     39: struct val *op_minus ();
                     40: struct val *op_times ();
                     41: struct val *op_div ();
                     42: struct val *op_rem ();
                     43: struct val *op_colon ();
                     44:
                     45: char **av;
                     46: %}
                     47:
                     48: %union
                     49: {
                     50:        struct val *val;
                     51: }
                     52:
                     53: %left <val> '|'
                     54: %left <val> '&'
                     55: %left <val> '=' '>' '<' GE LE NE
                     56: %left <val> '+' '-'
                     57: %left <val> '*' '/' '%'
                     58: %left <val> ':'
                     59:
                     60: %token <val> TOKEN
                     61: %type <val> start expr
                     62:
                     63: %%
                     64:
                     65: start: expr { result = $$; }
                     66:
                     67: expr:  TOKEN
                     68:        | '(' expr ')' { $$ = $2; }
                     69:        | expr '|' expr { $$ = op_or ($1, $3); }
                     70:        | expr '&' expr { $$ = op_and ($1, $3); }
                     71:        | expr '=' expr { $$ = op_eq ($1, $3); }
                     72:        | expr '>' expr { $$ = op_gt ($1, $3); }
                     73:        | expr '<' expr { $$ = op_lt ($1, $3); }
                     74:        | expr GE expr  { $$ = op_ge ($1, $3); }
                     75:        | expr LE expr  { $$ = op_le ($1, $3); }
                     76:        | expr NE expr  { $$ = op_ne ($1, $3); }
                     77:        | expr '+' expr { $$ = op_plus ($1, $3); }
                     78:        | expr '-' expr { $$ = op_minus ($1, $3); }
                     79:        | expr '*' expr { $$ = op_times ($1, $3); }
                     80:        | expr '/' expr { $$ = op_div ($1, $3); }
                     81:        | expr '%' expr { $$ = op_rem ($1, $3); }
                     82:        | expr ':' expr { $$ = op_colon ($1, $3); }
                     83:        ;
                     84:
                     85:
                     86: %%
                     87:
                     88: struct val *
1.4       cgd        89: make_integer (i)
                     90: int i;
                     91: {
                     92:        struct val *vp;
                     93:
1.5       cgd        94:        vp = (struct val *) malloc (sizeof (*vp));
1.4       cgd        95:        if (vp == NULL) {
1.11      jtc        96:                err (2, NULL);
1.4       cgd        97:        }
                     98:
                     99:        vp->type = integer;
                    100:        vp->u.i  = i;
                    101:        return vp;
                    102: }
                    103:
                    104: struct val *
                    105: make_str (s)
                    106: char *s;
1.1       cgd       107: {
                    108:        struct val *vp;
                    109:
1.5       cgd       110:        vp = (struct val *) malloc (sizeof (*vp));
1.4       cgd       111:        if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
1.11      jtc       112:                err (2, NULL);
1.1       cgd       113:        }
                    114:
1.4       cgd       115:        vp->type = string;
                    116:        return vp;
                    117: }
                    118:
                    119:
                    120: void
                    121: free_value (vp)
                    122: struct val *vp;
                    123: {
                    124:        if (vp->type == string)
                    125:                free (vp->u.s);
1.14      jtc       126:        free (vp);
1.4       cgd       127: }
                    128:
1.1       cgd       129:
1.4       cgd       130: int
                    131: to_integer (vp)
                    132: struct val *vp;
                    133: {
                    134:        char *s;
                    135:        int neg;
                    136:        int i;
                    137:
                    138:        if (vp->type == integer)
                    139:                return 1;
                    140:
                    141:        s = vp->u.s;
                    142:        i = 0;
                    143:
                    144:        neg = (*s == '-');
                    145:        if (neg)
                    146:                s++;
                    147:
                    148:        for (;*s; s++) {
                    149:                if (!isdigit (*s))
                    150:                        return 0;
                    151:
                    152:                i *= 10;
                    153:                i += *s - '0';
1.1       cgd       154:        }
                    155:
1.4       cgd       156:        free (vp->u.s);
                    157:        if (neg)
                    158:                i *= -1;
                    159:
                    160:        vp->type = integer;
                    161:        vp->u.i  = i;
                    162:        return 1;
1.1       cgd       163: }
                    164:
1.4       cgd       165: void
                    166: to_string (vp)
                    167: struct val *vp;
1.1       cgd       168: {
1.4       cgd       169:        char *tmp;
                    170:
                    171:        if (vp->type == string)
                    172:                return;
                    173:
                    174:        tmp = malloc (25);
                    175:        if (tmp == NULL) {
1.11      jtc       176:                err (2, NULL);
1.4       cgd       177:        }
                    178:
                    179:        sprintf (tmp, "%d", vp->u.i);
                    180:        vp->type = string;
                    181:        vp->u.s  = tmp;
                    182: }
                    183:
1.1       cgd       184:
1.4       cgd       185: int
                    186: isstring (vp)
                    187: struct val *vp;
                    188: {
                    189:        return (vp->type == string);
1.1       cgd       190: }
                    191:
1.4       cgd       192:
1.1       cgd       193: int
                    194: yylex ()
                    195: {
                    196:        struct val *vp;
                    197:        char *p;
                    198:
                    199:        if (*av == NULL)
                    200:                return (0);
                    201:
                    202:        p = *av++;
                    203:
                    204:        if (strlen (p) == 1) {
1.4       cgd       205:                if (strchr ("|&=<>+-*/%:()", *p))
1.1       cgd       206:                        return (*p);
                    207:        } else if (strlen (p) == 2 && p[1] == '=') {
                    208:                switch (*p) {
                    209:                case '>': return (GE);
                    210:                case '<': return (LE);
                    211:                case '!': return (NE);
                    212:                }
                    213:        }
                    214:
1.4       cgd       215:        yylval.val = make_str (p);
1.1       cgd       216:        return (TOKEN);
                    217: }
                    218:
                    219: int
                    220: is_zero_or_null (vp)
                    221: struct val *vp;
                    222: {
1.4       cgd       223:        if (vp->type == integer) {
1.5       cgd       224:                return (vp->u.i == 0);
1.4       cgd       225:        } else {
1.9       jtc       226:                return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
1.4       cgd       227:        }
1.5       cgd       228:        /* NOTREACHED */
1.1       cgd       229: }
                    230:
                    231: void
                    232: main (argc, argv)
                    233: int argc;
                    234: char **argv;
                    235: {
1.12      jtc       236:        setlocale (LC_ALL, "");
                    237:
1.1       cgd       238:        av = argv + 1;
                    239:
                    240:        yyparse ();
                    241:
1.4       cgd       242:        if (result->type == integer)
                    243:                printf ("%d\n", result->u.i);
1.1       cgd       244:        else
1.4       cgd       245:                printf ("%s\n", result->u.s);
1.1       cgd       246:
1.12      jtc       247:        exit (is_zero_or_null (result));
1.1       cgd       248: }
                    249:
                    250: int
                    251: yyerror (s)
                    252: char *s;
                    253: {
1.11      jtc       254:        errx (2, "syntax error");
1.1       cgd       255: }
                    256:
                    257:
                    258: struct val *
                    259: op_or (a, b)
                    260: struct val *a, *b;
                    261: {
1.4       cgd       262:        if (is_zero_or_null (a)) {
                    263:                free_value (a);
1.1       cgd       264:                return (b);
1.4       cgd       265:        } else {
                    266:                free_value (b);
1.1       cgd       267:                return (a);
1.4       cgd       268:        }
1.1       cgd       269: }
                    270:
                    271: struct val *
                    272: op_and (a, b)
                    273: struct val *a, *b;
                    274: {
1.4       cgd       275:        if (is_zero_or_null (a) || is_zero_or_null (b)) {
                    276:                free_value (a);
                    277:                free_value (b);
1.1       cgd       278:                return (make_integer (0));
1.4       cgd       279:        } else {
                    280:                free_value (b);
1.1       cgd       281:                return (a);
1.4       cgd       282:        }
1.1       cgd       283: }
                    284:
                    285: struct val *
                    286: op_eq (a, b)
                    287: struct val *a, *b;
                    288: {
1.4       cgd       289:        struct val *r;
                    290:
                    291:        if (isstring (a) || isstring (b)) {
                    292:                to_string (a);
                    293:                to_string (b);
1.10      jtc       294:                r = make_integer (strcoll (a->u.s, b->u.s) == 0);
1.4       cgd       295:        } else {
                    296:                r = make_integer (a->u.i == b->u.i);
                    297:        }
                    298:
                    299:        free_value (a);
                    300:        free_value (b);
                    301:        return r;
1.1       cgd       302: }
                    303:
                    304: struct val *
                    305: op_gt (a, b)
                    306: struct val *a, *b;
                    307: {
1.4       cgd       308:        struct val *r;
                    309:
                    310:        if (isstring (a) || isstring (b)) {
                    311:                to_string (a);
                    312:                to_string (b);
1.10      jtc       313:                r = make_integer (strcoll (a->u.s, b->u.s) > 0);
1.4       cgd       314:        } else {
                    315:                r= make_integer (a->u.i > b->u.i);
                    316:        }
                    317:
                    318:        free_value (a);
                    319:        free_value (b);
                    320:        return r;
1.1       cgd       321: }
                    322:
                    323: struct val *
                    324: op_lt (a, b)
                    325: struct val *a, *b;
                    326: {
1.4       cgd       327:        struct val *r;
                    328:
                    329:        if (isstring (a) || isstring (b)) {
                    330:                to_string (a);
                    331:                to_string (b);
1.10      jtc       332:                r = make_integer (strcoll (a->u.s, b->u.s) < 0);
1.4       cgd       333:        } else {
                    334:                r = make_integer (a->u.i < b->u.i);
                    335:        }
                    336:
                    337:        free_value (a);
                    338:        free_value (b);
                    339:        return r;
1.1       cgd       340: }
                    341:
                    342: struct val *
                    343: op_ge (a, b)
                    344: struct val *a, *b;
                    345: {
1.4       cgd       346:        struct val *r;
                    347:
                    348:        if (isstring (a) || isstring (b)) {
                    349:                to_string (a);
                    350:                to_string (b);
1.10      jtc       351:                r = make_integer (strcoll (a->u.s, b->u.s) >= 0);
1.4       cgd       352:        } else {
                    353:                r = make_integer (a->u.i >= b->u.i);
                    354:        }
                    355:
                    356:        free_value (a);
                    357:        free_value (b);
                    358:        return r;
1.1       cgd       359: }
                    360:
                    361: struct val *
                    362: op_le (a, b)
                    363: struct val *a, *b;
                    364: {
1.4       cgd       365:        struct val *r;
                    366:
                    367:        if (isstring (a) || isstring (b)) {
                    368:                to_string (a);
                    369:                to_string (b);
1.10      jtc       370:                r = make_integer (strcoll (a->u.s, b->u.s) <= 0);
1.4       cgd       371:        } else {
                    372:                r = make_integer (a->u.i <= b->u.i);
                    373:        }
                    374:
                    375:        free_value (a);
                    376:        free_value (b);
                    377:        return r;
1.1       cgd       378: }
                    379:
                    380: struct val *
                    381: op_ne (a, b)
                    382: struct val *a, *b;
                    383: {
1.4       cgd       384:        struct val *r;
                    385:
                    386:        if (isstring (a) || isstring (b)) {
                    387:                to_string (a);
                    388:                to_string (b);
1.10      jtc       389:                r = make_integer (strcoll (a->u.s, b->u.s) != 0);
1.4       cgd       390:        } else {
                    391:                r = make_integer (a->u.i != b->u.i);
                    392:        }
                    393:
                    394:        free_value (a);
                    395:        free_value (b);
                    396:        return r;
1.1       cgd       397: }
                    398:
                    399: struct val *
                    400: op_plus (a, b)
                    401: struct val *a, *b;
                    402: {
1.4       cgd       403:        struct val *r;
                    404:
                    405:        if (!to_integer (a) || !to_integer (b)) {
1.11      jtc       406:                errx (2, "non-numeric argument");
1.4       cgd       407:        }
1.1       cgd       408:
1.4       cgd       409:        r = make_integer (a->u.i + b->u.i);
                    410:        free_value (a);
                    411:        free_value (b);
                    412:        return r;
1.1       cgd       413: }
                    414:
                    415: struct val *
                    416: op_minus (a, b)
                    417: struct val *a, *b;
                    418: {
1.4       cgd       419:        struct val *r;
                    420:
                    421:        if (!to_integer (a) || !to_integer (b)) {
1.11      jtc       422:                errx (2, "non-numeric argument");
1.4       cgd       423:        }
1.1       cgd       424:
1.4       cgd       425:        r = make_integer (a->u.i - b->u.i);
                    426:        free_value (a);
                    427:        free_value (b);
                    428:        return r;
1.1       cgd       429: }
                    430:
                    431: struct val *
                    432: op_times (a, b)
                    433: struct val *a, *b;
                    434: {
1.4       cgd       435:        struct val *r;
1.1       cgd       436:
1.4       cgd       437:        if (!to_integer (a) || !to_integer (b)) {
1.11      jtc       438:                errx (2, "non-numeric argument");
1.4       cgd       439:        }
                    440:
                    441:        r = make_integer (a->u.i * b->u.i);
                    442:        free_value (a);
                    443:        free_value (b);
                    444:        return (r);
1.1       cgd       445: }
                    446:
                    447: struct val *
                    448: op_div (a, b)
                    449: struct val *a, *b;
                    450: {
1.4       cgd       451:        struct val *r;
                    452:
                    453:        if (!to_integer (a) || !to_integer (b)) {
1.11      jtc       454:                errx (2, "non-numeric argument");
1.4       cgd       455:        }
                    456:
                    457:        if (b->u.i == 0) {
1.11      jtc       458:                errx (2, "division by zero");
1.4       cgd       459:        }
1.1       cgd       460:
1.4       cgd       461:        r = make_integer (a->u.i / b->u.i);
                    462:        free_value (a);
                    463:        free_value (b);
                    464:        return r;
1.1       cgd       465: }
                    466:
                    467: struct val *
                    468: op_rem (a, b)
                    469: struct val *a, *b;
                    470: {
1.4       cgd       471:        struct val *r;
                    472:
                    473:        if (!to_integer (a) || !to_integer (b)) {
1.11      jtc       474:                errx (2, "non-numeric argument");
1.4       cgd       475:        }
                    476:
                    477:        if (b->u.i == 0) {
1.11      jtc       478:                errx (2, "division by zero");
1.4       cgd       479:        }
1.1       cgd       480:
1.4       cgd       481:        r = make_integer (a->u.i % b->u.i);
                    482:        free_value (a);
                    483:        free_value (b);
                    484:        return r;
1.1       cgd       485: }
                    486:
1.6       jtc       487: #include <regex.h>
1.1       cgd       488:
                    489: struct val *
                    490: op_colon (a, b)
                    491: struct val *a, *b;
                    492: {
1.6       jtc       493:        regex_t rp;
1.12      jtc       494:        regmatch_t rm[2];
1.6       jtc       495:        char errbuf[256];
                    496:        int eval;
                    497:        struct val *v;
                    498:
1.7       jtc       499:        /* coerce to both arguments to strings */
                    500:        to_string(a);
                    501:        to_string(b);
1.6       jtc       502:
                    503:        /* compile regular expression */
1.13      jtc       504:        if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
1.6       jtc       505:                regerror (eval, &rp, errbuf, sizeof(errbuf));
1.11      jtc       506:                errx (2, "%s", errbuf);
1.6       jtc       507:        }
                    508:
                    509:        /* compare string against pattern */
1.13      jtc       510:        /* remember that patterns are anchored to the beginning of the line */
                    511:        if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) {
1.6       jtc       512:                if (rm[1].rm_so >= 0) {
1.11      jtc       513:                        *(a->u.s + rm[1].rm_eo) = '\0';
1.6       jtc       514:                        v = make_str (a->u.s + rm[1].rm_so);
1.1       cgd       515:
                    516:                } else {
1.14.2.1! cgd       517:                        v = make_integer ((int)(rm[0].rm_eo - rm[0].rm_so));
1.1       cgd       518:                }
                    519:        } else {
1.11      jtc       520:                if (rp.re_nsub == 0) {
                    521:                        v = make_integer (0);
                    522:                } else {
                    523:                        v = make_str ("");
                    524:                }
1.1       cgd       525:        }
1.6       jtc       526:
                    527:        /* free arguments and pattern buffer */
                    528:        free_value (a);
                    529:        free_value (b);
                    530:        regfree (&rp);
1.5       cgd       531:
1.6       jtc       532:        return v;
1.1       cgd       533: }

CVSweb <webmaster@jp.NetBSD.org>