version 1.69, 2009/09/15 08:16:20 |
version 1.76, 2009/09/21 14:07:07 |
|
|
#include "term.h" |
#include "term.h" |
#include "mdoc.h" |
#include "mdoc.h" |
|
|
|
/* FIXME: check HANG lists: they seem to be broken... : |
|
* .Bl -hang -width Ds |
|
* .It a |
|
* b |
|
* .It Fl f Ns Ar option... |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* . |
|
* .It a sasd fasd as afsd sfad sfds sadfs sd sfd ssfad asfd |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* Override default compiler behaviour. See |
|
* .Sx Compiler Options |
|
* for details. |
|
* .El |
|
* |
|
*/ |
|
|
#define INDENT 5 |
#define INDENT 5 |
#define HALFINDENT 3 |
#define HALFINDENT 3 |
|
|
Line 78 static int termp_bd_pre(DECL_ARGS); |
|
Line 113 static int termp_bd_pre(DECL_ARGS); |
|
static int termp_bf_pre(DECL_ARGS); |
static int termp_bf_pre(DECL_ARGS); |
static int termp_bold_pre(DECL_ARGS); |
static int termp_bold_pre(DECL_ARGS); |
static int termp_bq_pre(DECL_ARGS); |
static int termp_bq_pre(DECL_ARGS); |
static int termp_br_pre(DECL_ARGS); |
|
static int termp_brq_pre(DECL_ARGS); |
static int termp_brq_pre(DECL_ARGS); |
static int termp_bt_pre(DECL_ARGS); |
static int termp_bt_pre(DECL_ARGS); |
static int termp_cd_pre(DECL_ARGS); |
static int termp_cd_pre(DECL_ARGS); |
Line 98 static int termp_nm_pre(DECL_ARGS); |
|
Line 132 static int termp_nm_pre(DECL_ARGS); |
|
static int termp_ns_pre(DECL_ARGS); |
static int termp_ns_pre(DECL_ARGS); |
static int termp_op_pre(DECL_ARGS); |
static int termp_op_pre(DECL_ARGS); |
static int termp_pf_pre(DECL_ARGS); |
static int termp_pf_pre(DECL_ARGS); |
static int termp_pp_pre(DECL_ARGS); |
|
static int termp_pq_pre(DECL_ARGS); |
static int termp_pq_pre(DECL_ARGS); |
static int termp_qq_pre(DECL_ARGS); |
static int termp_qq_pre(DECL_ARGS); |
static int termp_rs_pre(DECL_ARGS); |
static int termp_rs_pre(DECL_ARGS); |
Line 113 static int termp_ud_pre(DECL_ARGS); |
|
Line 146 static int termp_ud_pre(DECL_ARGS); |
|
static int termp_xr_pre(DECL_ARGS); |
static int termp_xr_pre(DECL_ARGS); |
static int termp_xx_pre(DECL_ARGS); |
static int termp_xx_pre(DECL_ARGS); |
|
|
static const struct termact termacts[MDOC_MAX] = { |
static const struct termact termacts[MDOC_MAX] = { |
{ termp_ap_pre, NULL }, /* Ap */ |
{ termp_ap_pre, NULL }, /* Ap */ |
{ NULL, NULL }, /* Dd */ |
{ NULL, NULL }, /* Dd */ |
{ NULL, NULL }, /* Dt */ |
{ NULL, NULL }, /* Dt */ |
{ NULL, NULL }, /* Os */ |
{ NULL, NULL }, /* Os */ |
{ termp_sh_pre, termp_sh_post }, /* Sh */ |
{ termp_sh_pre, termp_sh_post }, /* Sh */ |
{ termp_ss_pre, termp_ss_post }, /* Ss */ |
{ termp_ss_pre, termp_ss_post }, /* Ss */ |
{ termp_pp_pre, NULL }, /* Pp */ |
{ termp_sp_pre, NULL }, /* Pp */ |
{ termp_d1_pre, termp_d1_post }, /* D1 */ |
{ termp_d1_pre, termp_d1_post }, /* D1 */ |
{ termp_d1_pre, termp_d1_post }, /* Dl */ |
{ termp_d1_pre, termp_d1_post }, /* Dl */ |
{ termp_bd_pre, termp_bd_post }, /* Bd */ |
{ termp_bd_pre, termp_bd_post }, /* Bd */ |
Line 153 static const struct termact termacts[MDOC_MAX] = { |
|
Line 186 static const struct termact termacts[MDOC_MAX] = { |
|
{ termp_rv_pre, NULL }, /* Rv */ |
{ termp_rv_pre, NULL }, /* Rv */ |
{ NULL, NULL }, /* St */ |
{ NULL, NULL }, /* St */ |
{ termp_under_pre, NULL }, /* Va */ |
{ termp_under_pre, NULL }, /* Va */ |
{ termp_under_pre, termp_vt_post }, /* Vt */ /* FIXME: type name */ |
{ termp_under_pre, termp_vt_post }, /* Vt */ |
{ termp_xr_pre, NULL }, /* Xr */ |
{ termp_xr_pre, NULL }, /* Xr */ |
{ NULL, termp____post }, /* %A */ |
{ NULL, termp____post }, /* %A */ |
{ NULL, termp____post }, /* %B */ |
{ NULL, termp____post }, /* %B */ |
Line 221 static const struct termact termacts[MDOC_MAX] = { |
|
Line 254 static const struct termact termacts[MDOC_MAX] = { |
|
{ NULL, NULL }, /* Fr */ |
{ NULL, NULL }, /* Fr */ |
{ termp_ud_pre, NULL }, /* Ud */ |
{ termp_ud_pre, NULL }, /* Ud */ |
{ NULL, termp_lb_post }, /* Lb */ |
{ NULL, termp_lb_post }, /* Lb */ |
{ termp_pp_pre, NULL }, /* Lp */ |
{ termp_sp_pre, NULL }, /* Lp */ |
{ termp_lk_pre, NULL }, /* Lk */ |
{ termp_lk_pre, NULL }, /* Lk */ |
{ termp_under_pre, NULL }, /* Mt */ |
{ termp_under_pre, NULL }, /* Mt */ |
{ termp_brq_pre, termp_brq_post }, /* Brq */ |
{ termp_brq_pre, termp_brq_post }, /* Brq */ |
Line 232 static const struct termact termacts[MDOC_MAX] = { |
|
Line 265 static const struct termact termacts[MDOC_MAX] = { |
|
{ NULL, NULL }, /* En */ |
{ NULL, NULL }, /* En */ |
{ termp_xx_pre, NULL }, /* Dx */ |
{ termp_xx_pre, NULL }, /* Dx */ |
{ NULL, NULL }, /* %Q */ |
{ NULL, NULL }, /* %Q */ |
{ termp_br_pre, NULL }, /* br */ |
{ termp_sp_pre, NULL }, /* br */ |
{ termp_sp_pre, NULL }, /* sp */ |
{ termp_sp_pre, NULL }, /* sp */ |
}; |
}; |
|
|
Line 252 static void fmt_block_vspace(struct termp *, |
|
Line 285 static void fmt_block_vspace(struct termp *, |
|
const struct mdoc_node *, |
const struct mdoc_node *, |
const struct mdoc_node *); |
const struct mdoc_node *); |
static void print_node(DECL_ARGS); |
static void print_node(DECL_ARGS); |
static void print_head(struct termp *, |
static void print_head(DECL_ARGS); |
const struct mdoc_meta *); |
|
static void print_body(DECL_ARGS); |
static void print_body(DECL_ARGS); |
static void print_foot(struct termp *, |
static void print_foot(DECL_ARGS); |
const struct mdoc_meta *); |
|
|
|
|
|
int |
void |
mdoc_run(struct termp *p, const struct mdoc *m) |
mdoc_run(struct termp *p, const struct mdoc *mdoc) |
{ |
{ |
/* |
const struct mdoc_node *n; |
* Main output function. When this is called, assume that the |
const struct mdoc_meta *m; |
* tree is properly formed. |
|
*/ |
n = mdoc_node(mdoc); |
print_head(p, mdoc_meta(m)); |
m = mdoc_meta(mdoc); |
assert(mdoc_node(m)); |
|
assert(MDOC_ROOT == mdoc_node(m)->type); |
print_head(p, NULL, m, n); |
if (mdoc_node(m)->child) |
if (n->child) |
print_body(p, NULL, mdoc_meta(m), mdoc_node(m)->child); |
print_body(p, NULL, m, n->child); |
print_foot(p, mdoc_meta(m)); |
print_foot(p, NULL, m, n); |
return(1); |
|
} |
} |
|
|
|
|
Line 281 print_body(DECL_ARGS) |
|
Line 311 print_body(DECL_ARGS) |
|
{ |
{ |
|
|
print_node(p, pair, meta, node); |
print_node(p, pair, meta, node); |
if ( ! node->next) |
if (node->next) |
return; |
print_body(p, pair, meta, node->next); |
print_body(p, pair, meta, node->next); |
|
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static void |
static void |
print_node(DECL_ARGS) |
print_node(DECL_ARGS) |
{ |
{ |
int dochild, bold, under; |
int chld, bold, under; |
struct termpair npair; |
struct termpair npair; |
size_t offset, rmargin; |
size_t offset, rmargin; |
|
|
dochild = 1; |
chld = 1; |
offset = p->offset; |
offset = p->offset; |
rmargin = p->rmargin; |
rmargin = p->rmargin; |
bold = p->bold; |
bold = p->bold; |
under = p->under; |
under = p->under; |
|
|
|
bzero(&npair, sizeof(struct termpair)); |
npair.ppair = pair; |
npair.ppair = pair; |
npair.flag = 0; |
|
npair.count = 0; |
|
|
|
/* |
|
* Note on termpair. This allows a pre function to set a termp |
|
* flag that is automatically unset after the body, but before |
|
* the post function. Thus, if a pre uses a termpair flag, it |
|
* must be reapplied in the post for use. |
|
*/ |
|
|
|
if (MDOC_TEXT != node->type) { |
if (MDOC_TEXT != node->type) { |
if (termacts[node->tok].pre) |
if (termacts[node->tok].pre) |
if ( ! (*termacts[node->tok].pre)(p, &npair, meta, node)) |
chld = (*termacts[node->tok].pre) |
dochild = 0; |
(p, &npair, meta, node); |
} else /* MDOC_TEXT == node->type */ |
} else |
term_word(p, node->string); |
term_word(p, node->string); |
|
|
/* Children. */ |
if (chld && node->child) |
|
|
if (dochild && node->child) |
|
print_body(p, &npair, meta, node->child); |
print_body(p, &npair, meta, node->child); |
|
|
|
/* |
|
* XXX - if bold/under were to span scopes, this wouldn't be |
|
* possible, but because decoration is always in-scope, we can |
|
* get away with this. |
|
*/ |
|
|
p->bold = bold; |
p->bold = bold; |
p->under = under; |
p->under = under; |
|
|
/* Post-processing. */ |
|
|
|
if (MDOC_TEXT != node->type) |
if (MDOC_TEXT != node->type) |
if (termacts[node->tok].post) |
if (termacts[node->tok].post) |
(*termacts[node->tok].post)(p, &npair, meta, node); |
(*termacts[node->tok].post) |
|
(p, &npair, meta, node); |
|
|
p->offset = offset; |
p->offset = offset; |
p->rmargin = rmargin; |
p->rmargin = rmargin; |
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static void |
static void |
print_foot(struct termp *p, const struct mdoc_meta *meta) |
print_foot(DECL_ARGS) |
{ |
{ |
struct tm *tm; |
struct tm *tm; |
char *buf, *os; |
char *buf, *os; |
Line 352 print_foot(struct termp *p, const struct mdoc_meta *me |
|
Line 378 print_foot(struct termp *p, const struct mdoc_meta *me |
|
*/ |
*/ |
|
|
if (NULL == (buf = malloc(p->rmargin))) |
if (NULL == (buf = malloc(p->rmargin))) |
err(1, "malloc"); |
err(EXIT_FAILURE, "malloc"); |
if (NULL == (os = malloc(p->rmargin))) |
if (NULL == (os = malloc(p->rmargin))) |
err(1, "malloc"); |
err(EXIT_FAILURE, "malloc"); |
|
|
tm = localtime(&meta->date); |
tm = localtime(&meta->date); |
|
|
if (0 == strftime(buf, p->rmargin, "%B %e, %Y", tm)) |
if (0 == strftime(buf, p->rmargin, "%B %e, %Y", tm)) |
err(1, "strftime"); |
err(EXIT_FAILURE, "strftime"); |
|
|
(void)strlcpy(os, meta->os, p->rmargin); |
(void)strlcpy(os, meta->os, p->rmargin); |
|
|
Line 396 print_foot(struct termp *p, const struct mdoc_meta *me |
|
Line 422 print_foot(struct termp *p, const struct mdoc_meta *me |
|
} |
} |
|
|
|
|
|
/* FIXME: put in utility library. */ |
|
/* ARGSUSED */ |
static void |
static void |
print_head(struct termp *p, const struct mdoc_meta *meta) |
print_head(DECL_ARGS) |
{ |
{ |
char *buf, *title; |
char *buf, *title; |
|
|
Line 405 print_head(struct termp *p, const struct mdoc_meta *me |
|
Line 433 print_head(struct termp *p, const struct mdoc_meta *me |
|
p->offset = 0; |
p->offset = 0; |
|
|
if (NULL == (buf = malloc(p->rmargin))) |
if (NULL == (buf = malloc(p->rmargin))) |
err(1, "malloc"); |
err(EXIT_FAILURE, "malloc"); |
if (NULL == (title = malloc(p->rmargin))) |
if (NULL == (title = malloc(p->rmargin))) |
err(1, "malloc"); |
err(EXIT_FAILURE, "malloc"); |
|
|
/* |
/* |
* The header is strange. It has three components, which are |
* The header is strange. It has three components, which are |
Line 431 print_head(struct termp *p, const struct mdoc_meta *me |
|
Line 459 print_head(struct termp *p, const struct mdoc_meta *me |
|
(void)strlcat(buf, ")", p->rmargin); |
(void)strlcat(buf, ")", p->rmargin); |
} |
} |
|
|
(void)snprintf(title, p->rmargin, "%s(%d)", |
snprintf(title, p->rmargin, "%s(%d)", meta->title, meta->msec); |
meta->title, meta->msec); |
|
|
|
p->offset = 0; |
p->offset = 0; |
p->rmargin = (p->maxrmargin - strlen(buf) + 1) / 2; |
p->rmargin = (p->maxrmargin - strlen(buf) + 1) / 2; |
Line 465 print_head(struct termp *p, const struct mdoc_meta *me |
|
Line 492 print_head(struct termp *p, const struct mdoc_meta *me |
|
} |
} |
|
|
|
|
|
/* FIXME: put in utility file for front-ends. */ |
static size_t |
static size_t |
arg_width(const struct mdoc_argv *arg, int pos) |
arg_width(const struct mdoc_argv *arg, int pos) |
{ |
{ |
Line 491 arg_width(const struct mdoc_argv *arg, int pos) |
|
Line 519 arg_width(const struct mdoc_argv *arg, int pos) |
|
} |
} |
|
|
|
|
|
/* FIXME: put in utility file for front-ends. */ |
static int |
static int |
arg_listtype(const struct mdoc_node *n) |
arg_listtype(const struct mdoc_node *n) |
{ |
{ |
Line 532 arg_listtype(const struct mdoc_node *n) |
|
Line 561 arg_listtype(const struct mdoc_node *n) |
|
} |
} |
|
|
|
|
|
/* FIXME: put in utility file for front-ends. */ |
static size_t |
static size_t |
arg_offset(const struct mdoc_argv *arg) |
arg_offset(const struct mdoc_argv *arg) |
{ |
{ |
Line 731 termp_it_pre(DECL_ARGS) |
|
Line 761 termp_it_pre(DECL_ARGS) |
|
* the 0 will be adjusted to default 10 or, if in the |
* the 0 will be adjusted to default 10 or, if in the |
* last column case, set to stretch to the margin). |
* last column case, set to stretch to the margin). |
*/ |
*/ |
for (i = 0, n = node->prev; n && n && |
for (i = 0, n = node->prev; n && |
i < (int)bl->args[vals[2]].argv->sz; |
i < (int)bl->args[vals[2]].argv->sz; |
n = n->prev, i++) |
n = n->prev, i++) |
offset += arg_width |
offset += arg_width |
Line 1131 termp_ns_pre(DECL_ARGS) |
|
Line 1161 termp_ns_pre(DECL_ARGS) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static int |
static int |
termp_pp_pre(DECL_ARGS) |
|
{ |
|
|
|
term_vspace(p); |
|
return(1); |
|
} |
|
|
|
|
|
/* ARGSUSED */ |
|
static int |
|
termp_rs_pre(DECL_ARGS) |
termp_rs_pre(DECL_ARGS) |
{ |
{ |
|
|
Line 1846 termp_sp_pre(DECL_ARGS) |
|
Line 1866 termp_sp_pre(DECL_ARGS) |
|
{ |
{ |
int i, len; |
int i, len; |
|
|
if (NULL == node->child) { |
switch (node->type) { |
term_vspace(p); |
case (MDOC_sp): |
return(0); |
len = node->child ? atoi(node->child->string) : 1; |
|
break; |
|
case (MDOC_br): |
|
len = 0; |
|
break; |
|
default: |
|
len = 1; |
|
break; |
} |
} |
|
|
len = atoi(node->child->string); |
|
if (0 == len) |
if (0 == len) |
term_newln(p); |
term_newln(p); |
for (i = 0; i < len; i++) |
for (i = 0; i < len; i++) |
term_vspace(p); |
term_vspace(p); |
|
|
return(0); |
return(0); |
} |
|
|
|
|
|
/* ARGSUSED */ |
|
static int |
|
termp_br_pre(DECL_ARGS) |
|
{ |
|
|
|
term_newln(p); |
|
return(1); |
|
} |
} |
|
|
|
|