#include #include #include #include "wrap.h" /* We really should be able to pass the void * version to stdio routines and get automatic casting per the prototype. Unfortunately, this does not work for routines which are implemented as macros - so much for not caring whether a routine is a macro or not! */ #define f ((FILE *)fv) static int wrapper_close(void *fv) { fclose(f); return(0); } static int wrapper_read_comment(void *fv, char *buf, int nb) { int c; int done; done = 0; while (nb > 0) { c = getc(f); if (c == EOF) break; if (c == '\n') { while (1) { c = getc(f); if (c == EOF) { break; } else if (c == '#') { do { c = getc(f); } while ((c != EOF) && (c != '\n')); if (c == EOF) goto out; /* break 2 */ } else { ungetc(c,f); break; } } c = '\n'; } *buf++ = c; nb --; done ++; } out:; return(done?done:feof(f)?0:-1); } FILE *wrap_open_comment(FILE *arg, int closeunder) { return(funopen(arg,wrapper_read_comment,0,0,closeunder?wrapper_close:0)); } static int wrapper_read_continue(void *fv, char *buf, int nb) { int c; int done; done = 0; while (nb > 0) { c = getc(f); if (c == EOF) break; if (c == '\n') { c = getc(f); if (c == EOF) { c = '\n'; } else if ((c == ' ') || (c == '\t')) { do { c = getc(f); } while ((c == ' ') || (c == '\t') || (c == '\n')); if (c == EOF) break; ungetc(c,f); c = ' '; } else { ungetc(c,f); c = '\n'; } } *buf++ = c; nb --; done ++; } return(done?done:feof(f)?0:-1); } FILE *wrap_open_continue(FILE *arg, int closeunder) { return(funopen(arg,wrapper_read_continue,0,0,closeunder?wrapper_close:0)); } typedef struct hcs HCS; struct hcs { unsigned int inhdrs : 1; unsigned int closeunder : 1; FILE *fp; } ; static int wrapper_read_hdrcontinue(void *arg, char *buf, int nb) { HCS *h; int c; int done; h = arg; done = 0; while (nb > 0) { c = getc(h->fp); if (c == EOF) break; if (h->inhdrs) { if (c == '\n') { c = getc(h->fp); if (c == EOF) { c = '\n'; } else if ((c == ' ') || (c == '\t')) { do { c = getc(h->fp); } while ((c == ' ') || (c == '\t') || (c == '\n')); if (c == EOF) break; ungetc(c,h->fp); c = ' '; } else { if (c == '\n') h->inhdrs = 0; ungetc(c,h->fp); c = '\n'; } } } *buf++ = c; nb --; done ++; } return(done?done:feof(h->fp)?0:-1); } static int wrapper_close_hdrcontinue(void *arg) { if (((HCS *)arg)->closeunder) fclose(((HCS *)arg)->fp); free((HCS *)arg); return(0); } FILE *wrap_open_hdrcontinue(FILE *arg, int closeunder) { HCS *h; FILE *rv; h = malloc(sizeof(HCS)); h->inhdrs = 1; h->closeunder = !!closeunder; h->fp = arg; rv = funopen(h,wrapper_read_hdrcontinue,0,0,wrapper_close_hdrcontinue); if (! rv) { int e; e = errno; free(h); errno = e; } return(rv); }