=================================================================== RCS file: /cvs/mandoc/man_term.c,v retrieving revision 1.209 retrieving revision 1.228 diff -u -p -r1.209 -r1.228 --- mandoc/man_term.c 2017/07/31 15:19:06 1.209 +++ mandoc/man_term.c 2019/01/05 21:18:26 1.228 @@ -1,7 +1,7 @@ -/* $Id: man_term.c,v 1.209 2017/07/31 15:19:06 schwarze Exp $ */ +/* $Id: man_term.c,v 1.228 2019/01/05 21:18:26 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010-2015, 2017 Ingo Schwarze + * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,6 @@ #include #include "mandoc_aux.h" -#include "mandoc.h" #include "roff.h" #include "man.h" #include "out.h" @@ -37,8 +36,6 @@ #define MAXMARGINS 64 /* maximum number of indented scopes */ struct mtermp { - int fl; -#define MANT_LITERAL (1 << 0) int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */ int lmargincur; /* index of current margin */ int lmarginsz; /* actual number of nested margins */ @@ -51,7 +48,7 @@ struct mtermp { struct roff_node *n, \ const struct roff_meta *meta -struct termact { +struct man_term_act { int (*pre)(DECL_ARGS); void (*post)(DECL_ARGS); int flags; @@ -78,8 +75,10 @@ static int pre_PP(DECL_ARGS); static int pre_RS(DECL_ARGS); static int pre_SH(DECL_ARGS); static int pre_SS(DECL_ARGS); +static int pre_SY(DECL_ARGS); static int pre_TP(DECL_ARGS); static int pre_UR(DECL_ARGS); +static int pre_abort(DECL_ARGS); static int pre_alternate(DECL_ARGS); static int pre_ign(DECL_ARGS); static int pre_in(DECL_ARGS); @@ -89,18 +88,19 @@ static void post_IP(DECL_ARGS); static void post_HP(DECL_ARGS); static void post_RS(DECL_ARGS); static void post_SH(DECL_ARGS); -static void post_SS(DECL_ARGS); +static void post_SY(DECL_ARGS); static void post_TP(DECL_ARGS); static void post_UR(DECL_ARGS); -static const struct termact __termacts[MAN_MAX - MAN_TH] = { +static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = { { NULL, NULL, 0 }, /* TH */ { pre_SH, post_SH, 0 }, /* SH */ - { pre_SS, post_SS, 0 }, /* SS */ + { pre_SS, post_SH, 0 }, /* SS */ { pre_TP, post_TP, 0 }, /* TP */ - { pre_PP, NULL, 0 }, /* LP */ + { pre_TP, post_TP, 0 }, /* TQ */ + { pre_abort, NULL, 0 }, /* LP */ { pre_PP, NULL, 0 }, /* PP */ - { pre_PP, NULL, 0 }, /* P */ + { pre_abort, NULL, 0 }, /* P */ { pre_IP, post_IP, 0 }, /* IP */ { pre_HP, post_HP, 0 }, /* HP */ { NULL, NULL, 0 }, /* SM */ @@ -114,8 +114,6 @@ static const struct termact __termacts[MAN_MAX - MAN_T { pre_I, NULL, 0 }, /* I */ { pre_alternate, NULL, 0 }, /* IR */ { pre_alternate, NULL, 0 }, /* RI */ - { pre_literal, NULL, 0 }, /* nf */ - { pre_literal, NULL, 0 }, /* fi */ { NULL, NULL, 0 }, /* RE */ { pre_RS, post_RS, 0 }, /* RS */ { pre_DT, NULL, 0 }, /* DT */ @@ -123,6 +121,8 @@ static const struct termact __termacts[MAN_MAX - MAN_T { pre_PD, NULL, MAN_NOTEXT }, /* PD */ { pre_ign, NULL, 0 }, /* AT */ { pre_in, NULL, MAN_NOTEXT }, /* in */ + { pre_SY, post_SY, 0 }, /* SY */ + { NULL, NULL, 0 }, /* YS */ { pre_OP, NULL, 0 }, /* OP */ { pre_literal, NULL, 0 }, /* EX */ { pre_literal, NULL, 0 }, /* EE */ @@ -131,15 +131,22 @@ static const struct termact __termacts[MAN_MAX - MAN_T { pre_UR, post_UR, 0 }, /* MT */ { NULL, NULL, 0 }, /* ME */ }; -static const struct termact *termacts = __termacts - MAN_TH; +static const struct man_term_act *man_term_act(enum roff_tok); +static const struct man_term_act * +man_term_act(enum roff_tok tok) +{ + assert(tok >= MAN_TH && tok <= MAN_MAX); + return man_term_acts + (tok - MAN_TH); +} + void -terminal_man(void *arg, const struct roff_man *man) +terminal_man(void *arg, const struct roff_meta *man) { + struct mtermp mt; struct termp *p; struct roff_node *n; - struct mtermp mt; size_t save_defindent; p = (struct termp *)arg; @@ -151,7 +158,7 @@ terminal_man(void *arg, const struct roff_man *man) term_tab_set(p, "T"); term_tab_set(p, ".5i"); - memset(&mt, 0, sizeof(struct mtermp)); + memset(&mt, 0, sizeof(mt)); mt.lmargin[mt.lmargincur] = term_len(p, p->defindent); mt.offset = term_len(p, p->defindent); mt.pardist = 1; @@ -164,18 +171,17 @@ terminal_man(void *arg, const struct roff_man *man) !strcmp(n->child->child->string, "SYNOPSIS")) { if (n->child->next->child != NULL) print_man_nodelist(p, &mt, - n->child->next->child, - &man->meta); + n->child->next->child, man); term_newln(p); break; } n = n->next; } } else { - term_begin(p, print_man_head, print_man_foot, &man->meta); + term_begin(p, print_man_head, print_man_foot, man); p->flags |= TERMP_NOSPACE; if (n != NULL) - print_man_nodelist(p, &mt, n, &man->meta); + print_man_nodelist(p, &mt, n, man); term_end(p); } p->defindent = save_defindent; @@ -196,12 +202,12 @@ print_bvspace(struct termp *p, const struct roff_node term_newln(p); - if (n->body && n->body->child) + if (n->body != NULL && n->body->child != NULL) if (n->body->child->type == ROFFT_TBL) return; if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) - if (NULL == n->prev) + if (n->prev == NULL) return; for (i = 0; i < pardist; i++) @@ -210,16 +216,20 @@ print_bvspace(struct termp *p, const struct roff_node static int -pre_ign(DECL_ARGS) +pre_abort(DECL_ARGS) { + abort(); +} +static int +pre_ign(DECL_ARGS) +{ return 0; } static int pre_I(DECL_ARGS) { - term_fontrepl(p, TERMFONT_UNDER); return 1; } @@ -227,14 +237,8 @@ pre_I(DECL_ARGS) static int pre_literal(DECL_ARGS) { - term_newln(p); - if (n->tok == MAN_nf || n->tok == MAN_EX) - mt->fl |= MANT_LITERAL; - else - mt->fl &= ~MANT_LITERAL; - /* * Unlike .IP and .TP, .HP does not have a HEAD. * So in case a second call to term_flushln() is needed, @@ -247,7 +251,6 @@ pre_literal(DECL_ARGS) p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); p->flags |= TERMP_NOSPACE; } - return 0; } @@ -272,7 +275,7 @@ pre_alternate(DECL_ARGS) { enum termfont font[2]; struct roff_node *nn; - int savelit, i; + int i; switch (n->tok) { case MAN_RB: @@ -302,29 +305,21 @@ pre_alternate(DECL_ARGS) default: abort(); } - - savelit = MANT_LITERAL & mt->fl; - mt->fl &= ~MANT_LITERAL; - - for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) { + for (i = 0, nn = n->child; nn != NULL; nn = nn->next, i = 1 - i) { term_fontrepl(p, font[i]); - if (savelit && NULL == nn->next) - mt->fl |= MANT_LITERAL; assert(nn->type == ROFFT_TEXT); term_word(p, nn->string); if (nn->flags & NODE_EOS) p->flags |= TERMP_SENTENCE; - if (nn->next) + if (nn->next != NULL) p->flags |= TERMP_NOSPACE; } - return 0; } static int pre_B(DECL_ARGS) { - term_fontrepl(p, TERMFONT_BOLD); return 1; } @@ -332,20 +327,19 @@ pre_B(DECL_ARGS) static int pre_OP(DECL_ARGS) { - term_word(p, "["); - p->flags |= TERMP_NOSPACE; + p->flags |= TERMP_KEEP | TERMP_NOSPACE; - if (NULL != (n = n->child)) { + if ((n = n->child) != NULL) { term_fontrepl(p, TERMFONT_BOLD); term_word(p, n->string); } - if (NULL != n && NULL != n->next) { + if (n != NULL && n->next != NULL) { term_fontrepl(p, TERMFONT_UNDER); term_word(p, n->next->string); } - term_fontrepl(p, TERMFONT_NONE); + p->flags &= ~TERMP_KEEP; p->flags |= TERMP_NOSPACE; term_word(p, "]"); return 0; @@ -369,9 +363,9 @@ pre_in(DECL_ARGS) cp = n->child->string; less = 0; - if ('-' == *cp) + if (*cp == '-') less = -1; - else if ('+' == *cp) + else if (*cp == '+') less = 1; else cp--; @@ -413,13 +407,18 @@ pre_HP(DECL_ARGS) case ROFFT_BLOCK: print_bvspace(p, n, mt->pardist); return 1; + case ROFFT_HEAD: + return 0; case ROFFT_BODY: break; default: - return 0; + abort(); } - if ( ! (MANT_LITERAL & mt->fl)) { + if (n->child == NULL) + return 0; + + if ((n->child->flags & NODE_NOFILL) == 0) { p->flags |= TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 2; } @@ -445,8 +444,10 @@ pre_HP(DECL_ARGS) static void post_HP(DECL_ARGS) { - switch (n->type) { + case ROFFT_BLOCK: + case ROFFT_HEAD: + break; case ROFFT_BODY: term_newln(p); @@ -466,25 +467,27 @@ post_HP(DECL_ARGS) p->tcol->rmargin = p->maxrmargin; break; default: - break; + abort(); } } static int pre_PP(DECL_ARGS) { - switch (n->type) { case ROFFT_BLOCK: mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); print_bvspace(p, n, mt->pardist); break; - default: + case ROFFT_HEAD: + return 0; + case ROFFT_BODY: p->tcol->offset = mt->offset; break; + default: + abort(); } - - return n->type != ROFFT_HEAD; + return 1; } static int @@ -492,21 +495,21 @@ pre_IP(DECL_ARGS) { struct roffsu su; const struct roff_node *nn; - int len, savelit; + int len; switch (n->type) { - case ROFFT_BODY: - p->flags |= TERMP_NOSPACE; - break; + case ROFFT_BLOCK: + print_bvspace(p, n, mt->pardist); + return 1; case ROFFT_HEAD: p->flags |= TERMP_NOBREAK; p->trailspace = 1; break; - case ROFFT_BLOCK: - print_bvspace(p, n, mt->pardist); - /* FALLTHROUGH */ + case ROFFT_BODY: + p->flags |= TERMP_NOSPACE; + break; default: - return 1; + abort(); } /* Calculate the offset from the optional second argument. */ @@ -526,33 +529,25 @@ pre_IP(DECL_ARGS) case ROFFT_HEAD: p->tcol->offset = mt->offset; p->tcol->rmargin = mt->offset + len; - - savelit = MANT_LITERAL & mt->fl; - mt->fl &= ~MANT_LITERAL; - - if (n->child) + if (n->child != NULL) print_man_node(p, mt, n->child, meta); - - if (savelit) - mt->fl |= MANT_LITERAL; - return 0; case ROFFT_BODY: p->tcol->offset = mt->offset + len; p->tcol->rmargin = p->maxrmargin; break; default: - break; + abort(); } - return 1; } static void post_IP(DECL_ARGS) { - switch (n->type) { + case ROFFT_BLOCK: + break; case ROFFT_HEAD: term_flushln(p); p->flags &= ~TERMP_NOBREAK; @@ -564,7 +559,7 @@ post_IP(DECL_ARGS) p->tcol->offset = mt->offset; break; default: - break; + abort(); } } @@ -573,9 +568,13 @@ pre_TP(DECL_ARGS) { struct roffsu su; struct roff_node *nn; - int len, savelit; + int len; switch (n->type) { + case ROFFT_BLOCK: + if (n->tok == MAN_TP) + print_bvspace(p, n, mt->pardist); + return 1; case ROFFT_HEAD: p->flags |= TERMP_NOBREAK | TERMP_BRTRSP; p->trailspace = 1; @@ -583,11 +582,8 @@ pre_TP(DECL_ARGS) case ROFFT_BODY: p->flags |= TERMP_NOSPACE; break; - case ROFFT_BLOCK: - print_bvspace(p, n, mt->pardist); - /* FALLTHROUGH */ default: - return 1; + abort(); } /* Calculate offset. */ @@ -609,21 +605,15 @@ pre_TP(DECL_ARGS) p->tcol->offset = mt->offset; p->tcol->rmargin = mt->offset + len; - savelit = MANT_LITERAL & mt->fl; - mt->fl &= ~MANT_LITERAL; - /* Don't print same-line elements. */ nn = n->child; - while (NULL != nn && 0 == (NODE_LINE & nn->flags)) + while (nn != NULL && (nn->flags & NODE_LINE) == 0) nn = nn->next; - while (NULL != nn) { + while (nn != NULL) { print_man_node(p, mt, nn, meta); nn = nn->next; } - - if (savelit) - mt->fl |= MANT_LITERAL; return 0; case ROFFT_BODY: p->tcol->offset = mt->offset + len; @@ -632,17 +622,17 @@ pre_TP(DECL_ARGS) p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP); break; default: - break; + abort(); } - return 1; } static void post_TP(DECL_ARGS) { - switch (n->type) { + case ROFFT_BLOCK: + break; case ROFFT_HEAD: term_flushln(p); break; @@ -651,7 +641,7 @@ post_TP(DECL_ARGS) p->tcol->offset = mt->offset; break; default: - break; + abort(); } } @@ -662,7 +652,6 @@ pre_SS(DECL_ARGS) switch (n->type) { case ROFFT_BLOCK: - mt->fl &= ~MANT_LITERAL; mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent); @@ -674,8 +663,9 @@ pre_SS(DECL_ARGS) do { n = n->prev; } while (n != NULL && n->tok >= MAN_TH && - termacts[n->tok].flags & MAN_NOTEXT); - if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL)) + man_term_act(n->tok)->flags & MAN_NOTEXT); + if (n == NULL || n->type == ROFFT_COMMENT || + (n->tok == MAN_SS && n->body->child == NULL)) break; for (i = 0; i < mt->pardist; i++) @@ -697,26 +687,9 @@ pre_SS(DECL_ARGS) default: break; } - return 1; } -static void -post_SS(DECL_ARGS) -{ - - switch (n->type) { - case ROFFT_HEAD: - term_newln(p); - break; - case ROFFT_BODY: - term_newln(p); - break; - default: - break; - } -} - static int pre_SH(DECL_ARGS) { @@ -724,7 +697,6 @@ pre_SH(DECL_ARGS) switch (n->type) { case ROFFT_BLOCK: - mt->fl &= ~MANT_LITERAL; mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent); @@ -736,8 +708,9 @@ pre_SH(DECL_ARGS) do { n = n->prev; } while (n != NULL && n->tok >= MAN_TH && - termacts[n->tok].flags & MAN_NOTEXT); - if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL)) + man_term_act(n->tok)->flags & MAN_NOTEXT); + if (n == NULL || n->type == ROFFT_COMMENT || + (n->tok == MAN_SH && n->body->child == NULL)) break; for (i = 0; i < mt->pardist; i++) @@ -757,25 +730,23 @@ pre_SH(DECL_ARGS) p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); break; default: - break; + abort(); } - return 1; } static void post_SH(DECL_ARGS) { - switch (n->type) { - case ROFFT_HEAD: - term_newln(p); + case ROFFT_BLOCK: break; + case ROFFT_HEAD: case ROFFT_BODY: term_newln(p); break; default: - break; + abort(); } } @@ -790,8 +761,10 @@ pre_RS(DECL_ARGS) return 1; case ROFFT_HEAD: return 0; - default: + case ROFFT_BODY: break; + default: + abort(); } n = n->parent->head; @@ -819,42 +792,99 @@ pre_RS(DECL_ARGS) static void post_RS(DECL_ARGS) { - switch (n->type) { case ROFFT_BLOCK: - return; case ROFFT_HEAD: return; - default: - term_newln(p); + case ROFFT_BODY: break; + default: + abort(); } - + term_newln(p); mt->offset -= n->parent->head->aux; p->tcol->offset = mt->offset; - if (--mt->lmarginsz < MAXMARGINS) mt->lmargincur = mt->lmarginsz; } static int -pre_UR(DECL_ARGS) +pre_SY(DECL_ARGS) { + const struct roff_node *nn; + int len; + switch (n->type) { + case ROFFT_BLOCK: + if (n->prev == NULL || n->prev->tok != MAN_SY) + print_bvspace(p, n, mt->pardist); + return 1; + case ROFFT_HEAD: + case ROFFT_BODY: + break; + default: + abort(); + } + + nn = n->parent->head->child; + len = nn == NULL ? 1 : term_strlen(p, nn->string) + 1; + + switch (n->type) { + case ROFFT_HEAD: + p->tcol->offset = mt->offset; + p->tcol->rmargin = mt->offset + len; + if (n->next->child == NULL || + (n->next->child->flags & NODE_NOFILL) == 0) + p->flags |= TERMP_NOBREAK; + term_fontrepl(p, TERMFONT_BOLD); + break; + case ROFFT_BODY: + mt->lmargin[mt->lmargincur] = len; + p->tcol->offset = mt->offset + len; + p->tcol->rmargin = p->maxrmargin; + p->flags |= TERMP_NOSPACE; + break; + default: + abort(); + } + return 1; +} + +static void +post_SY(DECL_ARGS) +{ + switch (n->type) { + case ROFFT_BLOCK: + break; + case ROFFT_HEAD: + term_flushln(p); + p->flags &= ~TERMP_NOBREAK; + break; + case ROFFT_BODY: + term_newln(p); + p->tcol->offset = mt->offset; + break; + default: + abort(); + } +} + +static int +pre_UR(DECL_ARGS) +{ return n->type != ROFFT_HEAD; } static void post_UR(DECL_ARGS) { - if (n->type != ROFFT_BLOCK) return; term_word(p, "<"); p->flags |= TERMP_NOSPACE; - if (NULL != n->child->child) + if (n->child->child != NULL) print_man_node(p, mt, n->child->child, meta); p->flags |= TERMP_NOSPACE; @@ -864,7 +894,8 @@ post_UR(DECL_ARGS) static void print_man_node(DECL_ARGS) { - int c; + const struct man_term_act *act; + int c; switch (n->type) { case ROFFT_TEXT: @@ -882,10 +913,13 @@ print_man_node(DECL_ARGS) } else if (*n->string == ' ' && n->flags & NODE_LINE && (p->flags & TERMP_NONEWLINE) == 0) term_newln(p); + else if (n->flags & NODE_DELIMC) + p->flags |= TERMP_NOSPACE; term_word(p, n->string); goto out; - + case ROFFT_COMMENT: + return; case ROFFT_EQN: if ( ! (n->flags & NODE_LINE)) p->flags |= TERMP_NOSPACE; @@ -907,20 +941,20 @@ print_man_node(DECL_ARGS) return; } - assert(n->tok >= MAN_TH && n->tok <= MAN_MAX); - if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) + act = man_term_act(n->tok); + if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM) term_fontrepl(p, TERMFONT_NONE); c = 1; - if (termacts[n->tok].pre) - c = (*termacts[n->tok].pre)(p, mt, n, meta); + if (act->pre != NULL) + c = (*act->pre)(p, mt, n, meta); - if (c && n->child) + if (c && n->child != NULL) print_man_nodelist(p, mt, n->child, meta); - if (termacts[n->tok].post) - (*termacts[n->tok].post)(p, mt, n, meta); - if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) + if (act->post != NULL) + (*act->post)(p, mt, n, meta); + if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM) term_fontrepl(p, TERMFONT_NONE); out: @@ -931,7 +965,7 @@ out: * -man doesn't have nested macros, we don't need to be * more specific than this. */ - if (mt->fl & MANT_LITERAL && + if (n->flags & NODE_NOFILL && ! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) && (n->next == NULL || n->next->flags & NODE_LINE)) { p->flags |= TERMP_BRNEVER | TERMP_NOSPACE; @@ -946,15 +980,13 @@ out: p->tcol->rmargin = p->maxrmargin; } } - if (NODE_EOS & n->flags) + if (n->flags & NODE_EOS) p->flags |= TERMP_SENTENCE; } - static void print_man_nodelist(DECL_ARGS) { - while (n != NULL) { print_man_node(p, mt, n, meta); n = n->next; @@ -989,7 +1021,7 @@ print_man_foot(struct termp *p, const struct roff_meta } mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec); - } else if (meta->os) { + } else if (meta->os != NULL) { title = mandoc_strdup(meta->os); } else { title = mandoc_strdup(""); @@ -1029,6 +1061,18 @@ print_man_foot(struct termp *p, const struct roff_meta term_word(p, title); term_flushln(p); + + /* + * Reset the terminal state for more output after the footer: + * Some output modes, in particular PostScript and PDF, print + * the header and the footer into a buffer such that it can be + * reused for multiple output pages, then go on to format the + * main text. + */ + + p->tcol->offset = 0; + p->flags = 0; + free(title); }