int _readx(Rune *p, int n, int nmode, int line) { int c, omode; Rune *e; while((c = getrune()) == ' ' || c == '\t') ; ungetrune(c); omode = inputmode; inputmode = nmode; e = p+n-1; for(c=getnext(); p<e; c=getnext()){ if(c < 0) break; if(!line && (c == ' ' || c == '\t')) break; if(c == '\n'){ if(!line) ungetnext(c); break; } *p++ = c; } inputmode = omode; *p = 0; if(c < 0) return -1; return 0; }
void r_comment(Rune *name) { int c; USED(name); while((c = getrune()) >= 0 && c != '\n') ; }
void startbody(void) { int c; while((c = getrune()) == ' ' || c == '\t') ; ungetrune(c); }
/* * Get the next logical character in the input stream. */ int getnext(void) { int i, r; next: r = getrune(); if(r < 0) return -1; if(r == Uformatted){ br(); assert(!isoutput); while((r = getrune()) >= 0 && r != Uunformatted){ if(r == Uformatted) continue; outrune(r); } goto next; } if(r == Uunformatted) goto next; if(r == backslash){ r = getrune(); if(r < 0) return -1; for(i=0; i<nesc; i++){ if(r == esc[i].r && (inputmode&esc[i].mode)==inputmode){ if(esc[i].f == e_warn) warn("ignoring %C%C", backslash, r); r = esc[i].f(); if(r <= 0) goto next; return r; } } if(inputmode&(ArgMode|CopyMode)){ ungetrune(r); r = backslash; } } return r; }
int e_quote(void) { int c; if(inputmode&ArgMode){ /* Leave \" around for argument parsing */ ungetrune('"'); return '\\'; } while((c = getrune()) >= 0 && c != '\n') ; return '\n'; }
int e_X(void) { int c; while((c = getrune()) >= 0 && c != '\'' && c != '\n') outrune(c); if(c == '\n'){ warn("newline in %CX'...'", backslash); outrune(c); } if(c < 0) warn("eof in %CX'...'", backslash); return 0; }
void skipbody(void) { int c, cc, nbrace; nbrace = 0; for(cc=0; (c = getrune()) >= 0; cc=c){ if(c == '\n' && nbrace <= 0) break; if(cc == '\\' && c == '{') nbrace++; if(cc == '\\' && c == '}') nbrace--; } }
/* * Get the next argument from the current line. */ Rune* copyarg(void) { static Rune buf[MaxLine]; int c; Rune *r; if(_readx(buf, sizeof buf, ArgMode, 0) < 0) return nil; r = runestrstr(buf, L("\\\"")); if(r){ *r = 0; while((c = getrune()) >= 0 && c != '\n') ; ungetrune('\n'); } r = erunestrdup(buf); return r; }
/* * Process a dot line. The dot has been read. */ void dotline(int dot) { int argc, i; Rune *a, *argv[1+MAXARG]; /* * Read request/macro name */ a = copyarg(); if(a == nil || a[0] == 0){ free(a); getrune(); /* \n */ return; } argv[0] = a; /* * Check for .if, .ie, and others with special parsing. */ for(i=0; i<nraw; i++){ if(runestrcmp(raw[i].name, a) == 0){ raw[i].f(raw[i].name); free(a); return; } } /* * Read rest of line in copy mode, invoke regular request. */ a = readline(ArgMode); if(a == nil){ free(argv[0]); return; } argc = 1+parseargs(a, argv+1); for(i=0; i<nreq; i++){ if(runestrcmp(req[i].name, argv[0]) == 0){ if(req[i].argc != -1){ if(argc < 1+req[i].argc){ warn("not enough arguments for %C%S", dot, req[i].name); free(argv[0]); free(a); return; } if(argc > 1+req[i].argc) warn("too many arguments for %C%S", dot, req[i].name); } req[i].f(argc, argv); free(argv[0]); free(a); return; } } /* * Invoke user-defined macros. */ runmacro(dot, argc, argv); free(argv[0]); free(a); }
int ifeval(void) { int c, cc, neg, nc; Rune line[MaxLine], *p, *e, *q; Rune *a; while((c = getnext()) == ' ' || c == '\t') ; neg = 0; while(c == '!'){ neg = !neg; c = getnext(); } if('0' <= c && c <= '9'){ ungetnext(c); a = copyarg(); c = (eval(a)>0) ^ neg; free(a); return c; } switch(c){ case ' ': case '\n': ungetnext(c); return !neg; case 'o': /* odd page */ case 't': /* troff */ case 'h': /* htmlroff */ while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0) ; return 1 ^ neg; case 'n': /* nroff */ case 'e': /* even page */ while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0) ; return 0 ^ neg; } /* string comparison 'string1'string2' */ p = line; e = p+nelem(line); nc = 0; q = nil; while((cc=getnext()) >= 0 && cc != '\n' && p<e){ if(cc == c){ if(++nc == 2) break; q = p; } *p++ = cc; } if(cc != c){ ungetnext(cc); return 0; } if(nc < 2){ return 0; } *p = 0; return (q-line == p-(q+1) && memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg; }