Annotation of coherent/d/bin/test/test.y, revision 1.1.1.1

1.1       root        1: %{
                      2: /*
                      3:  * Set return status based on
                      4:  * various specified conditions,
                      5:  * mostly related to files.
                      6:  * Used mostly in shell files.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <sys/stat.h>
                     11: #include <access.h>
                     12: #include "testnode.h"
                     13: 
                     14: #define        NPRIM   (sizeof(prims)/sizeof(prims[0]))
                     15: #define        NFNAME  500             /* size of filename buffer */
                     16: %}
                     17: %start command
                     18: 
                     19: %union {
                     20:        NODE *nodeptr;
                     21:        char *fname;
                     22:        }
                     23: 
                     24: %left  OR
                     25: %left  AND
                     26: %left  '!'
                     27: %token _R _W _F _D _S _T _Z _N
                     28: %token SEQ SNEQ
                     29: %token _EQ _NE _GT _GE _LT _LE
                     30: %type  <nodeptr> exp
                     31: %token <fname> STR
                     32: %%
                     33: 
                     34: command:
                     35:        exp '\n'                { code = $1; return; }
                     36:        ;
                     37: 
                     38: exp:
                     39:         '(' exp ')'            { $$ = $2; }
                     40:       | '!' exp                        { $$ = bnode('!', $2, NULL); }
                     41:       | exp OR exp             { $$ = bnode(OR, $1, $3); }
                     42:       | exp AND exp            { $$ = bnode(AND, $1, $3); }
                     43:       | _R STR                 { $$ = lnode(xr, $2, NULL); }
                     44:       | _W STR                 { $$ = lnode(xw, $2, NULL); }
                     45:       | _F STR                 { $$ = lnode(xf, $2, NULL); }
                     46:       | _D STR                 { $$ = lnode(xd, $2, NULL); }
                     47:       | _S STR                 { $$ = lnode(xs, $2, NULL); }
                     48:       | _T STR                 { $$ = lnode(xt, $2, NULL); }
                     49:       | _T                     { $$ = lnode(xt, "1", NULL); }
                     50:       | _Z STR                 { $$ = lnode(xz, $2, NULL); }
                     51:       | _N STR                 { $$ = lnode(xn, $2, NULL); }
                     52:       | STR SEQ STR            { $$ = lnode(xseq, $1, $3); }
                     53:       | STR SNEQ STR           { $$ = lnode(xsneq, $1, $3); }
                     54:       | STR _EQ STR            { $$ = lnode(xeq, $1, $3); }
                     55:       | STR _NE STR            { $$ = lnode(xne, $1, $3); }
                     56:       | STR _GT STR            { $$ = lnode(xgt, $1, $3); }
                     57:       | STR _GE STR            { $$ = lnode(xge, $1, $3); }
                     58:       | STR _LT STR            { $$ = lnode(xlt, $1, $3); }
                     59:       | STR _LE STR            { $$ = lnode(xle, $1, $3); }
                     60:       | STR                    { $$ = lnode(xn, $1, NULL); }
                     61:        ;
                     62: 
                     63: %%
                     64: struct prim    {
                     65:        char    *p_name;
                     66:        int     p_lval;
                     67:        int     p_bin;
                     68: }      prims[] = {
                     69:        "-r", _R, 0,
                     70:        "-w", _W, 0,
                     71:        "-f", _F, 0,
                     72:        "-d", _D, 0,
                     73:        "-s", _S, 0,
                     74:        "-t", _T, 0,
                     75:        "-z", _Z, 0,
                     76:        "-n", _N, 0,
                     77:        "-eq", _EQ, 1,
                     78:        "-ne", _NE, 1,
                     79:        "-gt", _GT, 1,
                     80:        "-ge", _GE, 1,
                     81:        "-lt", _LT, 1,
                     82:        "-le", _LE, 1,
                     83:        "-o", OR, 1,
                     84:        "-a", AND, 1
                     85: };
                     86: 
                     87: 
                     88: char   **gav;
                     89: int    gac;
                     90: 
                     91: struct stat    sb;
                     92: 
                     93: NODE   *code;
                     94: 
                     95: char   *next();
                     96: NODE   *bnode();
                     97: NODE   *lnode();
                     98: long   atol();
                     99: int    xr();
                    100: int    xw();
                    101: int    xf();
                    102: int    xd();
                    103: int    xs();
                    104: int    xt();
                    105: int    xz();
                    106: int    xn();
                    107: int    xseq();
                    108: int    xsneq();
                    109: int    xeq();
                    110: int    xne();
                    111: int    xgt();
                    112: int    xge();
                    113: int    xlt();
                    114: 
                    115: main(argc, argv)
                    116: char *argv[];
                    117: {
                    118:        gav = argv+1;
                    119:        gac = argc-1;
                    120:        if (argv[0][0]=='[' && argv[0][1]=='\0') {
                    121:                if (strcmp(argv[gac], "]") != 0)
                    122:                        tsterr("unbalanced [..]");
                    123:                gac--;
                    124:        }
                    125:        if (gac == 0)
                    126:                exit(1);
                    127:        yyparse();
                    128:        exit(!execute(code));
                    129: }
                    130: 
                    131: /*
                    132:  * Lexical analyser
                    133:  */
                    134: yylex()
                    135: {
                    136:        static char laststr = 0; /* 1 if last token was string */
                    137:        register char *ap;
                    138:        register struct prim *pp;
                    139: 
                    140:        if ((yylval.fname = ap = next()) == NULL)
                    141:                return ('\n');
                    142: 
                    143:        if (*ap == '-') {
                    144:                for (pp = prims; pp < &prims[NPRIM]; pp++) {
                    145:                        if (strcmp(pp->p_name, ap) == 0) {
                    146:                                if (!laststr && pp->p_bin)
                    147:                                        break;
                    148:                                laststr = 0;
                    149:                                return (pp->p_lval);
                    150:                        }
                    151:                }
                    152:        }
                    153:        else {
                    154:                laststr = 0;
                    155:                if (strcmp("!=", ap) == 0)
                    156:                        return (SNEQ);
                    157: 
                    158:                if (ap[1] == '\0') {
                    159:                        if (ap[0]==')') {
                    160:                                laststr = 1;
                    161:                                return(')');
                    162:                        }
                    163:                        if (ap[0]=='(' || ap[0]=='!')
                    164:                                return (ap[0]);
                    165:                        if (ap[0]=='=')
                    166:                                return (SEQ);
                    167:                }
                    168:        }
                    169:        laststr = 1;
                    170:        return (STR);
                    171: }
                    172: 
                    173: yyerror()
                    174: {
                    175:        fprintf(stderr, "Test expression syntax error\n");
                    176:        usage();
                    177: }
                    178: 
                    179: /*
                    180:  * Return the next argument from the arg list.
                    181:  */
                    182: char *
                    183: next()
                    184: {
                    185:        if (gac < 1)
                    186:                return (NULL);
                    187:        gac--;
                    188:        return (*gav++);
                    189: }
                    190: 
                    191: /*
                    192:  * Build an expression tree node (non-leaf)
                    193:  */
                    194: NODE *
                    195: bnode(op, left, right)
                    196: int op;
                    197: NODE *left, *right;
                    198: {
                    199:        register NODE *np;
                    200:        char *malloc();
                    201: 
                    202:        if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
                    203:                tsterr("Out of space");
                    204:        np->n_un.n_op = op;
                    205:        np->n_left = left;
                    206:        np->n_right = right;
                    207:        return (np);
                    208: }
                    209: 
                    210: /*
                    211:  * Build a leaf node in expression tree.
                    212:  */
                    213: NODE *
                    214: lnode(fn, str1, str2)
                    215: int (*fn)();
                    216: char *str1, *str2;
                    217: {
                    218:        register NODE *np;
                    219:        char *malloc();
                    220: 
                    221:        if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
                    222:                tsterr("Out of space");
                    223:        np->n_left = np->n_right = NULL;
                    224:        np->n_un.n_fun = fn;
                    225:        np->n_s1 = str1;
                    226:        np->n_s2 = str2;
                    227:        return (np);
                    228: }
                    229: 
                    230: /*
                    231:  * Execute compiled code.
                    232:  */
                    233: execute(np)
                    234: register NODE *np;
                    235: {
                    236:        if (np->n_left != NULL)
                    237:                switch (np->n_un.n_op) {
                    238:                case AND:
                    239:                        if (execute(np->n_left) && execute(np->n_right))
                    240:                                return (1);
                    241:                        return (0);
                    242: 
                    243:                case OR:
                    244:                        if (execute(np->n_left) || execute(np->n_right))
                    245:                                return (1);
                    246:                        return (0);
                    247: 
                    248:                case '!':
                    249:                        return (!execute(np->n_left));
                    250: 
                    251:                default:
                    252:                        tsterr("Panic: bad tree (op %d)", np->n_un.n_op);
                    253:                }
                    254:        else
                    255:                return ((*np->n_un.n_fun)(np));
                    256:        /* NOTREACHED */
                    257: }
                    258: 
                    259: /*
                    260:  * Check to see if the file exists
                    261:  * and if readable.
                    262:  */
                    263: xr(np)
                    264: NODE *np;
                    265: {
                    266:        return (access(np->n_s1, AREAD) >= 0);
                    267: }
                    268: 
                    269: /*
                    270:  * Check if the file exists and is
                    271:  * writeable.
                    272:  */
                    273: xw(np)
                    274: NODE *np;
                    275: {
                    276:        return (access(np->n_s1, AWRITE) >= 0);
                    277: }
                    278: 
                    279: /*
                    280:  * Check if the file exists and is not
                    281:  * a directory.
                    282:  */
                    283: xf(np)
                    284: NODE *np;
                    285: {
                    286:        return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)!=S_IFDIR);
                    287: }
                    288: 
                    289: /*
                    290:  * Check to see if the file exists
                    291:  * and is a directory.
                    292:  */
                    293: xd(np)
                    294: NODE *np;
                    295: {
                    296:        return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR);
                    297: }
                    298: 
                    299: /*
                    300:  * Check to see if the file exists
                    301:  * and has a non-zero size.
                    302:  */
                    303: xs(np)
                    304: NODE *np;
                    305: {
                    306:        return (stat(np->n_s1, &sb)>=0 && sb.st_size>0);
                    307: }
                    308: 
                    309: /*
                    310:  * Check to see if the file
                    311:  * descriptor is associated
                    312:  * with a terminal.
                    313:  */
                    314: xt(np)
                    315: NODE *np;
                    316: {
                    317:        return (isatty(atoi(np->n_s1)));
                    318: }
                    319: 
                    320: /*
                    321:  * True if the length of the given
                    322:  * string is zero.
                    323:  */
                    324: xz(np)
                    325: NODE *np;
                    326: {
                    327:        return (np->n_s1[0] == '\0');
                    328: }
                    329: 
                    330: /*
                    331:  * True if the length of the given
                    332:  * string is non-zero.
                    333:  */
                    334: xn(np)
                    335: NODE *np;
                    336: {
                    337:        return (np->n_s1[0] != '\0');
                    338: }
                    339: 
                    340: /*
                    341:  * True if the two strings are
                    342:  * lexicographically equal.
                    343:  */
                    344: xseq(np)
                    345: register NODE *np;
                    346: {
                    347:        return (strcmp(np->n_s1, np->n_s2) == 0);
                    348: }
                    349: 
                    350: /*
                    351:  * True if the two strings are
                    352:  * lexicographically unequal.
                    353:  */
                    354: xsneq(np)
                    355: register NODE *np;
                    356: {
                    357:        return (strcmp(np->n_s1, np->n_s2) != 0);
                    358: }
                    359: 
                    360: /*
                    361:  * True if the two numbers are
                    362:  * equal.
                    363:  */
                    364: xeq(np)
                    365: register NODE *np;
                    366: {
                    367:        return (atol(np->n_s1) == atol(np->n_s2));
                    368: }
                    369: 
                    370: /*
                    371:  * True if the two numbers are
                    372:  * not equal.
                    373:  */
                    374: xne(np)
                    375: register NODE *np;
                    376: {
                    377:        return (atol(np->n_s1) != atol(np->n_s2));
                    378: }
                    379: 
                    380: /*
                    381:  * True if the first number is
                    382:  * greater than the second.
                    383:  */
                    384: xgt(np)
                    385: register NODE *np;
                    386: {
                    387:        return (atol(np->n_s1) > atol(np->n_s2));
                    388: }
                    389: 
                    390: /*
                    391:  * True if the first number is
                    392:  * greater than or equal to the second.
                    393:  */
                    394: xge(np)
                    395: register NODE *np;
                    396: {
                    397:        return (atol(np->n_s1) >= atol(np->n_s2));
                    398: }
                    399: 
                    400: /*
                    401:  * True if the first number is
                    402:  * less than the second.
                    403:  */
                    404: xlt(np)
                    405: register NODE *np;
                    406: {
                    407:        return (atol(np->n_s1) < atol(np->n_s2));
                    408: }
                    409: 
                    410: /*
                    411:  * True if the first number is
                    412:  * less than or equal to the second.
                    413:  */
                    414: xle(np)
                    415: register NODE *np;
                    416: {
                    417:        return (atol(np->n_s1) <= atol(np->n_s2));
                    418: }
                    419: 
                    420: /*
                    421:  * Error messages.
                    422:  */
                    423: /* VARARGS */
                    424: tsterr(x)
                    425: {
                    426:        fprintf(stderr, "test: %r\n", &x);
                    427:        exit(1);
                    428: }
                    429: 
                    430: usage()
                    431: {
                    432:        fprintf(stderr, "Usage: test expression\n");
                    433:        exit(1);
                    434: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.