Annotation of mandoc/mlg.c, Revision 1.28
1.28 ! kristaps 1: /* $Id: mlg.c,v 1.27 2008/12/10 12:09:47 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 {
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.25 kristaps 61: enum roffmsec, enum roffvol);
1.26 kristaps 62: static int mlg_rofftail(void *, const struct tm *,
63: const char *, const char *,
64: enum roffmsec, enum roffvol);
1.20 kristaps 65: static int mlg_roffin(void *, int,
66: int *, const char **);
1.5 kristaps 67: static int mlg_roffdata(void *, int,
1.20 kristaps 68: const char *, const char *);
1.1 kristaps 69: static int mlg_roffout(void *, int);
1.20 kristaps 70: static int mlg_roffblkin(void *, int, int *,
71: const char **);
1.1 kristaps 72: static int mlg_roffblkout(void *, int);
1.8 kristaps 73: static int mlg_roffspecial(void *, int,
1.16 kristaps 74: const char *, const int *,
1.20 kristaps 75: const char **, const char **);
1.5 kristaps 76: static int mlg_roffblkheadin(void *, int,
1.20 kristaps 77: int *, const char **);
1.2 kristaps 78: static int mlg_roffblkheadout(void *, int);
1.5 kristaps 79: static int mlg_roffblkbodyin(void *, int,
1.20 kristaps 80: int *, const char **);
1.2 kristaps 81: static int mlg_roffblkbodyout(void *, int);
82:
1.20 kristaps 83: static int mlg_ref_special(struct md_mlg *, int,
84: const char *, const char **);
85: static int mlg_formatted_special(struct md_mlg *,
1.23 kristaps 86: int, const char *, const int *,
1.20 kristaps 87: const char **, const char **);
88: static int mlg_literal_special(struct md_mlg *,
89: int, const char *, const int *,
90: const char **, const char **);
91: static int mlg_function_special(struct md_mlg *,
92: const char *, const char **);
93: static int mlg_atom_special(struct md_mlg *, int,
94: const char *, const char **);
1.28 ! kristaps 95: static int mlg_link_special(struct md_mlg *, int,
! 96: const char *, const char **);
! 97: static int mlg_anchor_special(struct md_mlg *,
! 98: int, const char **);
1.20 kristaps 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.23 kristaps 112: static int mlg_err(struct md_mlg *, const char *,
1.13 kristaps 113: const char *, const char *, ...);
1.23 kristaps 114: static int mlg_msg(struct md_mlg *,
1.20 kristaps 115: enum roffmsg, const char *,
116: const char *, const char *);
1.23 kristaps 117: static int mlg_vmsg(struct md_mlg *, enum roffmsg,
1.13 kristaps 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:
244: assert(0 == p->pos);
1.24 kristaps 245: return(ml_putchars(p->mbuf, ' ', INDENT_SZ *
246: INDENT(p->indent), &p->pos));
1.1 kristaps 247: }
248:
249:
250: static int
251: mlg_newline(struct md_mlg *p)
252: {
253:
254: p->pos = 0;
1.11 kristaps 255: return(ml_nputs(p->mbuf, "\n", 1, NULL));
1.1 kristaps 256: }
257:
258:
259: static void
260: mlg_mode(struct md_mlg *p, enum md_tok ns)
261: {
1.3 kristaps 262:
1.1 kristaps 263: p->flags &= ~ML_OVERRIDE_ONE;
264: p->last = ns;
265: }
266:
267:
268: static int
1.19 kristaps 269: mlg_string(struct md_mlg *p, const char *start, const char *buf)
270: {
271:
272: return(mlg_nstring(p, start, buf, strlen(buf)));
273: }
274:
275:
276: static int
277: mlg_nstring(struct md_mlg *p, const char *start,
278: const char *buf, size_t sz)
279: {
280: int c;
281: ssize_t res;
282:
283: assert(p->mbuf);
284: assert(0 != p->indent);
285:
286: res = (*p->cbs.ml_beginstring)(p->mbuf, p->args, buf, sz);
287: if (-1 == res)
288: return(0);
289:
1.23 kristaps 290: if (0 == (c = ml_nputstring(p->mbuf, buf, sz, &p->pos)))
291: return(mlg_err(p, start, buf, "bad string "
292: "encoding: `%s'", buf));
293: else if (-1 == c)
1.19 kristaps 294: return(0);
295:
296: res = (*p->cbs.ml_endstring)(p->mbuf, p->args, buf, sz);
297: if (-1 == res)
298: return(0);
299:
300: return(1);
301: }
302:
303:
304: static int
1.20 kristaps 305: mlg_data(struct md_mlg *p, int space,
306: const char *start, const char *buf)
1.1 kristaps 307: {
308: size_t sz;
309:
310: assert(p->mbuf);
311: assert(0 != p->indent);
312:
313: if (ML_OVERRIDE_ONE & p->flags ||
314: ML_OVERRIDE_ALL & p->flags)
315: space = 0;
316:
1.8 kristaps 317: sz = strlen(buf);
1.1 kristaps 318:
1.8 kristaps 319: if (0 == p->pos) {
320: if ( ! mlg_indent(p))
321: return(0);
1.19 kristaps 322: if ( ! mlg_nstring(p, start, buf, sz))
1.8 kristaps 323: return(0);
1.1 kristaps 324:
1.24 kristaps 325: if (INDENT(p->indent) * INDENT_SZ + sz >= COLUMNS)
1.8 kristaps 326: if ( ! mlg_newline(p))
1.1 kristaps 327: return(0);
1.5 kristaps 328:
1.8 kristaps 329: return(1);
330: }
1.5 kristaps 331:
1.8 kristaps 332: if (space && sz + p->pos >= COLUMNS) {
333: if ( ! mlg_newline(p))
1.5 kristaps 334: return(0);
1.8 kristaps 335: if ( ! mlg_indent(p))
1.5 kristaps 336: return(0);
1.8 kristaps 337: } else if (space) {
338: if ( ! ml_nputs(p->mbuf, " ", 1, &p->pos))
1.1 kristaps 339: return(0);
1.8 kristaps 340: }
1.1 kristaps 341:
1.19 kristaps 342: return(mlg_nstring(p, start, buf, sz));
1.1 kristaps 343: }
344:
345:
346: int
347: mlg_line(struct md_mlg *p, char *buf)
348: {
349:
350: return(roff_engine(p->tree, buf));
351: }
352:
353:
354: int
355: mlg_exit(struct md_mlg *p, int flush)
356: {
357: int c;
358:
359: c = roff_free(p->tree, flush);
1.21 kristaps 360: (*p->cbs.ml_free)(p->data);
361:
1.1 kristaps 362: free(p);
1.11 kristaps 363:
1.1 kristaps 364: return(c);
365: }
366:
367:
368: struct md_mlg *
1.11 kristaps 369: mlg_alloc(const struct md_args *args,
1.1 kristaps 370: const struct md_rbuf *rbuf,
371: struct md_mbuf *mbuf,
1.11 kristaps 372: const struct ml_cbs *cbs)
1.1 kristaps 373: {
374: struct roffcb cb;
375: struct md_mlg *p;
376:
377: cb.roffhead = mlg_roffhead;
378: cb.rofftail = mlg_rofftail;
379: cb.roffin = mlg_roffin;
380: cb.roffout = mlg_roffout;
381: cb.roffblkin = mlg_roffblkin;
1.2 kristaps 382: cb.roffblkheadin = mlg_roffblkheadin;
383: cb.roffblkheadout = mlg_roffblkheadout;
384: cb.roffblkbodyin = mlg_roffblkbodyin;
385: cb.roffblkbodyout = mlg_roffblkbodyout;
1.1 kristaps 386: cb.roffblkout = mlg_roffblkout;
387: cb.roffspecial = mlg_roffspecial;
388: cb.roffmsg = mlg_roffmsg;
389: cb.roffdata = mlg_roffdata;
390:
391: if (NULL == (p = calloc(1, sizeof(struct md_mlg))))
392: err(1, "calloc");
393:
394: p->args = args;
395: p->mbuf = mbuf;
396: p->rbuf = rbuf;
397:
1.11 kristaps 398: (void)memcpy(&p->cbs, cbs, sizeof(struct ml_cbs));
399:
400: if (NULL == (p->tree = roff_alloc(&cb, p)))
401: free(p);
402: else if ( ! (*p->cbs.ml_alloc)(&p->data))
1.1 kristaps 403: free(p);
1.11 kristaps 404: else
405: return(p);
1.1 kristaps 406:
1.11 kristaps 407: return(NULL);
1.1 kristaps 408: }
409:
410:
411: static int
1.4 kristaps 412: mlg_roffhead(void *arg, const struct tm *tm, const char *os,
1.25 kristaps 413: const char *title, enum roffmsec sec, enum roffvol vol)
1.1 kristaps 414: {
415: struct md_mlg *p;
416:
417: assert(arg);
418: p = (struct md_mlg *)arg;
419:
420: mlg_mode(p, MD_BLK_IN);
1.11 kristaps 421:
1.26 kristaps 422: if ( ! (*p->cbs.ml_begin)(p->mbuf, p->args,
423: tm, os, title, sec, vol))
1.1 kristaps 424: return(0);
425:
426: p->indent++;
427: return(mlg_newline(p));
428: }
429:
430:
431: static int
1.26 kristaps 432: mlg_rofftail(void *arg, const struct tm *tm, const char *os,
433: const char *title, enum roffmsec sec, enum roffvol vol)
1.1 kristaps 434: {
435: struct md_mlg *p;
436:
437: assert(arg);
438: p = (struct md_mlg *)arg;
439:
1.11 kristaps 440: if (0 != p->pos)
441: if ( ! mlg_newline(p))
442: return(0);
443:
1.26 kristaps 444: if ( ! (*p->cbs.ml_end)(p->mbuf, p->args,
445: tm, os, title, sec, vol))
1.1 kristaps 446: return(0);
447:
448: mlg_mode(p, MD_BLK_OUT);
449: return(mlg_newline(p));
450: }
451:
452:
1.20 kristaps 453: static int
454: mlg_literal_special(struct md_mlg *p, int tok, const char *start,
455: const int *argc, const char **argv, const char **more)
456: {
457: char *lit;
458:
459: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
460: return(0);
461:
1.23 kristaps 462: lit = roff_literal(tok, argc, argv, more);
1.20 kristaps 463: assert(lit);
464:
1.23 kristaps 465: if ( ! mlg_string(p, start, lit))
1.20 kristaps 466: return(0);
1.23 kristaps 467:
1.20 kristaps 468: while (*more) {
469: if ( ! ml_nputs(p->mbuf, " ", 1, &p->pos))
470: return(0);
471: if ( ! mlg_string(p, start, *more++))
472: return(0);
473: }
474:
475: return(mlg_endtag(p, MD_NS_INLINE, tok));
476: }
477:
478:
479: static int
480: mlg_ref_special(struct md_mlg *p, int tok,
481: const char *start, const char **more)
482: {
483:
484: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
485: return(0);
486:
487: assert(*more);
488: if ( ! ml_puts(p->mbuf, *more++, &p->pos))
489: return(0);
490:
491: if (*more) {
492: if ( ! ml_nputs(p->mbuf, "(", 1, &p->pos))
493: return(0);
494: if ( ! mlg_string(p, start, *more++))
495: return(0);
496: if ( ! ml_nputs(p->mbuf, ")", 1, &p->pos))
497: return(0);
498: }
499:
500: assert(NULL == *more);
501: return(mlg_endtag(p, MD_NS_INLINE, tok));
502: }
503:
504:
1.27 kristaps 505: /* ARGSUSED */
1.20 kristaps 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:
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:
562: if ( ! ml_nputs(p->mbuf, "(", 1, &p->pos))
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) {
575: if ( ! ml_nputs(p->mbuf, ", ", 2, &p->pos))
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:
585: return(ml_nputs(p->mbuf, ")", 1, &p->pos));
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):
! 647: return(mlg_anchor_special(p, tok, more));
1.20 kristaps 648:
1.28 ! kristaps 649: case (ROFF_Sx):
! 650: return(mlg_link_special(p, tok, start, more));
! 651:
1.12 kristaps 652: case (ROFF_Nm):
1.20 kristaps 653: return(mlg_atom_special(p, tok, start, more));
1.18 kristaps 654:
655: case (ROFF_In):
656: /* NOTREACHED */
1.13 kristaps 657: case (ROFF_Ex):
1.17 kristaps 658: /* NOTREACHED */
659: case (ROFF_Rv):
1.23 kristaps 660: return(mlg_formatted_special(p, tok, start,
1.20 kristaps 661: argc, argv, more));
1.19 kristaps 662:
1.15 kristaps 663: case (ROFF_At):
1.20 kristaps 664: /* FALLTHROUGH */
665: case (ROFF_Bt):
666: /* FALLTHROUGH */
667: case (ROFF_Ud):
668: /* FALLTHROUGH */
669: case (ROFF_Ux):
670: /* FALLTHROUGH */
1.15 kristaps 671: case (ROFF_Bx):
672: /* FALLTHROUGH */
673: case (ROFF_Bsx):
674: /* FALLTHROUGH */
675: case (ROFF_Fx):
676: /* FALLTHROUGH */
677: case (ROFF_Nx):
678: /* FALLTHROUGH */
1.20 kristaps 679: case (ROFF_St):
680: /* FALLTHROUGH */
1.15 kristaps 681: case (ROFF_Ox):
1.20 kristaps 682: return(mlg_literal_special(p, tok, start,
683: argc, argv, more));
684: default:
1.15 kristaps 685: break;
1.1 kristaps 686: }
687:
1.23 kristaps 688: return(mlg_err(p, start, start, "`%s' not yet supported",
689: toknames[tok]));
1.1 kristaps 690: }
691:
692:
693: static int
1.20 kristaps 694: mlg_roffblkin(void *arg, int tok,
695: int *argc, const char **argv)
1.1 kristaps 696: {
697:
1.8 kristaps 698: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 699: MD_NS_BLOCK, tok, argc, argv));
700: }
701:
702:
703: static int
704: mlg_roffblkout(void *arg, int tok)
705: {
706:
1.9 kristaps 707: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BLOCK, tok));
1.2 kristaps 708: }
709:
710:
711: static int
1.20 kristaps 712: mlg_roffblkbodyin(void *arg, int tok,
713: int *argc, const char **argv)
1.2 kristaps 714: {
715:
1.8 kristaps 716: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 717: MD_NS_BODY, tok, argc, argv));
718: }
1.1 kristaps 719:
720:
1.2 kristaps 721: static int
722: mlg_roffblkbodyout(void *arg, int tok)
723: {
1.1 kristaps 724:
1.9 kristaps 725: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BODY, tok));
1.1 kristaps 726: }
727:
728:
729: static int
1.20 kristaps 730: mlg_roffblkheadin(void *arg, int tok,
731: int *argc, const char **argv)
1.1 kristaps 732: {
733:
1.8 kristaps 734: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 735: MD_NS_HEAD, tok, argc, argv));
736: }
1.1 kristaps 737:
738:
1.2 kristaps 739: static int
740: mlg_roffblkheadout(void *arg, int tok)
741: {
1.1 kristaps 742:
1.9 kristaps 743: return(mlg_endtag((struct md_mlg *)arg, MD_NS_HEAD, tok));
1.1 kristaps 744: }
745:
746:
747: static int
1.20 kristaps 748: mlg_roffin(void *arg, int tok, int *argc, const char **argv)
1.1 kristaps 749: {
750:
1.8 kristaps 751: return(mlg_begintag((struct md_mlg *)arg,
752: MD_NS_INLINE, tok, argc, argv));
1.1 kristaps 753: }
754:
755:
756: static int
757: mlg_roffout(void *arg, int tok)
758: {
759:
1.9 kristaps 760: return(mlg_endtag((struct md_mlg *)arg, MD_NS_INLINE, tok));
1.1 kristaps 761: }
762:
763:
1.23 kristaps 764: static int
1.20 kristaps 765: mlg_roffmsg(void *arg, enum roffmsg lvl, const char *buf,
766: const char *pos, const char *msg)
1.1 kristaps 767: {
1.5 kristaps 768:
1.23 kristaps 769: return(mlg_msg((struct md_mlg *)arg, lvl, buf, pos, msg));
1.5 kristaps 770: }
771:
772:
773: static int
1.20 kristaps 774: mlg_roffdata(void *arg, int space,
775: const char *start, const char *buf)
1.5 kristaps 776: {
1.1 kristaps 777: struct md_mlg *p;
778:
779: assert(arg);
780: p = (struct md_mlg *)arg;
781:
1.5 kristaps 782: if ( ! mlg_data(p, space, start, buf))
783: return(0);
784:
785: mlg_mode(p, MD_TEXT);
786: return(1);
787: }
788:
789:
1.23 kristaps 790: static int
1.13 kristaps 791: mlg_vmsg(struct md_mlg *p, enum roffmsg lvl, const char *start,
792: const char *pos, const char *fmt, va_list ap)
1.5 kristaps 793: {
1.13 kristaps 794: char buf[128];
1.5 kristaps 795:
1.13 kristaps 796: (void)vsnprintf(buf, sizeof(buf), fmt, ap);
1.23 kristaps 797: return(mlg_msg(p, lvl, start, pos, buf));
1.5 kristaps 798: }
799:
800:
1.23 kristaps 801: static int
1.13 kristaps 802: mlg_err(struct md_mlg *p, const char *start,
803: const char *pos, const char *fmt, ...)
804: {
805: va_list ap;
1.23 kristaps 806: int c;
1.13 kristaps 807:
808: va_start(ap, fmt);
1.23 kristaps 809: c = mlg_vmsg(p, ROFF_ERROR, start, pos, fmt, ap);
1.13 kristaps 810: va_end(ap);
1.23 kristaps 811: return(c);
1.5 kristaps 812: }
813:
814:
1.23 kristaps 815: static int
1.5 kristaps 816: mlg_msg(struct md_mlg *p, enum roffmsg lvl,
1.20 kristaps 817: const char *buf, const char *pos, const char *msg)
1.5 kristaps 818: {
819: char *level;
1.22 kristaps 820: char b[256];
821: int i;
1.5 kristaps 822:
1.1 kristaps 823: switch (lvl) {
824: case (ROFF_WARN):
1.23 kristaps 825: level = "warning";
1.1 kristaps 826: if ( ! (MD_WARN_ALL & p->args->warnings))
1.23 kristaps 827: return(1);
1.1 kristaps 828: break;
829: case (ROFF_ERROR):
830: level = "error";
831: break;
832: default:
833: abort();
1.23 kristaps 834: /* NOTREACHED */
1.1 kristaps 835: }
1.22 kristaps 836:
837: if (pos) {
838: assert(pos >= buf);
839: if (0 < p->args->verbosity) {
840: (void)snprintf(b, sizeof(b),
841: "%s:%zu: %s: %s\n",
842: p->rbuf->name, p->rbuf->line,
843: level, msg);
844: (void)strlcat(b, "Error at: ", sizeof(b));
845: (void)strlcat(b, p->rbuf->linebuf, sizeof(b));
846:
847: (void)strlcat(b, "\n ", sizeof(b));
848: for (i = 0; i < pos - buf; i++)
849: (void)strlcat(b, " ", sizeof(b));
850: (void)strlcat(b, "^", sizeof(b));
851:
852: } else
853: (void)snprintf(b, sizeof(b),
854: "%s:%zu: %s: %s (col %zu)",
855: p->rbuf->name, p->rbuf->line,
856: level, msg, pos - buf);
857: } else
858: (void)snprintf(b, sizeof(b), "%s: %s: %s",
1.1 kristaps 859: p->rbuf->name, level, msg);
1.22 kristaps 860:
861: (void)fprintf(stderr, "%s\n", b);
1.23 kristaps 862: return(lvl == ROFF_WARN ? 1 : 0);
1.1 kristaps 863: }
1.22 kristaps 864:
CVSweb