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

1.1       cgd         1: %{
                      2: /* Written by Pace Willisson (pace@blitz.com)
                      3:  * and placed in the public domain
1.2       cgd         4:  *
1.7     ! jtc         5:  * $Header: /b/source/CVS/src/bin/expr/expr.y,v 1.6 1993/06/14 19:59:07 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.5       cgd       222:        /* Like most other versions of expr, this version will return
                    223:           false for a string value of multiple zeros.*/
                    224:
1.4       cgd       225:        if (vp->type == integer) {
1.5       cgd       226:                return (vp->u.i == 0);
1.4       cgd       227:        } else {
1.5       cgd       228:                return (*vp->u.s == 0 || strcmp (vp->u.s, "0") == 0);
1.4       cgd       229:        }
1.5       cgd       230:        /* NOTREACHED */
1.1       cgd       231: }
                    232:
                    233: void
                    234: main (argc, argv)
                    235: int argc;
                    236: char **argv;
                    237: {
                    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:
                    247:        if (is_zero_or_null (result))
                    248:                exit (1);
                    249:        else
                    250:                exit (0);
                    251: }
                    252:
                    253: int
                    254: yyerror (s)
                    255: char *s;
                    256: {
1.4       cgd       257:        fprintf (stderr, "expr: syntax error\n");
1.1       cgd       258:        exit (2);
                    259: }
                    260:
                    261:
                    262: struct val *
                    263: op_or (a, b)
                    264: struct val *a, *b;
                    265: {
1.4       cgd       266:        if (is_zero_or_null (a)) {
                    267:                free_value (a);
1.1       cgd       268:                return (b);
1.4       cgd       269:        } else {
                    270:                free_value (b);
1.1       cgd       271:                return (a);
1.4       cgd       272:        }
1.1       cgd       273: }
                    274:
                    275: struct val *
                    276: op_and (a, b)
                    277: struct val *a, *b;
                    278: {
1.4       cgd       279:        if (is_zero_or_null (a) || is_zero_or_null (b)) {
                    280:                free_value (a);
                    281:                free_value (b);
1.1       cgd       282:                return (make_integer (0));
1.4       cgd       283:        } else {
                    284:                free_value (b);
1.1       cgd       285:                return (a);
1.4       cgd       286:        }
1.1       cgd       287: }
                    288:
                    289: struct val *
                    290: op_eq (a, b)
                    291: struct val *a, *b;
                    292: {
1.4       cgd       293:        struct val *r;
                    294:
                    295:        /* attempt to coerce both arguments to integers */
                    296:        (void) to_integer (a);
                    297:        (void) to_integer (b);
                    298:
                    299:        /* But if either one of them really is a string, do
                    300:           a string comparison */
                    301:        if (isstring (a) || isstring (b)) {
                    302:                to_string (a);
                    303:                to_string (b);
                    304:                r = make_integer (strcmp (a->u.s, b->u.s) == 0);
                    305:        } else {
                    306:                r = make_integer (a->u.i == b->u.i);
                    307:        }
                    308:
                    309:        free_value (a);
                    310:        free_value (b);
                    311:        return r;
1.1       cgd       312: }
                    313:
                    314: struct val *
                    315: op_gt (a, b)
                    316: struct val *a, *b;
                    317: {
1.4       cgd       318:        struct val *r;
                    319:
                    320:        /* attempt to coerce both arguments to integers */
                    321:        (void) to_integer (a);
                    322:        (void) to_integer (b);
                    323:
                    324:        /* But if either one of them really is a string, do
                    325:           a string comparison */
                    326:        if (isstring (a) || isstring (b)) {
                    327:                to_string (a);
                    328:                to_string (b);
                    329:                r = make_integer (strcmp (a->u.s, b->u.s) > 0);
                    330:        } else {
                    331:                r= make_integer (a->u.i > b->u.i);
                    332:        }
                    333:
                    334:        free_value (a);
                    335:        free_value (b);
                    336:        return r;
1.1       cgd       337: }
                    338:
                    339: struct val *
                    340: op_lt (a, b)
                    341: struct val *a, *b;
                    342: {
1.4       cgd       343:        struct val *r;
                    344:
                    345:        /* attempt to coerce both arguments to integers */
                    346:        (void) to_integer (a);
                    347:        (void) to_integer (b);
                    348:
                    349:        /* But if either one of them really is a string, do
                    350:           a string comparison */
                    351:        if (isstring (a) || isstring (b)) {
                    352:                to_string (a);
                    353:                to_string (b);
                    354:                r = make_integer (strcmp (a->u.s, b->u.s) < 0);
                    355:        } else {
                    356:                r = make_integer (a->u.i < b->u.i);
                    357:        }
                    358:
                    359:        free_value (a);
                    360:        free_value (b);
                    361:        return r;
1.1       cgd       362: }
                    363:
                    364: struct val *
                    365: op_ge (a, b)
                    366: struct val *a, *b;
                    367: {
1.4       cgd       368:        struct val *r;
                    369:
                    370:        /* attempt to coerce both arguments to integers */
                    371:        (void) to_integer (a);
                    372:        (void) to_integer (b);
                    373:
                    374:        /* But if either one of them really is a string, do
                    375:           a string comparison */
                    376:        if (isstring (a) || isstring (b)) {
                    377:                to_string (a);
                    378:                to_string (b);
                    379:                r = make_integer (strcmp (a->u.s, b->u.s) >= 0);
                    380:        } else {
                    381:                r = make_integer (a->u.i >= b->u.i);
                    382:        }
                    383:
                    384:        free_value (a);
                    385:        free_value (b);
                    386:        return r;
1.1       cgd       387: }
                    388:
                    389: struct val *
                    390: op_le (a, b)
                    391: struct val *a, *b;
                    392: {
1.4       cgd       393:        struct val *r;
                    394:
                    395:        /* attempt to coerce both arguments to integers */
                    396:        (void) to_integer (a);
                    397:        (void) to_integer (b);
                    398:
                    399:        /* But if either one of them really is a string, do
                    400:           a string comparison */
                    401:        if (isstring (a) || isstring (b)) {
                    402:                to_string (a);
                    403:                to_string (b);
                    404:                r = make_integer (strcmp (a->u.s, b->u.s) <= 0);
                    405:        } else {
                    406:                r = make_integer (a->u.i <= b->u.i);
                    407:        }
                    408:
                    409:        free_value (a);
                    410:        free_value (b);
                    411:        return r;
1.1       cgd       412: }
                    413:
                    414: struct val *
                    415: op_ne (a, b)
                    416: struct val *a, *b;
                    417: {
1.4       cgd       418:        struct val *r;
                    419:
                    420:        /* attempt to coerce both arguments to integers */
                    421:        (void) to_integer (a);
                    422:        (void) to_integer (b);
                    423:
                    424:        /* But if either one of them really is a string, do
                    425:           a string comparison */
                    426:        if (isstring (a) || isstring (b)) {
                    427:                to_string (a);
                    428:                to_string (b);
                    429:                r = make_integer (strcmp (a->u.s, b->u.s) != 0);
                    430:        } else {
                    431:                r = make_integer (a->u.i != b->u.i);
                    432:        }
                    433:
                    434:        free_value (a);
                    435:        free_value (b);
                    436:        return r;
1.1       cgd       437: }
                    438:
                    439: struct val *
                    440: op_plus (a, b)
                    441: struct val *a, *b;
                    442: {
1.4       cgd       443:        struct val *r;
                    444:
                    445:        if (!to_integer (a) || !to_integer (b)) {
                    446:                fprintf (stderr, "expr: non-numeric argument\n");
                    447:                exit (2);
                    448:        }
1.1       cgd       449:
1.4       cgd       450:        r = make_integer (a->u.i + b->u.i);
                    451:        free_value (a);
                    452:        free_value (b);
                    453:        return r;
1.1       cgd       454: }
                    455:
                    456: struct val *
                    457: op_minus (a, b)
                    458: struct val *a, *b;
                    459: {
1.4       cgd       460:        struct val *r;
                    461:
                    462:        if (!to_integer (a) || !to_integer (b)) {
                    463:                fprintf (stderr, "expr: non-numeric argument\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_times (a, b)
                    475: struct val *a, *b;
                    476: {
1.4       cgd       477:        struct val *r;
1.1       cgd       478:
1.4       cgd       479:        if (!to_integer (a) || !to_integer (b)) {
                    480:                fprintf (stderr, "expr: non-numeric argument\n");
                    481:                exit (2);
                    482:        }
                    483:
                    484:        r = make_integer (a->u.i * b->u.i);
                    485:        free_value (a);
                    486:        free_value (b);
                    487:        return (r);
1.1       cgd       488: }
                    489:
                    490: struct val *
                    491: op_div (a, b)
                    492: struct val *a, *b;
                    493: {
1.4       cgd       494:        struct val *r;
                    495:
                    496:        if (!to_integer (a) || !to_integer (b)) {
                    497:                fprintf (stderr, "expr: non-numeric argument\n");
                    498:                exit (2);
                    499:        }
                    500:
                    501:        if (b->u.i == 0) {
                    502:                fprintf (stderr, "expr: division by zero\n");
                    503:                exit (2);
                    504:        }
1.1       cgd       505:
1.4       cgd       506:        r = make_integer (a->u.i / b->u.i);
                    507:        free_value (a);
                    508:        free_value (b);
                    509:        return r;
1.1       cgd       510: }
                    511:
                    512: struct val *
                    513: op_rem (a, b)
                    514: struct val *a, *b;
                    515: {
1.4       cgd       516:        struct val *r;
                    517:
                    518:        if (!to_integer (a) || !to_integer (b)) {
                    519:                fprintf (stderr, "expr: non-numeric argument\n");
                    520:                exit (2);
                    521:        }
                    522:
                    523:        if (b->u.i == 0) {
                    524:                fprintf (stderr, "expr: division by zero\n");
                    525:                exit (2);
                    526:        }
1.1       cgd       527:
1.4       cgd       528:        r = make_integer (a->u.i % b->u.i);
                    529:        free_value (a);
                    530:        free_value (b);
                    531:        return r;
1.1       cgd       532: }
                    533:
1.6       jtc       534: #include <regex.h>
                    535: #define SE_MAX 30
1.1       cgd       536:
                    537: struct val *
                    538: op_colon (a, b)
                    539: struct val *a, *b;
                    540: {
1.6       jtc       541:        regex_t rp;
                    542:        regmatch_t rm[SE_MAX];
                    543:        char errbuf[256];
                    544:        int eval;
                    545:        struct val *v;
                    546:
1.7     ! jtc       547:        /* coerce to both arguments to strings */
        !           548:        to_string(a);
        !           549:        to_string(b);
1.6       jtc       550:
                    551:        /* compile regular expression */
1.7     ! jtc       552:        if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
1.6       jtc       553:                regerror (eval, &rp, errbuf, sizeof(errbuf));
                    554:                fprintf (stderr, "expr: %s\n", errbuf);
                    555:                exit (2);
                    556:        }
                    557:        free (newpat);
                    558:
                    559:        /* compare string against pattern */
                    560:        if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) {
                    561:                if (rm[1].rm_so >= 0) {
                    562:                        *(a->u.s + rm[1].rm_eo) = 0;
                    563:                        v = make_str (a->u.s + rm[1].rm_so);
1.1       cgd       564:
                    565:                } else {
1.6       jtc       566:                        v = make_integer (rm[0].rm_eo - rm[0].rm_so);
1.1       cgd       567:                }
                    568:        } else {
1.6       jtc       569:                v = make_integer (0);
1.1       cgd       570:        }
1.6       jtc       571:
                    572:        /* free arguments and pattern buffer */
                    573:        free_value (a);
                    574:        free_value (b);
                    575:        regfree (&rp);
1.5       cgd       576:
1.6       jtc       577:        return v;
1.1       cgd       578: }

CVSweb <webmaster@jp.NetBSD.org>