Annotation of mandoc/validate.c, Revision 1.22
1.22 ! kristaps 1: /* $Id: validate.c,v 1.21 2009/01/09 14:45:44 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.2 kristaps 24:
1.18 kristaps 25: typedef int (*v_pre)(struct mdoc *, struct mdoc_node *);
26: typedef int (*v_post)(struct mdoc *);
1.14 kristaps 27:
28:
29: struct valids {
1.17 kristaps 30: v_pre pre;
31: v_post *post;
1.14 kristaps 32: };
1.1 kristaps 33:
1.11 kristaps 34:
1.20 kristaps 35: static int pre_prologue(struct mdoc *, struct mdoc_node *);
36: static int pre_prologue(struct mdoc *, struct mdoc_node *);
37: static int pre_prologue(struct mdoc *, struct mdoc_node *);
1.18 kristaps 38: static int post_headchild_err_ge1(struct mdoc *);
1.21 kristaps 39: static int post_elemchild_err_ge1(struct mdoc *);
1.22 ! kristaps 40: static int post_elemchild_warn_eq0(struct mdoc *);
1.18 kristaps 41: static int post_bodychild_warn_ge1(struct mdoc *);
1.21 kristaps 42: static int post_sh(struct mdoc *);
1.17 kristaps 43:
1.21 kristaps 44: static v_post posts_sh[] = { post_headchild_err_ge1,
45: post_bodychild_warn_ge1, post_sh, NULL };
1.22 ! kristaps 46: static v_post posts_ss[] = { post_headchild_err_ge1, NULL };
! 47: static v_post posts_pp[] = { post_elemchild_warn_eq0, NULL };
1.21 kristaps 48: static v_post posts_dd[] = { post_elemchild_err_ge1, NULL };
1.9 kristaps 49:
1.12 kristaps 50:
1.9 kristaps 51: const struct valids mdoc_valids[MDOC_MAX] = {
1.17 kristaps 52: { NULL, NULL }, /* \" */
1.21 kristaps 53: { pre_prologue, posts_dd }, /* Dd */
54: { pre_prologue, NULL }, /* Dt */
55: { pre_prologue, NULL }, /* Os */
56: { NULL, posts_sh }, /* Sh */ /* FIXME: preceding Pp. */
1.22 ! kristaps 57: { NULL, posts_ss }, /* Ss */ /* FIXME: preceding Pp. */
! 58: { NULL, posts_pp }, /* Pp */ /* FIXME: proceeding... */
1.17 kristaps 59: { NULL, NULL }, /* D1 */
60: { NULL, NULL }, /* Dl */
61: { NULL, NULL }, /* Bd */ /* FIXME: preceding Pp. */
62: { NULL, NULL }, /* Ed */
63: { NULL, NULL }, /* Bl */ /* FIXME: preceding Pp. */
64: { NULL, NULL }, /* El */
65: { NULL, NULL }, /* It */
66: { NULL, NULL }, /* Ad */
67: { NULL, NULL }, /* An */
68: { NULL, NULL }, /* Ar */
69: { NULL, NULL }, /* Cd */
70: { NULL, NULL }, /* Cm */
71: { NULL, NULL }, /* Dv */
72: { NULL, NULL }, /* Er */
73: { NULL, NULL }, /* Ev */
74: { NULL, NULL }, /* Ex */
75: { NULL, NULL }, /* Fa */
76: { NULL, NULL }, /* Fd */
77: { NULL, NULL }, /* Fl */
78: { NULL, NULL }, /* Fn */
79: { NULL, NULL }, /* Ft */
80: { NULL, NULL }, /* Ic */
81: { NULL, NULL }, /* In */
82: { NULL, NULL }, /* Li */
83: { NULL, NULL }, /* Nd */
84: { NULL, NULL }, /* Nm */
85: { NULL, NULL }, /* Op */
86: { NULL, NULL }, /* Ot */
87: { NULL, NULL }, /* Pa */
88: { NULL, NULL }, /* Rv */
89: { NULL, NULL }, /* St */
90: { NULL, NULL }, /* Va */
91: { NULL, NULL }, /* Vt */
92: { NULL, NULL }, /* Xr */
93: { NULL, NULL }, /* %A */
94: { NULL, NULL }, /* %B */
95: { NULL, NULL }, /* %D */
96: { NULL, NULL }, /* %I */
97: { NULL, NULL }, /* %J */
98: { NULL, NULL }, /* %N */
99: { NULL, NULL }, /* %O */
100: { NULL, NULL }, /* %P */
101: { NULL, NULL }, /* %R */
102: { NULL, NULL }, /* %T */
103: { NULL, NULL }, /* %V */
104: { NULL, NULL }, /* Ac */
105: { NULL, NULL }, /* Ao */
106: { NULL, NULL }, /* Aq */
107: { NULL, NULL }, /* At */ /* FIXME */
108: { NULL, NULL }, /* Bc */
109: { NULL, NULL }, /* Bf */
110: { NULL, NULL }, /* Bo */
111: { NULL, NULL }, /* Bq */
112: { NULL, NULL }, /* Bsx */
113: { NULL, NULL }, /* Bx */
114: { NULL, NULL }, /* Db */
115: { NULL, NULL }, /* Dc */
116: { NULL, NULL }, /* Do */
117: { NULL, NULL }, /* Dq */
118: { NULL, NULL }, /* Ec */
119: { NULL, NULL }, /* Ef */ /* -symbolic, etc. */
120: { NULL, NULL }, /* Em */
121: { NULL, NULL }, /* Eo */
122: { NULL, NULL }, /* Fx */
123: { NULL, NULL }, /* Ms */
124: { NULL, NULL }, /* No */
125: { NULL, NULL }, /* Ns */
126: { NULL, NULL }, /* Nx */
127: { NULL, NULL }, /* Ox */
128: { NULL, NULL }, /* Pc */
129: { NULL, NULL }, /* Pf */ /* 2 or more arguments */
130: { NULL, NULL }, /* Po */
131: { NULL, NULL }, /* Pq */ /* FIXME: ignore following Sh/Ss */
132: { NULL, NULL }, /* Qc */
133: { NULL, NULL }, /* Ql */
134: { NULL, NULL }, /* Qo */
135: { NULL, NULL }, /* Qq */
136: { NULL, NULL }, /* Re */
137: { NULL, NULL }, /* Rs */
138: { NULL, NULL }, /* Sc */
139: { NULL, NULL }, /* So */
140: { NULL, NULL }, /* Sq */
141: { NULL, NULL }, /* Sm */
142: { NULL, NULL }, /* Sx */
143: { NULL, NULL }, /* Sy */
144: { NULL, NULL }, /* Tn */
145: { NULL, NULL }, /* Ux */
146: { NULL, NULL }, /* Xc */
147: { NULL, NULL }, /* Xo */
148: { NULL, NULL }, /* Fo */
149: { NULL, NULL }, /* Fc */
150: { NULL, NULL }, /* Oo */
151: { NULL, NULL }, /* Oc */
152: { NULL, NULL }, /* Bk */
153: { NULL, NULL }, /* Ek */
154: { NULL, NULL }, /* Bt */
155: { NULL, NULL }, /* Hf */
156: { NULL, NULL }, /* Fr */
157: { NULL, NULL }, /* Ud */
1.9 kristaps 158: };
1.6 kristaps 159:
160:
161: static int
1.18 kristaps 162: post_bodychild_warn_ge1(struct mdoc *mdoc)
1.6 kristaps 163: {
164:
1.17 kristaps 165: if (MDOC_BODY != mdoc->last->type)
1.8 kristaps 166: return(1);
1.17 kristaps 167: if (mdoc->last->child)
1.9 kristaps 168: return(1);
1.1 kristaps 169:
1.18 kristaps 170: return(mdoc_warn(mdoc, WARN_ARGS_GE1));
1.8 kristaps 171: }
1.1 kristaps 172:
173:
1.8 kristaps 174: static int
1.22 ! kristaps 175: post_elemchild_warn_eq0(struct mdoc *mdoc)
! 176: {
! 177:
! 178: assert(MDOC_ELEM == mdoc->last->type);
! 179: if (NULL == mdoc->last->child)
! 180: return(1);
! 181: return(mdoc_warn(mdoc, WARN_ARGS_EQ0));
! 182: }
! 183:
! 184:
! 185: static int
1.21 kristaps 186: post_elemchild_err_ge1(struct mdoc *mdoc)
1.8 kristaps 187: {
1.1 kristaps 188:
1.21 kristaps 189: assert(MDOC_ELEM == mdoc->last->type);
1.17 kristaps 190: if (mdoc->last->child)
1.9 kristaps 191: return(1);
1.18 kristaps 192: return(mdoc_err(mdoc, ERR_ARGS_GE1));
1.1 kristaps 193: }
194:
195:
1.9 kristaps 196: static int
1.21 kristaps 197: post_headchild_err_ge1(struct mdoc *mdoc)
1.14 kristaps 198: {
199:
1.17 kristaps 200: if (MDOC_HEAD != mdoc->last->type)
1.14 kristaps 201: return(1);
1.21 kristaps 202: if (mdoc->last->child)
1.11 kristaps 203: return(1);
1.21 kristaps 204: return(mdoc_err(mdoc, ERR_ARGS_GE1));
1.14 kristaps 205: }
206:
207:
208: static int
1.20 kristaps 209: pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
210: {
211:
212: if (SEC_PROLOGUE != mdoc->sec_lastn)
213: return(mdoc_verr(mdoc, node, ERR_SEC_NPROLOGUE));
214: assert(MDOC_ELEM == node->type);
215:
216: /* Check for ordering. */
217:
218: switch (node->data.elem.tok) {
219: case (MDOC_Os):
220: if (mdoc->meta.title[0] && mdoc->meta.date)
221: break;
222: return(mdoc_verr(mdoc, node, ERR_SEC_PROLOGUE_OO));
223: case (MDOC_Dt):
224: if (0 == mdoc->meta.title[0] && mdoc->meta.date)
225: break;
226: return(mdoc_verr(mdoc, node, ERR_SEC_PROLOGUE_OO));
227: case (MDOC_Dd):
228: if (0 == mdoc->meta.title[0] && 0 == mdoc->meta.date)
229: break;
230: return(mdoc_verr(mdoc, node, ERR_SEC_PROLOGUE_OO));
231: default:
232: abort();
233: /* NOTREACHED */
234: }
235:
236: /* Check for repetition. */
237:
238: switch (node->data.elem.tok) {
239: case (MDOC_Os):
240: if (0 == mdoc->meta.os[0])
241: return(1);
242: break;
243: case (MDOC_Dd):
244: if (0 == mdoc->meta.date)
245: return(1);
246: break;
247: case (MDOC_Dt):
248: if (0 == mdoc->meta.title[0])
249: return(1);
250: break;
251: default:
252: abort();
253: /* NOTREACHED */
254: }
255:
256: return(mdoc_verr(mdoc, node, ERR_SEC_PROLOGUE_REP));
257: }
258:
259:
1.21 kristaps 260: /*
261: * Warn if sections (those that are with a known title, such as NAME,
262: * DESCRIPTION, and so forth) are out of the conventional order.
263: */
1.20 kristaps 264: static int
1.21 kristaps 265: post_sh(struct mdoc *mdoc)
1.14 kristaps 266: {
1.21 kristaps 267: enum mdoc_sec sec;
268: int i;
269: struct mdoc_node *n;
270: char *args[MDOC_LINEARG_MAX];
271:
272: if (MDOC_HEAD != mdoc->last->type)
273: return(1);
274:
275: assert(MDOC_Sh == mdoc->last->data.head.tok);
276:
277: n = mdoc->last->child;
278: assert(n);
1.14 kristaps 279:
1.21 kristaps 280: for (i = 0; n && i < MDOC_LINEARG_MAX; n = n->next, i++) {
281: assert(MDOC_TEXT == n->type);
282: assert(NULL == n->child);
283: assert(n->data.text.string);
284: args[i] = n->data.text.string;
285: }
286:
287: sec = mdoc_atosec((size_t)i, (const char **)args);
288: if (SEC_CUSTOM == sec)
289: return(1);
290: if (sec > mdoc->sec_lastn)
291: return(1);
292:
293: if (sec == mdoc->sec_lastn)
294: return(mdoc_warn(mdoc, WARN_SEC_REP));
295: return(mdoc_warn(mdoc, WARN_SEC_OO));
1.11 kristaps 296: }
297:
298:
1.17 kristaps 299: int
1.18 kristaps 300: mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *node)
1.11 kristaps 301: {
1.18 kristaps 302: int t;
303:
304: switch (node->type) {
305: case (MDOC_BODY):
1.20 kristaps 306: t = node->data.body.tok;
1.18 kristaps 307: break;
308: case (MDOC_ELEM):
1.20 kristaps 309: t = node->data.elem.tok;
1.18 kristaps 310: break;
311: case (MDOC_BLOCK):
1.20 kristaps 312: t = node->data.block.tok;
1.18 kristaps 313: break;
314: case (MDOC_HEAD):
1.20 kristaps 315: t = node->data.head.tok;
1.18 kristaps 316: break;
317: default:
318: return(1);
319: }
1.11 kristaps 320:
1.18 kristaps 321: if (NULL == mdoc_valids[t].pre)
1.11 kristaps 322: return(1);
1.18 kristaps 323: return((*mdoc_valids[t].pre)(mdoc, node));
1.11 kristaps 324: }
325:
326:
1.17 kristaps 327: int
1.18 kristaps 328: mdoc_valid_post(struct mdoc *mdoc)
1.11 kristaps 329: {
1.17 kristaps 330: v_post *p;
331: int t;
1.11 kristaps 332:
1.17 kristaps 333: switch (mdoc->last->type) {
334: case (MDOC_BODY):
335: t = mdoc->last->data.body.tok;
336: break;
337: case (MDOC_ELEM):
338: t = mdoc->last->data.elem.tok;
339: break;
340: case (MDOC_BLOCK):
341: t = mdoc->last->data.block.tok;
342: break;
343: case (MDOC_HEAD):
344: t = mdoc->last->data.head.tok;
345: break;
346: default:
1.8 kristaps 347: return(1);
348: }
1.14 kristaps 349:
1.17 kristaps 350: if (NULL == mdoc_valids[t].post)
1.9 kristaps 351: return(1);
1.8 kristaps 352:
1.17 kristaps 353: for (p = mdoc_valids[t].post; *p; p++)
1.18 kristaps 354: if ( ! (*p)(mdoc))
1.17 kristaps 355: return(0);
1.11 kristaps 356:
1.14 kristaps 357: return(1);
1.11 kristaps 358: }
1.14 kristaps 359:
CVSweb