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