[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.9

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

CVSweb <webmaster@jp.NetBSD.org>