|
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 - download
Length: 6878 (0x1ade) Types: TextFile Notes: UNIX file Names: »lex.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/rsh/lex.c« └─ ⟦this⟧ »cmd/sh/lex.c«
/* * A shell. * Lexical analyser. */ #include "sh.h" #include "y.tab.h" /* * Local externals. */ int lastget = '\0'; /* Pushed back character */ int eolflag = 0; /* End of line */ /* * Keyword table. */ typedef struct key { int k_lexv; /* Lexical value */ char *k_name; /* Keyword name */ } KEY; /* * Keyword table. */ KEY keytab[] ={ _CASE, "case", _DO, "do", _DONE, "done", _ELIF, "elif", _ELSE, "else", _ESAC, "esac", _FI, "fi", _FOR, "for", _IF, "if", _IN, "in", _THEN, "then", _UNTIL, "until", _WHILE, "while", _OBRAC, "{", _CBRAC, "}", _NULL }; /* * Get the next lexical token. */ yylex() { register int c; again: while ((c=getn())==' ' || c=='\t') ; strp = strt; if (class(c, MDIGI)) { *strp++ = c; c = getn(); if (c=='>' || c=='<') { *strp++ = c; return (lexiors(c)); } ungetn(c); return (lexname()); } if (!class(c, MNAME)) { ungetn(c); if ((c = lexname()) == 0) goto again; else if (c < 0) return (c); if (keyflag) { register KEY *kp; for (kp=keytab; kp->k_lexv!=_NULL; kp++) { if (strcmp(strt, kp->k_name) == 0) return (kp->k_lexv); } } return (c); } *strp++ = c; *strp = '\0'; switch (c) { case ';': return (isnext(c, _DSEMI)); case '>': return (lexiors(c)); case '<': return (lexiors(c)); case '&': return (isnext(c, _ANDF)); case '|': #ifdef NAMEPIPE if ( ! isnext(')', 0)) return (_NCLOSE); #endif return (isnext(c, _ORF)); #ifdef NAMEPIPE case '(': return (isnext('|', _NOPEN)); #endif default: return (c); } } isnext(c, t1) register int c; { register int c2; if ((c2=getn()) == c) { *strp++ = c2; *strp = '\0'; return (t1); } ungetn(c2); return (strp[-1]); } /* * Scan a single argument. * Return 0 if it's an escaped newline, EOF if EOF is found, * or _NAME or _ASGN if any part of an argument is found. */ lexname() { int q, asgn; register int c, m; register char *cp; q = 0; asgn = 0; m = MNQUO; cp = strp; for (;;) { c = getn(); if (asgn==0) asgn = class(c, MBVAR) ? 1 : -1; else if (asgn==1) asgn = class(c, MRVAR) ? 1 : (c=='=' ? 2 : -1); if (cp >= strt + STRSIZE) etoolong(); else *cp++ = c; if (!class(c, m)) continue; switch (c) { case '"': m = (q^=1) ? MDQUO : MNQUO; continue; case '\'': strp = cp; if ((c = collect('\'', 1)) != '\'') break; cp = strp; continue; case '\\': if ((c=getn()) < 0) { syntax(); break; } if (c == '\n') { ungetn((c=getn())<0 ? '\n' : c); if (--cp == strp) return (0); continue; } *cp++ = c; continue; case '$': if ((c=getn()) == '{') { *cp++ = c; strp = cp; if ((c = collect('}', 0)) != '}') break; cp = strp; continue; } ungetn(c); continue; case '`': strp = cp; if ((c = collect('`', 0)) != '`') break; cp = strp; continue; } break; } if (c < 0) return (c); if (q) { emisschar('"'); *cp = '\0'; } else { *--cp = '\0'; } ungetn(c); strp = cp; #ifdef VERBOSE if (vflag) prints("\t<%d> <%s> %s\n", getpid(), (asgn==2 ? "ASGN" : "NAME"), strt); #endif if (errflag) return (_NULL); else if (asgn==2) return (_ASGN); else return (_NAME); return (asgn==2 ? _ASGN : _NAME); } /* * Lex an io redirection string, including the file name if any. * Called with one '>' or '<' in buffer, optionally preceded by * a digit. */ lexiors(c1) { register int c; register char *name; char *tmp, *iors; int hfd, quote; BUF **bpp; *strp++ = c = getn(); if (c=='&') { *strp++ = c = getn(); *strp = '\0'; if (c < 0) return (c); if (c!='-' && !class(c, MDIGI)) eredir(); return (_IORS); } if (c==c1) c1 += 0200; else { *--strp = '\0'; ungetn(c); } /* Collect file name */ while ((c=getn())==' '||c=='\t') *strp++ = c; ungetn(c); name = strp; if (c=='\n') { eredir(); return (_IORS); } while ((c = lexname())==0); if (c < 0) return (c); if (c1!='<'+0200) return (_IORS); /* Collect here document */ if ((c=getn())!='\n') { eredir(); ++strp; c = collect('\n', 1); } if (c < 0) return (c); bpp = savebuf(); strp = strt; /* Simplify quoted to ?<file from ?<<file */ if (quote = (int)any(name, "\"\\'")) *++strp = *strt; tmp = name; name = duplstr(name, 0); strcpy(tmp, shtmp()); iors = duplstr(strp, 0); tmp += iors - strp; eval(name, EWORD); name = duplstr(strcat(strt, "\n"), 0); if ((hfd = creat(tmp, 0666)) < 0) ecantmake(tmp); for (;;) { strp = strt; if ((c = collect('\n', 2)) < 0) break; *strp = '\0'; if (strcmp(strt, name)==0) break; if (hfd < 0) continue; if (! quote && strp > strt + 1 && strp[-2]=='\\') *(strp-=2) = '\0'; if (! quote && *strt=='\\' && strcmp(name, strt+1)==0) write(hfd, strt+1, strp-strt-1); else write(hfd, strt, strp-strt); } close(hfd); cleanup(0, tmp); ungetn('\n'); strcpy(strt, iors); freebuf(bpp); /* Check for interrupt, since EOF is legal for once */ if (c < 0 && ! recover(ILEX)) return (c); return (_IORS); } /* * Collect characters until the end character is found. If `f' is * set, all characters are passed through otherwise '\' escapes the * next character and newline is not allowed. * If `f' is set to 2, then no error is desired. */ collect(ec, f) register int ec; { register int c; register char *cp; cp = strp; while ((c=getn()) != ec) { if (c<0 || (c=='\n' && f==0)) { if (--f <= 0) emisschar(ec); return (c); } if (c=='\\' && f==0) { if ((c=getn()) < 0) { syntax(); return (c); } if (c == '\n') continue; } if (cp >= strt + STRSIZE) etoolong(); else *cp++ = c; } *cp++ = ec; strp = cp; return (ec); } /* * Get a character. */ getn() { register int c; register int t; if (lastget != '\0') { c = lastget; lastget = '\0'; return (c); } switch (t = sesp->s_type) { case SSTR: case SFILE: yyline += eolflag; eolflag = 0; if (prpflag && sesp->s_flag) { if (prpflag -= 1) { prompt("\n"); prpflag -= 1; } prompt(comflag ? vps1 : vps2); comflag = 0; } if ((c=getc(sesp->s_ifp))=='\n') { if (sesp->s_flag) { prpflag = 1; yyline = 1; } else eolflag = 1; } if (vflag) putc(c, stderr); return (c); case SARGS: case SARGV: if (sesp->s_flag) return (EOF); if ((c=*sesp->s_strp++) == '\0') { if (t == SARGV && (sesp->s_strp=*++sesp->s_argv) != NULL) c = ' '; else { sesp->s_flag = 1; c = '\n'; } } if (vflag) putc(c, stderr); return (c); } } /* * Unget a character. */ ungetn(c) { lastget = c; } /* * Returns true if the intersection of two * strings is non-NULL, otherwise 0. */ char * any(s, spcl) char *s, *spcl; { register char *p1, *p2; for (p1 = s; *p1; p1++) for (p2 = spcl; *p2; p2++) if (*p2 == *p1) return (p1); return (NULL); }