/* This file is in the public domain. */ #include #include #include #include #include #include "stdio-util.h" typedef struct allocblk ALLOCBLK; typedef struct rstrblk RSTRBLK; typedef struct bracketblk BRACKETBLK; struct allocblk { char **bufp; int *lenp; char *buf; int len; } ; struct rstrblk { const char *buf; int len; off_t ptr; }; struct bracketblk { FILE *sub; const char *pre; const char *post; char *free; unsigned int flags; int atnl; } ; static int alloc_w(void *av, const char *b, int l) { ALLOCBLK *a; a = av; if (a->bufp) { a->buf = realloc(a->buf,a->len+l); bcopy(b,a->buf+a->len,l); } a->len += l; return(l); } static int alloc_c(void *av) { ALLOCBLK *a; a = av; if (a->bufp) *a->bufp = a->buf; if (a->lenp) *a->lenp = a->len; free(a); return(0); } FILE *fopen_alloc(char **bufp, int *lenp) { FILE *f; ALLOCBLK *a; a = malloc(sizeof(ALLOCBLK)); if (a == 0) return(0); a->bufp = bufp; a->lenp = lenp; a->buf = 0; a->len = 0; f = funopen(a,0,&alloc_w,0,&alloc_c); if (f == 0) free(a); return(f); } static int rstr_r(void *bv, char *buf, int len) { RSTRBLK *b; int n; b = bv; if (b->ptr < 0) { errno = EINVAL; return(-1); } else if (b->ptr >= b->len) { return(0); } n = b->len - b->ptr; if (n > len) n = len; bcopy(b->buf+b->ptr,buf,n); b->ptr += n; return(n); } static int rstr_c(void *bv) { free(bv); return(0); } FILE *fopen_rstr(const char *s, int l) { RSTRBLK *b; FILE *f; b = malloc(sizeof(RSTRBLK)); if (b == 0) return(0); if (l < 0) l = strlen(s); b->buf = s; b->len = l; b->ptr = 0; f = funopen(b,&rstr_r,0,0,&rstr_c); if (f == 0) free(b); return(f); } static int null_w(void *cookie __attribute__((__unused__)), const char *buf __attribute__((__unused__)), int len) { return(len); } FILE *fopen_null(void) { return(funopen(0,0,&null_w,0,0)); } int peekc(FILE *f) { int c; c = getc(f); if (c != EOF) ungetc(c,f); return(c); } static int bracket_w(void *bv, const char *b, int l0) { BRACKETBLK *bb; const void *nlv; const char *nl; int l; bb = bv; l = l0; while (l > 0) { nlv = memchr(b,'\n',l); if (nlv == 0) { if (bb->atnl) fprintf(bb->sub,"%s",bb->pre); fwrite(b,1,l,bb->sub); bb->atnl = 0; break; } nl = nlv; if (nl == b) { if (bb->atnl) { if (! (bb->flags & FWB_NOTEMPTY)) { fprintf(bb->sub,"%s%s",bb->pre,bb->post); } } else { fprintf(bb->sub,"%s",bb->post); } } else { if (bb->atnl) fprintf(bb->sub,"%s",bb->pre); fwrite(b,1,nl-b,bb->sub); fprintf(bb->sub,"%s",bb->post); } putc('\n',bb->sub); bb->atnl = 1; l -= (nl+1) - b; b = nl + 1; } return(l0); } static int bracket_c(void *bv) { BRACKETBLK *b; b = bv; if (b->flags & FWB_CLOSE) fclose(b->sub); free(b->free); free(b); return(0); } FILE *fopen_w_bracket(FILE *sub, const char *pre, const char *post, unsigned int flags) { BRACKETBLK *b; FILE *f; b = malloc(sizeof(BRACKETBLK)); if (b == 0) return(0); b->sub = sub; if (flags & FWB_COPY) { int l1; int l2; l1 = strlen(pre); l2 = strlen(post); b->free = malloc(l1+1+l2+1); if (b->free == 0) { free(b); return(0); } bcopy(pre,b->free,l1+1); bcopy(post,b->free+l1+1,l2+1); b->pre = b->free; b->post = b->free + l1 + 1; } else { b->pre = pre; b->post = post; b->free = 0; } b->flags = flags; b->atnl = 1; f = funopen(b,0,&bracket_w,0,&bracket_c); if (f == 0) { if (flags & FWB_COPY) free(b->free); free(b); } return(f); }