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