|
|
1.1 root 1:
2: #line 1 "../test.y"
3:
4: /*
5: * Set return status based on
6: * various specified conditions,
7: * mostly related to files.
8: * Used mostly in shell files.
9: */
10:
11: #include <stdio.h>
12: #include <sys/stat.h>
13: #include <access.h>
14: #include "testnode.h"
15:
16: #define NPRIM (sizeof(prims)/sizeof(prims[0]))
17: #define NFNAME 500 /* size of filename buffer */
18:
19: #include "y.tab.h"
20: #define YYCLEARIN yychar = -1000
21: #define YYERROK yyerrflag = 0
22: extern int yychar;
23: extern short yyerrflag;
24: #ifndef YYMAXDEPTH
25: #define YYMAXDEPTH 150
26: #endif
27: YYSTYPE yyval, yylval;
28:
29: #line 63 "../test.y"
30:
31: struct prim {
32: char *p_name;
33: int p_lval;
34: int p_bin;
35: } prims[] = {
36: "-r", _R, 0,
37: "-w", _W, 0,
38: "-f", _F, 0,
39: "-d", _D, 0,
40: "-s", _S, 0,
41: "-t", _T, 0,
42: "-z", _Z, 0,
43: "-n", _N, 0,
44: "-eq", _EQ, 1,
45: "-ne", _NE, 1,
46: "-gt", _GT, 1,
47: "-ge", _GE, 1,
48: "-lt", _LT, 1,
49: "-le", _LE, 1,
50: "-o", OR, 1,
51: "-a", AND, 1
52: };
53:
54:
55: char **gav;
56: int gac;
57:
58: struct stat sb;
59:
60: NODE *code;
61:
62: char *next();
63: NODE *bnode();
64: NODE *lnode();
65: long atol();
66: int xr();
67: int xw();
68: int xf();
69: int xd();
70: int xs();
71: int xt();
72: int xz();
73: int xn();
74: int xseq();
75: int xsneq();
76: int xeq();
77: int xne();
78: int xgt();
79: int xge();
80: int xlt();
81:
82: main(argc, argv)
83: char *argv[];
84: {
85: gav = argv+1;
86: gac = argc-1;
87: if (argv[0][0]=='[' && argv[0][1]=='\0') {
88: if (strcmp(argv[gac], "]") != 0)
89: tsterr("unbalanced [..]");
90: gac--;
91: }
92: if (gac == 0)
93: exit(1);
94: yyparse();
95: exit(!execute(code));
96: }
97:
98: /*
99: * Lexical analyser
100: */
101: yylex()
102: {
103: static char laststr = 0; /* 1 if last token was string */
104: register char *ap;
105: register struct prim *pp;
106:
107: if ((yylval.fname = ap = next()) == NULL)
108: return ('\n');
109:
110: if (*ap == '-') {
111: for (pp = prims; pp < &prims[NPRIM]; pp++) {
112: if (strcmp(pp->p_name, ap) == 0) {
113: if (!laststr && pp->p_bin)
114: break;
115: laststr = 0;
116: return (pp->p_lval);
117: }
118: }
119: }
120: else {
121: laststr = 0;
122: if (strcmp("!=", ap) == 0)
123: return (SNEQ);
124:
125: if (ap[1] == '\0') {
126: if (ap[0]==')') {
127: laststr = 1;
128: return(')');
129: }
130: if (ap[0]=='(' || ap[0]=='!')
131: return (ap[0]);
132: if (ap[0]=='=')
133: return (SEQ);
134: }
135: }
136: laststr = 1;
137: return (STR);
138: }
139:
140: yyerror()
141: {
142: fprintf(stderr, "Test expression syntax error\n");
143: usage();
144: }
145:
146: /*
147: * Return the next argument from the arg list.
148: */
149: char *
150: next()
151: {
152: if (gac < 1)
153: return (NULL);
154: gac--;
155: return (*gav++);
156: }
157:
158: /*
159: * Build an expression tree node (non-leaf)
160: */
161: NODE *
162: bnode(op, left, right)
163: int op;
164: NODE *left, *right;
165: {
166: register NODE *np;
167: char *malloc();
168:
169: if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
170: tsterr("Out of space");
171: np->n_un.n_op = op;
172: np->n_left = left;
173: np->n_right = right;
174: return (np);
175: }
176:
177: /*
178: * Build a leaf node in expression tree.
179: */
180: NODE *
181: lnode(fn, str1, str2)
182: int (*fn)();
183: char *str1, *str2;
184: {
185: register NODE *np;
186: char *malloc();
187:
188: if ((np = (NODE *)malloc(sizeof (NODE))) == NULL)
189: tsterr("Out of space");
190: np->n_left = np->n_right = NULL;
191: np->n_un.n_fun = fn;
192: np->n_s1 = str1;
193: np->n_s2 = str2;
194: return (np);
195: }
196:
197: /*
198: * Execute compiled code.
199: */
200: execute(np)
201: register NODE *np;
202: {
203: if (np->n_left != NULL)
204: switch (np->n_un.n_op) {
205: case AND:
206: if (execute(np->n_left) && execute(np->n_right))
207: return (1);
208: return (0);
209:
210: case OR:
211: if (execute(np->n_left) || execute(np->n_right))
212: return (1);
213: return (0);
214:
215: case '!':
216: return (!execute(np->n_left));
217:
218: default:
219: tsterr("Panic: bad tree (op %d)", np->n_un.n_op);
220: }
221: else
222: return ((*np->n_un.n_fun)(np));
223: /* NOTREACHED */
224: }
225:
226: /*
227: * Check to see if the file exists
228: * and if readable.
229: */
230: xr(np)
231: NODE *np;
232: {
233: return (access(np->n_s1, AREAD) >= 0);
234: }
235:
236: /*
237: * Check if the file exists and is
238: * writeable.
239: */
240: xw(np)
241: NODE *np;
242: {
243: return (access(np->n_s1, AWRITE) >= 0);
244: }
245:
246: /*
247: * Check if the file exists and is not
248: * a directory.
249: */
250: xf(np)
251: NODE *np;
252: {
253: return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)!=S_IFDIR);
254: }
255:
256: /*
257: * Check to see if the file exists
258: * and is a directory.
259: */
260: xd(np)
261: NODE *np;
262: {
263: return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR);
264: }
265:
266: /*
267: * Check to see if the file exists
268: * and has a non-zero size.
269: */
270: xs(np)
271: NODE *np;
272: {
273: return (stat(np->n_s1, &sb)>=0 && sb.st_size>0);
274: }
275:
276: /*
277: * Check to see if the file
278: * descriptor is associated
279: * with a terminal.
280: */
281: xt(np)
282: NODE *np;
283: {
284: return (isatty(atoi(np->n_s1)));
285: }
286:
287: /*
288: * True if the length of the given
289: * string is zero.
290: */
291: xz(np)
292: NODE *np;
293: {
294: return (np->n_s1[0] == '\0');
295: }
296:
297: /*
298: * True if the length of the given
299: * string is non-zero.
300: */
301: xn(np)
302: NODE *np;
303: {
304: return (np->n_s1[0] != '\0');
305: }
306:
307: /*
308: * True if the two strings are
309: * lexicographically equal.
310: */
311: xseq(np)
312: register NODE *np;
313: {
314: return (strcmp(np->n_s1, np->n_s2) == 0);
315: }
316:
317: /*
318: * True if the two strings are
319: * lexicographically unequal.
320: */
321: xsneq(np)
322: register NODE *np;
323: {
324: return (strcmp(np->n_s1, np->n_s2) != 0);
325: }
326:
327: /*
328: * True if the two numbers are
329: * equal.
330: */
331: xeq(np)
332: register NODE *np;
333: {
334: return (atol(np->n_s1) == atol(np->n_s2));
335: }
336:
337: /*
338: * True if the two numbers are
339: * not equal.
340: */
341: xne(np)
342: register NODE *np;
343: {
344: return (atol(np->n_s1) != atol(np->n_s2));
345: }
346:
347: /*
348: * True if the first number is
349: * greater than the second.
350: */
351: xgt(np)
352: register NODE *np;
353: {
354: return (atol(np->n_s1) > atol(np->n_s2));
355: }
356:
357: /*
358: * True if the first number is
359: * greater than or equal to the second.
360: */
361: xge(np)
362: register NODE *np;
363: {
364: return (atol(np->n_s1) >= atol(np->n_s2));
365: }
366:
367: /*
368: * True if the first number is
369: * less than the second.
370: */
371: xlt(np)
372: register NODE *np;
373: {
374: return (atol(np->n_s1) < atol(np->n_s2));
375: }
376:
377: /*
378: * True if the first number is
379: * less than or equal to the second.
380: */
381: xle(np)
382: register NODE *np;
383: {
384: return (atol(np->n_s1) <= atol(np->n_s2));
385: }
386:
387: /*
388: * Error messages.
389: */
390: /* VARARGS */
391: tsterr(x)
392: {
393: fprintf(stderr, "test: %r\n", &x);
394: exit(1);
395: }
396:
397: usage()
398: {
399: fprintf(stderr, "Usage: test expression\n");
400: exit(1);
401: }
402: #ifdef YYTNAMES
403: readonly struct yytname yytnames[26] =
404: {
405: "$end", -1,
406: "error", -2,
407: "OR", 256,
408: "AND", 257,
409: "'!'", 33,
410: "_R", 258,
411: "_W", 259,
412: "_F", 260,
413: "_D", 261,
414: "_S", 262,
415: "_T", 263,
416: "_Z", 264,
417: "_N", 265,
418: "SEQ", 266,
419: "SNEQ", 267,
420: "_EQ", 268,
421: "_NE", 269,
422: "_GT", 270,
423: "_GE", 271,
424: "_LT", 272,
425: "_LE", 273,
426: "STR", 275,
427: "'\\n'", 10,
428: "'('", 40,
429: "')'", 41,
430: NULL
431: } ;
432: #endif
433: #include <action.h>
434: unsigned char yypdnt[24] = {
435: 0, 1, 2, 2, 2, 2, 2, 2,
436: 2, 2, 2, 2, 2, 2, 2, 2,
437: 2, 2, 2, 2, 2, 2, 2, 2
438: };
439: unsigned char yypn[24] = {
440: 2, 2, 3, 2, 3, 3, 2, 2,
441: 2, 2, 2, 2, 1, 2, 2, 3,
442: 3, 3, 3, 3, 3, 3, 3, 1
443: };
444: unsigned char yypgo[3] = {
445: 0, 0, 2
446: };
447: unsigned int yygo[12] = {
448: -1000, 12, 1, 14, 11, 31, 33, 45,
449: 34, 46, -1000, 13
450: };
451: unsigned char yypa[47] = {
452: 0, 0, 24, 28, 32, 36, 40, 44,
453: 48, 52, 56, 0, 74, 78, 86, 88,
454: 90, 92, 94, 96, 98, 100, 102, 104,
455: 108, 112, 116, 120, 124, 128, 132, 136,
456: 144, 0, 0, 148, 150, 152, 154, 156,
457: 158, 160, 162, 164, 166, 168, 172
458: };
459: unsigned int yyact[174] = {
460: 1, 33, 2, 258, 3, 259, 4, 260,
461: 5, 261, 6, 262, 7, 263, 8, 264,
462: 9, 265, 10, 275, 11, 40, 24576, -1000,
463: 15, 275, 24576, -1000, 16, 275, 24576, -1000,
464: 17, 275, 24576, -1000, 18, 275, 24576, -1000,
465: 19, 275, 24576, -1000, 20, 275, 8204, -1000,
466: 21, 275, 24576, -1000, 22, 275, 24576, -1000,
467: 23, 266, 24, 267, 25, 268, 26, 269,
468: 27, 270, 28, 271, 29, 272, 30, 273,
469: 8215, -1000, 32, -1, 24576, -1000, 33, 256,
470: 34, 257, 35, 10, 24576, -1000, 8195, -1000,
471: 8198, -1000, 8199, -1000, 8200, -1000, 8201, -1000,
472: 8202, -1000, 8203, -1000, 8205, -1000, 8206, -1000,
473: 36, 275, 24576, -1000, 37, 275, 24576, -1000,
474: 38, 275, 24576, -1000, 39, 275, 24576, -1000,
475: 40, 275, 24576, -1000, 41, 275, 24576, -1000,
476: 42, 275, 24576, -1000, 43, 275, 24576, -1000,
477: 33, 256, 34, 257, 44, 41, 24576, -1000,
478: 16384, -1, 24576, -1000, 8193, -1000, 8207, -1000,
479: 8208, -1000, 8209, -1000, 8210, -1000, 8211, -1000,
480: 8212, -1000, 8213, -1000, 8214, -1000, 8194, -1000,
481: 34, 257, 8196, -1000, 8197, -1000
482: };
483: #define YYNOCHAR (-1000)
484: #define yyerrok yyerrflag=0
485: #define yyclearin yylval=YYNOCHAR
486: int yystack[YYMAXDEPTH];
487: YYSTYPE yyvstack[YYMAXDEPTH], *yyv;
488: int yychar;
489:
490: #ifdef YYDEBUG
491: int yydebug = 1; /* No sir, not in the BSS */
492: #include <stdio.h>
493: #endif
494:
495: short yyerrflag;
496: int *yys;
497:
498: yyparse()
499: {
500: register YYSTYPE *yypvt;
501: int act;
502: register unsigned *ip, yystate;
503: int pno;
504: yystate = 0;
505: yychar = YYNOCHAR;
506: yyv = &yyvstack[-1];
507: yys = &yystack[-1];
508:
509: stack:
510: if( ++yys >= &yystack[YYMAXDEPTH] ) {
511: write(2, "Stack overflow\n", 15);
512: exit(1);
513: }
514: *yys = yystate;
515: *++yyv = yyval;
516: #ifdef YYDEBUG
517: if( yydebug )
518: fprintf(stdout, "Stack state %d, char %d\n", yystate, yychar);
519: #endif
520:
521: read:
522: ip = &yyact[yypa[yystate]];
523: if( ip[1] != YYNOCHAR ) {
524: if( yychar == YYNOCHAR ) {
525: yychar = yylex();
526: #ifdef YYDEBUG
527: if( yydebug )
528: fprintf(stdout, "lex read char %d, val %d\n", yychar, yylval);
529: #endif
530: }
531: while (ip[1]!=YYNOCHAR) {
532: if (ip[1]==yychar)
533: break;
534: ip += 2;
535: }
536: }
537: act = ip[0];
538: switch( act>>YYACTSH ) {
539: case YYSHIFTACT:
540: if( ip[1]==YYNOCHAR )
541: goto YYerract;
542: if( yychar != -1 )
543: yychar = YYNOCHAR; /* dont throw away EOF */
544: yystate = act&YYAMASK;
545: yyval = yylval;
546: #ifdef YYDEBUG
547: if( yydebug )
548: fprintf(stdout, "shift %d\n", yystate);
549: #endif
550: if( yyerrflag )
551: --yyerrflag;
552: goto stack;
553:
554: case YYACCEPTACT:
555: #ifdef YYDEBUG
556: if( yydebug )
557: fprintf(stdout, "accept\n");
558: #endif
559: return(0);
560:
561: case YYERRACT:
562: YYerract:
563: switch (yyerrflag) {
564: case 0:
565: yyerror("Syntax error");
566:
567: case 1:
568: case 2:
569:
570: yyerrflag = 3;
571: while( yys >= & yystack[0] ) {
572: ip = &yyact[yypa[*yys]];
573: while( ip[1]!=YYNOCHAR )
574: ip += 2;
575: if( (*ip&~YYAMASK) == (YYSHIFTACT<<YYACTSH) ) {
576: yystate = *ip&YYAMASK;
577: goto stack;
578: }
579: #ifdef YYDEBUG
580: if( yydebug )
581: fprintf(stderr, "error recovery leaves state %d, uncovers %d\n", *yys, yys[-1]);
582: #endif
583: yys--;
584: yyv--;
585: }
586: #ifdef YYDEBUG
587: if( yydebug )
588: fprintf(stderr, "no shift on error; abort\n");
589: #endif
590: return(1);
591:
592: case 3:
593: #ifdef YYDEBUG
594: if( yydebug )
595: fprintf(stderr, "Error recovery clobbers char %o\n", yychar);
596: #endif
597: if( yychar==YYEOFVAL )
598: return(1);
599: yychar = YYNOCHAR;
600: goto read;
601: }
602:
603: case YYREDACT:
604: pno = act&YYAMASK;
605: #ifdef YYDEBUG
606: if( yydebug )
607: fprintf(stdout, "reduce %d\n", pno);
608: #endif
609: yypvt = yyv;
610: yyv -= yypn[pno];
611: yys -= yypn[pno];
612: yyval = yyv[1];
613: switch(pno) {
614:
615: case 1: {
616:
617: #line 35 "../test.y"
618: code = yypvt[-1].nodeptr; return; }break;
619:
620: case 2: {
621:
622: #line 39 "../test.y"
623: yyval.nodeptr = yypvt[-1].nodeptr; }break;
624:
625: case 3: {
626:
627: #line 40 "../test.y"
628: yyval.nodeptr = bnode('!', yypvt[0].nodeptr, NULL); }break;
629:
630: case 4: {
631:
632: #line 41 "../test.y"
633: yyval.nodeptr = bnode(OR, yypvt[-2].nodeptr, yypvt[0].nodeptr); }break;
634:
635: case 5: {
636:
637: #line 42 "../test.y"
638: yyval.nodeptr = bnode(AND, yypvt[-2].nodeptr, yypvt[0].nodeptr); }break;
639:
640: case 6: {
641:
642: #line 43 "../test.y"
643: yyval.nodeptr = lnode(xr, yypvt[0].fname, NULL); }break;
644:
645: case 7: {
646:
647: #line 44 "../test.y"
648: yyval.nodeptr = lnode(xw, yypvt[0].fname, NULL); }break;
649:
650: case 8: {
651:
652: #line 45 "../test.y"
653: yyval.nodeptr = lnode(xf, yypvt[0].fname, NULL); }break;
654:
655: case 9: {
656:
657: #line 46 "../test.y"
658: yyval.nodeptr = lnode(xd, yypvt[0].fname, NULL); }break;
659:
660: case 10: {
661:
662: #line 47 "../test.y"
663: yyval.nodeptr = lnode(xs, yypvt[0].fname, NULL); }break;
664:
665: case 11: {
666:
667: #line 48 "../test.y"
668: yyval.nodeptr = lnode(xt, yypvt[0].fname, NULL); }break;
669:
670: case 12: {
671:
672: #line 49 "../test.y"
673: yyval.nodeptr = lnode(xt, "1", NULL); }break;
674:
675: case 13: {
676:
677: #line 50 "../test.y"
678: yyval.nodeptr = lnode(xz, yypvt[0].fname, NULL); }break;
679:
680: case 14: {
681:
682: #line 51 "../test.y"
683: yyval.nodeptr = lnode(xn, yypvt[0].fname, NULL); }break;
684:
685: case 15: {
686:
687: #line 52 "../test.y"
688: yyval.nodeptr = lnode(xseq, yypvt[-2].fname, yypvt[0].fname); }break;
689:
690: case 16: {
691:
692: #line 53 "../test.y"
693: yyval.nodeptr = lnode(xsneq, yypvt[-2].fname, yypvt[0].fname); }break;
694:
695: case 17: {
696:
697: #line 54 "../test.y"
698: yyval.nodeptr = lnode(xeq, yypvt[-2].fname, yypvt[0].fname); }break;
699:
700: case 18: {
701:
702: #line 55 "../test.y"
703: yyval.nodeptr = lnode(xne, yypvt[-2].fname, yypvt[0].fname); }break;
704:
705: case 19: {
706:
707: #line 56 "../test.y"
708: yyval.nodeptr = lnode(xgt, yypvt[-2].fname, yypvt[0].fname); }break;
709:
710: case 20: {
711:
712: #line 57 "../test.y"
713: yyval.nodeptr = lnode(xge, yypvt[-2].fname, yypvt[0].fname); }break;
714:
715: case 21: {
716:
717: #line 58 "../test.y"
718: yyval.nodeptr = lnode(xlt, yypvt[-2].fname, yypvt[0].fname); }break;
719:
720: case 22: {
721:
722: #line 59 "../test.y"
723: yyval.nodeptr = lnode(xle, yypvt[-2].fname, yypvt[0].fname); }break;
724:
725: case 23: {
726:
727: #line 60 "../test.y"
728: yyval.nodeptr = lnode(xn, yypvt[0].fname, NULL); }break;
729:
730: }
731: ip = &yygo[ yypgo[yypdnt[pno]] ];
732: while( *ip!=*yys && *ip!=YYNOCHAR )
733: ip += 2;
734: yystate = ip[1];
735: goto stack;
736: }
737: }
738:
739:
740:
741:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.