Annotation of mandoc/validate.c, Revision 1.4
1.4 ! kristaps 1: /* $Id: validate.c,v 1.3 2008/11/30 12:41:45 kristaps Exp $ */
1.1 kristaps 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 <sys/param.h>
20:
21: #include <assert.h>
22: #include <ctype.h>
23: #include <err.h>
24: #include <stdio.h>
25: #include <stdlib.h>
26: #include <string.h>
27:
28: #include "libmdocml.h"
29: #include "private.h"
30:
1.2 kristaps 31: #define INDENT 4
32:
1.1 kristaps 33: #ifdef __linux__ /* FIXME */
1.2 kristaps 34: #define strlcat strncat
1.1 kristaps 35: #endif
36:
37: struct md_valid {
38: const struct md_args *args;
39: const struct md_rbuf *rbuf;
40: struct md_mbuf *mbuf;
41: struct rofftree *tree;
42:
43: size_t indent;
44: size_t pos;
45:
46: int flags;
47: #define MD_LITERAL (1 << 0)
48: };
49:
50: static void roffmsg(void *arg, enum roffmsg,
51: const char *, const char *, char *);
52: static int roffhead(void *);
53: static int rofftail(void *);
54: static int roffin(void *, int, int *, char **);
1.4 ! kristaps 55: static int roffdata(void *, int, char *);
1.1 kristaps 56: static int roffout(void *, int);
1.2 kristaps 57: static int roffblkin(void *, int, int *, char **);
1.1 kristaps 58: static int roffblkout(void *, int);
59: static int roffspecial(void *, int);
60:
61: static int mbuf_newline(struct md_valid *);
62: static int mbuf_indent(struct md_valid *);
1.4 ! kristaps 63: static int mbuf_data(struct md_valid *, int, char *);
1.1 kristaps 64:
65:
66: static int
67: mbuf_indent(struct md_valid *p)
68: {
69: size_t i;
70:
1.2 kristaps 71: assert(p->pos == 0);
1.1 kristaps 72:
1.2 kristaps 73: for (i = 0; i < MIN(p->indent, INDENT); i++)
1.1 kristaps 74: if ( ! md_buf_putstring(p->mbuf, " "))
75: return(0);
76:
1.2 kristaps 77: p->pos += i * INDENT;
1.1 kristaps 78: return(1);
79: }
80:
81:
82: static int
83: mbuf_newline(struct md_valid *p)
84: {
85:
86: if ( ! md_buf_putchar(p->mbuf, '\n'))
87: return(0);
88:
89: p->pos = 0;
1.2 kristaps 90: return(1);
1.1 kristaps 91: }
92:
93:
94: static int
1.4 ! kristaps 95: mbuf_data(struct md_valid *p, int space, char *buf)
1.1 kristaps 96: {
97: size_t sz;
98: char *bufp;
99:
100: assert(p->mbuf);
101: assert(0 != p->indent);
102:
103: if (MD_LITERAL & p->flags)
104: return(md_buf_putstring(p->mbuf, buf));
105:
106: while (*buf) {
107: while (*buf && isspace(*buf))
108: buf++;
109:
110: if (0 == *buf)
111: break;
112:
113: bufp = buf;
114: while (*buf && ! isspace(*buf))
115: buf++;
116:
117: if (0 != *buf)
118: *buf++ = 0;
119:
120: /* Process word. */
121:
122: sz = strlen(bufp);
1.2 kristaps 123:
124: if (0 == p->pos) {
125: if ( ! mbuf_indent(p))
126: return(0);
1.1 kristaps 127: if ( ! md_buf_putstring(p->mbuf, bufp))
128: return(0);
129:
1.2 kristaps 130: if (p->indent * INDENT + sz >= 72) {
131: if ( ! mbuf_newline(p))
132: return(0);
133: continue;
134: }
1.1 kristaps 135:
1.3 kristaps 136: p->pos += sz;
1.1 kristaps 137: continue;
138: }
139:
1.2 kristaps 140: if (sz + p->pos >= 72) {
141: if ( ! mbuf_newline(p))
142: return(0);
143: if ( ! mbuf_indent(p))
144: return(0);
1.3 kristaps 145: } else if (space)
146: if ( ! md_buf_putchar(p->mbuf, ' '))
147: return(0);
1.1 kristaps 148:
149: if ( ! md_buf_putstring(p->mbuf, bufp))
150: return(0);
1.2 kristaps 151:
1.3 kristaps 152: p->pos += sz + (space ? 1 : 0);
1.1 kristaps 153: }
154:
155: return(1);
156: }
157:
158:
159: int
160: md_line_valid(void *arg, char *buf)
161: {
162: struct md_valid *p;
163:
164: p = (struct md_valid *)arg;
165: return(roff_engine(p->tree, buf));
166: }
167:
168:
169: int
170: md_exit_valid(void *data, int flush)
171: {
172: int c;
173: struct md_valid *p;
174:
175: p = (struct md_valid *)data;
176: c = roff_free(p->tree, flush);
177: free(p);
178:
179: return(c);
180: }
181:
182:
183: void *
184: md_init_valid(const struct md_args *args,
185: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
186: {
187: struct roffcb cb;
188: struct md_valid *p;
189:
190: cb.roffhead = roffhead;
191: cb.rofftail = rofftail;
192: cb.roffin = roffin;
193: cb.roffout = roffout;
194: cb.roffblkin = roffblkin;
195: cb.roffblkout = roffblkout;
196: cb.roffspecial = roffspecial;
197: cb.roffmsg = roffmsg;
198: cb.roffdata = roffdata;
199:
200: if (NULL == (p = calloc(1, sizeof(struct md_valid))))
201: err(1, "malloc");
202:
203: p->args = args;
204: p->mbuf = mbuf;
205: p->rbuf = rbuf;
206:
207: assert(mbuf);
208:
209: if (NULL == (p->tree = roff_alloc(&cb, p))) {
210: free(p);
211: return(NULL);
212: }
213:
214: return(p);
215: }
216:
217:
218: /* ARGSUSED */
219: static int
220: roffhead(void *arg)
221: {
1.2 kristaps 222: struct md_valid *p;
223:
224: assert(arg);
225: p = (struct md_valid *)arg;
226:
1.4 ! kristaps 227: if ( ! md_buf_putstring(p->mbuf, "<?xml version=\"1.0\" "
! 228: "encoding=\"UTF-8\"?>\n"))
! 229: return(0);
! 230:
! 231: if ( ! md_buf_putstring(p->mbuf, "<mdoc>"))
1.2 kristaps 232: return(0);
233: p->indent++;
1.1 kristaps 234:
1.4 ! kristaps 235: return(mbuf_newline(p));
1.1 kristaps 236: }
237:
238:
239: static int
240: rofftail(void *arg)
241: {
242: struct md_valid *p;
243:
244: assert(arg);
245: p = (struct md_valid *)arg;
246:
1.2 kristaps 247: if (0 != p->pos && ! mbuf_newline(p))
248: return(0);
1.4 ! kristaps 249: return(md_buf_putstring(p->mbuf, "</mdoc>\n"));
1.1 kristaps 250: }
251:
252:
253: static int
254: roffspecial(void *arg, int tok)
255: {
256:
257: return(1);
258: }
259:
260:
261: static int
1.2 kristaps 262: roffblkin(void *arg, int tok, int *argc, char **argv)
1.1 kristaps 263: {
264: struct md_valid *p;
265:
266: assert(arg);
267: p = (struct md_valid *)arg;
268:
1.2 kristaps 269: if (0 != p->pos) {
270: if ( ! mbuf_newline(p))
1.1 kristaps 271: return(0);
272: if ( ! mbuf_indent(p))
273: return(0);
1.2 kristaps 274: } else if ( ! mbuf_indent(p))
275: return(0);
1.1 kristaps 276:
1.2 kristaps 277: if ( ! md_buf_putchar(p->mbuf, '<'))
278: return(0);
1.1 kristaps 279: if ( ! md_buf_putstring(p->mbuf, toknames[tok]))
280: return(0);
1.2 kristaps 281: if ( ! md_buf_putchar(p->mbuf, '>'))
282: return(0);
283: if ( ! mbuf_newline(p))
1.1 kristaps 284: return(0);
285:
286: p->indent++;
1.2 kristaps 287: return(1);
1.1 kristaps 288: }
289:
290:
291: static int
292: roffblkout(void *arg, int tok)
293: {
294: struct md_valid *p;
295:
296: assert(arg);
297: p = (struct md_valid *)arg;
298:
1.2 kristaps 299: p->indent--;
300:
301: if (0 != p->pos) {
302: if ( ! mbuf_newline(p))
303: return(0);
304: if ( ! mbuf_indent(p))
305: return(0);
306: } else if ( ! mbuf_indent(p))
1.1 kristaps 307: return(0);
308:
1.2 kristaps 309: if ( ! md_buf_putstring(p->mbuf, "</"))
310: return(0);
311: if ( ! md_buf_putstring(p->mbuf, toknames[tok]))
312: return(0);
313: if ( ! md_buf_putstring(p->mbuf, ">"))
314: return(0);
315: if ( ! mbuf_newline(p))
316: return(0);
1.1 kristaps 317:
1.2 kristaps 318: return(1);
1.1 kristaps 319: }
320:
321:
322: static int
323: roffin(void *arg, int tok, int *argcp, char **argvp)
324: {
1.2 kristaps 325: struct md_valid *p;
326:
327: assert(arg);
328: p = (struct md_valid *)arg;
329:
330: if (0 == p->pos && ! mbuf_indent(p))
331: return(0);
332:
1.4 ! kristaps 333: /* FIXME: not always with a space... */
1.3 kristaps 334: if ( ! md_buf_putstring(p->mbuf, " <"))
1.2 kristaps 335: return(0);
336: if ( ! md_buf_putstring(p->mbuf, toknames[tok]))
337: return(0);
338: if ( ! md_buf_putstring(p->mbuf, ">"))
339: return(0);
340:
1.3 kristaps 341: p->pos += strlen(toknames[tok]) + 3;
1.1 kristaps 342:
343: return(1);
344: }
345:
346:
347: static int
348: roffout(void *arg, int tok)
349: {
1.2 kristaps 350: struct md_valid *p;
351:
352: assert(arg);
353: p = (struct md_valid *)arg;
354:
355: if (0 == p->pos && ! mbuf_indent(p))
356: return(0);
357:
358: if ( ! md_buf_putstring(p->mbuf, "</"))
359: return(0);
360: if ( ! md_buf_putstring(p->mbuf, toknames[tok]))
361: return(0);
1.3 kristaps 362: if ( ! md_buf_putstring(p->mbuf, ">"))
1.2 kristaps 363: return(0);
364:
1.3 kristaps 365: p->pos += strlen(toknames[tok]) + 2;
1.1 kristaps 366:
367: return(1);
368: }
369:
370:
371:
372: static void
373: roffmsg(void *arg, enum roffmsg lvl,
374: const char *buf, const char *pos, char *msg)
375: {
376: char *level;
377: struct md_valid *p;
378:
379: assert(arg);
380: p = (struct md_valid *)arg;
381:
382: switch (lvl) {
383: case (ROFF_WARN):
384: if ( ! (MD_WARN_ALL & p->args->warnings))
385: return;
386: level = "warning";
387: break;
388: case (ROFF_ERROR):
389: level = "error";
390: break;
391: default:
392: abort();
393: }
394:
395: if (pos)
396: (void)fprintf(stderr, "%s:%zu: %s: %s\n",
397: p->rbuf->name, p->rbuf->line, level, msg);
398: else
399: (void)fprintf(stderr, "%s: %s: %s\n",
400: p->rbuf->name, level, msg);
401:
402: }
403:
404:
405: static int
1.4 ! kristaps 406: roffdata(void *arg, int space, char *buf)
1.1 kristaps 407: {
408: struct md_valid *p;
409:
410: assert(arg);
411: p = (struct md_valid *)arg;
1.4 ! kristaps 412: return(mbuf_data(p, space, buf));
1.1 kristaps 413: }
CVSweb