Annotation of mandoc/mlg.c, Revision 1.29
1.29 ! kristaps 1: /* $Id: mlg.c,v 1.28 2008/12/10 13:41:58 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>
20: #include <ctype.h>
21: #include <err.h>
1.13 kristaps 22: #include <stdarg.h>
1.1 kristaps 23: #include <stdlib.h>
24: #include <stdio.h>
25: #include <string.h>
26:
27: #include "ml.h"
28:
29: /* TODO: literal tokens. */
30:
31: enum md_tok {
32: MD_TEXT,
33: MD_INLINE_IN,
34: MD_INLINE_OUT,
35: MD_BLK_IN,
1.27 kristaps 36: MD_BLK_OUT
1.1 kristaps 37: };
38:
39: struct md_mlg {
1.29 ! kristaps 40: struct ml_args args;
1.1 kristaps 41: struct rofftree *tree;
42: size_t indent;
43: size_t pos;
44: enum md_tok last;
45: void *arg;
1.11 kristaps 46: struct ml_cbs cbs;
1.1 kristaps 47: int flags;
48: #define ML_OVERRIDE_ONE (1 << 0)
49: #define ML_OVERRIDE_ALL (1 << 1)
50: };
51:
1.23 kristaps 52: static int mlg_roffmsg(void *arg,
1.20 kristaps 53: enum roffmsg, const char *,
54: const char *, const char *);
1.4 kristaps 55: static int mlg_roffhead(void *, const struct tm *,
56: const char *, const char *,
1.25 kristaps 57: enum roffmsec, enum roffvol);
1.26 kristaps 58: static int mlg_rofftail(void *, const struct tm *,
59: const char *, const char *,
60: enum roffmsec, enum roffvol);
1.20 kristaps 61: static int mlg_roffin(void *, int,
62: int *, const char **);
1.5 kristaps 63: static int mlg_roffdata(void *, int,
1.20 kristaps 64: const char *, const char *);
1.1 kristaps 65: static int mlg_roffout(void *, int);
1.20 kristaps 66: static int mlg_roffblkin(void *, int, int *,
67: const char **);
1.1 kristaps 68: static int mlg_roffblkout(void *, int);
1.8 kristaps 69: static int mlg_roffspecial(void *, int,
1.16 kristaps 70: const char *, const int *,
1.20 kristaps 71: const char **, const char **);
1.5 kristaps 72: static int mlg_roffblkheadin(void *, int,
1.20 kristaps 73: int *, const char **);
1.2 kristaps 74: static int mlg_roffblkheadout(void *, int);
1.5 kristaps 75: static int mlg_roffblkbodyin(void *, int,
1.20 kristaps 76: int *, const char **);
1.2 kristaps 77: static int mlg_roffblkbodyout(void *, int);
78:
1.20 kristaps 79: static int mlg_ref_special(struct md_mlg *, int,
80: const char *, const char **);
81: static int mlg_formatted_special(struct md_mlg *,
1.23 kristaps 82: int, const char *, const int *,
1.20 kristaps 83: const char **, const char **);
84: static int mlg_literal_special(struct md_mlg *,
85: int, const char *, const int *,
86: const char **, const char **);
87: static int mlg_function_special(struct md_mlg *,
88: const char *, const char **);
89: static int mlg_atom_special(struct md_mlg *, int,
90: const char *, const char **);
1.28 kristaps 91: static int mlg_link_special(struct md_mlg *, int,
92: const char *, const char **);
93: static int mlg_anchor_special(struct md_mlg *,
94: int, const char **);
1.20 kristaps 95:
1.1 kristaps 96: static int mlg_begintag(struct md_mlg *, enum md_ns,
1.20 kristaps 97: int, int *, const char **);
1.1 kristaps 98: static int mlg_endtag(struct md_mlg *, enum md_ns, int);
99: static int mlg_indent(struct md_mlg *);
100: static int mlg_newline(struct md_mlg *);
101: static void mlg_mode(struct md_mlg *, enum md_tok);
1.19 kristaps 102: static int mlg_nstring(struct md_mlg *,
103: const char *, const char *, size_t);
104: static int mlg_string(struct md_mlg *,
105: const char *, const char *);
1.5 kristaps 106: static int mlg_data(struct md_mlg *, int,
1.20 kristaps 107: const char *, const char *);
1.23 kristaps 108: static int mlg_err(struct md_mlg *, const char *,
1.13 kristaps 109: const char *, const char *, ...);
1.23 kristaps 110: static int mlg_msg(struct md_mlg *,
1.20 kristaps 111: enum roffmsg, const char *,
112: const char *, const char *);
1.23 kristaps 113: static int mlg_vmsg(struct md_mlg *, enum roffmsg,
1.13 kristaps 114: const char *, const char *,
115: const char *, va_list);
1.1 kristaps 116:
117: #ifdef __linux__
118: extern size_t strlcat(char *, const char *, size_t);
119: extern size_t strlcpy(char *, const char *, size_t);
120: #endif
121:
122:
123: static int
124: mlg_begintag(struct md_mlg *p, enum md_ns ns, int tok,
1.20 kristaps 125: int *argc, const char **argv)
1.1 kristaps 126: {
127: ssize_t res;
128:
1.8 kristaps 129: assert(MD_NS_DEFAULT != ns);
130:
131: switch (ns) {
132: case (MD_NS_INLINE):
133: if ( ! (ML_OVERRIDE_ONE & p->flags) &&
134: ! (ML_OVERRIDE_ALL & p->flags) &&
1.9 kristaps 135: p->pos + 11 >= COLUMNS)
1.8 kristaps 136: if ( ! mlg_newline(p))
137: return(0);
138: if (0 != p->pos && (MD_TEXT == p->last ||
139: MD_INLINE_OUT == p->last)
140: && ! (ML_OVERRIDE_ONE & p->flags)
141: && ! (ML_OVERRIDE_ALL & p->flags))
1.29 ! kristaps 142: if ( ! ml_nputs(p->args.mbuf, " ", 1, &p->pos))
1.8 kristaps 143: return(0);
144: if (0 == p->pos && ! mlg_indent(p))
145: return(0);
146: mlg_mode(p, MD_INLINE_IN);
147: break;
148: default:
149: if (0 != p->pos) {
150: if ( ! mlg_newline(p))
151: return(0);
152: if ( ! mlg_indent(p))
153: return(0);
154: } else if ( ! mlg_indent(p))
155: return(0);
156: p->indent++;
157: mlg_mode(p, MD_BLK_IN);
158: break;
159: }
1.1 kristaps 160:
1.29 ! kristaps 161: if ( ! ml_nputs(p->args.mbuf, "<", 1, &p->pos))
1.1 kristaps 162: return(0);
163:
1.29 ! kristaps 164: res = (*p->cbs.ml_begintag)(&p->args, ns, tok, argc, argv);
1.1 kristaps 165: if (-1 == res)
166: return(0);
167:
168: assert(res >= 0);
169: p->pos += (size_t)res;
170:
1.29 ! kristaps 171: if ( ! ml_nputs(p->args.mbuf, ">", 1, &p->pos))
1.8 kristaps 172: return(0);
173:
174: switch (ns) {
175: case (MD_NS_INLINE):
176: break;
177: default:
178: if ( ! mlg_newline(p))
179: return(0);
180: break;
181: }
1.1 kristaps 182:
1.8 kristaps 183: return(1);
1.1 kristaps 184: }
185:
186:
187: static int
188: mlg_endtag(struct md_mlg *p, enum md_ns ns, int tok)
189: {
190: ssize_t res;
191:
1.9 kristaps 192: assert(MD_NS_DEFAULT != ns);
193:
194: switch (ns) {
195: case (MD_NS_INLINE):
196: break;
197: default:
198: p->indent--;
199: if (0 != p->pos) {
200: if ( ! mlg_newline(p))
201: return(0);
202: if ( ! mlg_indent(p))
203: return(0);
204: } else if ( ! mlg_indent(p))
205: return(0);
206: break;
207: }
1.1 kristaps 208:
1.29 ! kristaps 209: if ( ! ml_nputs(p->args.mbuf, "</", 2, &p->pos))
1.1 kristaps 210: return(0);
211:
1.29 ! kristaps 212: res = (*p->cbs.ml_endtag)(&p->args, ns, tok);
1.1 kristaps 213: if (-1 == res)
214: return(0);
215:
216: assert(res >= 0);
217: p->pos += (size_t)res;
218:
1.29 ! kristaps 219: if ( ! ml_nputs(p->args.mbuf, ">", 1, &p->pos))
1.9 kristaps 220: return(0);
221:
222: switch (ns) {
223: case (MD_NS_INLINE):
224: mlg_mode(p, MD_INLINE_OUT);
225: break;
226: default:
227: mlg_mode(p, MD_BLK_OUT);
228: break;
229: }
1.1 kristaps 230:
1.9 kristaps 231: return(1);
1.1 kristaps 232: }
233:
234:
235: static int
236: mlg_indent(struct md_mlg *p)
237: {
238:
239: assert(0 == p->pos);
1.29 ! kristaps 240: return(ml_putchars(p->args.mbuf, ' ', INDENT_SZ *
1.24 kristaps 241: INDENT(p->indent), &p->pos));
1.1 kristaps 242: }
243:
244:
245: static int
246: mlg_newline(struct md_mlg *p)
247: {
248:
249: p->pos = 0;
1.29 ! kristaps 250: return(ml_nputs(p->args.mbuf, "\n", 1, NULL));
1.1 kristaps 251: }
252:
253:
254: static void
255: mlg_mode(struct md_mlg *p, enum md_tok ns)
256: {
1.3 kristaps 257:
1.1 kristaps 258: p->flags &= ~ML_OVERRIDE_ONE;
259: p->last = ns;
260: }
261:
262:
263: static int
1.19 kristaps 264: mlg_string(struct md_mlg *p, const char *start, const char *buf)
265: {
266:
267: return(mlg_nstring(p, start, buf, strlen(buf)));
268: }
269:
270:
271: static int
272: mlg_nstring(struct md_mlg *p, const char *start,
273: const char *buf, size_t sz)
274: {
275: int c;
276: ssize_t res;
277:
1.29 ! kristaps 278: assert(p->args.mbuf);
1.19 kristaps 279: assert(0 != p->indent);
280:
1.29 ! kristaps 281: res = (*p->cbs.ml_beginstring)(&p->args, buf, sz);
1.19 kristaps 282: if (-1 == res)
283: return(0);
284:
1.29 ! kristaps 285: if (0 == (c = ml_nputstring(p->args.mbuf, buf, sz, &p->pos)))
1.23 kristaps 286: return(mlg_err(p, start, buf, "bad string "
287: "encoding: `%s'", buf));
288: else if (-1 == c)
1.19 kristaps 289: return(0);
290:
1.29 ! kristaps 291: res = (*p->cbs.ml_endstring)(&p->args, buf, sz);
1.19 kristaps 292: if (-1 == res)
293: return(0);
294:
295: return(1);
296: }
297:
298:
299: static int
1.20 kristaps 300: mlg_data(struct md_mlg *p, int space,
301: const char *start, const char *buf)
1.1 kristaps 302: {
303: size_t sz;
304:
1.29 ! kristaps 305: assert(p->args.mbuf);
1.1 kristaps 306: assert(0 != p->indent);
307:
308: if (ML_OVERRIDE_ONE & p->flags ||
309: ML_OVERRIDE_ALL & p->flags)
310: space = 0;
311:
1.8 kristaps 312: sz = strlen(buf);
1.1 kristaps 313:
1.8 kristaps 314: if (0 == p->pos) {
315: if ( ! mlg_indent(p))
316: return(0);
1.19 kristaps 317: if ( ! mlg_nstring(p, start, buf, sz))
1.8 kristaps 318: return(0);
1.1 kristaps 319:
1.24 kristaps 320: if (INDENT(p->indent) * INDENT_SZ + sz >= COLUMNS)
1.8 kristaps 321: if ( ! mlg_newline(p))
1.1 kristaps 322: return(0);
1.5 kristaps 323:
1.8 kristaps 324: return(1);
325: }
1.5 kristaps 326:
1.8 kristaps 327: if (space && sz + p->pos >= COLUMNS) {
328: if ( ! mlg_newline(p))
1.5 kristaps 329: return(0);
1.8 kristaps 330: if ( ! mlg_indent(p))
1.5 kristaps 331: return(0);
1.8 kristaps 332: } else if (space) {
1.29 ! kristaps 333: if ( ! ml_nputs(p->args.mbuf, " ", 1, &p->pos))
1.1 kristaps 334: return(0);
1.8 kristaps 335: }
1.1 kristaps 336:
1.19 kristaps 337: return(mlg_nstring(p, start, buf, sz));
1.1 kristaps 338: }
339:
340:
341: int
342: mlg_line(struct md_mlg *p, char *buf)
343: {
344:
345: return(roff_engine(p->tree, buf));
346: }
347:
348:
349: int
350: mlg_exit(struct md_mlg *p, int flush)
351: {
352: int c;
353:
354: c = roff_free(p->tree, flush);
1.29 ! kristaps 355: (*p->cbs.ml_free)(p->args.data);
1.21 kristaps 356:
1.1 kristaps 357: free(p);
1.11 kristaps 358:
1.1 kristaps 359: return(c);
360: }
361:
362:
363: struct md_mlg *
1.11 kristaps 364: mlg_alloc(const struct md_args *args,
1.1 kristaps 365: const struct md_rbuf *rbuf,
366: struct md_mbuf *mbuf,
1.11 kristaps 367: const struct ml_cbs *cbs)
1.1 kristaps 368: {
369: struct roffcb cb;
370: struct md_mlg *p;
371:
372: cb.roffhead = mlg_roffhead;
373: cb.rofftail = mlg_rofftail;
374: cb.roffin = mlg_roffin;
375: cb.roffout = mlg_roffout;
376: cb.roffblkin = mlg_roffblkin;
1.2 kristaps 377: cb.roffblkheadin = mlg_roffblkheadin;
378: cb.roffblkheadout = mlg_roffblkheadout;
379: cb.roffblkbodyin = mlg_roffblkbodyin;
380: cb.roffblkbodyout = mlg_roffblkbodyout;
1.1 kristaps 381: cb.roffblkout = mlg_roffblkout;
382: cb.roffspecial = mlg_roffspecial;
383: cb.roffmsg = mlg_roffmsg;
384: cb.roffdata = mlg_roffdata;
385:
386: if (NULL == (p = calloc(1, sizeof(struct md_mlg))))
387: err(1, "calloc");
388:
1.29 ! kristaps 389: p->args.args = args;
! 390: p->args.mbuf = mbuf;
! 391: p->args.rbuf = rbuf;
1.1 kristaps 392:
1.11 kristaps 393: (void)memcpy(&p->cbs, cbs, sizeof(struct ml_cbs));
394:
395: if (NULL == (p->tree = roff_alloc(&cb, p)))
396: free(p);
1.29 ! kristaps 397: else if ( ! (*p->cbs.ml_alloc)(&p->args.data))
1.1 kristaps 398: free(p);
1.11 kristaps 399: else
400: return(p);
1.1 kristaps 401:
1.11 kristaps 402: return(NULL);
1.1 kristaps 403: }
404:
405:
406: static int
1.4 kristaps 407: mlg_roffhead(void *arg, const struct tm *tm, const char *os,
1.25 kristaps 408: const char *title, enum roffmsec sec, enum roffvol vol)
1.1 kristaps 409: {
410: struct md_mlg *p;
411:
412: assert(arg);
413: p = (struct md_mlg *)arg;
414:
415: mlg_mode(p, MD_BLK_IN);
1.11 kristaps 416:
1.29 ! kristaps 417: if ( ! (*p->cbs.ml_begin)(&p->args, tm, os, title, sec, vol))
1.1 kristaps 418: return(0);
419:
420: p->indent++;
421: return(mlg_newline(p));
422: }
423:
424:
425: static int
1.26 kristaps 426: mlg_rofftail(void *arg, const struct tm *tm, const char *os,
427: const char *title, enum roffmsec sec, enum roffvol vol)
1.1 kristaps 428: {
429: struct md_mlg *p;
430:
431: assert(arg);
432: p = (struct md_mlg *)arg;
433:
1.11 kristaps 434: if (0 != p->pos)
435: if ( ! mlg_newline(p))
436: return(0);
437:
1.29 ! kristaps 438: if ( ! (*p->cbs.ml_end)(&p->args, tm, os, title, sec, vol))
1.1 kristaps 439: return(0);
440:
441: mlg_mode(p, MD_BLK_OUT);
442: return(mlg_newline(p));
443: }
444:
445:
1.20 kristaps 446: static int
447: mlg_literal_special(struct md_mlg *p, int tok, const char *start,
448: const int *argc, const char **argv, const char **more)
449: {
450: char *lit;
451:
452: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
453: return(0);
454:
1.23 kristaps 455: lit = roff_literal(tok, argc, argv, more);
1.20 kristaps 456: assert(lit);
457:
1.23 kristaps 458: if ( ! mlg_string(p, start, lit))
1.20 kristaps 459: return(0);
1.23 kristaps 460:
1.20 kristaps 461: while (*more) {
1.29 ! kristaps 462: if ( ! ml_nputs(p->args.mbuf, " ", 1, &p->pos))
1.20 kristaps 463: return(0);
464: if ( ! mlg_string(p, start, *more++))
465: return(0);
466: }
467:
468: return(mlg_endtag(p, MD_NS_INLINE, tok));
469: }
470:
471:
472: static int
473: mlg_ref_special(struct md_mlg *p, int tok,
474: const char *start, const char **more)
475: {
476:
477: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
478: return(0);
479:
480: assert(*more);
1.29 ! kristaps 481: if ( ! ml_puts(p->args.mbuf, *more++, &p->pos))
1.20 kristaps 482: return(0);
483:
484: if (*more) {
1.29 ! kristaps 485: if ( ! ml_nputs(p->args.mbuf, "(", 1, &p->pos))
1.20 kristaps 486: return(0);
487: if ( ! mlg_string(p, start, *more++))
488: return(0);
1.29 ! kristaps 489: if ( ! ml_nputs(p->args.mbuf, ")", 1, &p->pos))
1.20 kristaps 490: return(0);
491: }
492:
493: assert(NULL == *more);
494: return(mlg_endtag(p, MD_NS_INLINE, tok));
495: }
496:
497:
1.27 kristaps 498: /* ARGSUSED */
1.20 kristaps 499: static int
1.23 kristaps 500: mlg_formatted_special(struct md_mlg *p, int tok, const char *start,
1.20 kristaps 501: const int *argc, const char **argv, const char **more)
502: {
503: char buf[256], *lit;
504:
505: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
506: return(0);
507:
1.23 kristaps 508: lit = roff_fmtstring(tok);
1.21 kristaps 509:
1.20 kristaps 510: assert(lit);
511: assert(*more);
512: (void)snprintf(buf, sizeof(buf), lit, *more++);
513: assert(NULL == *more);
514:
1.23 kristaps 515: if ( ! mlg_string(p, start, buf))
1.20 kristaps 516: return(0);
517:
518: return(mlg_endtag(p, MD_NS_INLINE, tok));
519: }
520:
521:
522: static int
523: mlg_atom_special(struct md_mlg *p, int tok,
524: const char *start, const char **more)
525: {
526:
1.29 ! kristaps 527: if (ROFFSec_SYNOP == p->args.section) {
! 528: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Pp, NULL, more))
! 529: return(0);
! 530: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Pp))
! 531: return(0);
! 532: }
! 533:
1.20 kristaps 534: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
535: return(0);
536:
537: assert(*more);
538: if ( ! mlg_string(p, start, *more++))
539: return(0);
540:
541: return(mlg_endtag(p, MD_NS_INLINE, tok));
542: }
543:
544:
545: static int
546: mlg_function_special(struct md_mlg *p,
547: const char *start, const char **more)
548: {
549:
550: assert(*more);
551:
552: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fn, NULL, more))
553: return(0);
554: if ( ! mlg_string(p, start, *more++))
555: return(0);
556: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fn))
557: return(0);
558:
559: if (NULL == *more)
560: return(1);
561:
1.29 ! kristaps 562: if ( ! ml_nputs(p->args.mbuf, "(", 1, &p->pos))
1.20 kristaps 563: return(0);
564:
565: p->flags |= ML_OVERRIDE_ONE;
566:
567: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more))
568: return(0);
569: if ( ! mlg_string(p, start, *more++))
570: return(0);
571: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa))
572: return(0);
573:
574: while (*more) {
1.29 ! kristaps 575: if ( ! ml_nputs(p->args.mbuf, ", ", 2, &p->pos))
1.20 kristaps 576: return(0);
577: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more))
578: return(0);
579: if ( ! mlg_string(p, start, *more++))
580: return(0);
581: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa))
582: return(0);
583: }
584:
1.29 ! kristaps 585: return(ml_nputs(p->args.mbuf, ")", 1, &p->pos));
1.20 kristaps 586: }
587:
588:
1.28 kristaps 589: static int
590: mlg_anchor_special(struct md_mlg *p, int tok, const char **more)
591: {
592: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
593: return(0);
594: return(mlg_endtag(p, MD_NS_INLINE, tok));
595: }
596:
597:
598: static int
599: mlg_link_special(struct md_mlg *p, int tok,
600: const char *start, const char **more)
601: {
602:
603: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
604: return(0);
605: if ( ! mlg_string(p, start, *more++))
606: return(0);
607: while (*more) {
608: if ( ! mlg_string(p, start, " "))
609: return(0);
610: if ( ! mlg_string(p, start, *more++))
611: return(0);
612: }
613: return(mlg_endtag(p, MD_NS_INLINE, tok));
614: }
615:
616:
1.16 kristaps 617: /* ARGSUSED */
1.1 kristaps 618: static int
1.16 kristaps 619: mlg_roffspecial(void *arg, int tok, const char *start,
1.20 kristaps 620: const int *argc, const char **argv, const char **more)
1.1 kristaps 621: {
622: struct md_mlg *p;
623:
624: assert(arg);
625: p = (struct md_mlg *)arg;
626:
627: switch (tok) {
1.15 kristaps 628: case (ROFF_Ns):
629: p->flags |= ML_OVERRIDE_ONE;
630: return(1);
1.20 kristaps 631:
1.15 kristaps 632: case (ROFF_Sm):
633: assert(*more);
634: if (0 == strcmp(*more, "on"))
635: p->flags |= ML_OVERRIDE_ALL;
636: else
637: p->flags &= ~ML_OVERRIDE_ALL;
638: return(1);
1.18 kristaps 639:
640: case (ROFF_Fn):
1.20 kristaps 641: return(mlg_function_special(p, start, more));
1.16 kristaps 642:
1.8 kristaps 643: case (ROFF_Xr):
1.20 kristaps 644: return(mlg_ref_special(p, tok, start, more));
1.28 kristaps 645:
646: case (ROFF_Sh):
1.29 ! kristaps 647: p->args.section = roff_sec(more);
1.28 kristaps 648: return(mlg_anchor_special(p, tok, more));
1.20 kristaps 649:
1.28 kristaps 650: case (ROFF_Sx):
651: return(mlg_link_special(p, tok, start, more));
652:
1.12 kristaps 653: case (ROFF_Nm):
1.20 kristaps 654: return(mlg_atom_special(p, tok, start, more));
1.18 kristaps 655:
656: case (ROFF_In):
657: /* NOTREACHED */
1.13 kristaps 658: case (ROFF_Ex):
1.17 kristaps 659: /* NOTREACHED */
660: case (ROFF_Rv):
1.23 kristaps 661: return(mlg_formatted_special(p, tok, start,
1.20 kristaps 662: argc, argv, more));
1.19 kristaps 663:
1.15 kristaps 664: case (ROFF_At):
1.20 kristaps 665: /* FALLTHROUGH */
666: case (ROFF_Bt):
667: /* FALLTHROUGH */
668: case (ROFF_Ud):
669: /* FALLTHROUGH */
670: case (ROFF_Ux):
671: /* FALLTHROUGH */
1.15 kristaps 672: case (ROFF_Bx):
673: /* FALLTHROUGH */
674: case (ROFF_Bsx):
675: /* FALLTHROUGH */
676: case (ROFF_Fx):
677: /* FALLTHROUGH */
678: case (ROFF_Nx):
679: /* FALLTHROUGH */
1.20 kristaps 680: case (ROFF_St):
681: /* FALLTHROUGH */
1.15 kristaps 682: case (ROFF_Ox):
1.20 kristaps 683: return(mlg_literal_special(p, tok, start,
684: argc, argv, more));
685: default:
1.15 kristaps 686: break;
1.1 kristaps 687: }
688:
1.23 kristaps 689: return(mlg_err(p, start, start, "`%s' not yet supported",
690: toknames[tok]));
1.1 kristaps 691: }
692:
693:
694: static int
1.20 kristaps 695: mlg_roffblkin(void *arg, int tok,
696: int *argc, const char **argv)
1.1 kristaps 697: {
698:
1.8 kristaps 699: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 700: MD_NS_BLOCK, tok, argc, argv));
701: }
702:
703:
704: static int
705: mlg_roffblkout(void *arg, int tok)
706: {
707:
1.9 kristaps 708: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BLOCK, tok));
1.2 kristaps 709: }
710:
711:
712: static int
1.20 kristaps 713: mlg_roffblkbodyin(void *arg, int tok,
714: int *argc, const char **argv)
1.2 kristaps 715: {
716:
1.8 kristaps 717: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 718: MD_NS_BODY, tok, argc, argv));
719: }
1.1 kristaps 720:
721:
1.2 kristaps 722: static int
723: mlg_roffblkbodyout(void *arg, int tok)
724: {
1.1 kristaps 725:
1.9 kristaps 726: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BODY, tok));
1.1 kristaps 727: }
728:
729:
730: static int
1.20 kristaps 731: mlg_roffblkheadin(void *arg, int tok,
732: int *argc, const char **argv)
1.1 kristaps 733: {
734:
1.8 kristaps 735: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 736: MD_NS_HEAD, tok, argc, argv));
737: }
1.1 kristaps 738:
739:
1.2 kristaps 740: static int
741: mlg_roffblkheadout(void *arg, int tok)
742: {
1.1 kristaps 743:
1.9 kristaps 744: return(mlg_endtag((struct md_mlg *)arg, MD_NS_HEAD, tok));
1.1 kristaps 745: }
746:
747:
748: static int
1.20 kristaps 749: mlg_roffin(void *arg, int tok, int *argc, const char **argv)
1.1 kristaps 750: {
751:
1.8 kristaps 752: return(mlg_begintag((struct md_mlg *)arg,
753: MD_NS_INLINE, tok, argc, argv));
1.1 kristaps 754: }
755:
756:
757: static int
758: mlg_roffout(void *arg, int tok)
759: {
760:
1.9 kristaps 761: return(mlg_endtag((struct md_mlg *)arg, MD_NS_INLINE, tok));
1.1 kristaps 762: }
763:
764:
1.23 kristaps 765: static int
1.20 kristaps 766: mlg_roffmsg(void *arg, enum roffmsg lvl, const char *buf,
767: const char *pos, const char *msg)
1.1 kristaps 768: {
1.5 kristaps 769:
1.23 kristaps 770: return(mlg_msg((struct md_mlg *)arg, lvl, buf, pos, msg));
1.5 kristaps 771: }
772:
773:
774: static int
1.20 kristaps 775: mlg_roffdata(void *arg, int space,
776: const char *start, const char *buf)
1.5 kristaps 777: {
1.1 kristaps 778: struct md_mlg *p;
779:
780: assert(arg);
781: p = (struct md_mlg *)arg;
782:
1.5 kristaps 783: if ( ! mlg_data(p, space, start, buf))
784: return(0);
785:
786: mlg_mode(p, MD_TEXT);
787: return(1);
788: }
789:
790:
1.23 kristaps 791: static int
1.13 kristaps 792: mlg_vmsg(struct md_mlg *p, enum roffmsg lvl, const char *start,
793: const char *pos, const char *fmt, va_list ap)
1.5 kristaps 794: {
1.13 kristaps 795: char buf[128];
1.5 kristaps 796:
1.13 kristaps 797: (void)vsnprintf(buf, sizeof(buf), fmt, ap);
1.23 kristaps 798: return(mlg_msg(p, lvl, start, pos, buf));
1.5 kristaps 799: }
800:
801:
1.23 kristaps 802: static int
1.13 kristaps 803: mlg_err(struct md_mlg *p, const char *start,
804: const char *pos, const char *fmt, ...)
805: {
806: va_list ap;
1.23 kristaps 807: int c;
1.13 kristaps 808:
809: va_start(ap, fmt);
1.23 kristaps 810: c = mlg_vmsg(p, ROFF_ERROR, start, pos, fmt, ap);
1.13 kristaps 811: va_end(ap);
1.23 kristaps 812: return(c);
1.5 kristaps 813: }
814:
815:
1.23 kristaps 816: static int
1.5 kristaps 817: mlg_msg(struct md_mlg *p, enum roffmsg lvl,
1.20 kristaps 818: const char *buf, const char *pos, const char *msg)
1.5 kristaps 819: {
1.29 ! kristaps 820: char *level, b[256];
! 821: size_t sz;
1.22 kristaps 822: int i;
1.5 kristaps 823:
1.29 ! kristaps 824: sz = sizeof(b);
! 825:
1.1 kristaps 826: switch (lvl) {
827: case (ROFF_WARN):
1.23 kristaps 828: level = "warning";
1.29 ! kristaps 829: if ( ! (MD_WARN_ALL & p->args.args->warnings))
1.23 kristaps 830: return(1);
1.1 kristaps 831: break;
832: case (ROFF_ERROR):
833: level = "error";
834: break;
835: default:
836: abort();
1.23 kristaps 837: /* NOTREACHED */
1.1 kristaps 838: }
1.22 kristaps 839:
840: if (pos) {
841: assert(pos >= buf);
1.29 ! kristaps 842: if (0 < p->args.args->verbosity) {
! 843: (void)snprintf(b, sz, "%s:%zu: %s: %s\n",
! 844: p->args.rbuf->name,
! 845: p->args.rbuf->line,
1.22 kristaps 846: level, msg);
847:
1.29 ! kristaps 848: (void)strlcat(b, "Error at: ", sz);
! 849: (void)strlcat(b, p->args.rbuf->linebuf, sz);
! 850: (void)strlcat(b, "\n ", sz);
! 851:
1.22 kristaps 852: for (i = 0; i < pos - buf; i++)
1.29 ! kristaps 853: (void)strlcat(b, " ", sz);
1.22 kristaps 854:
1.29 ! kristaps 855: (void)strlcat(b, "^", sz);
1.22 kristaps 856: } else
1.29 ! kristaps 857: (void)snprintf(b, sz, "%s:%zu: %s: %s (%zu)",
! 858: p->args.rbuf->name,
! 859: p->args.rbuf->line,
1.22 kristaps 860: level, msg, pos - buf);
861: } else
1.29 ! kristaps 862: (void)snprintf(b, sz, "%s: %s: %s",
! 863: p->args.rbuf->name, level, msg);
1.22 kristaps 864:
865: (void)fprintf(stderr, "%s\n", b);
1.23 kristaps 866: return(lvl == ROFF_WARN ? 1 : 0);
1.1 kristaps 867: }
1.22 kristaps 868:
CVSweb