1 /* $Id: mdoc_man.c,v 1.122 2017/06/14 22:51:25 schwarze Exp $ */
2 /*
3 * Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
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 above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include "config.h"
18
19 #include <sys/types.h>
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
185 { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
186 { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
187 { NULL, NULL, post_percent, NULL, NULL }, /* %N */
188 { NULL, NULL, post_percent, NULL, NULL }, /* %O */
189 { NULL, NULL, post_percent, NULL, NULL }, /* %P */
190 { NULL, NULL, post_percent, NULL, NULL }, /* %R */
191 { NULL, pre__t, post__t, NULL, NULL }, /* %T */
192 { NULL, NULL, post_percent, NULL, NULL }, /* %V */
193 { NULL, NULL, NULL, NULL, NULL }, /* Ac */
194 { cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
195 { cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
196 { NULL, NULL, NULL, NULL, NULL }, /* At */
197 { NULL, NULL, NULL, NULL, NULL }, /* Bc */
198 { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
199 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
200 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
201 { NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */
202 { NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */
203 { NULL, pre_skip, NULL, NULL, NULL }, /* Db */
204 { NULL, NULL, NULL, NULL, NULL }, /* Dc */
205 { cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Do */
206 { cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Dq */
207 { NULL, NULL, NULL, NULL, NULL }, /* Ec */
208 { NULL, NULL, NULL, NULL, NULL }, /* Ef */
209 { NULL, pre_em, post_font, NULL, NULL }, /* Em */
210 { cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
211 { NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */
212 { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
213 { NULL, pre_no, NULL, NULL, NULL }, /* No */
214 { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
215 { NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */
216 { NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */
217 { NULL, NULL, NULL, NULL, NULL }, /* Pc */
218 { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
219 { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
220 { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
221 { NULL, NULL, NULL, NULL, NULL }, /* Qc */
222 { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
223 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
224 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
225 { NULL, NULL, NULL, NULL, NULL }, /* Re */
226 { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
593 }
594
595 void
596 man_man(void *arg, const struct roff_man *man)
597 {
598
599 /*
600 * Dump the keep buffer.
601 * We're guaranteed by now that this exists (is non-NULL).
602 * Flush stdout afterward, just in case.
603 */
604 fputs(mparse_getkeep(man_mparse(man)), stdout);
605 fflush(stdout);
606 }
607
608 void
609 man_mdoc(void *arg, const struct roff_man *mdoc)
610 {
611 struct roff_node *n;
612
613 printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
614 mdoc->meta.title,
615 (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec),
616 mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol);
617
618 /* Disable hyphenation and if nroff, disable justification. */
619 printf(".nh\n.if n .ad l");
620
621 outflags = MMAN_nl | MMAN_Sm;
622 if (0 == fontqueue.size) {
623 fontqueue.size = 8;
624 fontqueue.head = fontqueue.tail = mandoc_malloc(8);
625 *fontqueue.tail = 'R';
626 }
627 for (n = mdoc->first->child; n != NULL; n = n->next)
628 print_node(&mdoc->meta, n);
629 putchar('\n');
630 }
631
632 static void
633 print_node(DECL_ARGS)
634 {
635 const struct manact *act;
636 struct roff_node *sub;
637 int cond, do_sub;
638
639 if (n->flags & NODE_NOPRT)
640 return;
641
642 /*
643 * Break the line if we were parsed subsequent the current node.
644 * This makes the page structure be more consistent.
645 */
646 if (MMAN_spc & outflags && NODE_LINE & n->flags)
647 outflags |= MMAN_nl;
1391 const struct roff_node *bln;
1392
1393 switch (n->type) {
1394 case ROFFT_HEAD:
1395 outflags |= MMAN_PP | MMAN_nl;
1396 bln = n->parent->parent;
1397 if (0 == bln->norm->Bl.comp ||
1398 (NULL == n->parent->prev &&
1399 NULL == bln->parent->prev))
1400 outflags |= MMAN_sp;
1401 outflags &= ~MMAN_br;
1402 switch (bln->norm->Bl.type) {
1403 case LIST_item:
1404 return 0;
1405 case LIST_inset:
1406 case LIST_diag:
1407 case LIST_ohang:
1408 if (bln->norm->Bl.type == LIST_diag)
1409 print_line(".B \"", 0);
1410 else
1411 print_line(".R \"", 0);
1412 outflags &= ~MMAN_spc;
1413 return 1;
1414 case LIST_bullet:
1415 case LIST_dash:
1416 case LIST_hyphen:
1417 print_width(&bln->norm->Bl, NULL);
1418 TPremain = 0;
1419 outflags |= MMAN_nl;
1420 font_push('B');
1421 if (LIST_bullet == bln->norm->Bl.type)
1422 print_word("\\(bu");
1423 else
1424 print_word("-");
1425 font_pop();
1426 outflags |= MMAN_nl;
1427 return 0;
1428 case LIST_enum:
1429 print_width(&bln->norm->Bl, NULL);
1430 TPremain = 0;
1431 outflags |= MMAN_nl;
1530 break;
1531 }
1532 break;
1533 default:
1534 break;
1535 }
1536 }
1537
1538 static void
1539 post_lb(DECL_ARGS)
1540 {
1541
1542 if (SEC_LIBRARY == n->sec)
1543 outflags |= MMAN_br;
1544 }
1545
1546 static int
1547 pre_lk(DECL_ARGS)
1548 {
1549 const struct roff_node *link, *descr, *punct;
1550 int display;
1551
1552 if ((link = n->child) == NULL)
1553 return 0;
1554
1555 /* Find beginning of trailing punctuation. */
1556 punct = n->last;
1557 while (punct != link && punct->flags & NODE_DELIMC)
1558 punct = punct->prev;
1559 punct = punct->next;
1560
1561 /* Link text. */
1562 if ((descr = link->next) != NULL && descr != punct) {
1563 font_push('I');
1564 while (descr != punct) {
1565 print_word(descr->string);
1566 descr = descr->next;
1567 }
1568 font_pop();
1569 print_word(":");
1570 }
1571
1572 /* Link target. */
1573 display = man_strlen(link->string) >= 26;
1574 if (display) {
1575 print_line(".RS", MMAN_Bk_susp);
1576 print_word("6n");
1577 outflags |= MMAN_nl;
1578 }
1579 font_push('B');
1580 print_word(link->string);
1581 font_pop();
1582
1583 /* Trailing punctuation. */
1584 while (punct != NULL) {
1585 print_word(punct->string);
1586 punct = punct->next;
1587 }
1588 if (display)
1589 print_line(".RE", MMAN_nl);
1590 return 0;
1591 }
1592
1593 static void
1594 pre_onearg(DECL_ARGS)
1595 {
1596 outflags |= MMAN_nl;
1597 print_word(".");
1598 outflags &= ~MMAN_spc;
1599 print_word(roff_name[n->tok]);
1600 if (n->child != NULL)
1601 print_word(n->child->string);
1602 outflags |= MMAN_nl;
1603 if (n->tok == ROFF_ce)
1604 for (n = n->child->next; n != NULL; n = n->next)
1605 print_node(meta, n);
1606 }
1607
1608 static int
1609 pre_li(DECL_ARGS)
|
1 /* $Id: mdoc_man.c,v 1.126 2018/04/11 17:11:13 schwarze Exp $ */
2 /*
3 * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
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 above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include "config.h"
18
19 #include <sys/types.h>
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
185 { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
186 { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
187 { NULL, NULL, post_percent, NULL, NULL }, /* %N */
188 { NULL, NULL, post_percent, NULL, NULL }, /* %O */
189 { NULL, NULL, post_percent, NULL, NULL }, /* %P */
190 { NULL, NULL, post_percent, NULL, NULL }, /* %R */
191 { NULL, pre__t, post__t, NULL, NULL }, /* %T */
192 { NULL, NULL, post_percent, NULL, NULL }, /* %V */
193 { NULL, NULL, NULL, NULL, NULL }, /* Ac */
194 { cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
195 { cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
196 { NULL, NULL, NULL, NULL, NULL }, /* At */
197 { NULL, NULL, NULL, NULL, NULL }, /* Bc */
198 { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
199 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
200 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
201 { NULL, pre_bk, post_bk, NULL, NULL }, /* Bsx */
202 { NULL, pre_bk, post_bk, NULL, NULL }, /* Bx */
203 { NULL, pre_skip, NULL, NULL, NULL }, /* Db */
204 { NULL, NULL, NULL, NULL, NULL }, /* Dc */
205 { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
206 { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
207 { NULL, NULL, NULL, NULL, NULL }, /* Ec */
208 { NULL, NULL, NULL, NULL, NULL }, /* Ef */
209 { NULL, pre_em, post_font, NULL, NULL }, /* Em */
210 { cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
211 { NULL, pre_bk, post_bk, NULL, NULL }, /* Fx */
212 { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
213 { NULL, pre_no, NULL, NULL, NULL }, /* No */
214 { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
215 { NULL, pre_bk, post_bk, NULL, NULL }, /* Nx */
216 { NULL, pre_bk, post_bk, NULL, NULL }, /* Ox */
217 { NULL, NULL, NULL, NULL, NULL }, /* Pc */
218 { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
219 { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
220 { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
221 { NULL, NULL, NULL, NULL, NULL }, /* Qc */
222 { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
223 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
224 { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
225 { NULL, NULL, NULL, NULL, NULL }, /* Re */
226 { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
593 }
594
595 void
596 man_man(void *arg, const struct roff_man *man)
597 {
598
599 /*
600 * Dump the keep buffer.
601 * We're guaranteed by now that this exists (is non-NULL).
602 * Flush stdout afterward, just in case.
603 */
604 fputs(mparse_getkeep(man_mparse(man)), stdout);
605 fflush(stdout);
606 }
607
608 void
609 man_mdoc(void *arg, const struct roff_man *mdoc)
610 {
611 struct roff_node *n;
612
613 printf(".\\\" Automatically generated from an mdoc input file."
614 " Do not edit.\n");
615 for (n = mdoc->first->child; n != NULL; n = n->next) {
616 if (n->type != ROFFT_COMMENT)
617 break;
618 printf(".\\\"%s\n", n->string);
619 }
620
621 printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
622 mdoc->meta.title,
623 (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec),
624 mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol);
625
626 /* Disable hyphenation and if nroff, disable justification. */
627 printf(".nh\n.if n .ad l");
628
629 outflags = MMAN_nl | MMAN_Sm;
630 if (0 == fontqueue.size) {
631 fontqueue.size = 8;
632 fontqueue.head = fontqueue.tail = mandoc_malloc(8);
633 *fontqueue.tail = 'R';
634 }
635 for (; n != NULL; n = n->next)
636 print_node(&mdoc->meta, n);
637 putchar('\n');
638 }
639
640 static void
641 print_node(DECL_ARGS)
642 {
643 const struct manact *act;
644 struct roff_node *sub;
645 int cond, do_sub;
646
647 if (n->flags & NODE_NOPRT)
648 return;
649
650 /*
651 * Break the line if we were parsed subsequent the current node.
652 * This makes the page structure be more consistent.
653 */
654 if (MMAN_spc & outflags && NODE_LINE & n->flags)
655 outflags |= MMAN_nl;
1399 const struct roff_node *bln;
1400
1401 switch (n->type) {
1402 case ROFFT_HEAD:
1403 outflags |= MMAN_PP | MMAN_nl;
1404 bln = n->parent->parent;
1405 if (0 == bln->norm->Bl.comp ||
1406 (NULL == n->parent->prev &&
1407 NULL == bln->parent->prev))
1408 outflags |= MMAN_sp;
1409 outflags &= ~MMAN_br;
1410 switch (bln->norm->Bl.type) {
1411 case LIST_item:
1412 return 0;
1413 case LIST_inset:
1414 case LIST_diag:
1415 case LIST_ohang:
1416 if (bln->norm->Bl.type == LIST_diag)
1417 print_line(".B \"", 0);
1418 else
1419 print_line(".BR \\& \"", 0);
1420 outflags &= ~MMAN_spc;
1421 return 1;
1422 case LIST_bullet:
1423 case LIST_dash:
1424 case LIST_hyphen:
1425 print_width(&bln->norm->Bl, NULL);
1426 TPremain = 0;
1427 outflags |= MMAN_nl;
1428 font_push('B');
1429 if (LIST_bullet == bln->norm->Bl.type)
1430 print_word("\\(bu");
1431 else
1432 print_word("-");
1433 font_pop();
1434 outflags |= MMAN_nl;
1435 return 0;
1436 case LIST_enum:
1437 print_width(&bln->norm->Bl, NULL);
1438 TPremain = 0;
1439 outflags |= MMAN_nl;
1538 break;
1539 }
1540 break;
1541 default:
1542 break;
1543 }
1544 }
1545
1546 static void
1547 post_lb(DECL_ARGS)
1548 {
1549
1550 if (SEC_LIBRARY == n->sec)
1551 outflags |= MMAN_br;
1552 }
1553
1554 static int
1555 pre_lk(DECL_ARGS)
1556 {
1557 const struct roff_node *link, *descr, *punct;
1558
1559 if ((link = n->child) == NULL)
1560 return 0;
1561
1562 /* Find beginning of trailing punctuation. */
1563 punct = n->last;
1564 while (punct != link && punct->flags & NODE_DELIMC)
1565 punct = punct->prev;
1566 punct = punct->next;
1567
1568 /* Link text. */
1569 if ((descr = link->next) != NULL && descr != punct) {
1570 font_push('I');
1571 while (descr != punct) {
1572 print_word(descr->string);
1573 descr = descr->next;
1574 }
1575 font_pop();
1576 print_word(":");
1577 }
1578
1579 /* Link target. */
1580 font_push('B');
1581 print_word(link->string);
1582 font_pop();
1583
1584 /* Trailing punctuation. */
1585 while (punct != NULL) {
1586 print_word(punct->string);
1587 punct = punct->next;
1588 }
1589 return 0;
1590 }
1591
1592 static void
1593 pre_onearg(DECL_ARGS)
1594 {
1595 outflags |= MMAN_nl;
1596 print_word(".");
1597 outflags &= ~MMAN_spc;
1598 print_word(roff_name[n->tok]);
1599 if (n->child != NULL)
1600 print_word(n->child->string);
1601 outflags |= MMAN_nl;
1602 if (n->tok == ROFF_ce)
1603 for (n = n->child->next; n != NULL; n = n->next)
1604 print_node(meta, n);
1605 }
1606
1607 static int
1608 pre_li(DECL_ARGS)
|