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