#include #include #include #include #include "irdr.h" #include "valist.h" #include "istack.h" #include "directive.h" typedef struct priv PRIV; struct priv { int lineno; FILE *f; char *fn; } ; static int get(PRIV *p) { int c; c = getc(p->f); if (c == '\n') p->lineno ++; return(c); } static void unget(int c, PRIV *p) { ungetc(c,p->f); if (c == '\n') p->lineno --; } static void stdio_init(void **privp, VALIST *args) { PRIV *p; char *fn; p = malloc(sizeof(PRIV)); p->lineno = 1; p->f = va_arg(args->ap,FILE *); fn = va_arg(args->ap,char *); p->fn = fn ? strdup(fn) : 0; *privp = p; } static void stdio_token(void *priv, TOKEN *tok) { PRIV *p; int c; int n; static int a = 0; static char *b = 0; char dq; int bq; void savec(char c) { if (n >= a) b = realloc(b,a=n+8); b[n++] = c; } p = priv; while <"whitespace"> (1) { c = get(p); switch (c) { case EOF: tok->type = TT_EOF; return; case '#': do c = get(p); while ((c != '\n') && (c != EOF)); if (c == EOF) { tok->type = TT_EOF; return; } break; case '\n': case ';': tok->type = TT_SEP; return; default: if (! isspace(c)) break <"whitespace">; break; } } dq = 0; bq = 0; n = 0; while <"token"> (1) { if (c == EOF) break <"token">; if (bq) { savec(c); bq = 0; } else if (c == '\\') { bq = 1; } else if (dq) { if (c == dq) { dq = 0; } else { savec(c); } } else { switch (c) { case '"': case '\'': dq = c; break; case '\n': case ';': case '#': unget(c,p); break <"token">; default: if (isspace(c)) break <"token">; savec(c); break; } } c = get(p); } savec('\0'); tok->type = TT_STR; tok->str = b; } static void stdio_baddir(void *priv, char *s) { PRIV *p; TOKEN t; p = priv; istack_err("unrecognized directive keyword `%s'",s); do stdio_token(priv,&t); while (t.type == TT_STR); } static void stdio_close(void *priv) { PRIV *p; p = priv; fclose(p->f); free(p->fn); free(priv); } static void stdio_err(void *priv, FILE *to) { PRIV *p; p = priv; fprintf(to," "); if (p->fn) fprintf(to,"\"%s\"",p->fn); else fprintf(to,"standard input"); fprintf(to,", line %d\n",p->lineno); } IRDR i_stdio = { &stdio_init, &stdio_token, &stdio_baddir, &stdio_close, &stdio_err };