xref: /plan9/sys/src/cmd/wikifs/parsehist.c (revision af2e6ba6a88ebbe37fe767755ab16d53fbb9977b)
1 /*
2  * Read a Wiki history file.
3  * It's a title line then a sequence of Wiki files separated by headers.
4  *
5  * Ddate/time
6  * #body
7  * #...
8  * #...
9  * #...
10  * etc.
11  */
12 
13 #include <u.h>
14 #include <libc.h>
15 #include <bio.h>
16 #include <String.h>
17 #include <thread.h>
18 #include "wiki.h"
19 
20 static char*
Brdwline(void * vb,int sep)21 Brdwline(void *vb, int sep)
22 {
23 	Biobufhdr *b;
24 	char *p;
25 
26 	b = vb;
27 	if(Bgetc(b) == '#'){
28 		if(p = Brdline(b, sep))
29 			p[Blinelen(b)-1] = '\0';
30 		return p;
31 	}else{
32 		Bungetc(b);
33 		return nil;
34 	}
35 }
36 
37 Whist*
Brdwhist(Biobuf * b)38 Brdwhist(Biobuf *b)
39 {
40 	int i, current, conflict, c, n;
41 	char *author, *comment, *p, *title;
42 	ulong t;
43 	Wdoc *w;
44 	Whist *h;
45 
46 	if((p = Brdline(b, '\n')) == nil){
47 		werrstr("short read: %r");
48 		return nil;
49 	}
50 
51 	p[Blinelen(b)-1] = '\0';
52 	p = strcondense(p, 1);
53 	title = estrdup(p);
54 
55 	w = nil;
56 	n = 0;
57 	t = -1;
58 	author = nil;
59 	comment = nil;
60 	conflict = 0;
61 	current = 0;
62 	while((c = Bgetc(b)) != Beof){
63 		if(c != '#'){
64 			p = Brdline(b, '\n');
65 			if(p == nil)
66 				break;
67 			p[Blinelen(b)-1] = '\0';
68 
69 			switch(c){
70 			case 'D':
71 				t = strtoul(p, 0, 10);
72 				break;
73 			case 'A':
74 				free(author);
75 				author = estrdup(p);
76 				break;
77 			case 'C':
78 				free(comment);
79 				comment = estrdup(p);
80 				break;
81 			case 'X':
82 				conflict = 1;
83 			}
84 		} else {	/* c=='#' */
85 			Bungetc(b);
86 			if(n%8 == 0)
87 				w = erealloc(w, (n+8)*sizeof(w[0]));
88 			w[n].time = t;
89 			w[n].author = author;
90 			w[n].comment = comment;
91 			comment = nil;
92 			author = nil;
93 			w[n].wtxt = Brdpage(Brdwline, b);
94 			w[n].conflict = conflict;
95 			if(w[n].wtxt == nil)
96 				goto Error;
97 			if(!conflict)
98 				current = n;
99 			n++;
100 			conflict = 0;
101 			t = -1;
102 		}
103 	}
104 	if(w==nil)
105 		goto Error;
106 
107 	free(comment);
108 	free(author);
109 	h = emalloc(sizeof *h);
110 	h->title = title;
111 	h->doc = w;
112 	h->ndoc = n;
113 	h->current = current;
114 	incref(h);
115 	setmalloctag(h, getcallerpc(&b));
116 	return h;
117 
118 Error:
119 	free(title);
120 	free(author);
121 	free(comment);
122 	for(i=0; i<n; i++){
123 		free(w[i].author);
124 		free(w[i].comment);
125 		freepage(w[i].wtxt);
126 	}
127 	free(w);
128 	return nil;
129 }
130 
131