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