version 1.231, 2019/07/22 03:21:49 |
version 1.237, 2022/04/27 17:11:24 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
|
* Copyright (c) 2010-2015,2017-2020,2022 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org> |
|
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
* |
|
* Plain text formatter for man(7), used by mandoc(1) |
|
* for ASCII, UTF-8, PostScript, and PDF output. |
*/ |
*/ |
#include "config.h" |
#include "config.h" |
|
|
|
|
#include "man.h" |
#include "man.h" |
#include "out.h" |
#include "out.h" |
#include "term.h" |
#include "term.h" |
#include "tag.h" |
#include "term_tag.h" |
#include "main.h" |
#include "main.h" |
|
|
#define MAXMARGINS 64 /* maximum number of indented scopes */ |
#define MAXMARGINS 64 /* maximum number of indented scopes */ |
Line 64 static void print_man_head(struct termp *, |
|
Line 67 static void print_man_head(struct termp *, |
|
static void print_man_foot(struct termp *, |
static void print_man_foot(struct termp *, |
const struct roff_meta *); |
const struct roff_meta *); |
static void print_bvspace(struct termp *, |
static void print_bvspace(struct termp *, |
const struct roff_node *, int); |
struct roff_node *, int); |
|
|
static int pre_B(DECL_ARGS); |
static int pre_B(DECL_ARGS); |
static int pre_DT(DECL_ARGS); |
static int pre_DT(DECL_ARGS); |
Line 94 static void post_SY(DECL_ARGS); |
|
Line 97 static void post_SY(DECL_ARGS); |
|
static void post_TP(DECL_ARGS); |
static void post_TP(DECL_ARGS); |
static void post_UR(DECL_ARGS); |
static void post_UR(DECL_ARGS); |
|
|
static void tag_man(struct termp *, struct roff_node *); |
|
|
|
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = { |
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = { |
{ NULL, NULL, 0 }, /* TH */ |
{ NULL, NULL, 0 }, /* TH */ |
{ pre_SH, post_SH, 0 }, /* SH */ |
{ pre_SH, post_SH, 0 }, /* SH */ |
Line 120 static const struct man_term_act man_term_acts[MAN_MAX |
|
Line 121 static const struct man_term_act man_term_acts[MAN_MAX |
|
{ pre_alternate, NULL, 0 }, /* RI */ |
{ pre_alternate, NULL, 0 }, /* RI */ |
{ NULL, NULL, 0 }, /* RE */ |
{ NULL, NULL, 0 }, /* RE */ |
{ pre_RS, post_RS, 0 }, /* RS */ |
{ pre_RS, post_RS, 0 }, /* RS */ |
{ pre_DT, NULL, 0 }, /* DT */ |
{ pre_DT, NULL, MAN_NOTEXT }, /* DT */ |
{ pre_ign, NULL, MAN_NOTEXT }, /* UC */ |
{ pre_ign, NULL, MAN_NOTEXT }, /* UC */ |
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */ |
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */ |
{ pre_ign, NULL, 0 }, /* AT */ |
{ pre_ign, NULL, MAN_NOTEXT }, /* AT */ |
{ pre_in, NULL, MAN_NOTEXT }, /* in */ |
{ pre_in, NULL, MAN_NOTEXT }, /* in */ |
{ pre_SY, post_SY, 0 }, /* SY */ |
{ pre_SY, post_SY, 0 }, /* SY */ |
{ NULL, NULL, 0 }, /* YS */ |
{ NULL, NULL, 0 }, /* YS */ |
Line 205 terminal_man(void *arg, const struct roff_meta *man) |
|
Line 206 terminal_man(void *arg, const struct roff_meta *man) |
|
* first, print it. |
* first, print it. |
*/ |
*/ |
static void |
static void |
print_bvspace(struct termp *p, const struct roff_node *n, int pardist) |
print_bvspace(struct termp *p, struct roff_node *n, int pardist) |
{ |
{ |
int i; |
struct roff_node *nch; |
|
int i; |
|
|
term_newln(p); |
term_newln(p); |
|
|
if (n->body != NULL && n->body->child != NULL) |
if (n->body != NULL && |
if (n->body->child->type == ROFFT_TBL) |
(nch = roff_node_child(n->body)) != NULL && |
return; |
nch->type == ROFFT_TBL) |
|
return; |
|
|
if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) |
if (n->parent->tok != MAN_RS && roff_node_prev(n) == NULL) |
if (n->prev == NULL) |
return; |
return; |
|
|
|
for (i = 0; i < pardist; i++) |
for (i = 0; i < pardist; i++) |
term_vspace(p); |
term_vspace(p); |
Line 538 pre_IP(DECL_ARGS) |
|
Line 540 pre_IP(DECL_ARGS) |
|
case ROFFT_HEAD: |
case ROFFT_HEAD: |
p->tcol->offset = mt->offset; |
p->tcol->offset = mt->offset; |
p->tcol->rmargin = mt->offset + len; |
p->tcol->rmargin = mt->offset + len; |
if (n->child != NULL) { |
if (n->child != NULL) |
print_man_node(p, mt, n->child, meta); |
print_man_node(p, mt, n->child, meta); |
tag_man(p, n->child); |
|
} |
|
return 0; |
return 0; |
case ROFFT_BODY: |
case ROFFT_BODY: |
p->tcol->offset = mt->offset + len; |
p->tcol->offset = mt->offset + len; |
Line 671 pre_SS(DECL_ARGS) |
|
Line 671 pre_SS(DECL_ARGS) |
|
* and after an empty subsection. |
* and after an empty subsection. |
*/ |
*/ |
|
|
do { |
if ((n = roff_node_prev(n)) == NULL || |
n = n->prev; |
(n->tok == MAN_SS && roff_node_child(n->body) == NULL)) |
} while (n != NULL && n->tok >= MAN_TH && |
|
man_term_act(n->tok)->flags & MAN_NOTEXT); |
|
if (n == NULL || n->type == ROFFT_COMMENT || |
|
(n->tok == MAN_SS && n->body->child == NULL)) |
|
break; |
break; |
|
|
for (i = 0; i < mt->pardist; i++) |
for (i = 0; i < mt->pardist; i++) |
Line 716 pre_SH(DECL_ARGS) |
|
Line 712 pre_SH(DECL_ARGS) |
|
* and after an empty section. |
* and after an empty section. |
*/ |
*/ |
|
|
do { |
if ((n = roff_node_prev(n)) == NULL || |
n = n->prev; |
(n->tok == MAN_SH && roff_node_child(n->body) == NULL)) |
} while (n != NULL && n->tok >= MAN_TH && |
|
man_term_act(n->tok)->flags & MAN_NOTEXT); |
|
if (n == NULL || n->type == ROFFT_COMMENT || |
|
(n->tok == MAN_SH && n->body->child == NULL)) |
|
break; |
break; |
|
|
for (i = 0; i < mt->pardist; i++) |
for (i = 0; i < mt->pardist; i++) |
Line 827 pre_SY(DECL_ARGS) |
|
Line 819 pre_SY(DECL_ARGS) |
|
|
|
switch (n->type) { |
switch (n->type) { |
case ROFFT_BLOCK: |
case ROFFT_BLOCK: |
if (n->prev == NULL || n->prev->tok != MAN_SY) |
if ((nn = roff_node_prev(n)) == NULL || nn->tok != MAN_SY) |
print_bvspace(p, n, mt->pardist); |
print_bvspace(p, n, mt->pardist); |
return 1; |
return 1; |
case ROFFT_HEAD: |
case ROFFT_HEAD: |
Line 908 print_man_node(DECL_ARGS) |
|
Line 900 print_man_node(DECL_ARGS) |
|
const struct man_term_act *act; |
const struct man_term_act *act; |
int c; |
int c; |
|
|
|
if (n->flags & NODE_ID) |
|
term_tag_write(n, p->line); |
|
|
switch (n->type) { |
switch (n->type) { |
case ROFFT_TEXT: |
case ROFFT_TEXT: |
/* |
/* |
Line 1026 print_man_foot(struct termp *p, const struct roff_meta |
|
Line 1021 print_man_foot(struct termp *p, const struct roff_meta |
|
*/ |
*/ |
|
|
if ( ! p->mdocstyle) { |
if ( ! p->mdocstyle) { |
if (meta->hasbody) { |
|
term_vspace(p); |
|
term_vspace(p); |
|
} |
|
mandoc_asprintf(&title, "%s(%s)", |
mandoc_asprintf(&title, "%s(%s)", |
meta->title, meta->msec); |
meta->title, meta->msec); |
} else if (meta->os != NULL) { |
} else if (meta->os != NULL) { |
Line 1148 print_man_head(struct termp *p, const struct roff_meta |
|
Line 1139 print_man_head(struct termp *p, const struct roff_meta |
|
*/ |
*/ |
|
|
term_vspace(p); |
term_vspace(p); |
if ( ! p->mdocstyle) { |
|
term_vspace(p); |
|
term_vspace(p); |
|
} |
|
free(title); |
free(title); |
} |
|
|
|
/* |
|
* Skip leading whitespace, dashes, backslashes, and font escapes, |
|
* then create a tag if the first following byte is a letter. |
|
* Priority is high unless whitespace is present. |
|
*/ |
|
static void |
|
tag_man(struct termp *p, struct roff_node *n) |
|
{ |
|
const char *cp, *arg; |
|
int prio, sz; |
|
|
|
assert(n->type == ROFFT_TEXT); |
|
cp = n->string; |
|
prio = 1; |
|
for (;;) { |
|
switch (*cp) { |
|
case ' ': |
|
case '\t': |
|
prio = INT_MAX; |
|
/* FALLTHROUGH */ |
|
case '-': |
|
cp++; |
|
break; |
|
case '\\': |
|
cp++; |
|
switch (mandoc_escape(&cp, &arg, &sz)) { |
|
case ESCAPE_FONT: |
|
case ESCAPE_FONTROMAN: |
|
case ESCAPE_FONTITALIC: |
|
case ESCAPE_FONTBOLD: |
|
case ESCAPE_FONTPREV: |
|
case ESCAPE_FONTBI: |
|
break; |
|
case ESCAPE_SPECIAL: |
|
if (sz != 1) |
|
return; |
|
switch (*arg) { |
|
case '&': |
|
case '-': |
|
case 'e': |
|
break; |
|
default: |
|
return; |
|
} |
|
break; |
|
default: |
|
return; |
|
} |
|
break; |
|
default: |
|
if (isalpha((unsigned char)*cp)) |
|
tag_put(cp, prio, p->line); |
|
return; |
|
} |
|
} |
|
} |
} |