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