xref: /plan9/sys/src/cmd/wikifs/parsehist.c (revision af2e6ba6a88ebbe37fe767755ab16d53fbb9977b)
19a747e4fSDavid du Colombier /*
29a747e4fSDavid du Colombier  * Read a Wiki history file.
39a747e4fSDavid du Colombier  * It's a title line then a sequence of Wiki files separated by headers.
49a747e4fSDavid du Colombier  *
59a747e4fSDavid du Colombier  * Ddate/time
69a747e4fSDavid du Colombier  * #body
79a747e4fSDavid du Colombier  * #...
89a747e4fSDavid du Colombier  * #...
99a747e4fSDavid du Colombier  * #...
109a747e4fSDavid du Colombier  * etc.
119a747e4fSDavid du Colombier  */
129a747e4fSDavid du Colombier 
139a747e4fSDavid du Colombier #include <u.h>
149a747e4fSDavid du Colombier #include <libc.h>
159a747e4fSDavid du Colombier #include <bio.h>
169a747e4fSDavid du Colombier #include <String.h>
179a747e4fSDavid du Colombier #include <thread.h>
189a747e4fSDavid du Colombier #include "wiki.h"
199a747e4fSDavid du Colombier 
209a747e4fSDavid du Colombier static char*
Brdwline(void * vb,int sep)219a747e4fSDavid du Colombier Brdwline(void *vb, int sep)
229a747e4fSDavid du Colombier {
239a747e4fSDavid du Colombier 	Biobufhdr *b;
249a747e4fSDavid du Colombier 	char *p;
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier 	b = vb;
279a747e4fSDavid du Colombier 	if(Bgetc(b) == '#'){
289a747e4fSDavid du Colombier 		if(p = Brdline(b, sep))
299a747e4fSDavid du Colombier 			p[Blinelen(b)-1] = '\0';
309a747e4fSDavid du Colombier 		return p;
319a747e4fSDavid du Colombier 	}else{
329a747e4fSDavid du Colombier 		Bungetc(b);
339a747e4fSDavid du Colombier 		return nil;
349a747e4fSDavid du Colombier 	}
359a747e4fSDavid du Colombier }
369a747e4fSDavid du Colombier 
379a747e4fSDavid du Colombier Whist*
Brdwhist(Biobuf * b)389a747e4fSDavid du Colombier Brdwhist(Biobuf *b)
399a747e4fSDavid du Colombier {
409a747e4fSDavid du Colombier 	int i, current, conflict, c, n;
419a747e4fSDavid du Colombier 	char *author, *comment, *p, *title;
429a747e4fSDavid du Colombier 	ulong t;
439a747e4fSDavid du Colombier 	Wdoc *w;
449a747e4fSDavid du Colombier 	Whist *h;
459a747e4fSDavid du Colombier 
469a747e4fSDavid du Colombier 	if((p = Brdline(b, '\n')) == nil){
479a747e4fSDavid du Colombier 		werrstr("short read: %r");
489a747e4fSDavid du Colombier 		return nil;
499a747e4fSDavid du Colombier 	}
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier 	p[Blinelen(b)-1] = '\0';
529a747e4fSDavid du Colombier 	p = strcondense(p, 1);
539a747e4fSDavid du Colombier 	title = estrdup(p);
549a747e4fSDavid du Colombier 
559a747e4fSDavid du Colombier 	w = nil;
569a747e4fSDavid du Colombier 	n = 0;
579a747e4fSDavid du Colombier 	t = -1;
589a747e4fSDavid du Colombier 	author = nil;
599a747e4fSDavid du Colombier 	comment = nil;
609a747e4fSDavid du Colombier 	conflict = 0;
619a747e4fSDavid du Colombier 	current = 0;
629a747e4fSDavid du Colombier 	while((c = Bgetc(b)) != Beof){
639a747e4fSDavid du Colombier 		if(c != '#'){
649a747e4fSDavid du Colombier 			p = Brdline(b, '\n');
659a747e4fSDavid du Colombier 			if(p == nil)
669a747e4fSDavid du Colombier 				break;
679a747e4fSDavid du Colombier 			p[Blinelen(b)-1] = '\0';
689a747e4fSDavid du Colombier 
699a747e4fSDavid du Colombier 			switch(c){
709a747e4fSDavid du Colombier 			case 'D':
719a747e4fSDavid du Colombier 				t = strtoul(p, 0, 10);
729a747e4fSDavid du Colombier 				break;
739a747e4fSDavid du Colombier 			case 'A':
749a747e4fSDavid du Colombier 				free(author);
759a747e4fSDavid du Colombier 				author = estrdup(p);
769a747e4fSDavid du Colombier 				break;
779a747e4fSDavid du Colombier 			case 'C':
789a747e4fSDavid du Colombier 				free(comment);
799a747e4fSDavid du Colombier 				comment = estrdup(p);
809a747e4fSDavid du Colombier 				break;
819a747e4fSDavid du Colombier 			case 'X':
829a747e4fSDavid du Colombier 				conflict = 1;
839a747e4fSDavid du Colombier 			}
849a747e4fSDavid du Colombier 		} else {	/* c=='#' */
859a747e4fSDavid du Colombier 			Bungetc(b);
869a747e4fSDavid du Colombier 			if(n%8 == 0)
879a747e4fSDavid du Colombier 				w = erealloc(w, (n+8)*sizeof(w[0]));
889a747e4fSDavid du Colombier 			w[n].time = t;
899a747e4fSDavid du Colombier 			w[n].author = author;
909a747e4fSDavid du Colombier 			w[n].comment = comment;
91*af2e6ba6SDavid du Colombier 			comment = nil;
92*af2e6ba6SDavid du Colombier 			author = nil;
939a747e4fSDavid du Colombier 			w[n].wtxt = Brdpage(Brdwline, b);
949a747e4fSDavid du Colombier 			w[n].conflict = conflict;
959a747e4fSDavid du Colombier 			if(w[n].wtxt == nil)
969a747e4fSDavid du Colombier 				goto Error;
979a747e4fSDavid du Colombier 			if(!conflict)
989a747e4fSDavid du Colombier 				current = n;
999a747e4fSDavid du Colombier 			n++;
1009a747e4fSDavid du Colombier 			conflict = 0;
1019a747e4fSDavid du Colombier 			t = -1;
1029a747e4fSDavid du Colombier 		}
1039a747e4fSDavid du Colombier 	}
1049a747e4fSDavid du Colombier 	if(w==nil)
1059a747e4fSDavid du Colombier 		goto Error;
1069a747e4fSDavid du Colombier 
1079a747e4fSDavid du Colombier 	free(comment);
1089a747e4fSDavid du Colombier 	free(author);
1099a747e4fSDavid du Colombier 	h = emalloc(sizeof *h);
1109a747e4fSDavid du Colombier 	h->title = title;
1119a747e4fSDavid du Colombier 	h->doc = w;
1129a747e4fSDavid du Colombier 	h->ndoc = n;
1139a747e4fSDavid du Colombier 	h->current = current;
1149a747e4fSDavid du Colombier 	incref(h);
115*af2e6ba6SDavid du Colombier 	setmalloctag(h, getcallerpc(&b));
1169a747e4fSDavid du Colombier 	return h;
1179a747e4fSDavid du Colombier 
1189a747e4fSDavid du Colombier Error:
1199a747e4fSDavid du Colombier 	free(title);
1209a747e4fSDavid du Colombier 	free(author);
1219a747e4fSDavid du Colombier 	free(comment);
122*af2e6ba6SDavid du Colombier 	for(i=0; i<n; i++){
123*af2e6ba6SDavid du Colombier 		free(w[i].author);
124*af2e6ba6SDavid du Colombier 		free(w[i].comment);
1259a747e4fSDavid du Colombier 		freepage(w[i].wtxt);
126*af2e6ba6SDavid du Colombier 	}
1279a747e4fSDavid du Colombier 	free(w);
1289a747e4fSDavid du Colombier 	return nil;
1299a747e4fSDavid du Colombier }
1309a747e4fSDavid du Colombier 
131