+#include "r.h"
+#define BUFSIZE 512
+char ibuf[BUFSIZE];
+char *ip = ibuf;
+
+char type[] = {
+ 0, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP,
+ CRAP, '\t', '\n', CRAP, CRAP, CRAP, CRAP, CRAP,
+ CRAP, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP,
+ CRAP, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP, CRAP,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG,
+ DIG, DIG, ':', ';', '<', '=', '>', '?',
+ '@', LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, '[', '\\', ']', '^', '_',
+ '`', LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, LET, LET, LET, LET, LET,
+ LET, LET, LET, '{', '|', '}', '~', 0,
+};
+
+gtok(s) char *s; { /* get token into s */
+ register c, t;
+ register char *p;
+ struct nlist *q;
+
+ for(;;) {
+ p = s;
+ *p++ = c = getchr();
+ switch(t = type[c]) {
+ case 0:
+ if (infptr > 0) {
+ fclose(infile[infptr]);
+ infptr--;
+ continue;
+ }
+ if (svargc > 1) {
+ svargc--;
+ svargv++;
+ if (infile[infptr] != stdin)
+ fclose(infile[infptr]);
+ if( (infile[infptr] = fopen(*svargv,"r")) == NULL )
+ cant(*svargv);
+ linect[infptr] = 0;
+ curfile[infptr] = *svargv;
+ continue;
+ }
+ return(EOF); /* real eof */
+ case ' ':
+ case '\t':
+ while ((c = getchr()) == ' ' || c == '\t')
+ ; /* skip others */
+ if (c == COMMENT || c == '_') {
+ putbak(c);
+ continue;
+ }
+ if (c != '\n') {
+ putbak(c);
+ *p = '\0';
+ return(' ');
+ } else {
+ *s = '\n';
+ *(s+1) = '\0';
+ return(*s);
+ }
+ case '_':
+ while ((c = getchr()) == ' ' || c == '\t')
+ ;
+ if (c == COMMENT) {
+ putbak(c);
+ gtok(s); /* recursive */
+ }
+ else if (c != '\n')
+ putbak(c);
+ continue;
+ case LET:
+ case DIG:
+ while ((t=type[*p = getchr()]) == LET || t == DIG)
+ p++;
+ putbak(*p);
+ *p = '\0';
+ if ((q = lookup(s))->name != NULL && q->ydef == 0) { /* found but not keyword */
+ if (q->def != fcnloc) { /* not "function" */
+ pbstr(q->def);
+ continue;
+ }
+ getfname(); /* recursive gtok */
+ }
+ for (p=s; *p; p++)
+ if (*p>='A' && *p<='Z')
+ *p += 'a' - 'A';
+ for (p=s; *p; p++)
+ if (*p < '0' || *p > '9')
+ return(LET);
+ return(DIG);
+ case '[':
+ *p = '\0';
+ return('{');
+ case ']':
+ *p = '\0';
+ return('}');
+ case '$':
+ case '\\':
+ if ((*p = getchr()) == '(' || *p == ')') {
+ putbak(*p=='(' ? '{' : '}');
+ continue;
+ }
+ if (*p == '"' || *p == '\'')
+ p++;
+ else
+ putbak(*p);
+ *p = '\0';
+ return('$');
+ case COMMENT:
+ comment[comptr++] = 'c';
+ while ((comment[comptr++] = getchr()) != '\n')
+ ;
+ flushcom();
+ *s = '\n';
+ *(s+1) = '\0';
+ return(*s);
+ case '"':
+ case '\'':
+ for (; (*p = getchr()) != c; p++) {
+ if (*p == '\\')
+ *++p = getchr();
+ if (*p == '\n') {
+ error("missing quote");
+ putbak('\n');
+ break;
+ }
+ }
+ *p++ = c;
+ *p = '\0';
+ return(QUOTE);
+ case '%':
+ while ((*p = getchr()) != '\n')
+ p++;
+ putbak(*p);
+ *p = '\0';
+ return('%');
+ case '>': case '<': case '=': case '!': case '^':
+ return(peek(p, '='));
+ case '&':
+ return(peek(p, '&'));
+ case '|':
+ return(peek(p, '|'));
+ case CRAP:
+ continue;
+ default:
+ *p = '\0';
+ return(*s);
+ }
+ }
+}
+
+gnbtok(s) char *s; {
+ register c;
+ while ((c = gtok(s)) == ' ' || c == '\t')
+ ;
+ return(c);
+}
+
+getfname() {
+ while (gtok(fcname) == ' ')
+ ;
+ pbstr(fcname);
+ putbak(' ');
+}
+
+peek(p, c1) char *p, c1; {
+ register c;
+ c = *(p-1);
+ if ((*p = getchr()) == c1)
+ p++;
+ else
+ putbak(*p);
+ *p = '\0';
+ return(c);
+}
+
+pbstr(str)
+register char *str;
+{
+ register char *p;
+
+ p = str;
+ while (*p++);
+ --p;
+ if (ip >= &ibuf[BUFSIZE]) {
+ error("pushback overflow");
+ exit(1);
+ }
+ while (p > str)
+ putbak(*--p);
+}
+
+getchr() {
+ register c;
+
+ if (ip > ibuf)
+ return(*--ip);
+ c = getc(infile[infptr]);
+ if (c == '\n')
+ linect[infptr]++;
+ if (c == EOF)
+ return(0);
+ return(c);
+}