|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6570 (0x19aa) Types: TextFile Notes: UNIX file Names: »test.y«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/test/test.y«
%{ /* * Set return status based on * various specified conditions, * mostly related to files. * Used mostly in shell files. */ #include <stdio.h> #include <stat.h> #include <access.h> #include "testnode.h" #define NPRIM (sizeof(prims)/sizeof(prims[0])) #define NFNAME 500 /* size of filename buffer */ %} %start command %union { NODE *nodeptr; char *fname; } %left OR %left AND %left '!' %token _R _W _F _D _S _T _Z _N %token SEQ SNEQ %token _EQ _NE _GT _GE _LT _LE %token <fname> STR %type <nodeptr> exp %% command: exp '\n' { code = $1; return; } ; exp: '(' exp ')' { $$ = $2; } | '!' exp { $$ = bnode('!', $2, NULL); } | exp OR exp { $$ = bnode(OR, $1, $3); } | exp AND exp { $$ = bnode(AND, $1, $3); } | _R STR { $$ = lnode(xr, $2, NULL); } | _W STR { $$ = lnode(xw, $2, NULL); } | _F STR { $$ = lnode(xf, $2, NULL); } | _D STR { $$ = lnode(xd, $2, NULL); } | _S STR { $$ = lnode(xs, $2, NULL); } | _T STR { $$ = lnode(xt, $2, NULL); } | _T { $$ = lnode(xt, "1", NULL); } | _Z STR { $$ = lnode(xz, $2, NULL); } | _N STR { $$ = lnode(xn, $2, NULL); } | STR SEQ STR { $$ = lnode(xseq, $1, $3); } | STR SNEQ STR { $$ = lnode(xsneq, $1, $3); } | STR _EQ STR { $$ = lnode(xeq, $1, $3); } | STR _NE STR { $$ = lnode(xne, $1, $3); } | STR _GT STR { $$ = lnode(xgt, $1, $3); } | STR _GE STR { $$ = lnode(xge, $1, $3); } | STR _LT STR { $$ = lnode(xlt, $1, $3); } | STR _LE STR { $$ = lnode(xle, $1, $3); } | STR { $$ = lnode(xn, $1, NULL); } ; %% struct prim { char *p_name; int p_lval; } prims[] = { "-r", _R, "-w", _W, "-f", _F, "-d", _D, "-s", _S, "-t", _T, "-z", _Z, "-n", _N, "-eq", _EQ, "-ne", _NE, "-gt", _GT, "-ge", _GE, "-lt", _LT, "-le", _LE, "-o", OR, "-a", AND, }; char **gav; int gac; struct stat sb; NODE *code; char *next(); NODE *bnode(); NODE *lnode(); long atol(); int xr(); int xw(); int xf(); int xd(); int xs(); int xt(); int xz(); int xn(); int xseq(); int xsneq(); int xeq(); int xne(); int xgt(); int xge(); int xlt(); main(argc, argv) char *argv[]; { gav = argv+1; gac = argc-1; if (argv[0][0]=='[' && argv[0][1]=='\0') { if (strcmp(argv[gac], "]") != 0) tsterr("unbalanced [..]"); gac--; } if (gac == 0) exit(1); yyparse(); exit(!execute(code)); } /* * Lexical analyser */ yylex() { register char *ap; register struct prim *pp; if ((ap = next()) == NULL) return ('\n'); if (ap[1] == '\0') if (ap[0]=='(' || ap[0]==')' || ap[0]=='!') return (ap[0]); if (ap[0]=='!' && ap[1]=='=' && ap[2]=='\0') return (SNEQ); if (ap[0]=='=' && ap[1]=='\0') return (SEQ); if (*ap == '-') for (pp = prims; pp < &prims[NPRIM]; pp++) if (strcmp(pp->p_name, ap) == 0) return (pp->p_lval); yylval.fname = ap; return (STR); } yyerror() { fprintf(stderr, "Test expression syntax error\n"); usage(); } /* * Return the next argument from the arg list. */ char * next() { if (gac < 1) return (NULL); gac--; return (*gav++); } /* * Build an expression tree node (non-leaf) */ NODE * bnode(op, left, right) int op; NODE *left, *right; { register NODE *np; char *malloc(); if ((np = (NODE *)malloc(sizeof (NODE))) == NULL) tsterr("Out of space"); np->n_un.n_op = op; np->n_left = left; np->n_right = right; return (np); } /* * Build a leaf node in expression tree. */ NODE * lnode(fn, str1, str2) int (*fn)(); char *str1, *str2; { register NODE *np; char *malloc(); if ((np = (NODE *)malloc(sizeof (NODE))) == NULL) tsterr("Out of space"); np->n_left = np->n_right = NULL; np->n_un.n_fun = fn; np->n_s1 = str1; np->n_s2 = str2; return (np); } /* * Execute compiled code. */ execute(np) register NODE *np; { if (np->n_left != NULL) switch (np->n_un.n_op) { case AND: if (execute(np->n_left) && execute(np->n_right)) return (1); return (0); case OR: if (execute(np->n_left) || execute(np->n_right)) return (1); return (0); case '!': return (!execute(np->n_left)); default: tsterr("Panic: bad tree (op %d)", np->n_un.n_op); } else return ((*np->n_un.n_fun)(np)); /* NOTREACHED */ } /* * Check to see if the file exists * and if readable. */ xr(np) NODE *np; { return (access(np->n_s1, AREAD) >= 0); } /* * Check if the file exists and is * writeable. */ xw(np) NODE *np; { return (access(np->n_s1, AWRITE) >= 0); } /* * Check if the file exists and is not * a directory. */ xf(np) NODE *np; { return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)!=S_IFDIR); } /* * Check to see if the file exists * and is a directory. */ xd(np) NODE *np; { return (stat(np->n_s1, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR); } /* * Check to see if the file exists * and has a non-zero size. */ xs(np) NODE *np; { return (stat(np->n_s1, &sb)>=0 && sb.st_size>0); } /* * Check to see if the file * descriptor is associated * with a terminal. */ xt(np) NODE *np; { return (isatty(atoi(np->n_s1))); } /* * True if the length of the given * string is zero. */ xz(np) NODE *np; { return (np->n_s1[0] == '\0'); } /* * True if the length of the given * string is non-zero. */ xn(np) NODE *np; { return (np->n_s1[0] != '\0'); } /* * True if the two strings are * lexicographically equal. */ xseq(np) register NODE *np; { return (strcmp(np->n_s1, np->n_s2) == 0); } /* * True if the two strings are * lexicographically unequal. */ xsneq(np) register NODE *np; { return (strcmp(np->n_s1, np->n_s2) != 0); } /* * True if the two numbers are * equal. */ xeq(np) register NODE *np; { return (atol(np->n_s1) == atol(np->n_s2)); } /* * True if the two numbers are * not equal. */ xne(np) register NODE *np; { return (atol(np->n_s1) != atol(np->n_s2)); } /* * True if the first number is * greater than the second. */ xgt(np) register NODE *np; { return (atol(np->n_s1) > atol(np->n_s2)); } /* * True if the first number is * greater than or equal to the second. */ xge(np) register NODE *np; { return (atol(np->n_s1) >= atol(np->n_s2)); } /* * True if the first number is * less than the second. */ xlt(np) register NODE *np; { return (atol(np->n_s1) < atol(np->n_s2)); } /* * True if the first number is * less than or equal to the second. */ xle(np) register NODE *np; { return (atol(np->n_s1) <= atol(np->n_s2)); } /* * Error messages. */ /* VARARGS */ tsterr(x) { fprintf(stderr, "test: %r\n", &x); exit(1); } usage() { fprintf(stderr, "Usage: test expression\n"); exit(1); }