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