Print this page
5051 import mdocml-1.12.3
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Approved by: TBD
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mandoc/mdoc.c
+++ new/usr/src/cmd/mandoc/mdoc.c
1 -/* $Id: mdoc.c,v 1.196 2011/09/30 00:13:28 schwarze Exp $ */
1 +/* $Id: mdoc.c,v 1.206 2013/12/24 19:11:46 schwarze Exp $ */
2 2 /*
3 3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 - * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
4 + * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5 5 *
6 6 * Permission to use, copy, modify, and distribute this software for any
7 7 * purpose with or without fee is hereby granted, provided that the above
8 8 * copyright notice and this permission notice appear in all copies.
9 9 *
10 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 17 */
18 18 #ifdef HAVE_CONFIG_H
19 19 #include "config.h"
20 20 #endif
21 21
22 22 #include <sys/types.h>
23 23
24 24 #include <assert.h>
25 25 #include <stdarg.h>
26 26 #include <stdio.h>
27 27 #include <stdlib.h>
28 28 #include <string.h>
29 29 #include <time.h>
30 30
31 31 #include "mdoc.h"
32 32 #include "mandoc.h"
33 33 #include "libmdoc.h"
34 34 #include "libmandoc.h"
35 35
36 36 const char *const __mdoc_macronames[MDOC_MAX] = {
37 37 "Ap", "Dd", "Dt", "Os",
38 38 "Sh", "Ss", "Pp", "D1",
39 39 "Dl", "Bd", "Ed", "Bl",
40 40 "El", "It", "Ad", "An",
41 41 "Ar", "Cd", "Cm", "Dv",
42 42 "Er", "Ev", "Ex", "Fa",
43 43 "Fd", "Fl", "Fn", "Ft",
44 44 "Ic", "In", "Li", "Nd",
45 45 "Nm", "Op", "Ot", "Pa",
46 46 "Rv", "St", "Va", "Vt",
47 47 /* LINTED */
48 48 "Xr", "%A", "%B", "%D",
49 49 /* LINTED */
50 50 "%I", "%J", "%N", "%O",
51 51 /* LINTED */
52 52 "%P", "%R", "%T", "%V",
53 53 "Ac", "Ao", "Aq", "At",
54 54 "Bc", "Bf", "Bo", "Bq",
55 55 "Bsx", "Bx", "Db", "Dc",
56 56 "Do", "Dq", "Ec", "Ef",
57 57 "Em", "Eo", "Fx", "Ms",
58 58 "No", "Ns", "Nx", "Ox",
59 59 "Pc", "Pf", "Po", "Pq",
60 60 "Qc", "Ql", "Qo", "Qq",
61 61 "Re", "Rs", "Sc", "So",
62 62 "Sq", "Sm", "Sx", "Sy",
63 63 "Tn", "Ux", "Xc", "Xo",
64 64 "Fo", "Fc", "Oo", "Oc",
65 65 "Bk", "Ek", "Bt", "Hf",
66 66 "Fr", "Ud", "Lb", "Lp",
67 67 "Lk", "Mt", "Brq", "Bro",
68 68 /* LINTED */
69 69 "Brc", "%C", "Es", "En",
70 70 /* LINTED */
71 71 "Dx", "%Q", "br", "sp",
72 72 /* LINTED */
73 73 "%U", "Ta"
74 74 };
75 75
76 76 const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
77 77 "split", "nosplit", "ragged",
78 78 "unfilled", "literal", "file",
79 79 "offset", "bullet", "dash",
80 80 "hyphen", "item", "enum",
81 81 "tag", "diag", "hang",
82 82 "ohang", "inset", "column",
83 83 "width", "compact", "std",
84 84 "filled", "words", "emphasis",
85 85 "symbolic", "nested", "centered"
86 86 };
87 87
88 88 const char * const *mdoc_macronames = __mdoc_macronames;
89 89 const char * const *mdoc_argnames = __mdoc_argnames;
90 90
91 91 static void mdoc_node_free(struct mdoc_node *);
92 92 static void mdoc_node_unlink(struct mdoc *,
93 93 struct mdoc_node *);
94 94 static void mdoc_free1(struct mdoc *);
95 95 static void mdoc_alloc1(struct mdoc *);
96 96 static struct mdoc_node *node_alloc(struct mdoc *, int, int,
↓ open down ↓ |
82 lines elided |
↑ open up ↑ |
97 97 enum mdoct, enum mdoc_type);
98 98 static int node_append(struct mdoc *,
99 99 struct mdoc_node *);
100 100 #if 0
101 101 static int mdoc_preptext(struct mdoc *, int, char *, int);
102 102 #endif
103 103 static int mdoc_ptext(struct mdoc *, int, char *, int);
104 104 static int mdoc_pmacro(struct mdoc *, int, char *, int);
105 105
106 106 const struct mdoc_node *
107 -mdoc_node(const struct mdoc *m)
107 +mdoc_node(const struct mdoc *mdoc)
108 108 {
109 109
110 - assert( ! (MDOC_HALT & m->flags));
111 - return(m->first);
110 + assert( ! (MDOC_HALT & mdoc->flags));
111 + return(mdoc->first);
112 112 }
113 113
114 114
115 115 const struct mdoc_meta *
116 -mdoc_meta(const struct mdoc *m)
116 +mdoc_meta(const struct mdoc *mdoc)
117 117 {
118 118
119 - assert( ! (MDOC_HALT & m->flags));
120 - return(&m->meta);
119 + assert( ! (MDOC_HALT & mdoc->flags));
120 + return(&mdoc->meta);
121 121 }
122 122
123 123
124 124 /*
125 125 * Frees volatile resources (parse tree, meta-data, fields).
126 126 */
127 127 static void
128 128 mdoc_free1(struct mdoc *mdoc)
129 129 {
130 130
131 131 if (mdoc->first)
132 132 mdoc_node_delete(mdoc, mdoc->first);
133 133 if (mdoc->meta.title)
134 134 free(mdoc->meta.title);
135 135 if (mdoc->meta.os)
136 136 free(mdoc->meta.os);
137 137 if (mdoc->meta.name)
138 138 free(mdoc->meta.name);
139 139 if (mdoc->meta.arch)
140 140 free(mdoc->meta.arch);
141 141 if (mdoc->meta.vol)
142 142 free(mdoc->meta.vol);
143 143 if (mdoc->meta.msec)
144 144 free(mdoc->meta.msec);
145 145 if (mdoc->meta.date)
146 146 free(mdoc->meta.date);
147 147 }
148 148
149 149
150 150 /*
151 151 * Allocate all volatile resources (parse tree, meta-data, fields).
152 152 */
153 153 static void
154 154 mdoc_alloc1(struct mdoc *mdoc)
155 155 {
156 156
157 157 memset(&mdoc->meta, 0, sizeof(struct mdoc_meta));
158 158 mdoc->flags = 0;
159 159 mdoc->lastnamed = mdoc->lastsec = SEC_NONE;
160 160 mdoc->last = mandoc_calloc(1, sizeof(struct mdoc_node));
161 161 mdoc->first = mdoc->last;
162 162 mdoc->last->type = MDOC_ROOT;
163 163 mdoc->last->tok = MDOC_MAX;
164 164 mdoc->next = MDOC_NEXT_CHILD;
165 165 }
166 166
167 167
168 168 /*
169 169 * Free up volatile resources (see mdoc_free1()) then re-initialises the
170 170 * data with mdoc_alloc1(). After invocation, parse data has been reset
171 171 * and the parser is ready for re-invocation on a new tree; however,
172 172 * cross-parse non-volatile data is kept intact.
173 173 */
174 174 void
175 175 mdoc_reset(struct mdoc *mdoc)
176 176 {
177 177
178 178 mdoc_free1(mdoc);
179 179 mdoc_alloc1(mdoc);
180 180 }
181 181
182 182
183 183 /*
184 184 * Completely free up all volatile and non-volatile parse resources.
185 185 * After invocation, the pointer is no longer usable.
186 186 */
187 187 void
188 188 mdoc_free(struct mdoc *mdoc)
189 189 {
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
190 190
191 191 mdoc_free1(mdoc);
192 192 free(mdoc);
193 193 }
194 194
195 195
196 196 /*
197 197 * Allocate volatile and non-volatile parse resources.
198 198 */
199 199 struct mdoc *
200 -mdoc_alloc(struct roff *roff, struct mparse *parse)
200 +mdoc_alloc(struct roff *roff, struct mparse *parse, char *defos)
201 201 {
202 202 struct mdoc *p;
203 203
204 204 p = mandoc_calloc(1, sizeof(struct mdoc));
205 205
206 206 p->parse = parse;
207 + p->defos = defos;
207 208 p->roff = roff;
208 209
209 210 mdoc_hash_init();
210 211 mdoc_alloc1(p);
211 212 return(p);
212 213 }
213 214
214 215
215 216 /*
216 217 * Climb back up the parse tree, validating open scopes. Mostly calls
217 218 * through to macro_end() in macro.c.
218 219 */
219 220 int
220 -mdoc_endparse(struct mdoc *m)
221 +mdoc_endparse(struct mdoc *mdoc)
221 222 {
222 223
223 - assert( ! (MDOC_HALT & m->flags));
224 - if (mdoc_macroend(m))
224 + assert( ! (MDOC_HALT & mdoc->flags));
225 + if (mdoc_macroend(mdoc))
225 226 return(1);
226 - m->flags |= MDOC_HALT;
227 + mdoc->flags |= MDOC_HALT;
227 228 return(0);
228 229 }
229 230
230 231 int
231 -mdoc_addeqn(struct mdoc *m, const struct eqn *ep)
232 +mdoc_addeqn(struct mdoc *mdoc, const struct eqn *ep)
232 233 {
233 234 struct mdoc_node *n;
234 235
235 - assert( ! (MDOC_HALT & m->flags));
236 + assert( ! (MDOC_HALT & mdoc->flags));
236 237
237 238 /* No text before an initial macro. */
238 239
239 - if (SEC_NONE == m->lastnamed) {
240 - mdoc_pmsg(m, ep->ln, ep->pos, MANDOCERR_NOTEXT);
240 + if (SEC_NONE == mdoc->lastnamed) {
241 + mdoc_pmsg(mdoc, ep->ln, ep->pos, MANDOCERR_NOTEXT);
241 242 return(1);
242 243 }
243 244
244 - n = node_alloc(m, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
245 + n = node_alloc(mdoc, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
245 246 n->eqn = ep;
246 247
247 - if ( ! node_append(m, n))
248 + if ( ! node_append(mdoc, n))
248 249 return(0);
249 250
250 - m->next = MDOC_NEXT_SIBLING;
251 + mdoc->next = MDOC_NEXT_SIBLING;
251 252 return(1);
252 253 }
253 254
254 255 int
255 -mdoc_addspan(struct mdoc *m, const struct tbl_span *sp)
256 +mdoc_addspan(struct mdoc *mdoc, const struct tbl_span *sp)
256 257 {
257 258 struct mdoc_node *n;
258 259
259 - assert( ! (MDOC_HALT & m->flags));
260 + assert( ! (MDOC_HALT & mdoc->flags));
260 261
261 262 /* No text before an initial macro. */
262 263
263 - if (SEC_NONE == m->lastnamed) {
264 - mdoc_pmsg(m, sp->line, 0, MANDOCERR_NOTEXT);
264 + if (SEC_NONE == mdoc->lastnamed) {
265 + mdoc_pmsg(mdoc, sp->line, 0, MANDOCERR_NOTEXT);
265 266 return(1);
266 267 }
267 268
268 - n = node_alloc(m, sp->line, 0, MDOC_MAX, MDOC_TBL);
269 + n = node_alloc(mdoc, sp->line, 0, MDOC_MAX, MDOC_TBL);
269 270 n->span = sp;
270 271
271 - if ( ! node_append(m, n))
272 + if ( ! node_append(mdoc, n))
272 273 return(0);
273 274
274 - m->next = MDOC_NEXT_SIBLING;
275 + mdoc->next = MDOC_NEXT_SIBLING;
275 276 return(1);
276 277 }
277 278
278 279
279 280 /*
280 281 * Main parse routine. Parses a single line -- really just hands off to
281 282 * the macro (mdoc_pmacro()) or text parser (mdoc_ptext()).
282 283 */
283 284 int
284 -mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
285 +mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
285 286 {
286 287
287 - assert( ! (MDOC_HALT & m->flags));
288 + assert( ! (MDOC_HALT & mdoc->flags));
288 289
289 - m->flags |= MDOC_NEWLINE;
290 + mdoc->flags |= MDOC_NEWLINE;
290 291
291 292 /*
292 293 * Let the roff nS register switch SYNOPSIS mode early,
293 294 * such that the parser knows at all times
294 295 * whether this mode is on or off.
295 296 * Note that this mode is also switched by the Sh macro.
296 297 */
297 - if (roff_regisset(m->roff, REG_nS)) {
298 - if (roff_regget(m->roff, REG_nS))
299 - m->flags |= MDOC_SYNOPSIS;
300 - else
301 - m->flags &= ~MDOC_SYNOPSIS;
302 - }
298 + if (roff_getreg(mdoc->roff, "nS"))
299 + mdoc->flags |= MDOC_SYNOPSIS;
300 + else
301 + mdoc->flags &= ~MDOC_SYNOPSIS;
303 302
304 - return(mandoc_getcontrol(buf, &offs) ?
305 - mdoc_pmacro(m, ln, buf, offs) :
306 - mdoc_ptext(m, ln, buf, offs));
303 + return(roff_getcontrol(mdoc->roff, buf, &offs) ?
304 + mdoc_pmacro(mdoc, ln, buf, offs) :
305 + mdoc_ptext(mdoc, ln, buf, offs));
307 306 }
308 307
309 308 int
310 309 mdoc_macro(MACRO_PROT_ARGS)
311 310 {
312 311 assert(tok < MDOC_MAX);
313 312
314 313 /* If we're in the body, deny prologue calls. */
315 314
316 315 if (MDOC_PROLOGUE & mdoc_macros[tok].flags &&
317 - MDOC_PBODY & m->flags) {
318 - mdoc_pmsg(m, line, ppos, MANDOCERR_BADBODY);
316 + MDOC_PBODY & mdoc->flags) {
317 + mdoc_pmsg(mdoc, line, ppos, MANDOCERR_BADBODY);
319 318 return(1);
320 319 }
321 320
322 321 /* If we're in the prologue, deny "body" macros. */
323 322
324 323 if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) &&
325 - ! (MDOC_PBODY & m->flags)) {
326 - mdoc_pmsg(m, line, ppos, MANDOCERR_BADPROLOG);
327 - if (NULL == m->meta.msec)
328 - m->meta.msec = mandoc_strdup("1");
329 - if (NULL == m->meta.title)
330 - m->meta.title = mandoc_strdup("UNKNOWN");
331 - if (NULL == m->meta.vol)
332 - m->meta.vol = mandoc_strdup("LOCAL");
333 - if (NULL == m->meta.os)
334 - m->meta.os = mandoc_strdup("LOCAL");
335 - if (NULL == m->meta.date)
336 - m->meta.date = mandoc_normdate
337 - (m->parse, NULL, line, ppos);
338 - m->flags |= MDOC_PBODY;
324 + ! (MDOC_PBODY & mdoc->flags)) {
325 + mdoc_pmsg(mdoc, line, ppos, MANDOCERR_BADPROLOG);
326 + if (NULL == mdoc->meta.msec)
327 + mdoc->meta.msec = mandoc_strdup("1");
328 + if (NULL == mdoc->meta.title)
329 + mdoc->meta.title = mandoc_strdup("UNKNOWN");
330 + if (NULL == mdoc->meta.vol)
331 + mdoc->meta.vol = mandoc_strdup("LOCAL");
332 + if (NULL == mdoc->meta.os)
333 + mdoc->meta.os = mandoc_strdup("LOCAL");
334 + if (NULL == mdoc->meta.date)
335 + mdoc->meta.date = mandoc_normdate
336 + (mdoc->parse, NULL, line, ppos);
337 + mdoc->flags |= MDOC_PBODY;
339 338 }
340 339
341 - return((*mdoc_macros[tok].fp)(m, tok, line, ppos, pos, buf));
340 + return((*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf));
342 341 }
343 342
344 343
345 344 static int
346 345 node_append(struct mdoc *mdoc, struct mdoc_node *p)
347 346 {
348 347
349 348 assert(mdoc->last);
350 349 assert(mdoc->first);
351 350 assert(MDOC_ROOT != p->type);
352 351
353 352 switch (mdoc->next) {
354 353 case (MDOC_NEXT_SIBLING):
355 354 mdoc->last->next = p;
356 355 p->prev = mdoc->last;
357 356 p->parent = mdoc->last->parent;
358 357 break;
359 358 case (MDOC_NEXT_CHILD):
360 359 mdoc->last->child = p;
361 360 p->parent = mdoc->last;
362 361 break;
363 362 default:
364 363 abort();
365 364 /* NOTREACHED */
366 365 }
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
367 366
368 367 p->parent->nchild++;
369 368
370 369 /*
371 370 * Copy over the normalised-data pointer of our parent. Not
372 371 * everybody has one, but copying a null pointer is fine.
373 372 */
374 373
375 374 switch (p->type) {
376 375 case (MDOC_BODY):
376 + if (ENDBODY_NOT != p->end)
377 + break;
377 378 /* FALLTHROUGH */
378 379 case (MDOC_TAIL):
379 380 /* FALLTHROUGH */
380 381 case (MDOC_HEAD):
381 382 p->norm = p->parent->norm;
382 383 break;
383 384 default:
384 385 break;
385 386 }
386 387
387 388 if ( ! mdoc_valid_pre(mdoc, p))
388 389 return(0);
389 390
390 391 switch (p->type) {
391 392 case (MDOC_HEAD):
392 393 assert(MDOC_BLOCK == p->parent->type);
393 394 p->parent->head = p;
394 395 break;
395 396 case (MDOC_TAIL):
396 397 assert(MDOC_BLOCK == p->parent->type);
397 398 p->parent->tail = p;
398 399 break;
399 400 case (MDOC_BODY):
400 401 if (p->end)
401 402 break;
402 403 assert(MDOC_BLOCK == p->parent->type);
403 404 p->parent->body = p;
404 405 break;
405 406 default:
406 407 break;
407 408 }
408 409
409 410 mdoc->last = p;
410 411
411 412 switch (p->type) {
412 413 case (MDOC_TBL):
413 414 /* FALLTHROUGH */
414 415 case (MDOC_TEXT):
415 416 if ( ! mdoc_valid_post(mdoc))
416 417 return(0);
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
417 418 break;
418 419 default:
419 420 break;
420 421 }
421 422
422 423 return(1);
423 424 }
424 425
425 426
426 427 static struct mdoc_node *
427 -node_alloc(struct mdoc *m, int line, int pos,
428 +node_alloc(struct mdoc *mdoc, int line, int pos,
428 429 enum mdoct tok, enum mdoc_type type)
429 430 {
430 431 struct mdoc_node *p;
431 432
432 433 p = mandoc_calloc(1, sizeof(struct mdoc_node));
433 - p->sec = m->lastsec;
434 + p->sec = mdoc->lastsec;
434 435 p->line = line;
435 436 p->pos = pos;
437 + p->lastline = line;
436 438 p->tok = tok;
437 439 p->type = type;
438 440
439 441 /* Flag analysis. */
440 442
441 - if (MDOC_SYNOPSIS & m->flags)
443 + if (MDOC_SYNOPSIS & mdoc->flags)
442 444 p->flags |= MDOC_SYNPRETTY;
443 445 else
444 446 p->flags &= ~MDOC_SYNPRETTY;
445 - if (MDOC_NEWLINE & m->flags)
447 + if (MDOC_NEWLINE & mdoc->flags)
446 448 p->flags |= MDOC_LINE;
447 - m->flags &= ~MDOC_NEWLINE;
449 + mdoc->flags &= ~MDOC_NEWLINE;
448 450
449 451 return(p);
450 452 }
451 453
452 454
453 455 int
454 -mdoc_tail_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
456 +mdoc_tail_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
455 457 {
456 458 struct mdoc_node *p;
457 459
458 - p = node_alloc(m, line, pos, tok, MDOC_TAIL);
459 - if ( ! node_append(m, p))
460 + p = node_alloc(mdoc, line, pos, tok, MDOC_TAIL);
461 + if ( ! node_append(mdoc, p))
460 462 return(0);
461 - m->next = MDOC_NEXT_CHILD;
463 + mdoc->next = MDOC_NEXT_CHILD;
462 464 return(1);
463 465 }
464 466
465 467
466 468 int
467 -mdoc_head_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
469 +mdoc_head_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
468 470 {
469 471 struct mdoc_node *p;
470 472
471 - assert(m->first);
472 - assert(m->last);
473 + assert(mdoc->first);
474 + assert(mdoc->last);
473 475
474 - p = node_alloc(m, line, pos, tok, MDOC_HEAD);
475 - if ( ! node_append(m, p))
476 + p = node_alloc(mdoc, line, pos, tok, MDOC_HEAD);
477 + if ( ! node_append(mdoc, p))
476 478 return(0);
477 - m->next = MDOC_NEXT_CHILD;
479 + mdoc->next = MDOC_NEXT_CHILD;
478 480 return(1);
479 481 }
480 482
481 483
482 484 int
483 -mdoc_body_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
485 +mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
484 486 {
485 487 struct mdoc_node *p;
486 488
487 - p = node_alloc(m, line, pos, tok, MDOC_BODY);
488 - if ( ! node_append(m, p))
489 + p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
490 + if ( ! node_append(mdoc, p))
489 491 return(0);
490 - m->next = MDOC_NEXT_CHILD;
492 + mdoc->next = MDOC_NEXT_CHILD;
491 493 return(1);
492 494 }
493 495
494 496
495 497 int
496 -mdoc_endbody_alloc(struct mdoc *m, int line, int pos, enum mdoct tok,
498 +mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
497 499 struct mdoc_node *body, enum mdoc_endbody end)
498 500 {
499 501 struct mdoc_node *p;
500 502
501 - p = node_alloc(m, line, pos, tok, MDOC_BODY);
503 + p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
502 504 p->pending = body;
505 + p->norm = body->norm;
503 506 p->end = end;
504 - if ( ! node_append(m, p))
507 + if ( ! node_append(mdoc, p))
505 508 return(0);
506 - m->next = MDOC_NEXT_SIBLING;
509 + mdoc->next = MDOC_NEXT_SIBLING;
507 510 return(1);
508 511 }
509 512
510 513
511 514 int
512 -mdoc_block_alloc(struct mdoc *m, int line, int pos,
515 +mdoc_block_alloc(struct mdoc *mdoc, int line, int pos,
513 516 enum mdoct tok, struct mdoc_arg *args)
514 517 {
515 518 struct mdoc_node *p;
516 519
517 - p = node_alloc(m, line, pos, tok, MDOC_BLOCK);
520 + p = node_alloc(mdoc, line, pos, tok, MDOC_BLOCK);
518 521 p->args = args;
519 522 if (p->args)
520 523 (args->refcnt)++;
521 524
522 525 switch (tok) {
523 526 case (MDOC_Bd):
524 527 /* FALLTHROUGH */
525 528 case (MDOC_Bf):
526 529 /* FALLTHROUGH */
527 530 case (MDOC_Bl):
528 531 /* FALLTHROUGH */
529 532 case (MDOC_Rs):
530 533 p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
531 534 break;
532 535 default:
533 536 break;
534 537 }
535 538
536 - if ( ! node_append(m, p))
539 + if ( ! node_append(mdoc, p))
537 540 return(0);
538 - m->next = MDOC_NEXT_CHILD;
541 + mdoc->next = MDOC_NEXT_CHILD;
539 542 return(1);
540 543 }
541 544
542 545
543 546 int
544 -mdoc_elem_alloc(struct mdoc *m, int line, int pos,
547 +mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos,
545 548 enum mdoct tok, struct mdoc_arg *args)
546 549 {
547 550 struct mdoc_node *p;
548 551
549 - p = node_alloc(m, line, pos, tok, MDOC_ELEM);
552 + p = node_alloc(mdoc, line, pos, tok, MDOC_ELEM);
550 553 p->args = args;
551 554 if (p->args)
552 555 (args->refcnt)++;
553 556
554 557 switch (tok) {
555 558 case (MDOC_An):
556 559 p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
557 560 break;
558 561 default:
559 562 break;
560 563 }
561 564
562 - if ( ! node_append(m, p))
565 + if ( ! node_append(mdoc, p))
563 566 return(0);
564 - m->next = MDOC_NEXT_CHILD;
567 + mdoc->next = MDOC_NEXT_CHILD;
565 568 return(1);
566 569 }
567 570
568 571 int
569 -mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
572 +mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p)
570 573 {
571 574 struct mdoc_node *n;
572 575
573 - n = node_alloc(m, line, pos, MDOC_MAX, MDOC_TEXT);
574 - n->string = roff_strdup(m->roff, p);
576 + n = node_alloc(mdoc, line, pos, MDOC_MAX, MDOC_TEXT);
577 + n->string = roff_strdup(mdoc->roff, p);
575 578
576 - if ( ! node_append(m, n))
579 + if ( ! node_append(mdoc, n))
577 580 return(0);
578 581
579 - m->next = MDOC_NEXT_SIBLING;
582 + mdoc->next = MDOC_NEXT_SIBLING;
580 583 return(1);
581 584 }
582 585
586 +void
587 +mdoc_word_append(struct mdoc *mdoc, const char *p)
588 +{
589 + struct mdoc_node *n;
590 + char *addstr, *newstr;
583 591
592 + n = mdoc->last;
593 + addstr = roff_strdup(mdoc->roff, p);
594 + if (-1 == asprintf(&newstr, "%s %s", n->string, addstr)) {
595 + perror(NULL);
596 + exit((int)MANDOCLEVEL_SYSERR);
597 + }
598 + free(addstr);
599 + free(n->string);
600 + n->string = newstr;
601 + mdoc->next = MDOC_NEXT_SIBLING;
602 +}
603 +
584 604 static void
585 605 mdoc_node_free(struct mdoc_node *p)
586 606 {
587 607
588 608 if (MDOC_BLOCK == p->type || MDOC_ELEM == p->type)
589 609 free(p->norm);
590 610 if (p->string)
591 611 free(p->string);
592 612 if (p->args)
593 613 mdoc_argv_free(p->args);
594 614 free(p);
595 615 }
596 616
597 617
598 618 static void
599 -mdoc_node_unlink(struct mdoc *m, struct mdoc_node *n)
619 +mdoc_node_unlink(struct mdoc *mdoc, struct mdoc_node *n)
600 620 {
601 621
602 622 /* Adjust siblings. */
603 623
604 624 if (n->prev)
605 625 n->prev->next = n->next;
606 626 if (n->next)
607 627 n->next->prev = n->prev;
608 628
609 629 /* Adjust parent. */
610 630
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
611 631 if (n->parent) {
612 632 n->parent->nchild--;
613 633 if (n->parent->child == n)
614 634 n->parent->child = n->prev ? n->prev : n->next;
615 635 if (n->parent->last == n)
616 636 n->parent->last = n->prev ? n->prev : NULL;
617 637 }
618 638
619 639 /* Adjust parse point, if applicable. */
620 640
621 - if (m && m->last == n) {
641 + if (mdoc && mdoc->last == n) {
622 642 if (n->prev) {
623 - m->last = n->prev;
624 - m->next = MDOC_NEXT_SIBLING;
643 + mdoc->last = n->prev;
644 + mdoc->next = MDOC_NEXT_SIBLING;
625 645 } else {
626 - m->last = n->parent;
627 - m->next = MDOC_NEXT_CHILD;
646 + mdoc->last = n->parent;
647 + mdoc->next = MDOC_NEXT_CHILD;
628 648 }
629 649 }
630 650
631 - if (m && m->first == n)
632 - m->first = NULL;
651 + if (mdoc && mdoc->first == n)
652 + mdoc->first = NULL;
633 653 }
634 654
635 655
636 656 void
637 -mdoc_node_delete(struct mdoc *m, struct mdoc_node *p)
657 +mdoc_node_delete(struct mdoc *mdoc, struct mdoc_node *p)
638 658 {
639 659
640 660 while (p->child) {
641 661 assert(p->nchild);
642 - mdoc_node_delete(m, p->child);
662 + mdoc_node_delete(mdoc, p->child);
643 663 }
644 664 assert(0 == p->nchild);
645 665
646 - mdoc_node_unlink(m, p);
666 + mdoc_node_unlink(mdoc, p);
647 667 mdoc_node_free(p);
648 668 }
649 669
670 +int
671 +mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p)
672 +{
673 +
674 + mdoc_node_unlink(mdoc, p);
675 + return(node_append(mdoc, p));
676 +}
677 +
650 678 #if 0
651 679 /*
652 680 * Pre-treat a text line.
653 681 * Text lines can consist of equations, which must be handled apart from
654 682 * the regular text.
655 683 * Thus, use this function to step through a line checking if it has any
656 684 * equations embedded in it.
657 685 * This must handle multiple equations AND equations that do not end at
658 686 * the end-of-line, i.e., will re-enter in the next roff parse.
659 687 */
660 688 static int
661 -mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
689 +mdoc_preptext(struct mdoc *mdoc, int line, char *buf, int offs)
662 690 {
663 691 char *start, *end;
664 692 char delim;
665 693
666 694 while ('\0' != buf[offs]) {
667 695 /* Mark starting position if eqn is set. */
668 696 start = NULL;
669 - if ('\0' != (delim = roff_eqndelim(m->roff)))
697 + if ('\0' != (delim = roff_eqndelim(mdoc->roff)))
670 698 if (NULL != (start = strchr(buf + offs, delim)))
671 699 *start++ = '\0';
672 700
673 701 /* Parse text as normal. */
674 - if ( ! mdoc_ptext(m, line, buf, offs))
702 + if ( ! mdoc_ptext(mdoc, line, buf, offs))
675 703 return(0);
676 704
677 705 /* Continue only if an equation exists. */
678 706 if (NULL == start)
679 707 break;
680 708
681 709 /* Read past the end of the equation. */
682 710 offs += start - (buf + offs);
683 711 assert(start == &buf[offs]);
684 712 if (NULL != (end = strchr(buf + offs, delim))) {
685 713 *end++ = '\0';
686 714 while (' ' == *end)
687 715 end++;
688 716 }
689 717
690 718 /* Parse the equation itself. */
691 - roff_openeqn(m->roff, NULL, line, offs, buf);
719 + roff_openeqn(mdoc->roff, NULL, line, offs, buf);
692 720
693 721 /* Process a finished equation? */
694 - if (roff_closeeqn(m->roff))
695 - if ( ! mdoc_addeqn(m, roff_eqn(m->roff)))
722 + if (roff_closeeqn(mdoc->roff))
723 + if ( ! mdoc_addeqn(mdoc, roff_eqn(mdoc->roff)))
696 724 return(0);
697 725 offs += (end - (buf + offs));
698 726 }
699 727
700 728 return(1);
701 729 }
702 730 #endif
703 731
704 732 /*
705 733 * Parse free-form text, that is, a line that does not begin with the
706 734 * control character.
707 735 */
708 736 static int
709 -mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
737 +mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
710 738 {
711 739 char *c, *ws, *end;
712 740 struct mdoc_node *n;
713 741
714 742 /* No text before an initial macro. */
715 743
716 - if (SEC_NONE == m->lastnamed) {
717 - mdoc_pmsg(m, line, offs, MANDOCERR_NOTEXT);
744 + if (SEC_NONE == mdoc->lastnamed) {
745 + mdoc_pmsg(mdoc, line, offs, MANDOCERR_NOTEXT);
718 746 return(1);
719 747 }
720 748
721 - assert(m->last);
722 - n = m->last;
749 + assert(mdoc->last);
750 + n = mdoc->last;
723 751
724 752 /*
725 753 * Divert directly to list processing if we're encountering a
726 754 * columnar MDOC_BLOCK with or without a prior MDOC_BLOCK entry
727 755 * (a MDOC_BODY means it's already open, in which case we should
728 756 * process within its context in the normal way).
729 757 */
730 758
731 759 if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
732 760 LIST_column == n->norm->Bl.type) {
733 761 /* `Bl' is open without any children. */
734 - m->flags |= MDOC_FREECOL;
735 - return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
762 + mdoc->flags |= MDOC_FREECOL;
763 + return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
736 764 }
737 765
738 766 if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
739 767 NULL != n->parent &&
740 768 MDOC_Bl == n->parent->tok &&
741 769 LIST_column == n->parent->norm->Bl.type) {
742 770 /* `Bl' has block-level `It' children. */
743 - m->flags |= MDOC_FREECOL;
744 - return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
771 + mdoc->flags |= MDOC_FREECOL;
772 + return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
745 773 }
746 774
747 775 /*
748 776 * Search for the beginning of unescaped trailing whitespace (ws)
749 777 * and for the first character not to be output (end).
750 778 */
751 779
752 780 /* FIXME: replace with strcspn(). */
753 781 ws = NULL;
754 782 for (c = end = buf + offs; *c; c++) {
755 783 switch (*c) {
756 784 case ' ':
757 785 if (NULL == ws)
758 786 ws = c;
759 787 continue;
760 788 case '\t':
761 789 /*
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
762 790 * Always warn about trailing tabs,
763 791 * even outside literal context,
764 792 * where they should be put on the next line.
765 793 */
766 794 if (NULL == ws)
767 795 ws = c;
768 796 /*
769 797 * Strip trailing tabs in literal context only;
770 798 * outside, they affect the next line.
771 799 */
772 - if (MDOC_LITERAL & m->flags)
800 + if (MDOC_LITERAL & mdoc->flags)
773 801 continue;
774 802 break;
775 803 case '\\':
776 804 /* Skip the escaped character, too, if any. */
777 805 if (c[1])
778 806 c++;
779 807 /* FALLTHROUGH */
780 808 default:
781 809 ws = NULL;
782 810 break;
783 811 }
784 812 end = c + 1;
785 813 }
786 814 *end = '\0';
787 815
788 816 if (ws)
789 - mdoc_pmsg(m, line, (int)(ws-buf), MANDOCERR_EOLNSPACE);
817 + mdoc_pmsg(mdoc, line, (int)(ws-buf), MANDOCERR_EOLNSPACE);
790 818
791 - if ('\0' == buf[offs] && ! (MDOC_LITERAL & m->flags)) {
792 - mdoc_pmsg(m, line, (int)(c-buf), MANDOCERR_NOBLANKLN);
819 + if ('\0' == buf[offs] && ! (MDOC_LITERAL & mdoc->flags)) {
820 + mdoc_pmsg(mdoc, line, (int)(c-buf), MANDOCERR_NOBLANKLN);
793 821
794 822 /*
795 823 * Insert a `sp' in the case of a blank line. Technically,
796 824 * blank lines aren't allowed, but enough manuals assume this
797 825 * behaviour that we want to work around it.
798 826 */
799 - if ( ! mdoc_elem_alloc(m, line, offs, MDOC_sp, NULL))
827 + if ( ! mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL))
800 828 return(0);
801 829
802 - m->next = MDOC_NEXT_SIBLING;
803 - return(1);
830 + mdoc->next = MDOC_NEXT_SIBLING;
831 +
832 + return(mdoc_valid_post(mdoc));
804 833 }
805 834
806 - if ( ! mdoc_word_alloc(m, line, offs, buf+offs))
835 + if ( ! mdoc_word_alloc(mdoc, line, offs, buf+offs))
807 836 return(0);
808 837
809 - if (MDOC_LITERAL & m->flags)
838 + if (MDOC_LITERAL & mdoc->flags)
810 839 return(1);
811 840
812 841 /*
813 842 * End-of-sentence check. If the last character is an unescaped
814 843 * EOS character, then flag the node as being the end of a
815 844 * sentence. The front-end will know how to interpret this.
816 845 */
817 846
818 847 assert(buf < end);
819 848
820 849 if (mandoc_eos(buf+offs, (size_t)(end-buf-offs), 0))
821 - m->last->flags |= MDOC_EOS;
850 + mdoc->last->flags |= MDOC_EOS;
822 851
823 852 return(1);
824 853 }
825 854
826 855
827 856 /*
828 857 * Parse a macro line, that is, a line beginning with the control
829 858 * character.
830 859 */
831 860 static int
832 -mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
861 +mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
833 862 {
834 863 enum mdoct tok;
835 864 int i, sv;
836 865 char mac[5];
837 866 struct mdoc_node *n;
838 867
839 868 /* Empty post-control lines are ignored. */
840 869
841 870 if ('"' == buf[offs]) {
842 - mdoc_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
871 + mdoc_pmsg(mdoc, ln, offs, MANDOCERR_BADCOMMENT);
843 872 return(1);
844 873 } else if ('\0' == buf[offs])
845 874 return(1);
846 875
847 876 sv = offs;
848 877
849 878 /*
850 879 * Copy the first word into a nil-terminated buffer.
851 880 * Stop copying when a tab, space, or eoln is encountered.
852 881 */
853 882
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
854 883 i = 0;
855 884 while (i < 4 && '\0' != buf[offs] &&
856 885 ' ' != buf[offs] && '\t' != buf[offs])
857 886 mac[i++] = buf[offs++];
858 887
859 888 mac[i] = '\0';
860 889
861 890 tok = (i > 1 || i < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
862 891
863 892 if (MDOC_MAX == tok) {
864 - mandoc_vmsg(MANDOCERR_MACRO, m->parse,
893 + mandoc_vmsg(MANDOCERR_MACRO, mdoc->parse,
865 894 ln, sv, "%s", buf + sv - 1);
866 895 return(1);
867 896 }
868 897
869 898 /* Disregard the first trailing tab, if applicable. */
870 899
871 900 if ('\t' == buf[offs])
872 901 offs++;
873 902
874 903 /* Jump to the next non-whitespace word. */
875 904
876 905 while (buf[offs] && ' ' == buf[offs])
877 906 offs++;
878 907
879 908 /*
880 909 * Trailing whitespace. Note that tabs are allowed to be passed
881 910 * into the parser as "text", so we only warn about spaces here.
882 911 */
883 912
884 913 if ('\0' == buf[offs] && ' ' == buf[offs - 1])
885 - mdoc_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
914 + mdoc_pmsg(mdoc, ln, offs - 1, MANDOCERR_EOLNSPACE);
886 915
887 916 /*
888 917 * If an initial macro or a list invocation, divert directly
889 918 * into macro processing.
890 919 */
891 920
892 - if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
893 - if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
921 + if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
922 + if ( ! mdoc_macro(mdoc, tok, ln, sv, &offs, buf))
894 923 goto err;
895 924 return(1);
896 925 }
897 926
898 - n = m->last;
899 - assert(m->last);
927 + n = mdoc->last;
928 + assert(mdoc->last);
900 929
901 930 /*
902 931 * If the first macro of a `Bl -column', open an `It' block
903 932 * context around the parsed macro.
904 933 */
905 934
906 935 if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
907 936 LIST_column == n->norm->Bl.type) {
908 - m->flags |= MDOC_FREECOL;
909 - if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
937 + mdoc->flags |= MDOC_FREECOL;
938 + if ( ! mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf))
910 939 goto err;
911 940 return(1);
912 941 }
913 942
914 943 /*
915 944 * If we're following a block-level `It' within a `Bl -column'
916 945 * context (perhaps opened in the above block or in ptext()),
917 946 * then open an `It' block context around the parsed macro.
918 947 */
919 948
920 949 if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
921 950 NULL != n->parent &&
922 951 MDOC_Bl == n->parent->tok &&
923 952 LIST_column == n->parent->norm->Bl.type) {
924 - m->flags |= MDOC_FREECOL;
925 - if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
953 + mdoc->flags |= MDOC_FREECOL;
954 + if ( ! mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf))
926 955 goto err;
927 956 return(1);
928 957 }
929 958
930 959 /* Normal processing of a macro. */
931 960
932 - if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
961 + if ( ! mdoc_macro(mdoc, tok, ln, sv, &offs, buf))
933 962 goto err;
934 963
935 964 return(1);
936 965
937 966 err: /* Error out. */
938 967
939 - m->flags |= MDOC_HALT;
968 + mdoc->flags |= MDOC_HALT;
940 969 return(0);
941 970 }
942 971
943 972 enum mdelim
944 973 mdoc_isdelim(const char *p)
945 974 {
946 975
947 976 if ('\0' == p[0])
948 977 return(DELIM_NONE);
949 978
950 979 if ('\0' == p[1])
951 980 switch (p[0]) {
952 981 case('('):
953 982 /* FALLTHROUGH */
954 983 case('['):
955 984 return(DELIM_OPEN);
956 985 case('|'):
957 986 return(DELIM_MIDDLE);
958 987 case('.'):
959 988 /* FALLTHROUGH */
960 989 case(','):
961 990 /* FALLTHROUGH */
962 991 case(';'):
963 992 /* FALLTHROUGH */
964 993 case(':'):
965 994 /* FALLTHROUGH */
966 995 case('?'):
967 996 /* FALLTHROUGH */
968 997 case('!'):
969 998 /* FALLTHROUGH */
970 999 case(')'):
971 1000 /* FALLTHROUGH */
972 1001 case(']'):
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
973 1002 return(DELIM_CLOSE);
974 1003 default:
975 1004 return(DELIM_NONE);
976 1005 }
977 1006
978 1007 if ('\\' != p[0])
979 1008 return(DELIM_NONE);
980 1009
981 1010 if (0 == strcmp(p + 1, "."))
982 1011 return(DELIM_CLOSE);
983 - if (0 == strcmp(p + 1, "*(Ba"))
1012 + if (0 == strcmp(p + 1, "fR|\\fP"))
984 1013 return(DELIM_MIDDLE);
985 1014
986 1015 return(DELIM_NONE);
987 1016 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX