version 1.380, 2020/03/13 15:32:28 |
version 1.390, 2021/10/04 14:19:14 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2010-2021 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 Joerg Sonnenberger <joerg@netbsd.org> |
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> |
* |
* |
|
|
#include "mandoc.h" |
#include "mandoc.h" |
#include "mandoc_xr.h" |
#include "mandoc_xr.h" |
#include "roff.h" |
#include "roff.h" |
#include "tag.h" |
|
#include "mdoc.h" |
#include "mdoc.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
#include "roff_int.h" |
#include "roff_int.h" |
#include "libmdoc.h" |
#include "libmdoc.h" |
|
#include "tag.h" |
|
|
/* FIXME: .Bl -diag can't have non-text children in HEAD. */ |
/* FIXME: .Bl -diag can't have non-text children in HEAD. */ |
|
|
Line 92 static void post_es(POST_ARGS); |
|
Line 92 static void post_es(POST_ARGS); |
|
static void post_eoln(POST_ARGS); |
static void post_eoln(POST_ARGS); |
static void post_ex(POST_ARGS); |
static void post_ex(POST_ARGS); |
static void post_fa(POST_ARGS); |
static void post_fa(POST_ARGS); |
|
static void post_fl(POST_ARGS); |
static void post_fn(POST_ARGS); |
static void post_fn(POST_ARGS); |
static void post_fname(POST_ARGS); |
static void post_fname(POST_ARGS); |
static void post_fo(POST_ARGS); |
static void post_fo(POST_ARGS); |
static void post_hyph(POST_ARGS); |
static void post_hyph(POST_ARGS); |
static void post_ignpar(POST_ARGS); |
|
static void post_it(POST_ARGS); |
static void post_it(POST_ARGS); |
static void post_lb(POST_ARGS); |
static void post_lb(POST_ARGS); |
static void post_nd(POST_ARGS); |
static void post_nd(POST_ARGS); |
Line 109 static void post_prevpar(POST_ARGS); |
|
Line 109 static void post_prevpar(POST_ARGS); |
|
static void post_root(POST_ARGS); |
static void post_root(POST_ARGS); |
static void post_rs(POST_ARGS); |
static void post_rs(POST_ARGS); |
static void post_rv(POST_ARGS); |
static void post_rv(POST_ARGS); |
|
static void post_section(POST_ARGS); |
static void post_sh(POST_ARGS); |
static void post_sh(POST_ARGS); |
static void post_sh_head(POST_ARGS); |
static void post_sh_head(POST_ARGS); |
static void post_sh_name(POST_ARGS); |
static void post_sh_name(POST_ARGS); |
Line 129 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
Line 130 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
post_dt, /* Dt */ |
post_dt, /* Dt */ |
post_os, /* Os */ |
post_os, /* Os */ |
post_sh, /* Sh */ |
post_sh, /* Sh */ |
post_ignpar, /* Ss */ |
post_section, /* Ss */ |
post_par, /* Pp */ |
post_par, /* Pp */ |
post_display, /* D1 */ |
post_display, /* D1 */ |
post_display, /* Dl */ |
post_display, /* Dl */ |
Line 150 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
Line 151 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
post_ex, /* Ex */ |
post_ex, /* Ex */ |
post_fa, /* Fa */ |
post_fa, /* Fa */ |
NULL, /* Fd */ |
NULL, /* Fd */ |
post_tag, /* Fl */ |
post_fl, /* Fl */ |
post_fn, /* Fn */ |
post_fn, /* Fn */ |
post_delim_nb, /* Ft */ |
post_delim_nb, /* Ft */ |
post_tag, /* Ic */ |
post_tag, /* Ic */ |
Line 163 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
Line 164 static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = |
|
post_defaults, /* Pa */ |
post_defaults, /* Pa */ |
post_rv, /* Rv */ |
post_rv, /* Rv */ |
post_st, /* St */ |
post_st, /* St */ |
post_delim_nb, /* Va */ |
post_tag, /* Va */ |
post_delim_nb, /* Vt */ |
post_delim_nb, /* Vt */ |
post_xr, /* Xr */ |
post_xr, /* Xr */ |
NULL, /* %A */ |
NULL, /* %A */ |
Line 1105 post_tg(POST_ARGS) |
|
Line 1106 post_tg(POST_ARGS) |
|
struct roff_node *n; /* The .Tg node. */ |
struct roff_node *n; /* The .Tg node. */ |
struct roff_node *nch; /* The first child of the .Tg node. */ |
struct roff_node *nch; /* The first child of the .Tg node. */ |
struct roff_node *nn; /* The next node after the .Tg node. */ |
struct roff_node *nn; /* The next node after the .Tg node. */ |
|
struct roff_node *np; /* The parent of the next node. */ |
struct roff_node *nt; /* The TEXT node containing the tag. */ |
struct roff_node *nt; /* The TEXT node containing the tag. */ |
size_t len; /* The number of bytes in the tag. */ |
size_t len; /* The number of bytes in the tag. */ |
|
|
Line 1150 post_tg(POST_ARGS) |
|
Line 1152 post_tg(POST_ARGS) |
|
} |
} |
|
|
/* By default, tag the .Tg node itself. */ |
/* By default, tag the .Tg node itself. */ |
if (nn == NULL) |
if (nn == NULL || nn->flags & NODE_ID) |
nn = n; |
nn = n; |
|
|
/* Explicit tagging of specific macros. */ |
/* Explicit tagging of specific macros. */ |
Line 1158 post_tg(POST_ARGS) |
|
Line 1160 post_tg(POST_ARGS) |
|
case MDOC_Sh: |
case MDOC_Sh: |
case MDOC_Ss: |
case MDOC_Ss: |
case MDOC_Fo: |
case MDOC_Fo: |
nn = nn->head; |
nn = nn->head->child == NULL ? n : nn->head; |
/* FALLTHROUGH */ |
break; |
|
case MDOC_It: |
|
np = nn->parent; |
|
while (np->tok != MDOC_Bl) |
|
np = np->parent; |
|
switch (np->norm->Bl.type) { |
|
case LIST_column: |
|
break; |
|
case LIST_diag: |
|
case LIST_hang: |
|
case LIST_inset: |
|
case LIST_ohang: |
|
case LIST_tag: |
|
nn = nn->head; |
|
break; |
|
case LIST_bullet: |
|
case LIST_dash: |
|
case LIST_enum: |
|
case LIST_hyphen: |
|
case LIST_item: |
|
nn = nn->body->child == NULL ? n : nn->body; |
|
break; |
|
default: |
|
abort(); |
|
} |
|
break; |
|
case MDOC_Bd: |
|
case MDOC_Bl: |
|
case MDOC_D1: |
|
case MDOC_Dl: |
|
nn = nn->body->child == NULL ? n : nn->body; |
|
break; |
|
case MDOC_Pp: |
|
break; |
case MDOC_Cm: |
case MDOC_Cm: |
case MDOC_Dv: |
case MDOC_Dv: |
case MDOC_Em: |
case MDOC_Em: |
Line 1172 post_tg(POST_ARGS) |
|
Line 1207 post_tg(POST_ARGS) |
|
case MDOC_Ms: |
case MDOC_Ms: |
case MDOC_No: |
case MDOC_No: |
case MDOC_Sy: |
case MDOC_Sy: |
if (nn->child != NULL && (nn->flags & NODE_ID) == 0) |
if (nn->child == NULL) |
break; |
nn = n; |
/* FALLTHROUGH */ |
break; |
default: |
default: |
nn = n; |
nn = n; |
break; |
break; |
Line 1594 post_es(POST_ARGS) |
|
Line 1629 post_es(POST_ARGS) |
|
} |
} |
|
|
static void |
static void |
|
post_fl(POST_ARGS) |
|
{ |
|
struct roff_node *n; |
|
char *cp; |
|
|
|
/* |
|
* Transform ".Fl Fl long" to ".Fl \-long", |
|
* resulting for example in better HTML output. |
|
*/ |
|
|
|
n = mdoc->last; |
|
if (n->prev != NULL && n->prev->tok == MDOC_Fl && |
|
n->prev->child == NULL && n->child != NULL && |
|
(n->flags & NODE_LINE) == 0) { |
|
mandoc_asprintf(&cp, "\\-%s", n->child->string); |
|
free(n->child->string); |
|
n->child->string = cp; |
|
roff_node_delete(mdoc, n->prev); |
|
} |
|
post_tag(mdoc); |
|
} |
|
|
|
static void |
post_xx(POST_ARGS) |
post_xx(POST_ARGS) |
{ |
{ |
struct roff_node *n; |
struct roff_node *n; |
Line 2164 post_rs(POST_ARGS) |
|
Line 2222 post_rs(POST_ARGS) |
|
static void |
static void |
post_hyph(POST_ARGS) |
post_hyph(POST_ARGS) |
{ |
{ |
struct roff_node *nch; |
struct roff_node *n, *nch; |
char *cp; |
char *cp; |
|
|
for (nch = mdoc->last->child; nch != NULL; nch = nch->next) { |
n = mdoc->last; |
|
for (nch = n->child; nch != NULL; nch = nch->next) { |
if (nch->type != ROFFT_TEXT) |
if (nch->type != ROFFT_TEXT) |
continue; |
continue; |
cp = nch->string; |
cp = nch->string; |
Line 2176 post_hyph(POST_ARGS) |
|
Line 2235 post_hyph(POST_ARGS) |
|
while (*(++cp) != '\0') |
while (*(++cp) != '\0') |
if (*cp == '-' && |
if (*cp == '-' && |
isalpha((unsigned char)cp[-1]) && |
isalpha((unsigned char)cp[-1]) && |
isalpha((unsigned char)cp[1])) |
isalpha((unsigned char)cp[1])) { |
|
if (n->tag == NULL && n->flags & NODE_ID) |
|
n->tag = mandoc_strdup(nch->string); |
*cp = ASCII_HYPH; |
*cp = ASCII_HYPH; |
|
} |
} |
} |
} |
} |
|
|
Line 2202 post_sx(POST_ARGS) |
|
Line 2264 post_sx(POST_ARGS) |
|
static void |
static void |
post_sh(POST_ARGS) |
post_sh(POST_ARGS) |
{ |
{ |
post_ignpar(mdoc); |
post_section(mdoc); |
|
|
switch (mdoc->last->type) { |
switch (mdoc->last->type) { |
case ROFFT_HEAD: |
case ROFFT_HEAD: |
Line 2535 post_xr(POST_ARGS) |
|
Line 2597 post_xr(POST_ARGS) |
|
} |
} |
|
|
static void |
static void |
post_ignpar(POST_ARGS) |
post_section(POST_ARGS) |
{ |
{ |
struct roff_node *np; |
struct roff_node *n, *nch; |
|
char *cp, *tag; |
|
|
switch (mdoc->last->type) { |
n = mdoc->last; |
|
switch (n->type) { |
case ROFFT_BLOCK: |
case ROFFT_BLOCK: |
post_prevpar(mdoc); |
post_prevpar(mdoc); |
return; |
return; |
case ROFFT_HEAD: |
case ROFFT_HEAD: |
|
tag = NULL; |
|
deroff(&tag, n); |
|
if (tag != NULL) { |
|
for (cp = tag; *cp != '\0'; cp++) |
|
if (*cp == ' ') |
|
*cp = '_'; |
|
if ((nch = n->child) != NULL && |
|
nch->type == ROFFT_TEXT && |
|
strcmp(nch->string, tag) == 0) |
|
tag_put(NULL, TAG_STRONG, n); |
|
else |
|
tag_put(tag, TAG_FALLBACK, n); |
|
free(tag); |
|
} |
post_delim(mdoc); |
post_delim(mdoc); |
post_hyph(mdoc); |
post_hyph(mdoc); |
return; |
return; |
Line 2552 post_ignpar(POST_ARGS) |
|
Line 2630 post_ignpar(POST_ARGS) |
|
default: |
default: |
return; |
return; |
} |
} |
|
if ((nch = n->child) != NULL && |
if ((np = mdoc->last->child) != NULL) |
(nch->tok == MDOC_Pp || nch->tok == ROFF_br || |
if (np->tok == MDOC_Pp || |
nch->tok == ROFF_sp)) { |
np->tok == ROFF_br || np->tok == ROFF_sp) { |
mandoc_msg(MANDOCERR_PAR_SKIP, nch->line, nch->pos, |
mandoc_msg(MANDOCERR_PAR_SKIP, np->line, np->pos, |
"%s after %s", roff_name[nch->tok], |
"%s after %s", roff_name[np->tok], |
roff_name[n->tok]); |
roff_name[mdoc->last->tok]); |
roff_node_delete(mdoc, nch); |
roff_node_delete(mdoc, np); |
} |
} |
if ((nch = n->last) != NULL && |
|
(nch->tok == MDOC_Pp || nch->tok == ROFF_br)) { |
if ((np = mdoc->last->last) != NULL) |
mandoc_msg(MANDOCERR_PAR_SKIP, nch->line, nch->pos, |
if (np->tok == MDOC_Pp || np->tok == ROFF_br) { |
"%s at the end of %s", roff_name[nch->tok], |
mandoc_msg(MANDOCERR_PAR_SKIP, np->line, np->pos, |
roff_name[n->tok]); |
"%s at the end of %s", roff_name[np->tok], |
roff_node_delete(mdoc, nch); |
roff_name[mdoc->last->tok]); |
} |
roff_node_delete(mdoc, np); |
|
} |
|
} |
} |
|
|
static void |
static void |
Line 2713 post_dt(POST_ARGS) |
|
Line 2789 post_dt(POST_ARGS) |
|
mandoc_msg(MANDOCERR_MSEC_BAD, |
mandoc_msg(MANDOCERR_MSEC_BAD, |
nn->line, nn->pos, "Dt ... %s", nn->string); |
nn->line, nn->pos, "Dt ... %s", nn->string); |
mdoc->meta.vol = mandoc_strdup(nn->string); |
mdoc->meta.vol = mandoc_strdup(nn->string); |
} else |
} else { |
mdoc->meta.vol = mandoc_strdup(cp); |
mdoc->meta.vol = mandoc_strdup(cp); |
|
if (mdoc->filesec != '\0' && |
|
mdoc->filesec != *nn->string && |
|
*nn->string >= '1' && *nn->string <= '9') |
|
mandoc_msg(MANDOCERR_MSEC_FILE, nn->line, nn->pos, |
|
"*.%c vs Dt ... %c", mdoc->filesec, *nn->string); |
|
} |
|
|
/* Optional third argument: architecture. */ |
/* Optional third argument: architecture. */ |
|
|
Line 2790 post_os(POST_ARGS) |
|
Line 2872 post_os(POST_ARGS) |
|
{ |
{ |
#ifndef OSNAME |
#ifndef OSNAME |
struct utsname utsname; |
struct utsname utsname; |
static char *defbuf; |
|
#endif |
#endif |
struct roff_node *n; |
struct roff_node *n; |
|
|
Line 2827 post_os(POST_ARGS) |
|
Line 2908 post_os(POST_ARGS) |
|
#ifdef OSNAME |
#ifdef OSNAME |
mdoc->meta.os = mandoc_strdup(OSNAME); |
mdoc->meta.os = mandoc_strdup(OSNAME); |
#else /*!OSNAME */ |
#else /*!OSNAME */ |
if (defbuf == NULL) { |
if (mdoc->os_r == NULL) { |
if (uname(&utsname) == -1) { |
if (uname(&utsname) == -1) { |
mandoc_msg(MANDOCERR_OS_UNAME, n->line, n->pos, "Os"); |
mandoc_msg(MANDOCERR_OS_UNAME, n->line, n->pos, "Os"); |
defbuf = mandoc_strdup("UNKNOWN"); |
mdoc->os_r = mandoc_strdup("UNKNOWN"); |
} else |
} else |
mandoc_asprintf(&defbuf, "%s %s", |
mandoc_asprintf(&mdoc->os_r, "%s %s", |
utsname.sysname, utsname.release); |
utsname.sysname, utsname.release); |
} |
} |
mdoc->meta.os = mandoc_strdup(defbuf); |
mdoc->meta.os = mandoc_strdup(mdoc->os_r); |
#endif /*!OSNAME*/ |
#endif /*!OSNAME*/ |
|
|
out: |
out: |