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