ref: 720585ccc54165aa6d41a0fe85374223ac3a9e37
dir: /test.c/
#include <u.h> #include <libc.h> #include <bio.h> typedef struct Ctx Ctx; typedef struct Range Range; struct Ctx { Biobuf *f; Range *r; u8int *buf; int bufsz; int off; }; struct Range { int start; int len; int prevoff; Range *par; }; int ctxpushrange(Ctx *ctx, int off, int len) { Range *r; int x; r = nil; if(ctx->r != nil){ if(len < 0) len = ctx->r->len - off; if(len < 0 || off+len > ctx->r->len){ werrstr("range overflow (len %d) by %d bytes", len, off+len - ctx->r->len); goto err; } off += ctx->r->start; }else if(len < 0){ len = 0x7fffffff; } if((r = malloc(sizeof(*r))) == nil){ werrstr("no memory"); goto err; } r->par = ctx->r; r->start = off; r->len = len; r->prevoff = ctx->off; if((x = Bseek(ctx->f, off, 0)) != off){ werrstr("seek offset: need %d, got %d", off, x); goto err; } ctx->off = off; ctx->r = r; return 0; err: free(r); return -1; } int ctxpoprange(Ctx *ctx) { Range *r; int x; r = ctx->r; if(r == nil){ werrstr("pop without push"); goto err; } if((x = Bseek(ctx->f, r->prevoff, 0)) != r->prevoff){ werrstr("seek offset: need %d, got %d", r->prevoff, x); goto err; } ctx->off = r->prevoff; ctx->r = r->par; free(r); return 0; err: return -1; } u8int * ctxreadn(Ctx *ctx, int n) { Range *r; u8int *b; int x; r = ctx->r; if(r != nil && ctx->off+n > r->start+r->len){ werrstr("need %d at %d, have %d at %d", n, ctx->off, r->len, r->start); goto err; } if(n > ctx->bufsz){ if((b = realloc(ctx->buf, n)) == nil){ werrstr("no memory"); goto err; } ctx->buf = b; ctx->bufsz = n; } if((x = Bread(ctx->f, ctx->buf, n)) != n){ werrstr("need %d, got %d; off %d", n, x, ctx->off); goto err; } ctx->off += n; return ctx->buf; err: return nil; } int ctxarray(Ctx *ctx, void **arr_, void *fun_, int elsz, int num) { int i; int (*fun)(Ctx*, void*); u8int *arr; if((arr = calloc(num, elsz)) == nil){ werrstr("no memory"); goto err; } fun = fun_; for(i = 0; i < num; i++){ if(fun(ctx, arr + i*elsz) < 0) goto err; } *arr_ = arr; return 0; err: free(arr); return -1; } #include "out.h" void main(int argc, char **argv) { TableDirectory td; Biobuf *out; Ctx ctx; int i; otfinit(); out = Bfdopen(1, OWRITE); for(i = 1; i < argc; i++){ Bprint(out, "%s\n", argv[i]); if((ctx.f = Bopen(argv[i], OREAD)) == nil){ fprint(2, "%r\n"); }else if(read_TableDirectory(&ctx, &td) != 0){ fprint(2, "%s: %r\n", argv[i]); } else { print_TableDirectory(out, indentΔ, &td); } if(ctx.f != nil) Bterm(ctx.f); } Bterm(out); exits(nil); }