Annotation of mandoc/term.c, Revision 1.14
1.14 ! kristaps 1: /* $Id: term.c,v 1.13 2009/02/24 13:46:54 kristaps Exp $ */
1.1 kristaps 2: /*
1.10 kristaps 3: * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 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 <stdlib.h>
21: #include <string.h>
22:
1.10 kristaps 23: #include "term.h"
24:
25: #define INDENT 4
26:
27: /*
28: * Performs actions on nodes of the abstract syntax tree. Both pre- and
29: * post-fix operations are defined here.
30: */
31:
32: /* FIXME: indent/tab. */
1.12 kristaps 33: /* FIXME: handle nested lists. */
1.10 kristaps 34:
35: #define TTYPE_PROG 0
36: #define TTYPE_CMD_FLAG 1
37: #define TTYPE_CMD_ARG 2
38: #define TTYPE_SECTION 3
39: #define TTYPE_FUNC_DECL 4
40: #define TTYPE_VAR_DECL 5
41: #define TTYPE_FUNC_TYPE 6
42: #define TTYPE_FUNC_NAME 7
43: #define TTYPE_FUNC_ARG 8
44: #define TTYPE_LINK 9
45: #define TTYPE_SSECTION 10
46: #define TTYPE_FILE 11
1.11 kristaps 47: #define TTYPE_EMPH 12
1.14 ! kristaps 48: #define TTYPE_CONFIG 13
! 49: #define TTYPE_CMD 14
! 50: #define TTYPE_INCLUDE 15
! 51: #define TTYPE_NMAX 16
1.10 kristaps 52:
53: /*
54: * These define "styles" for element types, like command arguments or
55: * executable names. This is useful when multiple macros must decorate
56: * the same thing (like .Ex -std cmd and .Nm cmd).
57: */
58:
59: const int ttypes[TTYPE_NMAX] = {
60: TERMP_BOLD, /* TTYPE_PROG */
61: TERMP_BOLD, /* TTYPE_CMD_FLAG */
62: TERMP_UNDERLINE, /* TTYPE_CMD_ARG */
63: TERMP_BOLD, /* TTYPE_SECTION */
64: TERMP_BOLD, /* TTYPE_FUNC_DECL */
65: TERMP_UNDERLINE, /* TTYPE_VAR_DECL */
66: TERMP_UNDERLINE, /* TTYPE_FUNC_TYPE */
67: TERMP_BOLD, /* TTYPE_FUNC_NAME */
68: TERMP_UNDERLINE, /* TTYPE_FUNC_ARG */
69: TERMP_UNDERLINE, /* TTYPE_LINK */
70: TERMP_BOLD, /* TTYPE_SSECTION */
1.11 kristaps 71: TERMP_UNDERLINE, /* TTYPE_FILE */
1.14 ! kristaps 72: TERMP_UNDERLINE, /* TTYPE_EMPH */
! 73: TERMP_BOLD, /* TTYPE_CONFIG */
! 74: TERMP_BOLD, /* TTYPE_CMD */
! 75: TERMP_BOLD /* TTYPE_INCLUDE */
1.10 kristaps 76: };
1.7 kristaps 77:
1.10 kristaps 78: static int arg_hasattr(int, size_t,
79: const struct mdoc_arg *);
80: static int arg_getattr(int, size_t,
81: const struct mdoc_arg *);
1.12 kristaps 82: static size_t arg_offset(const struct mdoc_arg *);
83: static size_t arg_width(const struct mdoc_arg *);
1.10 kristaps 84:
85: /*
86: * What follows describes prefix and postfix operations for the abstract
87: * syntax tree descent.
88: */
1.1 kristaps 89:
1.10 kristaps 90: #define DECL_ARGS \
91: struct termp *p, \
92: const struct mdoc_meta *meta, \
93: const struct mdoc_node *node
94:
95: #define DECL_PRE(name) \
96: static int name##_pre(DECL_ARGS)
97: #define DECL_POST(name) \
98: static void name##_post(DECL_ARGS)
99: #define DECL_PREPOST(name) \
100: DECL_PRE(name); \
101: DECL_POST(name);
102:
103: DECL_PREPOST(termp_aq);
104: DECL_PREPOST(termp_ar);
1.12 kristaps 105: DECL_PREPOST(termp_bd);
1.14 ! kristaps 106: DECL_PREPOST(termp_cd);
! 107: DECL_PREPOST(termp_cm);
1.10 kristaps 108: DECL_PREPOST(termp_d1);
109: DECL_PREPOST(termp_dq);
1.11 kristaps 110: DECL_PREPOST(termp_em);
1.10 kristaps 111: DECL_PREPOST(termp_fa);
112: DECL_PREPOST(termp_fd);
113: DECL_PREPOST(termp_fl);
114: DECL_PREPOST(termp_fn);
115: DECL_PREPOST(termp_ft);
1.14 ! kristaps 116: DECL_PREPOST(termp_ic);
! 117: DECL_PREPOST(termp_in);
1.10 kristaps 118: DECL_PREPOST(termp_it);
119: DECL_PREPOST(termp_nm);
120: DECL_PREPOST(termp_op);
121: DECL_PREPOST(termp_pa);
122: DECL_PREPOST(termp_pf);
1.11 kristaps 123: DECL_PREPOST(termp_qo);
1.10 kristaps 124: DECL_PREPOST(termp_qq);
125: DECL_PREPOST(termp_sh);
126: DECL_PREPOST(termp_ss);
127: DECL_PREPOST(termp_sq);
128: DECL_PREPOST(termp_sx);
129: DECL_PREPOST(termp_va);
130: DECL_PREPOST(termp_vt);
131:
1.14 ! kristaps 132: DECL_PRE(termp_at);
1.10 kristaps 133: DECL_PRE(termp_bx);
134: DECL_PRE(termp_ex);
135: DECL_PRE(termp_nd);
136: DECL_PRE(termp_ns);
137: DECL_PRE(termp_nx);
138: DECL_PRE(termp_ox);
139: DECL_PRE(termp_pp);
1.14 ! kristaps 140: DECL_PRE(termp_rv);
! 141: DECL_PRE(termp_st);
1.10 kristaps 142: DECL_PRE(termp_ud);
143: DECL_PRE(termp_xr);
144:
145: DECL_POST(termp_bl);
146:
147: const struct termact __termacts[MDOC_MAX] = {
148: { NULL, NULL }, /* \" */
149: { NULL, NULL }, /* Dd */
150: { NULL, NULL }, /* Dt */
151: { NULL, NULL }, /* Os */
152: { termp_sh_pre, termp_sh_post }, /* Sh */
153: { termp_ss_pre, termp_ss_post }, /* Ss */
154: { termp_pp_pre, NULL }, /* Pp */
155: { termp_d1_pre, termp_d1_post }, /* D1 */
156: { NULL, NULL }, /* Dl */
1.12 kristaps 157: { termp_bd_pre, termp_bd_post }, /* Bd */
1.10 kristaps 158: { NULL, NULL }, /* Ed */
159: { NULL, termp_bl_post }, /* Bl */
160: { NULL, NULL }, /* El */
161: { termp_it_pre, termp_it_post }, /* It */
162: { NULL, NULL }, /* Ad */
163: { NULL, NULL }, /* An */
164: { termp_ar_pre, termp_ar_post }, /* Ar */
1.14 ! kristaps 165: { termp_cd_pre, termp_cd_post }, /* Cd */
! 166: { termp_cm_pre, termp_cm_post }, /* Cm */
1.10 kristaps 167: { NULL, NULL }, /* Dv */
168: { NULL, NULL }, /* Er */
169: { NULL, NULL }, /* Ev */
170: { termp_ex_pre, NULL }, /* Ex */
171: { termp_fa_pre, termp_fa_post }, /* Fa */
172: { termp_fd_pre, termp_fd_post }, /* Fd */
173: { termp_fl_pre, termp_fl_post }, /* Fl */
174: { termp_fn_pre, termp_fn_post }, /* Fn */
175: { termp_ft_pre, termp_ft_post }, /* Ft */
1.14 ! kristaps 176: { termp_ic_pre, termp_ic_post }, /* Ic */
! 177: { termp_in_pre, termp_in_post }, /* In */
1.10 kristaps 178: { NULL, NULL }, /* Li */
179: { termp_nd_pre, NULL }, /* Nd */
180: { termp_nm_pre, termp_nm_post }, /* Nm */
181: { termp_op_pre, termp_op_post }, /* Op */
182: { NULL, NULL }, /* Ot */
183: { termp_pa_pre, termp_pa_post }, /* Pa */
1.14 ! kristaps 184: { termp_rv_pre, NULL }, /* Rv */
! 185: { termp_st_pre, NULL }, /* St */
1.10 kristaps 186: { termp_va_pre, termp_va_post }, /* Va */
187: { termp_vt_pre, termp_vt_post }, /* Vt */
188: { termp_xr_pre, NULL }, /* Xr */
189: { NULL, NULL }, /* %A */
190: { NULL, NULL }, /* %B */
191: { NULL, NULL }, /* %D */
192: { NULL, NULL }, /* %I */
193: { NULL, NULL }, /* %J */
194: { NULL, NULL }, /* %N */
195: { NULL, NULL }, /* %O */
196: { NULL, NULL }, /* %P */
197: { NULL, NULL }, /* %R */
198: { NULL, NULL }, /* %T */
199: { NULL, NULL }, /* %V */
200: { NULL, NULL }, /* Ac */
1.14 ! kristaps 201: { termp_aq_pre, termp_aq_post }, /* Ao */
1.10 kristaps 202: { termp_aq_pre, termp_aq_post }, /* Aq */
1.14 ! kristaps 203: { termp_at_pre, NULL }, /* At */
1.10 kristaps 204: { NULL, NULL }, /* Bc */
205: { NULL, NULL }, /* Bf */
206: { NULL, NULL }, /* Bo */
207: { NULL, NULL }, /* Bq */
208: { NULL, NULL }, /* Bsx */
209: { termp_bx_pre, NULL }, /* Bx */
210: { NULL, NULL }, /* Db */
211: { NULL, NULL }, /* Dc */
212: { NULL, NULL }, /* Do */
213: { termp_dq_pre, termp_dq_post }, /* Dq */
214: { NULL, NULL }, /* Ec */
215: { NULL, NULL }, /* Ef */
1.11 kristaps 216: { termp_em_pre, termp_em_post }, /* Em */
1.10 kristaps 217: { NULL, NULL }, /* Eo */
218: { NULL, NULL }, /* Fx */
219: { NULL, NULL }, /* Ms */
220: { NULL, NULL }, /* No */
221: { termp_ns_pre, NULL }, /* Ns */
222: { termp_nx_pre, NULL }, /* Nx */
223: { termp_ox_pre, NULL }, /* Ox */
224: { NULL, NULL }, /* Pc */
225: { termp_pf_pre, termp_pf_post }, /* Pf */
226: { NULL, NULL }, /* Po */
227: { NULL, NULL }, /* Pq */
228: { NULL, NULL }, /* Qc */
229: { NULL, NULL }, /* Ql */
1.11 kristaps 230: { termp_qo_pre, termp_qo_post }, /* Qo */
1.10 kristaps 231: { termp_qq_pre, termp_qq_post }, /* Qq */
232: { NULL, NULL }, /* Re */
233: { NULL, NULL }, /* Rs */
234: { NULL, NULL }, /* Sc */
235: { NULL, NULL }, /* So */
236: { termp_sq_pre, termp_sq_post }, /* Sq */
237: { NULL, NULL }, /* Sm */
238: { termp_sx_pre, termp_sx_post }, /* Sx */
239: { NULL, NULL }, /* Sy */
240: { NULL, NULL }, /* Tn */
241: { NULL, NULL }, /* Ux */
242: { NULL, NULL }, /* Xc */
243: { NULL, NULL }, /* Xo */
244: { NULL, NULL }, /* Fo */
245: { NULL, NULL }, /* Fc */
246: { NULL, NULL }, /* Oo */
247: { NULL, NULL }, /* Oc */
248: { NULL, NULL }, /* Bk */
249: { NULL, NULL }, /* Ek */
250: { NULL, NULL }, /* Bt */
251: { NULL, NULL }, /* Hf */
252: { NULL, NULL }, /* Fr */
253: { termp_ud_pre, NULL }, /* Ud */
1.2 kristaps 254: };
255:
1.10 kristaps 256: const struct termact *termacts = __termacts;
257:
258:
259: static size_t
1.12 kristaps 260: arg_width(const struct mdoc_arg *arg)
1.10 kristaps 261: {
1.12 kristaps 262:
263: /* TODO */
264: assert(*arg->value);
265: return(strlen(*arg->value));
266: }
267:
268:
269: static size_t
270: arg_offset(const struct mdoc_arg *arg)
271: {
272:
273: /* TODO */
274: assert(*arg->value);
275: if (0 == strcmp(*arg->value, "indent"))
1.10 kristaps 276: return(INDENT);
1.12 kristaps 277: if (0 == strcmp(*arg->value, "indent-two"))
1.10 kristaps 278: return(INDENT * 2);
279:
1.12 kristaps 280: return(strlen(*arg->value));
1.10 kristaps 281: }
282:
1.3 kristaps 283:
1.10 kristaps 284: static int
285: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
1.2 kristaps 286: {
287:
1.10 kristaps 288: return(-1 != arg_getattr(arg, argc, argv));
289: }
290:
291:
292: static int
293: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
294: {
295: int i;
296:
297: for (i = 0; i < (int)argc; i++)
298: if (argv[i].arg == arg)
299: return(i);
300: return(-1);
301: }
302:
303:
304: /* ARGSUSED */
305: static int
306: termp_dq_pre(DECL_ARGS)
307: {
308:
309: if (MDOC_BODY != node->type)
310: return(1);
311:
312: word(p, "``");
313: p->flags |= TERMP_NOSPACE;
314: return(1);
315: }
316:
317:
318: /* ARGSUSED */
319: static void
320: termp_dq_post(DECL_ARGS)
321: {
322:
323: if (MDOC_BODY != node->type)
324: return;
1.3 kristaps 325:
1.10 kristaps 326: p->flags |= TERMP_NOSPACE;
327: word(p, "''");
328: }
1.2 kristaps 329:
1.3 kristaps 330:
1.10 kristaps 331: /* ARGSUSED */
332: static void
333: termp_it_post(DECL_ARGS)
334: {
335: const struct mdoc_node *n, *it;
336: const struct mdoc_block *bl;
337: int i;
1.12 kristaps 338: size_t width, offset;
1.2 kristaps 339:
1.8 kristaps 340: /*
1.10 kristaps 341: * This (and termp_it_pre()) are the most complicated functions
342: * here. They must account for a considerable number of
343: * switches that completely change the output behaviour, like
344: * -tag versus -column. Yech.
1.8 kristaps 345: */
1.10 kristaps 346:
347: switch (node->type) {
348: case (MDOC_BODY):
349: /* FALLTHROUGH */
350: case (MDOC_HEAD):
351: break;
352: default:
1.8 kristaps 353: return;
354: }
355:
1.10 kristaps 356: it = node->parent;
357: assert(MDOC_BLOCK == it->type);
358: assert(MDOC_It == it->tok);
359:
360: n = it->parent;
361: assert(MDOC_BODY == n->type);
362: assert(MDOC_Bl == n->tok);
363: n = n->parent;
364: bl = &n->data.block;
365:
366: /* If `-tag', adjust our margins accordingly. */
367:
368: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.12 kristaps 369: flushln(p);
370:
371: /* FIXME: this should auto-size. */
1.10 kristaps 372: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
1.12 kristaps 373: width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
374:
375: /* FIXME: nesting! Should happen at block. */
376: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
377: offset = i >= 0 ? arg_width(&bl->argv[i]) : 0;
1.10 kristaps 378:
379: if (MDOC_HEAD == node->type) {
380: p->rmargin = p->maxrmargin;
1.12 kristaps 381: p->offset -= offset;
1.10 kristaps 382: p->flags &= ~TERMP_NOBREAK;
383: } else {
1.12 kristaps 384: p->offset -= width;
1.10 kristaps 385: p->flags &= ~TERMP_NOLPAD;
1.2 kristaps 386: }
1.10 kristaps 387: }
1.2 kristaps 388:
1.10 kristaps 389: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
390: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1.12 kristaps 391: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.3 kristaps 392:
1.10 kristaps 393: flushln(p);
1.12 kristaps 394: p->offset -= offset;
1.10 kristaps 395: return;
1.2 kristaps 396: }
1.10 kristaps 397: }
398:
399:
400: /* ARGSUSED */
401: static int
402: termp_it_pre(DECL_ARGS)
403: {
404: const struct mdoc_node *n, *it;
405: const struct mdoc_block *bl;
406: int i;
1.12 kristaps 407: size_t width, offset;
1.2 kristaps 408:
1.3 kristaps 409: /*
1.10 kristaps 410: * Also see termp_it_post() for general comments.
1.3 kristaps 411: */
412:
1.10 kristaps 413: switch (node->type) {
414: case (MDOC_BODY):
415: /* FALLTHROUGH */
416: case (MDOC_HEAD):
417: it = node->parent;
418: break;
419: case (MDOC_BLOCK):
420: it = node;
421: break;
422: default:
423: return(1);
424: }
425:
426: assert(MDOC_BLOCK == it->type);
427: assert(MDOC_It == it->tok);
428:
429: n = it->parent;
430: assert(MDOC_BODY == n->type);
431: assert(MDOC_Bl == n->tok);
432: n = n->parent;
433: bl = &n->data.block;
434:
435: /* If `-compact', don't assert vertical space. */
436:
437: if (MDOC_BLOCK == node->type) {
438: if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
439: newln(p);
440: else
441: vspace(p);
442: return(1);
443: }
444:
445: assert(MDOC_HEAD == node->type
446: || MDOC_BODY == node->type);
447:
1.12 kristaps 448: /* FIXME: see termp_it_post(). */
449:
1.10 kristaps 450: /* If `-tag', adjust our margins accordingly. */
451:
452: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.12 kristaps 453: p->flags |= TERMP_NOSPACE;
454:
1.10 kristaps 455: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
1.12 kristaps 456: width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
1.10 kristaps 457:
1.12 kristaps 458: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
459: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.10 kristaps 460:
461: if (MDOC_HEAD == node->type) {
462: p->flags |= TERMP_NOBREAK;
1.12 kristaps 463: p->offset += offset;
1.10 kristaps 464: p->rmargin = p->offset + width;
465: } else {
466: p->flags |= TERMP_NOSPACE;
467: p->flags |= TERMP_NOLPAD;
1.12 kristaps 468: p->offset += width;
1.10 kristaps 469: }
470: return(1);
471: }
472:
473: /* If `-ohang', adjust left-margin. */
474:
475: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
476: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1.12 kristaps 477: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.10 kristaps 478:
479: p->flags |= TERMP_NOSPACE;
1.12 kristaps 480: p->offset += offset;
1.10 kristaps 481: return(1);
482: }
1.3 kristaps 483:
1.10 kristaps 484: return(1);
1.2 kristaps 485: }
486:
487:
1.10 kristaps 488: /* ARGSUSED */
489: static void
490: termp_nm_post(DECL_ARGS)
491: {
492:
493: p->flags &= ~ttypes[TTYPE_PROG];
494: }
495:
496:
497: /* ARGSUSED */
498: static void
499: termp_fl_post(DECL_ARGS)
500: {
501:
502: p->flags &= ~ttypes[TTYPE_CMD_FLAG];
503: }
504:
505:
506: /* ARGSUSED */
507: static int
508: termp_ar_pre(DECL_ARGS)
509: {
510:
511: p->flags |= ttypes[TTYPE_CMD_ARG];
512: if (NULL == node->child)
513: word(p, "...");
514: return(1);
515: }
516:
517:
518: /* ARGSUSED */
519: static int
520: termp_nm_pre(DECL_ARGS)
521: {
522:
523: p->flags |= ttypes[TTYPE_PROG];
524: if (NULL == node->child)
525: word(p, meta->name);
526: return(1);
527: }
528:
529:
530: /* ARGSUSED */
531: static int
532: termp_ns_pre(DECL_ARGS)
1.2 kristaps 533: {
534:
535: p->flags |= TERMP_NOSPACE;
1.10 kristaps 536: return(1);
537: }
538:
539:
540: /* ARGSUSED */
541: static int
542: termp_pp_pre(DECL_ARGS)
543: {
544:
545: vspace(p);
546: return(1);
547: }
548:
549:
550: /* ARGSUSED */
551: static void
552: termp_ar_post(DECL_ARGS)
553: {
554:
555: p->flags &= ~ttypes[TTYPE_CMD_ARG];
556: }
557:
558:
559: /* ARGSUSED */
560: static int
1.14 ! kristaps 561: termp_st_pre(DECL_ARGS)
! 562: {
! 563: const char *tp;
! 564:
! 565: assert(1 == node->data.elem.argc);
! 566:
! 567: tp = mdoc_st2a(node->data.elem.argv[0].arg);
! 568: word(p, tp);
! 569:
! 570: return(1);
! 571: }
! 572:
! 573:
! 574: /* ARGSUSED */
! 575: static int
! 576: termp_rv_pre(DECL_ARGS)
! 577: {
! 578: int i;
! 579:
! 580: i = arg_getattr(MDOC_Std, node->data.elem.argc,
! 581: node->data.elem.argv);
! 582: assert(i >= 0);
! 583:
! 584: newln(p);
! 585: word(p, "The");
! 586:
! 587: p->flags |= ttypes[TTYPE_FUNC_NAME];
! 588: word(p, *node->data.elem.argv[i].value);
! 589: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
! 590:
! 591: word(p, "() function returns the value 0 if successful;");
! 592: word(p, "otherwise the value -1 is returned and the");
! 593: word(p, "global variable");
! 594:
! 595: p->flags |= ttypes[TTYPE_VAR_DECL];
! 596: word(p, "errno");
! 597: p->flags &= ~ttypes[TTYPE_VAR_DECL];
! 598:
! 599: word(p, "is set to indicate the error.");
! 600:
! 601: return(1);
! 602: }
! 603:
! 604:
! 605: /* ARGSUSED */
! 606: static int
1.10 kristaps 607: termp_ex_pre(DECL_ARGS)
608: {
609: int i;
610:
611: i = arg_getattr(MDOC_Std, node->data.elem.argc,
612: node->data.elem.argv);
613: assert(i >= 0);
614:
615: word(p, "The");
616: p->flags |= ttypes[TTYPE_PROG];
617: word(p, *node->data.elem.argv[i].value);
618: p->flags &= ~ttypes[TTYPE_PROG];
619: word(p, "utility exits 0 on success, and >0 if an error occurs.");
620:
621: return(1);
622: }
623:
624:
625: /* ARGSUSED */
626: static int
627: termp_nd_pre(DECL_ARGS)
628: {
629:
630: word(p, "\\-");
631: return(1);
632: }
633:
634:
635: /* ARGSUSED */
636: static void
637: termp_bl_post(DECL_ARGS)
638: {
639:
640: if (MDOC_BLOCK == node->type)
641: newln(p);
642: }
643:
644:
645: /* ARGSUSED */
646: static void
647: termp_op_post(DECL_ARGS)
648: {
649:
650: if (MDOC_BODY != node->type)
1.2 kristaps 651: return;
1.10 kristaps 652: p->flags |= TERMP_NOSPACE;
653: word(p, "\\(rB");
654: }
655:
656:
657: /* ARGSUSED */
658: static void
659: termp_sh_post(DECL_ARGS)
660: {
661:
662: switch (node->type) {
663: case (MDOC_HEAD):
664: p->flags &= ~ttypes[TTYPE_SECTION];
665: newln(p);
666: break;
667: case (MDOC_BODY):
668: newln(p);
669: p->offset = 0;
670: break;
671: default:
672: break;
673: }
674: }
675:
676:
677: /* ARGSUSED */
678: static int
679: termp_xr_pre(DECL_ARGS)
680: {
681: const struct mdoc_node *n;
682:
683: n = node->child;
684: assert(n);
685:
686: assert(MDOC_TEXT == n->type);
687: word(p, n->data.text.string);
688:
689: if (NULL == (n = n->next))
690: return(0);
691:
692: assert(MDOC_TEXT == n->type);
693: p->flags |= TERMP_NOSPACE;
694: word(p, "(");
695: p->flags |= TERMP_NOSPACE;
696: word(p, n->data.text.string);
697: p->flags |= TERMP_NOSPACE;
698: word(p, ")");
699:
700: return(0);
1.2 kristaps 701: }
702:
703:
1.10 kristaps 704: /* ARGSUSED */
705: static int
706: termp_vt_pre(DECL_ARGS)
1.2 kristaps 707: {
708:
1.10 kristaps 709: /* FIXME: this can be "type name". */
710: p->flags |= ttypes[TTYPE_VAR_DECL];
711: return(1);
1.2 kristaps 712: }
713:
714:
1.10 kristaps 715: /* ARGSUSED */
1.2 kristaps 716: static void
1.10 kristaps 717: termp_vt_post(DECL_ARGS)
718: {
719:
720: p->flags &= ~ttypes[TTYPE_VAR_DECL];
721: if (node->sec == SEC_SYNOPSIS)
722: vspace(p);
723: }
724:
725:
726: /* ARGSUSED */
727: static int
728: termp_fd_pre(DECL_ARGS)
1.2 kristaps 729: {
730:
1.10 kristaps 731: /*
732: * FIXME: this naming is bad. This value is used, in general,
733: * for the #include header or other preprocessor statement.
734: */
735: p->flags |= ttypes[TTYPE_FUNC_DECL];
736: return(1);
1.2 kristaps 737: }
738:
739:
1.10 kristaps 740: /* ARGSUSED */
1.2 kristaps 741: static void
1.10 kristaps 742: termp_fd_post(DECL_ARGS)
1.2 kristaps 743: {
744:
1.10 kristaps 745: p->flags &= ~ttypes[TTYPE_FUNC_DECL];
746: if (node->sec == SEC_SYNOPSIS)
747: vspace(p);
748:
749: }
750:
751:
752: /* ARGSUSED */
753: static int
754: termp_sh_pre(DECL_ARGS)
755: {
1.2 kristaps 756:
1.10 kristaps 757: switch (node->type) {
758: case (MDOC_HEAD):
759: vspace(p);
760: p->flags |= ttypes[TTYPE_SECTION];
1.2 kristaps 761: break;
1.10 kristaps 762: case (MDOC_BODY):
763: p->offset = INDENT;
1.2 kristaps 764: break;
1.10 kristaps 765: default:
766: break;
767: }
768: return(1);
769: }
770:
771:
772: /* ARGSUSED */
773: static int
774: termp_op_pre(DECL_ARGS)
775: {
776:
777: switch (node->type) {
778: case (MDOC_BODY):
779: word(p, "\\(lB");
780: p->flags |= TERMP_NOSPACE;
1.2 kristaps 781: break;
782: default:
1.10 kristaps 783: break;
1.2 kristaps 784: }
1.10 kristaps 785: return(1);
786: }
787:
788:
789: /* ARGSUSED */
790: static int
791: termp_ud_pre(DECL_ARGS)
792: {
793:
794: word(p, "currently under development.");
795: return(1);
796: }
797:
798:
799: /* ARGSUSED */
800: static int
801: termp_fl_pre(DECL_ARGS)
802: {
803:
804: p->flags |= ttypes[TTYPE_CMD_FLAG];
805: word(p, "\\-");
806: p->flags |= TERMP_NOSPACE;
807: return(1);
808: }
809:
810:
811: /* ARGSUSED */
812: static int
813: termp_d1_pre(DECL_ARGS)
814: {
815:
816: if (MDOC_BODY != node->type)
817: return(1);
818: newln(p);
819: p->offset += INDENT;
820: return(1);
1.2 kristaps 821: }
822:
823:
1.10 kristaps 824: /* ARGSUSED */
1.2 kristaps 825: static void
1.10 kristaps 826: termp_d1_post(DECL_ARGS)
827: {
828:
829: if (MDOC_BODY != node->type)
830: return;
831: newln(p);
832: p->offset -= INDENT;
833: }
834:
835:
836: /* ARGSUSED */
837: static int
838: termp_aq_pre(DECL_ARGS)
1.6 kristaps 839: {
840:
1.10 kristaps 841: if (MDOC_BODY != node->type)
842: return(1);
843: word(p, "<");
844: p->flags |= TERMP_NOSPACE;
845: return(1);
846: }
1.6 kristaps 847:
848:
1.10 kristaps 849: /* ARGSUSED */
850: static void
851: termp_aq_post(DECL_ARGS)
852: {
1.6 kristaps 853:
1.10 kristaps 854: if (MDOC_BODY != node->type)
1.6 kristaps 855: return;
1.10 kristaps 856: p->flags |= TERMP_NOSPACE;
857: word(p, ">");
858: }
1.6 kristaps 859:
1.10 kristaps 860:
861: /* ARGSUSED */
862: static int
863: termp_ft_pre(DECL_ARGS)
864: {
865:
866: p->flags |= ttypes[TTYPE_FUNC_TYPE];
867: return(1);
1.6 kristaps 868: }
869:
870:
1.10 kristaps 871: /* ARGSUSED */
1.6 kristaps 872: static void
1.10 kristaps 873: termp_ft_post(DECL_ARGS)
1.2 kristaps 874: {
875:
1.10 kristaps 876: p->flags &= ~ttypes[TTYPE_FUNC_TYPE];
877: if (node->sec == SEC_SYNOPSIS)
878: newln(p);
879:
880: }
1.2 kristaps 881:
882:
1.10 kristaps 883: /* ARGSUSED */
884: static int
885: termp_fn_pre(DECL_ARGS)
886: {
887: const struct mdoc_node *n;
888:
889: assert(node->child);
890: assert(MDOC_TEXT == node->child->type);
1.2 kristaps 891:
1.10 kristaps 892: /* FIXME: can be "type funcname" "type varname"... */
1.2 kristaps 893:
1.10 kristaps 894: p->flags |= ttypes[TTYPE_FUNC_NAME];
895: word(p, node->child->data.text.string);
896: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
897:
898: p->flags |= TERMP_NOSPACE;
899: word(p, "(");
900:
901: p->flags |= TERMP_NOSPACE;
902: for (n = node->child->next; n; n = n->next) {
903: assert(MDOC_TEXT == n->type);
904: p->flags |= ttypes[TTYPE_FUNC_ARG];
905: word(p, n->data.text.string);
906: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
907: if ((n->next))
908: word(p, ",");
1.6 kristaps 909: }
1.2 kristaps 910:
1.10 kristaps 911: p->flags |= TERMP_NOSPACE;
912: word(p, ")");
913:
914: if (SEC_SYNOPSIS == node->sec)
915: word(p, ";");
916:
917: return(0);
1.2 kristaps 918: }
919:
920:
1.10 kristaps 921: /* ARGSUSED */
922: static void
923: termp_fn_post(DECL_ARGS)
1.2 kristaps 924: {
925:
1.10 kristaps 926: if (node->sec == SEC_SYNOPSIS)
927: vspace(p);
928:
929: }
1.2 kristaps 930:
931:
1.10 kristaps 932: /* ARGSUSED */
933: static int
934: termp_sx_pre(DECL_ARGS)
935: {
1.8 kristaps 936:
1.10 kristaps 937: p->flags |= ttypes[TTYPE_LINK];
938: return(1);
1.2 kristaps 939: }
940:
941:
1.10 kristaps 942: /* ARGSUSED */
1.1 kristaps 943: static void
1.10 kristaps 944: termp_sx_post(DECL_ARGS)
1.2 kristaps 945: {
946:
1.10 kristaps 947: p->flags &= ~ttypes[TTYPE_LINK];
948: }
1.2 kristaps 949:
1.4 kristaps 950:
1.10 kristaps 951: /* ARGSUSED */
952: static int
953: termp_fa_pre(DECL_ARGS)
954: {
1.2 kristaps 955:
1.10 kristaps 956: p->flags |= ttypes[TTYPE_FUNC_ARG];
957: return(1);
958: }
1.2 kristaps 959:
960:
1.10 kristaps 961: /* ARGSUSED */
962: static void
963: termp_fa_post(DECL_ARGS)
964: {
965:
966: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
967: }
1.2 kristaps 968:
969:
1.10 kristaps 970: /* ARGSUSED */
971: static int
972: termp_va_pre(DECL_ARGS)
973: {
1.2 kristaps 974:
1.10 kristaps 975: p->flags |= ttypes[TTYPE_VAR_DECL];
976: return(1);
1.2 kristaps 977: }
978:
979:
1.10 kristaps 980: /* ARGSUSED */
1.2 kristaps 981: static void
1.10 kristaps 982: termp_va_post(DECL_ARGS)
1.1 kristaps 983: {
984:
1.10 kristaps 985: p->flags &= ~ttypes[TTYPE_VAR_DECL];
986: }
1.1 kristaps 987:
1.7 kristaps 988:
1.10 kristaps 989: /* ARGSUSED */
990: static int
991: termp_bd_pre(DECL_ARGS)
992: {
993: const struct mdoc_block *bl;
994: const struct mdoc_node *n;
1.12 kristaps 995: int i;
1.1 kristaps 996:
1.10 kristaps 997: if (MDOC_BLOCK == node->type) {
998: vspace(p);
999: return(1);
1000: } else if (MDOC_BODY != node->type)
1001: return(1);
1002:
1003: assert(MDOC_BLOCK == node->parent->type);
1004:
1005: bl = &node->parent->data.block;
1.12 kristaps 1006:
1007: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1008: if (-1 != i) {
1009: assert(1 == bl->argv[i].sz);
1010: p->offset += arg_offset(&bl->argv[i]);
1011: }
1012:
1.10 kristaps 1013: if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
1014: return(1);
1015:
1016: p->flags |= TERMP_LITERAL;
1017:
1018: for (n = node->child; n; n = n->next) {
1019: assert(MDOC_TEXT == n->type); /* FIXME */
1020: if ((*n->data.text.string)) {
1021: word(p, n->data.text.string);
1022: flushln(p);
1023: } else
1024: vspace(p);
1.1 kristaps 1025:
1.10 kristaps 1026: }
1.1 kristaps 1027:
1.10 kristaps 1028: p->flags &= ~TERMP_LITERAL;
1029: return(0);
1030: }
1.1 kristaps 1031:
1032:
1.10 kristaps 1033: /* ARGSUSED */
1.12 kristaps 1034: static void
1035: termp_bd_post(DECL_ARGS)
1036: {
1037: int i;
1038: const struct mdoc_block *bl;
1039:
1040: if (MDOC_BODY != node->type)
1041: return;
1042:
1043: assert(MDOC_BLOCK == node->parent->type);
1044: bl = &node->parent->data.block;
1045:
1046: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1047: if (-1 != i) {
1048: assert(1 == bl->argv[i].sz);
1049: p->offset -= arg_offset(&bl->argv[i]);
1050: }
1051: }
1052:
1053:
1054: /* ARGSUSED */
1.10 kristaps 1055: static int
1056: termp_qq_pre(DECL_ARGS)
1057: {
1.1 kristaps 1058:
1.10 kristaps 1059: if (MDOC_BODY != node->type)
1060: return(1);
1061: word(p, "\"");
1062: p->flags |= TERMP_NOSPACE;
1063: return(1);
1.1 kristaps 1064: }
1065:
1066:
1.10 kristaps 1067: /* ARGSUSED */
1.1 kristaps 1068: static void
1.10 kristaps 1069: termp_qq_post(DECL_ARGS)
1.1 kristaps 1070: {
1071:
1.10 kristaps 1072: if (MDOC_BODY != node->type)
1073: return;
1074: p->flags |= TERMP_NOSPACE;
1075: word(p, "\"");
1076: }
1077:
1078:
1079: /* ARGSUSED */
1080: static int
1081: termp_bx_pre(DECL_ARGS)
1082: {
1.1 kristaps 1083:
1.10 kristaps 1084: word(p, "BSD");
1085: return(1);
1086: }
1087:
1088:
1089: /* ARGSUSED */
1090: static int
1091: termp_ox_pre(DECL_ARGS)
1092: {
1093:
1094: word(p, "OpenBSD");
1095: return(1);
1096: }
1097:
1098:
1099: /* ARGSUSED */
1100: static int
1101: termp_nx_pre(DECL_ARGS)
1102: {
1103:
1104: word(p, "NetBSD");
1105: return(1);
1106: }
1107:
1108:
1109: /* ARGSUSED */
1110: static int
1111: termp_sq_pre(DECL_ARGS)
1112: {
1113:
1114: if (MDOC_BODY != node->type)
1115: return(1);
1.13 kristaps 1116: word(p, "\'");
1.10 kristaps 1117: p->flags |= TERMP_NOSPACE;
1118: return(1);
1119: }
1.1 kristaps 1120:
1121:
1.10 kristaps 1122: /* ARGSUSED */
1123: static void
1124: termp_sq_post(DECL_ARGS)
1125: {
1126:
1127: if (MDOC_BODY != node->type)
1128: return;
1129: p->flags |= TERMP_NOSPACE;
1130: word(p, "\'");
1131: }
1.2 kristaps 1132:
1133:
1.10 kristaps 1134: /* ARGSUSED */
1135: static int
1136: termp_pf_pre(DECL_ARGS)
1137: {
1.1 kristaps 1138:
1.10 kristaps 1139: p->flags |= TERMP_IGNDELIM;
1140: return(1);
1141: }
1.1 kristaps 1142:
1143:
1.10 kristaps 1144: /* ARGSUSED */
1145: static void
1146: termp_pf_post(DECL_ARGS)
1147: {
1.1 kristaps 1148:
1.10 kristaps 1149: p->flags &= ~TERMP_IGNDELIM;
1150: p->flags |= TERMP_NOSPACE;
1151: }
1.1 kristaps 1152:
1153:
1.10 kristaps 1154: /* ARGSUSED */
1155: static int
1156: termp_ss_pre(DECL_ARGS)
1157: {
1.1 kristaps 1158:
1.10 kristaps 1159: switch (node->type) {
1160: case (MDOC_HEAD):
1161: vspace(p);
1162: p->flags |= ttypes[TTYPE_SSECTION];
1163: p->offset = INDENT / 2;
1164: break;
1165: default:
1166: break;
1167: }
1.1 kristaps 1168:
1.10 kristaps 1169: return(1);
1.1 kristaps 1170: }
1171:
1172:
1.10 kristaps 1173: /* ARGSUSED */
1174: static void
1175: termp_ss_post(DECL_ARGS)
1.1 kristaps 1176: {
1177:
1.10 kristaps 1178: switch (node->type) {
1179: case (MDOC_HEAD):
1180: p->flags &= ~ttypes[TTYPE_SSECTION];
1181: newln(p);
1182: p->offset = INDENT;
1183: break;
1184: default:
1185: break;
1186: }
1187: }
1.2 kristaps 1188:
1189:
1.10 kristaps 1190: /* ARGSUSED */
1191: static int
1192: termp_pa_pre(DECL_ARGS)
1193: {
1.2 kristaps 1194:
1.10 kristaps 1195: p->flags |= ttypes[TTYPE_FILE];
1196: return(1);
1.1 kristaps 1197: }
1198:
1199:
1.10 kristaps 1200: /* ARGSUSED */
1201: static void
1202: termp_pa_post(DECL_ARGS)
1203: {
1204:
1205: p->flags &= ~ttypes[TTYPE_FILE];
1206: }
1.11 kristaps 1207:
1208:
1209: /* ARGSUSED */
1210: static int
1211: termp_qo_pre(DECL_ARGS)
1212: {
1213:
1214: if (MDOC_BODY != node->type)
1215: return(1);
1216: word(p, "\"");
1217: p->flags |= TERMP_NOSPACE;
1218: return(1);
1219: }
1220:
1221:
1222: /* ARGSUSED */
1223: static void
1224: termp_qo_post(DECL_ARGS)
1225: {
1226:
1227: if (MDOC_BODY != node->type)
1228: return;
1229: p->flags |= TERMP_NOSPACE;
1230: word(p, "\"");
1231: }
1232:
1233:
1234: /* ARGSUSED */
1235: static int
1236: termp_em_pre(DECL_ARGS)
1237: {
1238:
1239: p->flags |= ttypes[TTYPE_EMPH];
1240: return(1);
1241: }
1242:
1243:
1244: /* ARGSUSED */
1245: static void
1246: termp_em_post(DECL_ARGS)
1247: {
1248:
1249: p->flags &= ~ttypes[TTYPE_EMPH];
1250: }
1.14 ! kristaps 1251:
! 1252:
! 1253: /* ARGSUSED */
! 1254: static int
! 1255: termp_cd_pre(DECL_ARGS)
! 1256: {
! 1257:
! 1258: p->flags |= ttypes[TTYPE_CONFIG];
! 1259: return(1);
! 1260: }
! 1261:
! 1262:
! 1263: /* ARGSUSED */
! 1264: static void
! 1265: termp_cd_post(DECL_ARGS)
! 1266: {
! 1267:
! 1268: p->flags &= ~ttypes[TTYPE_CONFIG];
! 1269: }
! 1270:
! 1271:
! 1272: /* ARGSUSED */
! 1273: static int
! 1274: termp_cm_pre(DECL_ARGS)
! 1275: {
! 1276:
! 1277: p->flags |= ttypes[TTYPE_CMD_FLAG];
! 1278: return(1);
! 1279: }
! 1280:
! 1281:
! 1282: /* ARGSUSED */
! 1283: static void
! 1284: termp_cm_post(DECL_ARGS)
! 1285: {
! 1286:
! 1287: p->flags &= ~ttypes[TTYPE_CMD_FLAG];
! 1288: }
! 1289:
! 1290:
! 1291: /* ARGSUSED */
! 1292: static int
! 1293: termp_ic_pre(DECL_ARGS)
! 1294: {
! 1295:
! 1296: p->flags |= ttypes[TTYPE_CMD];
! 1297: return(1);
! 1298: }
! 1299:
! 1300:
! 1301: /* ARGSUSED */
! 1302: static void
! 1303: termp_ic_post(DECL_ARGS)
! 1304: {
! 1305:
! 1306: p->flags &= ~ttypes[TTYPE_CMD];
! 1307: }
! 1308:
! 1309:
! 1310: /* ARGSUSED */
! 1311: static int
! 1312: termp_in_pre(DECL_ARGS)
! 1313: {
! 1314:
! 1315: p->flags |= ttypes[TTYPE_INCLUDE];
! 1316: return(1);
! 1317: }
! 1318:
! 1319:
! 1320: /* ARGSUSED */
! 1321: static void
! 1322: termp_in_post(DECL_ARGS)
! 1323: {
! 1324:
! 1325: p->flags &= ~ttypes[TTYPE_INCLUDE];
! 1326: }
! 1327:
! 1328:
! 1329: /* ARGSUSED */
! 1330: static int
! 1331: termp_at_pre(DECL_ARGS)
! 1332: {
! 1333: enum mdoc_att c;
! 1334:
! 1335: c = ATT_DEFAULT;
! 1336: if (node->child) {
! 1337: assert(MDOC_TEXT == node->child->type);
! 1338: c = mdoc_atoatt(node->child->data.text.string);
! 1339: }
! 1340:
! 1341: word(p, mdoc_att2a(c));
! 1342: return(0);
! 1343: }
CVSweb