Annotation of mandoc/mlg.c, Revision 1.20
1.20 ! kristaps 1: /* $Id: mlg.c,v 1.19 2008/12/07 21:30:49 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 *,
67: const char *, 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);
365: free(p);
1.11 kristaps 366:
367: (*p->cbs.ml_free)(p->data);
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,
418: const char *title, const char *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:
! 465: lit = ml_literal(tok, argc, argv, more);
! 466: assert(lit);
! 467:
! 468: if ( ! ml_puts(p->mbuf, lit, &p->pos))
! 469: return(0);
! 470: while (*more) {
! 471: if ( ! ml_nputs(p->mbuf, " ", 1, &p->pos))
! 472: return(0);
! 473: if ( ! mlg_string(p, start, *more++))
! 474: return(0);
! 475: }
! 476:
! 477: return(mlg_endtag(p, MD_NS_INLINE, tok));
! 478: }
! 479:
! 480:
! 481: static int
! 482: mlg_ref_special(struct md_mlg *p, int tok,
! 483: const char *start, const char **more)
! 484: {
! 485:
! 486: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
! 487: return(0);
! 488:
! 489: assert(*more);
! 490: if ( ! ml_puts(p->mbuf, *more++, &p->pos))
! 491: return(0);
! 492:
! 493: if (*more) {
! 494: if ( ! ml_nputs(p->mbuf, "(", 1, &p->pos))
! 495: return(0);
! 496: if ( ! mlg_string(p, start, *more++))
! 497: return(0);
! 498: if ( ! ml_nputs(p->mbuf, ")", 1, &p->pos))
! 499: return(0);
! 500: }
! 501:
! 502: assert(NULL == *more);
! 503: return(mlg_endtag(p, MD_NS_INLINE, tok));
! 504: }
! 505:
! 506:
! 507: static int
! 508: mlg_formatted_special(struct md_mlg *p, int tok,
! 509: const int *argc, const char **argv, const char **more)
! 510: {
! 511: char buf[256], *lit;
! 512:
! 513: /* FIXME: *more must be ml-filtered. */
! 514:
! 515: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
! 516: return(0);
! 517:
! 518: lit = ml_literal(tok, argc, argv, more);
! 519: assert(lit);
! 520: assert(*more);
! 521: (void)snprintf(buf, sizeof(buf), lit, *more++);
! 522: assert(NULL == *more);
! 523:
! 524: if ( ! ml_puts(p->mbuf, buf, &p->pos))
! 525: return(0);
! 526:
! 527: return(mlg_endtag(p, MD_NS_INLINE, tok));
! 528: }
! 529:
! 530:
! 531: static int
! 532: mlg_atom_special(struct md_mlg *p, int tok,
! 533: const char *start, const char **more)
! 534: {
! 535:
! 536: if ( ! mlg_begintag(p, MD_NS_INLINE, tok, NULL, more))
! 537: return(0);
! 538:
! 539: assert(*more);
! 540: if ( ! mlg_string(p, start, *more++))
! 541: return(0);
! 542:
! 543: assert(NULL == *more);
! 544: return(mlg_endtag(p, MD_NS_INLINE, tok));
! 545: }
! 546:
! 547:
! 548: static int
! 549: mlg_function_special(struct md_mlg *p,
! 550: const char *start, const char **more)
! 551: {
! 552:
! 553: assert(*more);
! 554:
! 555: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fn, NULL, more))
! 556: return(0);
! 557: if ( ! mlg_string(p, start, *more++))
! 558: return(0);
! 559: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fn))
! 560: return(0);
! 561:
! 562: if (NULL == *more)
! 563: return(1);
! 564:
! 565: if ( ! ml_nputs(p->mbuf, "(", 1, &p->pos))
! 566: return(0);
! 567:
! 568: p->flags |= ML_OVERRIDE_ONE;
! 569:
! 570: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more))
! 571: return(0);
! 572: if ( ! mlg_string(p, start, *more++))
! 573: return(0);
! 574: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa))
! 575: return(0);
! 576:
! 577: while (*more) {
! 578: if ( ! ml_nputs(p->mbuf, ", ", 2, &p->pos))
! 579: return(0);
! 580: if ( ! mlg_begintag(p, MD_NS_INLINE, ROFF_Fa, NULL, more))
! 581: return(0);
! 582: if ( ! mlg_string(p, start, *more++))
! 583: return(0);
! 584: if ( ! mlg_endtag(p, MD_NS_INLINE, ROFF_Fa))
! 585: return(0);
! 586: }
! 587:
! 588: return(ml_nputs(p->mbuf, ")", 1, &p->pos));
! 589: }
! 590:
! 591:
1.16 kristaps 592: /* ARGSUSED */
1.1 kristaps 593: static int
1.16 kristaps 594: mlg_roffspecial(void *arg, int tok, const char *start,
1.20 ! kristaps 595: const int *argc, const char **argv, const char **more)
1.1 kristaps 596: {
597: struct md_mlg *p;
598:
599: assert(arg);
600: p = (struct md_mlg *)arg;
601:
602: switch (tok) {
1.15 kristaps 603: case (ROFF_Ns):
604: p->flags |= ML_OVERRIDE_ONE;
605: return(1);
1.20 ! kristaps 606:
1.15 kristaps 607: case (ROFF_Sm):
608: assert(*more);
609: if (0 == strcmp(*more, "on"))
610: p->flags |= ML_OVERRIDE_ALL;
611: else
612: p->flags &= ~ML_OVERRIDE_ALL;
613: return(1);
1.18 kristaps 614:
615: case (ROFF_Fn):
1.20 ! kristaps 616: return(mlg_function_special(p, start, more));
1.16 kristaps 617:
1.8 kristaps 618: case (ROFF_Xr):
1.20 ! kristaps 619: return(mlg_ref_special(p, tok, start, more));
! 620:
! 621: case (ROFF_Sx): /* FIXME */
1.15 kristaps 622: /* FALLTHROUGH */
1.12 kristaps 623: case (ROFF_Nm):
1.20 ! kristaps 624: return(mlg_atom_special(p, tok, start, more));
1.18 kristaps 625:
626: case (ROFF_In):
627: /* NOTREACHED */
1.13 kristaps 628: case (ROFF_Ex):
1.17 kristaps 629: /* NOTREACHED */
630: case (ROFF_Rv):
1.20 ! kristaps 631: return(mlg_formatted_special(p, tok,
! 632: argc, argv, more));
1.19 kristaps 633:
1.15 kristaps 634: case (ROFF_At):
1.20 ! kristaps 635: /* FALLTHROUGH */
! 636: case (ROFF_Bt):
! 637: /* FALLTHROUGH */
! 638: case (ROFF_Ud):
! 639: /* FALLTHROUGH */
! 640: case (ROFF_Ux):
! 641: /* FALLTHROUGH */
1.15 kristaps 642: case (ROFF_Bx):
643: /* FALLTHROUGH */
644: case (ROFF_Bsx):
645: /* FALLTHROUGH */
646: case (ROFF_Fx):
647: /* FALLTHROUGH */
648: case (ROFF_Nx):
649: /* FALLTHROUGH */
1.20 ! kristaps 650: case (ROFF_St):
! 651: /* FALLTHROUGH */
1.15 kristaps 652: case (ROFF_Ox):
1.20 ! kristaps 653: return(mlg_literal_special(p, tok, start,
! 654: argc, argv, more));
! 655: default:
1.15 kristaps 656: break;
1.1 kristaps 657: }
658:
1.20 ! kristaps 659: mlg_err(p, start, start, "`%s' not yet supported",
! 660: toknames[tok]);
! 661: return(0);
1.1 kristaps 662: }
663:
664:
665: static int
1.20 ! kristaps 666: mlg_roffblkin(void *arg, int tok,
! 667: int *argc, const char **argv)
1.1 kristaps 668: {
669:
1.8 kristaps 670: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 671: MD_NS_BLOCK, tok, argc, argv));
672: }
673:
674:
675: static int
676: mlg_roffblkout(void *arg, int tok)
677: {
678:
1.9 kristaps 679: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BLOCK, tok));
1.2 kristaps 680: }
681:
682:
683: static int
1.20 ! kristaps 684: mlg_roffblkbodyin(void *arg, int tok,
! 685: int *argc, const char **argv)
1.2 kristaps 686: {
687:
1.8 kristaps 688: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 689: MD_NS_BODY, tok, argc, argv));
690: }
1.1 kristaps 691:
692:
1.2 kristaps 693: static int
694: mlg_roffblkbodyout(void *arg, int tok)
695: {
1.1 kristaps 696:
1.9 kristaps 697: return(mlg_endtag((struct md_mlg *)arg, MD_NS_BODY, tok));
1.1 kristaps 698: }
699:
700:
701: static int
1.20 ! kristaps 702: mlg_roffblkheadin(void *arg, int tok,
! 703: int *argc, const char **argv)
1.1 kristaps 704: {
705:
1.8 kristaps 706: return(mlg_begintag((struct md_mlg *)arg,
1.2 kristaps 707: MD_NS_HEAD, tok, argc, argv));
708: }
1.1 kristaps 709:
710:
1.2 kristaps 711: static int
712: mlg_roffblkheadout(void *arg, int tok)
713: {
1.1 kristaps 714:
1.9 kristaps 715: return(mlg_endtag((struct md_mlg *)arg, MD_NS_HEAD, tok));
1.1 kristaps 716: }
717:
718:
719: static int
1.20 ! kristaps 720: mlg_roffin(void *arg, int tok, int *argc, const char **argv)
1.1 kristaps 721: {
722:
1.8 kristaps 723: return(mlg_begintag((struct md_mlg *)arg,
724: MD_NS_INLINE, tok, argc, argv));
1.1 kristaps 725: }
726:
727:
728: static int
729: mlg_roffout(void *arg, int tok)
730: {
731:
1.9 kristaps 732: return(mlg_endtag((struct md_mlg *)arg, MD_NS_INLINE, tok));
1.1 kristaps 733: }
734:
735:
736: static void
1.20 ! kristaps 737: mlg_roffmsg(void *arg, enum roffmsg lvl, const char *buf,
! 738: const char *pos, const char *msg)
1.1 kristaps 739: {
1.5 kristaps 740:
741: mlg_msg((struct md_mlg *)arg, lvl, buf, pos, msg);
742: }
743:
744:
745: static int
1.20 ! kristaps 746: mlg_roffdata(void *arg, int space,
! 747: const char *start, const char *buf)
1.5 kristaps 748: {
1.1 kristaps 749: struct md_mlg *p;
750:
751: assert(arg);
752: p = (struct md_mlg *)arg;
753:
1.5 kristaps 754: if ( ! mlg_data(p, space, start, buf))
755: return(0);
756:
757: mlg_mode(p, MD_TEXT);
758: return(1);
759: }
760:
761:
762: static void
1.13 kristaps 763: mlg_vmsg(struct md_mlg *p, enum roffmsg lvl, const char *start,
764: const char *pos, const char *fmt, va_list ap)
1.5 kristaps 765: {
1.13 kristaps 766: char buf[128];
1.5 kristaps 767:
1.13 kristaps 768: (void)vsnprintf(buf, sizeof(buf), fmt, ap);
769: mlg_msg(p, lvl, start, pos, buf);
1.5 kristaps 770: }
771:
772:
773: static void
1.13 kristaps 774: mlg_err(struct md_mlg *p, const char *start,
775: const char *pos, const char *fmt, ...)
776: {
777: va_list ap;
778:
779: va_start(ap, fmt);
780: mlg_vmsg(p, ROFF_ERROR, start, pos, fmt, ap);
781: va_end(ap);
1.5 kristaps 782: }
783:
784:
785: static void
786: mlg_msg(struct md_mlg *p, enum roffmsg lvl,
1.20 ! kristaps 787: const char *buf, const char *pos, const char *msg)
1.5 kristaps 788: {
789: char *level;
790:
1.1 kristaps 791: switch (lvl) {
792: case (ROFF_WARN):
793: if ( ! (MD_WARN_ALL & p->args->warnings))
794: return;
795: level = "warning";
796: break;
797: case (ROFF_ERROR):
798: level = "error";
799: break;
800: default:
801: abort();
802: }
803:
804: if (pos)
805: (void)fprintf(stderr, "%s:%zu: %s: %s (column %zu)\n",
806: p->rbuf->name, p->rbuf->line, level,
807: msg, pos - buf);
808: else
809: (void)fprintf(stderr, "%s: %s: %s\n",
810: p->rbuf->name, level, msg);
811: }
CVSweb