ref: 01986adbbf75c07c613b11fcb81a8015a71e5664
dir: /sys/src/cmd/wikifs/parsehist.c/
/* * Read a Wiki history file. * It's a title line then a sequence of Wiki files separated by headers. * * Ddate/time * #body * #... * #... * #... * etc. */ #include <u.h> #include <libc.h> #include <bio.h> #include <String.h> #include <thread.h> #include "wiki.h" static char* Brdwline(void *vb, int sep) { Biobufhdr *b; char *p; b = vb; if(Bgetc(b) == '#'){ if(p = Brdline(b, sep)) p[Blinelen(b)-1] = '\0'; return p; }else{ Bungetc(b); return nil; } } Whist* Brdwhist(Biobuf *b) { int i, current, conflict, c, n; char *author, *comment, *p, *title; ulong t; Wdoc *w; Whist *h; if((p = Brdline(b, '\n')) == nil){ werrstr("short read: %r"); return nil; } p[Blinelen(b)-1] = '\0'; p = strcondense(p, 1); title = estrdup(p); w = nil; n = 0; t = -1; author = nil; comment = nil; conflict = 0; current = 0; while((c = Bgetc(b)) != Beof){ if(c != '#'){ p = Brdline(b, '\n'); if(p == nil) break; p[Blinelen(b)-1] = '\0'; switch(c){ case 'D': t = strtoul(p, 0, 10); break; case 'A': free(author); author = estrdup(p); break; case 'C': free(comment); comment = estrdup(p); break; case 'X': conflict = 1; } } else { /* c=='#' */ Bungetc(b); if(n%8 == 0) w = erealloc(w, (n+8)*sizeof(w[0])); w[n].time = t; w[n].author = author; w[n].comment = comment; comment = nil; author = nil; w[n].wtxt = Brdpage(Brdwline, b); w[n].conflict = conflict; if(w[n].wtxt == nil) goto Error; if(!conflict) current = n; n++; conflict = 0; t = -1; } } if(w==nil) goto Error; free(comment); free(author); h = emalloc(sizeof *h); h->title = title; h->doc = w; h->ndoc = n; h->current = current; incref(h); setmalloctag(h, getcallerpc(&b)); return h; Error: free(title); free(author); free(comment); for(i=0; i<n; i++){ free(w[i].author); free(w[i].comment); freepage(w[i].wtxt); } free(w); return nil; }