Annotation of mandoc/validate.c, Revision 1.15
1.15 ! kristaps 1: /* $Id: validate.c,v 1.14 2009/01/03 18:38:39 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 <assert.h>
1.8 kristaps 20: #include <stdlib.h>
1.1 kristaps 21:
22: #include "private.h"
23:
1.11 kristaps 24: /* FIXME: `.St' can only have one argument set. */
1.2 kristaps 25:
1.11 kristaps 26: typedef int (*v_args_sz)(struct mdoc *, int, int, int);
1.14 kristaps 27: typedef int (*v_args)(struct mdoc *, int, int,
28: int, const char *[],
29: int, const struct mdoc_arg *);
30: typedef int (*v_tree)(struct mdoc *, int, int);
31:
32:
33: struct valids {
34: v_args_sz sz;
35: v_args args;
36: v_tree tree_pre;
37: v_tree tree_post;
38: };
1.1 kristaps 39:
1.11 kristaps 40:
41: static int assert_eq0(struct mdoc *, int, int, int);
42: static int assert_le1(struct mdoc *, int, int, int);
43: static int need_eq0(struct mdoc *, int, int, int);
44: static int need_eq1(struct mdoc *, int, int, int);
45: static int need_ge1(struct mdoc *, int, int, int);
46: static int need_le2(struct mdoc *, int, int, int);
47: static int want_eq0(struct mdoc *, int, int, int);
48: static int want_ge1(struct mdoc *, int, int, int);
49:
1.14 kristaps 50: static int tree_pre_ref(struct mdoc *, int, int);
51: static int tree_pre_display(struct mdoc *, int, int);
1.9 kristaps 52:
1.14 kristaps 53: static int tree_post_onlyhead(struct mdoc *, int, int);
54: static int tree_post_onlybody(struct mdoc *, int, int);
55: static int tree_post_warnemptybody(struct mdoc *, int, int);
56:
57: static int args_bool(struct mdoc *, int, int,
58: int, const char *[],
59: int, const struct mdoc_arg *);
60: static int args_sh(struct mdoc *, int, int,
61: int, const char *[],
62: int, const struct mdoc_arg *);
63: static int args_an(struct mdoc *, int, int,
64: int, const char *[],
65: int, const struct mdoc_arg *);
66: static int args_nopunct(struct mdoc *, int, int,
67: int, const char *[],
68: int, const struct mdoc_arg *);
69: static int args_xr(struct mdoc *, int, int,
70: int, const char *[],
71: int, const struct mdoc_arg *);
1.9 kristaps 72:
1.12 kristaps 73:
1.9 kristaps 74: const struct valids mdoc_valids[MDOC_MAX] = {
1.14 kristaps 75: { NULL, NULL, NULL, NULL }, /* \" */
76: { NULL, NULL, NULL, NULL }, /* Dd */ /* TODO */
77: { NULL, NULL, NULL, NULL }, /* Dt */ /* TODO */
78: { NULL, NULL, NULL, NULL }, /* Os */ /* TODO */
1.15 ! kristaps 79: { want_ge1, args_sh, NULL, NULL }, /* Sh */ /* FIXME: preceding Pp. */
! 80: { want_ge1, NULL, NULL, NULL }, /* Ss */ /* FIXME: preceding Pp. */
1.14 kristaps 81: { want_eq0, NULL, NULL, NULL }, /* Pp */
82: { assert_eq0, NULL, tree_pre_display, tree_post_onlyhead }, /* D1 */
83: { assert_eq0, NULL, tree_pre_display, tree_post_onlyhead }, /* Dl */
1.15 ! kristaps 84: { want_eq0, NULL, tree_pre_display, tree_post_warnemptybody }, /* Bd */ /* FIXME: preceding Pp. */
1.14 kristaps 85: { assert_eq0, NULL, NULL, tree_post_onlybody }, /* Ed */
1.15 ! kristaps 86: { want_eq0, NULL, NULL, NULL }, /* Bl */ /* FIXME: preceding Pp. */
1.14 kristaps 87: { assert_eq0, NULL, NULL, tree_post_onlybody }, /* El */
88: { NULL, NULL, NULL, NULL }, /* It */
89: { need_ge1, NULL, NULL, NULL }, /* Ad */
90: { NULL, args_an, NULL, NULL }, /* An */
91: { NULL, NULL, NULL, NULL }, /* Ar */
92: { need_ge1, NULL, NULL, NULL }, /* Cd */
93: { NULL, NULL, NULL, NULL }, /* Cm */
94: { need_ge1, NULL, NULL, NULL }, /* Dv */
95: { need_ge1, NULL, NULL, NULL }, /* Er */
96: { need_ge1, NULL, NULL, NULL }, /* Ev */
97: { NULL, NULL, NULL, NULL }, /* Ex */
98: { need_ge1, NULL, NULL, NULL }, /* Fa */
99: { NULL, NULL, NULL, NULL }, /* Fd */
100: { NULL, NULL, NULL, NULL }, /* Fl */
101: { need_ge1, NULL, NULL, NULL }, /* Fn */
102: { want_ge1, NULL, NULL, NULL }, /* Ft */
103: { need_ge1, NULL, NULL, NULL }, /* Ic */
104: { need_eq1, NULL, NULL, NULL }, /* In */
105: { want_ge1, NULL, NULL, NULL }, /* Li */
106: { want_ge1, NULL, NULL, NULL }, /* Nd */
107: { NULL, NULL, NULL, NULL }, /* Nm */
108: { NULL, NULL, NULL, NULL }, /* Op */
109: { NULL, NULL, NULL, NULL }, /* Ot */
110: { want_ge1, NULL, NULL, NULL }, /* Pa */
111: { NULL, NULL, NULL, NULL }, /* Rv */
112: { NULL, NULL, NULL, NULL }, /* St */
113: { need_ge1, NULL, NULL, NULL }, /* Va */
114: { need_ge1, NULL, NULL, NULL }, /* Vt */
115: { need_le2, args_xr, NULL, NULL }, /* Xr */
116: { need_ge1, NULL, tree_pre_ref, NULL }, /* %A */
117: { need_ge1, NULL, tree_pre_ref, NULL }, /* %B */
118: { need_ge1, NULL, tree_pre_ref, NULL }, /* %D */
119: { need_ge1, NULL, tree_pre_ref, NULL }, /* %I */
120: { need_ge1, NULL, tree_pre_ref, NULL }, /* %J */
121: { need_ge1, NULL, tree_pre_ref, NULL }, /* %N */
122: { need_ge1, NULL, tree_pre_ref, NULL }, /* %O */
123: { need_ge1, NULL, tree_pre_ref, NULL }, /* %P */
124: { need_ge1, NULL, tree_pre_ref, NULL }, /* %R */
125: { need_ge1, NULL, tree_pre_ref, NULL }, /* %T */
126: { need_ge1, NULL, tree_pre_ref, NULL }, /* %V */
127: { NULL, NULL, NULL, NULL }, /* Ac */
128: { NULL, NULL, NULL, NULL }, /* Ao */
129: { NULL, NULL, NULL, NULL }, /* Aq */
1.15 ! kristaps 130: { need_le2, args_nopunct, NULL, NULL }, /* At */ /* FIXME */
1.14 kristaps 131: { NULL, NULL, NULL, NULL }, /* Bc */
132: { NULL, NULL, NULL, NULL }, /* Bf */
133: { NULL, NULL, NULL, NULL }, /* Bo */
134: { NULL, NULL, NULL, NULL }, /* Bq */
135: { assert_le1, NULL, NULL, NULL }, /* Bsx */
136: { assert_le1, NULL, NULL, NULL }, /* Bx */
137: { need_eq1, args_bool, NULL, NULL }, /* Db */
138: { NULL, NULL, NULL, NULL }, /* Dc */
139: { NULL, NULL, NULL, NULL }, /* Do */
140: { NULL, NULL, NULL, NULL }, /* Dq */
141: { NULL, NULL, NULL, NULL }, /* Ec */
142: { NULL, NULL, NULL, NULL }, /* Ef */ /* -symbolic, etc. */
143: { need_ge1, NULL, NULL, NULL }, /* Em */
144: { NULL, NULL, NULL, NULL }, /* Eo */
145: { assert_le1, NULL, NULL, NULL }, /* Fx */
146: { want_ge1, NULL, NULL, NULL }, /* Ms */
147: { NULL, NULL, NULL, NULL }, /* No */
148: { NULL, NULL, NULL, NULL }, /* Ns */
149: { assert_le1, NULL, NULL, NULL }, /* Nx */
150: { assert_le1, NULL, NULL, NULL }, /* Ox */
151: { NULL, NULL, NULL, NULL }, /* Pc */
152: { NULL, NULL, NULL, NULL }, /* Pf */ /* 2 or more arguments */
153: { NULL, NULL, NULL, NULL }, /* Po */
1.15 ! kristaps 154: { NULL, NULL, NULL, NULL }, /* Pq */ /* FIXME: ignore following Sh/Ss */
1.14 kristaps 155: { NULL, NULL, NULL, NULL }, /* Qc */
156: { NULL, NULL, NULL, NULL }, /* Ql */
157: { NULL, NULL, NULL, NULL }, /* Qo */
158: { NULL, NULL, NULL, NULL }, /* Qq */
159: { NULL, NULL, NULL, NULL }, /* Re */
160: { NULL, NULL, NULL, NULL }, /* Rs */
161: { NULL, NULL, NULL, NULL }, /* Sc */
162: { NULL, NULL, NULL, NULL }, /* So */
163: { NULL, NULL, NULL, NULL }, /* Sq */
164: { need_eq1, args_bool, NULL, NULL }, /* Sm */
165: { need_ge1, NULL, NULL, NULL }, /* Sx */
166: { need_ge1, NULL, NULL, NULL }, /* Sy */
167: { want_ge1, NULL, NULL, NULL }, /* Tn */
168: { assert_eq0, NULL, NULL, NULL }, /* Ux */
169: { NULL, NULL, NULL, NULL }, /* Xc */
170: { NULL, NULL, NULL, NULL }, /* Xo */
171: { NULL, NULL, NULL, NULL }, /* Fo */
172: { NULL, NULL, NULL, NULL }, /* Fc */
173: { NULL, NULL, NULL, NULL }, /* Oo */
174: { NULL, NULL, NULL, NULL }, /* Oc */
175: { NULL, NULL, NULL, NULL }, /* Bk */
176: { NULL, NULL, NULL, NULL }, /* Ek */
177: { need_eq0, NULL, NULL, NULL }, /* Bt */
178: { need_eq1, NULL, NULL, NULL }, /* Hf */
179: { NULL, NULL, NULL, NULL }, /* Fr */
180: { need_eq0, NULL, NULL, NULL }, /* Ud */
1.9 kristaps 181: };
1.6 kristaps 182:
183:
184: static int
1.9 kristaps 185: need_le2(struct mdoc *mdoc, int tok, int pos, int sz)
1.6 kristaps 186: {
1.11 kristaps 187: if (sz <= 2)
1.8 kristaps 188: return(1);
1.9 kristaps 189: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_LE2));
1.6 kristaps 190: }
191:
192:
193: static int
1.9 kristaps 194: want_ge1(struct mdoc *mdoc, int tok, int pos, int sz)
1.6 kristaps 195: {
1.9 kristaps 196: if (sz > 0)
1.8 kristaps 197: return(1);
1.9 kristaps 198: return(mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1));
1.6 kristaps 199: }
1.1 kristaps 200:
201:
202: static int
1.9 kristaps 203: want_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.1 kristaps 204: {
1.9 kristaps 205: if (sz == 0)
206: return(1);
207: return(mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0));
1.1 kristaps 208: }
209:
210:
211: static int
1.9 kristaps 212: need_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.1 kristaps 213: {
1.9 kristaps 214: if (sz == 0)
215: return(1);
216: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ0));
1.1 kristaps 217: }
218:
219:
220: static int
1.9 kristaps 221: assert_le1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1 kristaps 222: {
1.8 kristaps 223:
1.9 kristaps 224: assert(sz <= 1);
1.8 kristaps 225: return(1);
226: }
1.1 kristaps 227:
228:
1.8 kristaps 229: static int
1.9 kristaps 230: assert_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.8 kristaps 231: {
1.1 kristaps 232:
1.9 kristaps 233: assert(sz == 0);
1.1 kristaps 234: return(1);
235: }
236:
237:
1.8 kristaps 238: static int
1.9 kristaps 239: need_eq1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1 kristaps 240: {
1.9 kristaps 241: if (sz == 1)
242: return(1);
243: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ1));
1.1 kristaps 244: }
245:
246:
1.9 kristaps 247: static int
248: need_ge1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1 kristaps 249: {
1.9 kristaps 250: if (sz > 0)
251: return(1);
252: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
1.1 kristaps 253: }
254:
255:
1.9 kristaps 256: static int
1.14 kristaps 257: tree_post_onlybody(struct mdoc *mdoc, int tok, int pos)
1.12 kristaps 258: {
1.14 kristaps 259: struct mdoc_node *n;
260:
261: assert(mdoc->last);
262: n = mdoc->last;
263:
264: assert(MDOC_BLOCK == n->type);
265: assert(n->child);
266:
267: if (MDOC_BODY == n->child->type) {
268: if (n->child->child)
269: return(1);
270: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_EMPTYBODY));
271: }
272:
273: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_CHILDBODY));
274: }
275:
276:
277: static int
278: tree_post_warnemptybody(struct mdoc *mdoc, int tok, int pos)
279: {
280: struct mdoc_node *n;
281:
282: assert(mdoc->last);
283: n = mdoc->last;
284:
285: assert(MDOC_BLOCK == n->type);
286: assert(n->child);
287:
288: for (n = n->child; n; n = n->next)
289: if (MDOC_BODY == n->type)
290: break;
1.12 kristaps 291:
1.14 kristaps 292: if (n && n->child)
293: return(1);
294: return(mdoc_warn(mdoc, tok, pos, WARN_SYNTAX_EMPTYBODY));
1.12 kristaps 295: }
296:
297:
298: static int
1.14 kristaps 299: tree_post_onlyhead(struct mdoc *mdoc, int tok, int pos)
1.11 kristaps 300: {
301: struct mdoc_node *n;
302:
303: assert(mdoc->last);
304: n = mdoc->last;
305:
306: assert(MDOC_BLOCK == n->type);
307: assert(n->child);
308:
309: n = n->child;
310:
311: if (MDOC_HEAD != n->type)
1.14 kristaps 312: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_CHILDHEAD));
1.11 kristaps 313: if (n->child)
314: return(1);
1.14 kristaps 315: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_EMPTYHEAD));
316: }
317:
318:
319: static int
320: args_an(struct mdoc *mdoc, int tok, int pos,
321: int sz, const char *args[],
322: int argc, const struct mdoc_arg *argv)
323: {
324:
325: printf("argc=%d, sz=%d\n", argc, sz);
326: if (0 != argc && 0 != sz)
327: return(mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0));
328: return(1);
1.11 kristaps 329: }
330:
331:
332: static int
1.14 kristaps 333: args_sh(struct mdoc *mdoc, int tok, int pos,
334: int sz, const char *args[],
1.9 kristaps 335: int argc, const struct mdoc_arg *argv)
1.1 kristaps 336: {
1.9 kristaps 337: enum mdoc_sec sec;
1.2 kristaps 338:
1.9 kristaps 339: sec = mdoc_atosec((size_t)sz, args);
340: if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
341: if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
1.8 kristaps 342: return(0);
1.9 kristaps 343: if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
344: return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
1.2 kristaps 345:
1.9 kristaps 346: return(1);
1.1 kristaps 347: }
348:
349:
1.9 kristaps 350: static int
1.11 kristaps 351: args_bool(struct mdoc *mdoc, int tok, int pos,
1.14 kristaps 352: int sz, const char *args[],
1.11 kristaps 353: int argc, const struct mdoc_arg *argv)
354: {
1.14 kristaps 355: int i;
1.11 kristaps 356:
1.14 kristaps 357: for (i = 0; i < sz; i++) {
358: if (xstrcmp(args[i], "on"))
359: continue;
360: if (xstrcmp(args[i], "off"))
361: continue;
362: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGBAD));
363: }
364: return(1);
1.11 kristaps 365: }
366:
367:
368: static int
1.14 kristaps 369: tree_pre_ref(struct mdoc *mdoc, int tok, int pos)
1.11 kristaps 370: {
371: struct mdoc_node *n;
372:
373: assert(mdoc->last);
374: for (n = mdoc->last ; n; n = n->parent) {
375: if (MDOC_BLOCK != n->type)
376: continue;
377: if (MDOC_Rs != n->data.block.tok)
378: break;
379: return(1);
380: }
381:
382: return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NOCTX));
383: }
384:
385:
386: static int
1.14 kristaps 387: args_xr(struct mdoc *mdoc, int tok, int pos,
388: int sz, const char *args[],
1.11 kristaps 389: int argc, const struct mdoc_arg *argv)
390: {
391:
392: if (1 == sz)
393: return(1);
394: if (0 == sz)
395: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
396: if (MSEC_DEFAULT == mdoc_atomsec(args[1]))
397: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGFORM));
398: return(1);
399: }
400:
401:
402: static int
1.14 kristaps 403: args_nopunct(struct mdoc *mdoc, int tok, int pos,
404: int sz, const char *args[],
1.9 kristaps 405: int argc, const struct mdoc_arg *argv)
1.1 kristaps 406: {
1.9 kristaps 407: int i;
1.1 kristaps 408:
1.9 kristaps 409: if (0 == sz)
1.8 kristaps 410: return(1);
1.6 kristaps 411:
1.9 kristaps 412: i = 0;
413: if (ATT_DEFAULT == mdoc_atoatt(args[i]))
414: i++;
415: for ( ; i < sz; i++) {
416: if ( ! mdoc_isdelim(args[i]))
417: continue;
418: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
1.8 kristaps 419: }
1.9 kristaps 420: return(1);
1.1 kristaps 421: }
422:
423:
1.9 kristaps 424: static int
1.14 kristaps 425: tree_pre_display(struct mdoc *mdoc, int tok, int pos)
1.1 kristaps 426: {
1.9 kristaps 427: struct mdoc_node *node;
1.8 kristaps 428:
1.9 kristaps 429: assert(mdoc->last);
1.8 kristaps 430:
1.14 kristaps 431: /* Displays may not be nested in other displays. */
432:
1.9 kristaps 433: /* LINTED */
1.11 kristaps 434: for (node = mdoc->last; node; node = node->parent) {
1.9 kristaps 435: if (node->type != MDOC_BLOCK)
436: continue;
437: if (node->data.block.tok != MDOC_Bd)
1.8 kristaps 438: continue;
439: break;
440: }
1.9 kristaps 441: if (NULL == node)
442: return(1);
443: return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NONEST));
1.8 kristaps 444: }
445:
446:
447: int
1.11 kristaps 448: mdoc_valid_pre(struct mdoc *mdoc, int tok, int pos,
1.9 kristaps 449: int argc, const struct mdoc_arg *argv)
1.8 kristaps 450: {
451:
1.9 kristaps 452: assert(tok < MDOC_MAX);
453: if (mdoc_valids[tok].sz)
454: if ( ! (*mdoc_valids[tok].sz)(mdoc, tok, pos, sz))
1.5 kristaps 455: return(0);
1.14 kristaps 456: if (mdoc_valids[tok].args)
457: if ( ! (*mdoc_valids[tok].args)(mdoc, tok, pos,
458: sz, args, argc, argv))
459: return(0);
460: if (mdoc_valids[tok].tree_pre)
461: if ( ! (*mdoc_valids[tok].tree_pre)(mdoc, tok, pos))
462: return(0);
463: return(1);
1.1 kristaps 464: }
465:
1.11 kristaps 466:
467: int
1.15 ! kristaps 468: mdoc_valid_post(struct mdoc *mdoc, int tok, int pos,
! 469: int argc, const struct mdoc_arg *argv)
1.11 kristaps 470: {
471:
1.14 kristaps 472: if (mdoc_valids[tok].tree_post)
473: return((*mdoc_valids[tok].tree_post)(mdoc, tok, pos));
474: return(1);
1.11 kristaps 475: }
1.14 kristaps 476:
CVSweb