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