Annotation of mandoc/validate.c, Revision 1.2
1.2 ! kristaps 1: /* $Id: validate.c,v 1.1 2008/11/29 14:14:21 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: {
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:
136: if ( ! md_buf_putchar(p->mbuf, ' '))
137: return(0);
1.2 ! kristaps 138:
1.1 kristaps 139: p->pos += sz + 1;
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);
! 148: }
1.1 kristaps 149:
150: if ( ! md_buf_putstring(p->mbuf, bufp))
151: return(0);
152: if ( ! md_buf_putchar(p->mbuf, ' '))
153: return(0);
1.2 ! kristaps 154:
1.1 kristaps 155: p->pos += sz + 1;
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:
! 337: if ( ! md_buf_putstring(p->mbuf, "<"))
! 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:
! 344: p->pos += strlen(toknames[tok]) + 2;
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);
! 365: if ( ! md_buf_putstring(p->mbuf, "> "))
! 366: return(0);
! 367:
! 368: p->pos += strlen(toknames[tok]) + 3;
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