]> git.cameronkatri.com Git - mandoc.git/blob - libmdocml.c
Fuller seperation into mdocml/libmdocml.
[mandoc.git] / libmdocml.c
1 /* $Id: libmdocml.c,v 1.3 2008/11/22 20:15:34 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include <assert.h>
20 #include <fcntl.h>
21 #include <err.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "libmdocml.h"
28
29 #define BUFFER_LINE BUFSIZ
30
31 struct md_rbuf {
32 int fd;
33 char *name;
34 char *buf;
35 size_t bufsz;
36 size_t line;
37 };
38
39 struct md_mbuf {
40 int fd;
41 char *name;
42 char *buf;
43 size_t bufsz;
44 size_t pos;
45 };
46
47 typedef int (*md_line) (const struct md_args *, struct md_mbuf *,
48 const struct md_rbuf *,
49 const char *, size_t);
50 typedef int (*md_init) (const struct md_args *, struct md_mbuf *);
51 typedef int (*md_exit) (const struct md_args *, struct md_mbuf *);
52
53 static int md_line_dummy(const struct md_args *,
54 struct md_mbuf *,
55 const struct md_rbuf *,
56 const char *, size_t);
57
58 static int md_line_html4_strict(const struct md_args *,
59 struct md_mbuf *,
60 const struct md_rbuf *,
61 const char *, size_t);
62 static int md_init_html4_strict(const struct md_args *,
63 struct md_mbuf *);
64 static int md_exit_html4_strict(const struct md_args *,
65 struct md_mbuf *);
66
67 static int md_run_enter(const struct md_args *,
68 struct md_mbuf *, struct md_rbuf *);
69 static int md_run_leave(const struct md_args *,
70 struct md_mbuf *,
71 struct md_rbuf *, int);
72
73 static ssize_t md_buf_fill(struct md_rbuf *);
74 static int md_buf_flush(struct md_mbuf *);
75 static int md_buf_putchar(struct md_mbuf *, char);
76 static int md_buf_puts(struct md_mbuf *,
77 const char *, size_t);
78
79
80 static ssize_t
81 md_buf_fill(struct md_rbuf *in)
82 {
83 ssize_t ssz;
84
85 assert(in);
86 assert(in->buf);
87 assert(in->bufsz > 0);
88 assert(in->name);
89
90 if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
91 warn("%s", in->name);
92
93 return(ssz);
94 }
95
96
97 static int
98 md_buf_flush(struct md_mbuf *buf)
99 {
100 ssize_t sz;
101
102 assert(buf);
103 assert(buf->buf);
104 assert(buf->name);
105
106 if (0 == buf->pos)
107 return(1);
108
109 sz = write(buf->fd, buf->buf, buf->pos);
110
111 if (-1 == sz) {
112 warn("%s", buf->name);
113 return(0);
114 } else if ((size_t)sz != buf->pos) {
115 warnx("%s: short write", buf->name);
116 return(0);
117 }
118
119 buf->pos = 0;
120 return(1);
121 }
122
123
124 static int
125 md_buf_putchar(struct md_mbuf *buf, char c)
126 {
127 return(md_buf_puts(buf, &c, 1));
128 }
129
130
131 static int
132 md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
133 {
134 size_t ssz;
135
136 assert(p);
137 assert(buf);
138 assert(buf->buf);
139
140 /* LINTED */
141 while (buf->pos + sz > buf->bufsz) {
142 ssz = buf->bufsz - buf->pos;
143 (void)memcpy(/* LINTED */
144 buf->buf + buf->pos, p, ssz);
145 p += (long)ssz;
146 sz -= ssz;
147 buf->pos += ssz;
148
149 if ( ! md_buf_flush(buf))
150 return(0);
151 }
152
153 (void)memcpy(/* LINTED */
154 buf->buf + buf->pos, p, sz);
155 buf->pos += sz;
156 return(1);
157 }
158
159
160 static int
161 md_run_leave(const struct md_args *args,
162 struct md_mbuf *mbuf, struct md_rbuf *rbuf, int c)
163 {
164 assert(args);
165 assert(mbuf);
166 assert(rbuf);
167
168 /* Run exiters. */
169 switch (args->type) {
170 case (MD_HTML4_STRICT):
171 if ( ! md_exit_html4_strict(args, mbuf))
172 return(-1);
173 break;
174 case (MD_DUMMY):
175 break;
176 default:
177 abort();
178 }
179
180 /* Make final flush of buffer. */
181 if ( ! md_buf_flush(mbuf))
182 return(-1);
183
184 return(c);
185 }
186
187
188 static int
189 md_run_enter(const struct md_args *args,
190 struct md_mbuf *mbuf, struct md_rbuf *rbuf)
191 {
192 ssize_t sz, i;
193 char line[BUFFER_LINE];
194 size_t pos;
195 md_line fp;
196
197 assert(args);
198 assert(mbuf);
199 assert(rbuf);
200
201 /* Function ptrs to line-parsers. */
202 switch (args->type) {
203 case (MD_HTML4_STRICT):
204 fp = md_line_html4_strict;
205 break;
206 case (MD_DUMMY):
207 fp = md_line_dummy;
208 break;
209 default:
210 abort();
211 }
212
213 /* LINTED */
214 for (pos = 0; ; ) {
215 if (-1 == (sz = md_buf_fill(rbuf)))
216 return(-1);
217 else if (0 == sz)
218 break;
219
220 for (i = 0; i < sz; i++) {
221 if ('\n' == rbuf->buf[i]) {
222 if ( ! (*fp)(args, mbuf, rbuf, line, pos))
223 return(-1);
224 rbuf->line++;
225 pos = 0;
226 continue;
227 }
228
229 if (pos < BUFFER_LINE) {
230 /* LINTED */
231 line[pos++] = rbuf->buf[i];
232 continue;
233 }
234
235 warnx("%s: line %zu too long",
236 rbuf->name, rbuf->line);
237 return(-1);
238 }
239 }
240
241 if (0 != pos && ! (*fp)(args, mbuf, rbuf, line, pos))
242 return(-1);
243
244 return(md_run_leave(args, mbuf, rbuf, 0));
245 }
246
247
248 int
249 md_run(const struct md_args *args,
250 const struct md_buf *out, const struct md_buf *in)
251 {
252 struct md_mbuf mbuf;
253 struct md_rbuf rbuf;
254
255 assert(args);
256 assert(in);
257 assert(out);
258
259 (void)memcpy(&mbuf, out, sizeof(struct md_buf));
260 (void)memcpy(&rbuf, in, sizeof(struct md_buf));
261
262 mbuf.pos = 0;
263 rbuf.line = 1;
264
265 /* Run initialisers. */
266 switch (args->type) {
267 case (MD_HTML4_STRICT):
268 if ( ! md_init_html4_strict(args, &mbuf))
269 return(-1);
270 break;
271 case (MD_DUMMY):
272 break;
273 default:
274 abort();
275 }
276
277 /* Go into mainline. */
278 return(md_run_enter(args, &mbuf, &rbuf));
279 }
280
281
282 static int
283 md_line_dummy(const struct md_args *args, struct md_mbuf *out,
284 const struct md_rbuf *in, const char *buf, size_t sz)
285 {
286
287 assert(buf);
288 assert(out);
289 assert(in);
290 assert(args);
291
292 if ( ! md_buf_puts(out, buf, sz))
293 return(0);
294 if ( ! md_buf_putchar(out, '\n'))
295 return(0);
296
297 return(1);
298 }
299
300
301 static int
302 md_exit_html4_strict(const struct md_args *args, struct md_mbuf *p)
303 {
304
305 assert(p);
306 assert(args);
307 return(1);
308 }
309
310
311 static int
312 md_init_html4_strict(const struct md_args *args, struct md_mbuf *p)
313 {
314
315 assert(p);
316 assert(args);
317 return(1);
318 }
319
320
321 static int
322 md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,
323 const struct md_rbuf *in, const char *buf, size_t sz)
324 {
325
326 assert(args);
327 assert(buf);
328 assert(out);
329 assert(in);
330 (void)sz;
331
332 return(1);
333 }