|
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: 18840 (0x4998) Types: TextFile Notes: UNIX file Names: »expr.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/expr/expr.c«
#line 1 "/usr/src/cmd/expr.y" /* * Expr.y, yacc grammar for expr. Designed so no stdio is called, which * makes the final object code about 1/3 smaller. To make, say * yacc expr.y; cc -O -o expr y.tab.c; */ #include <ctype.h> #include <stdio.h> #define TRUE (0 == 0) #define FALSE (0 != 0) #define true(e) (*(e) == '\0' || (isnum(e) && atol(e) == 0) ? FALSE : TRUE) int exstat; /* exit status returned by main() */ char *result; /* final expr printed by main */ char s0[] = "0"; /* `0' integer - `false' expr */ char s1[] = "1"; /* `1' integer - `true' expr */ char *regexp(), *arithop(), *relop(), *realloc(), *ltoa(); long atol(); /* * The following names are used by the regular expression operator. */ #define BRSIZE 10 /* Length of brace list */ typedef struct { char *b_bp; /* Ptr to start of string matched */ char *b_ep; /* Ptr to end of string matched */ } BRACE; #define CSNUL 000 /* End of expression */ #define CSSOL 001 /* Match start of line */ #define CSEOL 002 /* End of line */ #define CSOPR 003 /* \( */ #define CSCPR 004 /* \) */ #define CSBRN 005 /* Match nth brace */ #define CSDOT 006 /* Any character */ #define CMDOT 007 /* Stream of any characters */ #define CSCHR 010 /* Match given character */ #define CMCHR 011 /* Match stream of given characters */ #define CSCCL 014 /* Character class */ #define CMCCL 015 /* Stream of character class */ #define CSNCL 016 /* Not character class */ #define CMNCL 017 /* Stream of not char class */ #define getx(c) *e++ #define ungetx(c) --e BRACE brlist[BRSIZE]; /* brace list */ int brcount; /* # of braces in reg_expr */ char *codebuf; /* Ptr to a compiled regular expr */ int cbsiz = 512; /* Initial size of codebuf */ char *match(); char *overflow(); #include "y.tab.h" #define YYCLEARIN yychar = -1000 #define YYERROK yyerrflag = 0 extern int yychar; extern short yyerrflag; #ifndef YYMAXDEPTH #define YYMAXDEPTH 150 #endif YYSTYPE yyval, yylval; #line 137 "/usr/src/cmd/expr.y" char **av; /* Global version of argv[] in main() */ int avx; /* Index into av[] */ main(argc, argv) int argc; char **argv; { if (argc == 1) return (2); av = argv; yyparse(); output(result, 1); output("\n", 1); return (exstat); } char * arithop(op, e1, e2) register int op; register char *e1, *e2; { register long v1, v2; if (!isnum(e1)) { avx -= 3; yyerror(); } if (!isnum(e2)) { --avx; yyerror(); } v1 = atol(e1); v2 = atol(e2); switch (op) { case '+': v1 += v2; break; case '-': v1 -= v2; break; case '*': v1 *= v2; break; case '/': v1 /= v2; break; case '%': v1 %= v2; break; } return (ltoa(v1)); } char * relop(op, e1, e2) register int op; register char *e1, *e2; { register int cmp; register long v1, v2; if (!isnum(e1) || !isnum(e2)) cmp = strcmp(e1, e2); else { v1 = atol(e1); v2 = atol(e2); cmp = (v1 > v2) ? 1 : (v1 == v2) ? 0 : -1; } switch (op) { case '<': return ((cmp < 0) ? s1 : s0); case '>': return ((cmp > 0) ? s1 : s0); case LE: return ((cmp <= 0) ? s1 : s0); case GE: return ((cmp >= 0) ? s1 : s0); case EQ: return ((cmp == 0) ? s1 : s0); case NEQ: return ((cmp != 0) ? s1 : s0); } } char * regexp(e1, e2) char *e1, *e2; { register char *a = e1; register char *b; register BRACE *brp; codebuf = malloc(512); compile(e2); if (brcount > 0) /* brcount is now the number of braces in e2 */ brlist[brcount].b_bp = brlist[brcount].b_ep = NULL; if (codebuf[0] == CSSOL) b = match(a, codebuf + 1); else for ( ; *a != '\0'; ++a) if ((b = match(a, codebuf)) != NULL) break; if (b == NULL) return ("0"); if (brcount == 0) return (ltoa((long)(b - a))); /* Remaining case is extraction of fields */ for (a = e1, brp = brlist; (b = brp->b_bp) != NULL; ++brp) while (b < brp->b_ep) *a++ = *b++; *a = '\0'; free (codebuf); return (e1); } isnum(e) register char *e; { register int c; if ((c = *e) == '-' || c == '+') ++e; while ((c = *e++) != '\0') if (!isdigit(c)) return (FALSE); return (TRUE); } /* * Convert long to ascii. Return pointer to the necessary malloced storage. */ char * ltoa(n) register long n; { char buf[12]; register char *bp = buf; register char *ep; register char *e; e = ep = malloc(12); if (n < 0) { *ep++ = '-'; n = -n; } do { *bp++ = (n % 10) + '0'; n /= 10; } while (n > 0); while (bp > buf) *ep++ = *--bp; *ep = '\0'; return (e); } /* * Compile the regular expression e into codebuf. * Invoke regerror() on a regular expression syntax error. */ compile(e) register char *e; { register int c; register char *cp, *lcp; int blevel, n, notflag, bstack[BRSIZE + 1]; brcount = 0; blevel = 0; cp = &codebuf[0]; if ((c = getx(c)) == '^') { *cp++ = CSSOL; c = getx(c); } while (c != '\0') { if (cp > &codebuf[cbsiz-4]) cp = overflow(cp); switch (c) { case '*': regerror(); case '.': if ((c = getx(c)) != '*') { *cp++ = CSDOT; continue; } *cp++ = CMDOT; c = getx(c); continue; case '$': if ((c = getx(c)) != '\0') { ungetx(c); c = '$'; goto character; } *cp++ = CSEOL; continue; case '[': /* * lcp[0] will contain C<S|M><C|N>CL. lcp[1] will be * the number of chars in the class. These are followed * by the members of the class singly enumerated. * ']' is valid only at the start of the member list. * '-' is valid only at the end of the member list. */ lcp = cp; if ((c = getx(c)) == '^') notflag = TRUE; else { notflag = FALSE; ungetx(c); } cp += 2; if ((c = getx(c)) == ']') *cp++ = c; else ungetx(c); while ((c = getx(c)) != ']') { if (c == '\0') regerror(); if (c!='-' || cp==lcp+2) { if (cp >= &codebuf[cbsiz-4]) cp = overflow(cp); *cp++ = c; continue; } /* c = '-' now. Lookahead at the next char */ if ((c = getx(c)) == '\0') regerror(); if (c == ']') { *cp++ = '-'; ungetx(c); continue; } if ((n=cp[-1]) > c) regerror(); while (++n <= c) { if (cp >= &codebuf[cbsiz-4]) cp = overflow(cp); *cp++ = n; } } if ((c = getx(c)) == '*') { lcp[0] = (notflag) ? CMNCL : CMCCL; c = getx(c); } else lcp[0] = (notflag) ? CSNCL : CSCCL; if ((n=cp-(lcp+2)) > 255) regerror(); *++lcp = n; continue; case '\\': switch (c = getx(c)) { case '\0': regerror(); case '(': *cp++ = CSOPR; *cp++ = bstack[blevel++] = brcount++; c = getx(c); continue; case ')': if (blevel == 0) regerror(); *cp++ = CSCPR; *cp++ = bstack[--blevel]; c = getx(c); continue; default: if (isascii(c) && isdigit(c)) { *cp++ = CSBRN; *cp++ = c-'0' - 1; c = getx(c); continue; } } default: character: *cp++ = CSCHR; *cp++ = c; if ((c = getx(c)) == '*') { cp[-2] = CMCHR; c = getx(c); } } } *cp++ = CSNUL; return; } /* * Given a pointer to a compiled expression `cp' and a pointer to a line `lp', * return a ptr to the char following the last char of the match * if successful, NULL otherwise. */ char * match(lp, cp) register char *lp, *cp; { register int n; char *llp, *lcp; for (;;) { switch (*cp++) { case CSNUL: return (lp); case CSEOL: if (*lp) return (NULL); return (lp); case CSOPR: brlist[*cp++].b_bp = lp; continue; case CSCPR: brlist[*cp++].b_ep = lp; continue; case CSBRN: n = *cp++; lcp = cp; cp = brlist[n].b_bp; n = brlist[n].b_ep - cp; if (n > strlen(lp)) return (NULL); while (n-- > 0) if (*lp++ != *cp++) return (NULL); cp = lcp; continue; case CSDOT: if (*lp++ == '\0') return (NULL); continue; case CMDOT: llp = lp; while (*lp) lp++; goto star; case CSCHR: if (*cp++ != *lp++) return (NULL); continue; case CMCHR: llp = lp; while (*cp == *lp) lp++; cp++; goto star; case CSCCL: n = *cp++; while (*cp++ != *lp) if (--n == 0) return (NULL); lp++; cp += n-1; continue; case CMCCL: llp = lp; lcp = cp; while (*lp) { cp = lcp; n = *cp++; while (*cp++ != *lp) if (--n == 0) goto star; lp++; } cp = lcp + *lcp + 1; goto star; case CSNCL: if (*lp == '\0') return (NULL); n = *cp++; while (n--) if (*cp++ == *lp) return (NULL); lp++; continue; case CMNCL: llp = lp; lcp = cp; while (*lp) { cp = lcp; n = *cp++; while (n--) { if (*cp++ == *lp) { cp = lcp + *lcp + 1; goto star; } } lp++; } cp = lcp + *lcp + 1; star: do { if (lcp=match(lp, cp)) return (lcp); } while (--lp >= llp); return (NULL); } } } /* * overflow enlarges codebuf by 128 bytes. The argument is a pointer * to a position in codebuf - the function returns a pointer with the same * relative position in the new buffer. */ char * overflow(pc) register char *pc; { register int posn = pc - codebuf; if ((codebuf = realloc(codebuf, cbsiz += 128)) == NULL) regerror(); return (codebuf + posn); } /* * An output function to avoid having to include stdio. */ output(s, fildes) register char *s; int fildes; { register int len; len = strlen(s); if ((write(fildes, s, len)) != len) exit(3); } yylex() { register int c; if ((yylval.str = av[++avx]) == NULL) return (EOF); if (av[avx][1] == '\0') switch (c = av[avx][0]) { case '{': case '}': case ',': case '|': case '&': case '<': case '>': case '+': case '-': case '*': case '/': case '%': case ':': case '!': case '(': case ')': return (c); default: return (STR); } if (av[avx][1] == '=' && av[avx][2] == '\0') switch (c = av[avx][0]) { case '<': return (LE); case '>': return (GE); case '=': return (EQ); case '!': return (NEQ); default: return (STR); } if (strcmp(yylval.str, "len") == 0) return (LEN); return (STR); } /* * The common code between yyerror() and regerror() (in regexp.c) is split * off into errexit(). */ yyerror() { output("expr: ", 2); errexit(); } regerror() { output("expr: regular expression ", 2); --avx; errexit(); } errexit() { output("syntax error at argument # ", 2); output(ltoa((long) avx), 2); output("\n", 2); exit(2); } #ifdef YYTNAMES struct yytname yytnames[25] = { "$end", -1, "error", -2, "STR", 256, "'|'", 124, "'&'", 38, "'<'", 60, "'>'", 62, "LE", 258, "GE", 259, "EQ", 260, "NEQ", 261, "'+'", 43, "'-'", 45, "'*'", 42, "'/'", 47, "'%'", 37, "':'", 58, "'!'", 33, "UMINUS", 262, "LEN", 263, "'('", 40, "')'", 41, "'{'", 123, "','", 44, "'}'", 125, NULL, } ; #endif unsigned yypdnt[24] = { 00, 01, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, } ; unsigned yypn[24] = { 02, 01, 03, 02, 02, 02, 03, 03, 03, 03, 03, 03, 03, 03, 03, 03, 03, 03, 03, 03, 05, 07, 01, 01, } ; unsigned yypgo[3] = { 00, 00, 02, } ; unsigned yygo[46] = { 0176030, 010, 03, 012, 04, 013, 05, 014, 06, 015, 07, 016, 020, 040, 021, 041, 022, 042, 023, 043, 024, 044, 025, 045, 026, 046, 027, 047, 030, 050, 031, 051, 032, 052, 033, 053, 034, 054, 035, 055, 037, 056, 057, 061, 0176030, 011, } ; unsigned yypa[51] = { 00, 016, 020, 00, 00, 00, 00, 00, 022, 026, 064, 066, 070, 072, 0132, 0172, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0176, 00, 0200, 0234, 0266, 0304, 0322, 0340, 0356, 0374, 0412, 0424, 0436, 0442, 0446, 0452, 0454, 00, 0516, 0520, 0560, } ; unsigned yyact[370] = { 02, 0400, 03, 055, 04, 041, 05, 0407, 06, 050, 07, 0173, 01, 0176030, 020027, 0176030, 020026, 0176030, 017, 0177777, 060000, 0176030, 020, 0174, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020001, 0176030, 020005, 0176030, 020004, 0176030, 020003, 0176030, 020, 0174, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 036, 051, 060000, 0176030, 020, 0174, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 037, 054, 060000, 0176030, 040000, 0177777, 060000, 0176030, 020002, 0176030, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020023, 0176030, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020022, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020014, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020015, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020016, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020017, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020020, 0176030, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 020021, 0176030, 032, 052, 033, 057, 034, 045, 035, 072, 020012, 0176030, 032, 052, 033, 057, 034, 045, 035, 072, 020013, 0176030, 035, 072, 020007, 0176030, 035, 072, 020010, 0176030, 035, 072, 020011, 0176030, 020006, 0176030, 020, 0174, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 057, 054, 060, 0175, 060000, 0176030, 020024, 0176030, 020, 0174, 021, 046, 022, 074, 023, 076, 024, 0402, 025, 0403, 026, 0404, 027, 0405, 030, 053, 031, 055, 032, 052, 033, 057, 034, 045, 035, 072, 062, 0175, 060000, 0176030, 020025, 0176030, } ; #include "action.h" #define YYNOCHAR (-1000) #define yyerrok yyerrflag=0 #define yyclearin yylval=YYNOCHAR int yystack[YYMAXDEPTH]; YYSTYPE yyvstack[YYMAXDEPTH], *yyv; int yychar; #ifdef YYDEBUG int yydebug = 1; /* No sir, not in the BSS */ #include <stdio.h> #endif short yyerrflag; int *yys; yyparse() { register YYSTYPE *yypvt; int act; register unsigned *ip, yystate; int pno; yystate = 0; yychar = YYNOCHAR; yyv = &yyvstack[-1]; yys = &yystack[-1]; stack: if( ++yys >= &yystack[YYMAXDEPTH] ) { write(2, "Stack overflow\n", 15); exit(1); } *yys = yystate; *++yyv = yyval; #ifdef YYDEBUG if( yydebug ) fprintf(stdout, "Stack state %d, char %d\n", yystate, yychar); #endif read: ip = &yyact[yypa[yystate]]; if( ip[1] != YYNOCHAR ) { if( yychar == YYNOCHAR ) { yychar = yylex(); #ifdef YYDEBUG if( yydebug ) fprintf(stdout, "lex read char %d, val %d\n", yychar, yylval); #endif } while (ip[1]!=YYNOCHAR) { if (ip[1]==yychar) break; ip += 2; } } act = ip[0]; switch( act>>YYACTSH ) { case YYSHIFTACT: if( ip[1]==YYNOCHAR ) goto YYerract; if( yychar != -1 ) yychar = YYNOCHAR; /* dont throw away EOF */ yystate = act&YYAMASK; yyval = yylval; #ifdef YYDEBUG if( yydebug ) fprintf(stdout, "shift %d\n", yystate); #endif if( yyerrflag ) --yyerrflag; goto stack; case YYACCEPTACT: #ifdef YYDEBUG if( yydebug ) fprintf(stdout, "accept\n"); #endif return(0); case YYERRACT: YYerract: switch (yyerrflag) { case 0: yyerror("Syntax error"); case 1: case 2: yyerrflag = 3; while( yys >= & yystack[0] ) { ip = &yyact[yypa[*yys]]; while( ip[1]!=YYNOCHAR ) ip += 2; if( (*ip&~YYAMASK) == (YYSHIFTACT<<YYACTSH) ) { yystate = *ip&YYAMASK; goto stack; } #ifdef YYDEBUG if( yydebug ) fprintf(stderr, "error recovery leaves state %d, uncovers %d\n", *yys, yys[-1]); #endif yys--; yyv--; } #ifdef YYDEBUG if( yydebug ) fprintf(stderr, "no shift on error; abort\n"); #endif return(1); case 3: #ifdef YYDEBUG if( yydebug ) fprintf(stderr, "Error recovery clobbers char %o\n", yychar); #endif if( yychar==YYEOFVAL ) return(1); yychar = YYNOCHAR; goto read; } case YYREDACT: pno = act&YYAMASK; #ifdef YYDEBUG if( yydebug ) fprintf(stdout, "reduce %d\n", pno); #endif yypvt = yyv; yyv -= yypn[pno]; yys -= yypn[pno]; yyval = yyv[1]; switch(pno) { case 1: { #line 92 "/usr/src/cmd/expr.y" result = yypvt[0].str; exstat = true(result) ? 0 : 1; }break; case 2: { #line 96 "/usr/src/cmd/expr.y" yyval.str = yypvt[-1].str; }break; case 3: { #line 98 "/usr/src/cmd/expr.y" yyval.str = ltoa((long)strlen(yypvt[0].str)); }break; case 4: { #line 99 "/usr/src/cmd/expr.y" yyval.str = true(yypvt[0].str) ? s0 : s1; }break; case 5: { #line 101 "/usr/src/cmd/expr.y" if (isnum(yypvt[0].str)) yyval.str = ltoa(-atol(yypvt[0].str)); else { --avx; yyerror(); } }break; case 6: { #line 109 "/usr/src/cmd/expr.y" yyval.str = regexp(yypvt[-2].str, yypvt[0].str); }break; case 7: { #line 111 "/usr/src/cmd/expr.y" yyval.str = arithop('*', yypvt[-2].str, yypvt[0].str); }break; case 8: { #line 112 "/usr/src/cmd/expr.y" yyval.str = arithop('/', yypvt[-2].str, yypvt[0].str); }break; case 9: { #line 113 "/usr/src/cmd/expr.y" yyval.str = arithop('%', yypvt[-2].str, yypvt[0].str); }break; case 10: { #line 114 "/usr/src/cmd/expr.y" yyval.str = arithop('+', yypvt[-2].str, yypvt[0].str); }break; case 11: { #line 115 "/usr/src/cmd/expr.y" yyval.str = arithop('-', yypvt[-2].str, yypvt[0].str); }break; case 12: { #line 117 "/usr/src/cmd/expr.y" yyval.str = relop('<', yypvt[-2].str, yypvt[0].str); }break; case 13: { #line 118 "/usr/src/cmd/expr.y" yyval.str = relop('>', yypvt[-2].str, yypvt[0].str); }break; case 14: { #line 119 "/usr/src/cmd/expr.y" yyval.str = relop(LE, yypvt[-2].str, yypvt[0].str); }break; case 15: { #line 120 "/usr/src/cmd/expr.y" yyval.str = relop(GE, yypvt[-2].str, yypvt[0].str); }break; case 16: { #line 121 "/usr/src/cmd/expr.y" yyval.str = relop(EQ, yypvt[-2].str, yypvt[0].str); }break; case 17: { #line 122 "/usr/src/cmd/expr.y" yyval.str = relop(NEQ, yypvt[-2].str, yypvt[0].str); }break; case 18: { #line 124 "/usr/src/cmd/expr.y" yyval.str = true(yypvt[0].str) ? yypvt[-2].str : s0; }break; case 19: { #line 125 "/usr/src/cmd/expr.y" yyval.str = true(yypvt[-2].str) ? yypvt[-2].str : yypvt[0].str; }break; case 20: { #line 127 "/usr/src/cmd/expr.y" yyval.str = true(yypvt[-3].str) ? yypvt[-1].str : s0; }break; case 21: { #line 128 "/usr/src/cmd/expr.y" yyval.str = true(yypvt[-5].str) ? yypvt[-3].str : yypvt[-1].str; }break; case 22: { #line 130 "/usr/src/cmd/expr.y" yyval.str = yypvt[0].str; }break; case 23: { #line 131 "/usr/src/cmd/expr.y" yyerror(); }break; } ip = &yygo[ yypgo[yypdnt[pno]] ]; while( *ip!=*yys && *ip!=YYNOCHAR ) ip += 2; yystate = ip[1]; goto stack; } }