diff options
-rw-r--r-- | libman.h | 8 | ||||
-rw-r--r-- | man.7 | 22 | ||||
-rw-r--r-- | man.c | 37 | ||||
-rw-r--r-- | man_html.c | 8 | ||||
-rw-r--r-- | man_macro.c | 25 | ||||
-rw-r--r-- | man_term.c | 79 | ||||
-rw-r--r-- | man_validate.c | 6 |
7 files changed, 127 insertions, 58 deletions
@@ -30,9 +30,10 @@ struct man { int pflags; int flags; #define MAN_HALT (1 << 0) -#define MAN_ELINE (1 << 1) /* Next-line element scope. */ -#define MAN_BLINE (1 << 2) /* Next-line block scope. */ -#define MAN_LITERAL (1 << 3) /* Literal input. */ +#define MAN_ELINE (1 << 1) /* Next-line element scope. */ +#define MAN_BLINE (1 << 2) /* Next-line block scope. */ +#define MAN_ILINE (1 << 3) /* Ignored in next-line scope. */ +#define MAN_LITERAL (1 << 4) /* Literal input. */ enum man_next next; struct man_node *last; struct man_node *first; @@ -70,6 +71,7 @@ struct man_macro { #define MAN_SCOPED (1 << 0) #define MAN_EXPLICIT (1 << 1) /* See blk_imp(). */ #define MAN_FSCOPED (1 << 2) /* See blk_imp(). */ +#define MAN_NSCOPED (1 << 3) /* See in_line_eoln(). */ }; extern const struct man_macro *const man_macros; @@ -423,8 +423,8 @@ subsequent lines until closed by another block macro. .Ss Line Macros Line macros are generally scoped to the current line, with the body consisting of zero or more arguments. If a macro is scoped to the next -line and the line arguments are empty, the next line is used instead, -else the general syntax is used. Thus: +line and the line arguments are empty, the next line, which must be +text, is used instead. Thus: .Bd -literal -offset indent \&.I foo @@ -433,9 +433,15 @@ foo .Pp is equivalent to .Sq \&.I foo . -If next-line macros are invoked consecutively, only the last is used; in -other words, if a next-line macro is preceded by a block macro, it is -ignored. +If next-line macros are invoked consecutively, only the last is used. +If a next-line macro is followed by a non-next-line macro, an error is +raised (unless in the case of +.Sx \&br , +.Sx \&sp , +or +.Sx \&na ) . +.Pp +The syntax is as follows: .Bd -literal -offset indent \&.YO \(lBbody...\(rB \(lBbody...\(rB @@ -488,8 +494,10 @@ macros should not be used. They're included for compatibility. .Ss Block Macros Block macros are comprised of a head and body. Like for in-line macros, the head is scoped to the current line and, in one circumstance, the -next line; the body is scoped to subsequent lines and is closed out by a -subsequent block macro invocation. +next line (the next-line stipulations for line macros apply here as +well). +.Pp +The syntax is as follows: .Bd -literal -offset indent \&.YO \(lBhead...\(rB \(lBhead...\(rB @@ -534,15 +534,29 @@ man_pmacro(struct man *m, int ln, char *buf) if ( ! man_pwarn(m, ln, i - 1, WTSPACE)) goto err; - /* Remove prior ELINE macro, if applicable. */ + /* + * Remove prior ELINE macro, as a macro is clobbering it by + * being invoked without prior text. Note that NSCOPED macros + * do not close out ELINE macros, as they print no text. + */ - if (m->flags & MAN_ELINE) { + if (m->flags & MAN_ELINE && + ! (MAN_NSCOPED & man_macros[c].flags)) { n = m->last; assert(NULL == n->child); assert(0 == n->nchild); if ( ! man_nwarn(m, n, WLNSCOPE)) return(0); + /* FIXME: when called as in: + * + * .B + * .br + * .B + * .br + * hello + */ + if (n->prev) { assert(n != n->parent->child); assert(n == n->prev->next); @@ -568,8 +582,25 @@ man_pmacro(struct man *m, int ln, char *buf) goto err; out: - if ( ! (MAN_BLINE & fl)) + /* + * We weren't in a block-line scope when entering the + * above-parsed macro, so return. + */ + + if ( ! (MAN_BLINE & fl)) { + m->flags &= ~MAN_ILINE; return(1); + } + + /* + * If we're in a block scope, then allow this macro to slip by + * without closing scope around it. + */ + + if (MAN_ILINE & m->flags) { + m->flags &= ~MAN_ILINE; + return(1); + } /* * If we've opened a new next-line element scope, then return @@ -574,8 +574,12 @@ man_IP_pre(MAN_ARGS) width = a2width(nn, &su); } - if (MAN_TP == n->tok && NULL != nn) + if (MAN_TP == n->tok && NULL != nn) { + while (nn && MAN_TEXT != nn->type) + nn = nn->next; + /* FIXME: sync with pre_TP(), man_term.c */ width = a2width(nn, &su); + } if (MAN_BLOCK == n->type) { bufcat_su(h, "margin-left", &su); @@ -605,6 +609,8 @@ man_IP_pre(MAN_ARGS) if ( ! width) return(1); + /* FIXME: sync with pre_TP(), man_term.c */ + if (MAN_IP == n->tok) for (nn = n->child; nn->next; nn = nn->next) print_man_node(m, nn, h); diff --git a/man_macro.c b/man_macro.c index 6f2e8348..dfd521e3 100644 --- a/man_macro.c +++ b/man_macro.c @@ -40,7 +40,7 @@ static int rew_block(int, enum man_type, const struct man_node *); const struct man_macro __man_macros[MAN_MAX] = { - { in_line_eoln, 0 }, /* br */ + { in_line_eoln, MAN_NSCOPED }, /* br */ { in_line_eoln, 0 }, /* TH */ { blk_imp, MAN_SCOPED }, /* SH */ { blk_imp, MAN_SCOPED }, /* SS */ @@ -61,9 +61,9 @@ const struct man_macro __man_macros[MAN_MAX] = { { in_line_eoln, MAN_SCOPED }, /* I */ { in_line_eoln, 0 }, /* IR */ { in_line_eoln, 0 }, /* RI */ - { in_line_eoln, 0 }, /* na */ + { in_line_eoln, MAN_NSCOPED }, /* na */ { in_line_eoln, 0 }, /* i */ - { in_line_eoln, 0 }, /* sp */ + { in_line_eoln, MAN_NSCOPED }, /* sp */ { in_line_eoln, 0 }, /* nf */ { in_line_eoln, 0 }, /* fi */ { in_line_eoln, 0 }, /* r */ @@ -320,14 +320,29 @@ in_line_eoln(MACRO_PROT_ARGS) return(0); } + /* + * If no arguments are specified and this is MAN_SCOPED (i.e., + * next-line scoped), then set our mode to indicate that we're + * waiting for terms to load into our context. + */ + if (n == m->last && MAN_SCOPED & man_macros[tok].flags) { + assert( ! (MAN_NSCOPED & man_macros[tok].flags)); m->flags |= MAN_ELINE; return(1); } + /* Set ignorable context, if applicable. */ + + if (MAN_NSCOPED & man_macros[tok].flags) { + assert( ! (MAN_SCOPED & man_macros[tok].flags)); + m->flags |= MAN_ILINE; + } + /* - * Note that when TH is pruned, we'll be back at the root, so - * make sure that we don't clobber as its sibling. + * Rewind our element scope. Note that when TH is pruned, we'll + * be back at the root, so make sure that we don't clobber as + * its sibling. */ for ( ; m->last; m->last = m->last->parent) { @@ -65,6 +65,8 @@ struct mtermp { struct termact { int (*pre)(DECL_ARGS); void (*post)(DECL_ARGS); + int flags; +#define MAN_NOTEXT (1 << 0) /* Never has text children. */ }; static int a2width(const struct man_node *); @@ -105,38 +107,38 @@ static void post_SS(DECL_ARGS); static void post_TP(DECL_ARGS); static const struct termact termacts[MAN_MAX] = { - { pre_br, NULL }, /* br */ - { NULL, NULL }, /* TH */ - { pre_SH, post_SH }, /* SH */ - { pre_SS, post_SS }, /* SS */ - { pre_TP, post_TP }, /* TP */ - { pre_PP, NULL }, /* LP */ - { pre_PP, NULL }, /* PP */ - { pre_PP, NULL }, /* P */ - { pre_IP, post_IP }, /* IP */ - { pre_HP, post_HP }, /* HP */ - { NULL, NULL }, /* SM */ - { pre_B, NULL }, /* SB */ - { pre_BI, NULL }, /* BI */ - { pre_BI, NULL }, /* IB */ - { pre_RB, NULL }, /* BR */ - { pre_RB, NULL }, /* RB */ - { NULL, NULL }, /* R */ - { pre_B, NULL }, /* B */ - { pre_I, NULL }, /* I */ - { pre_RI, NULL }, /* IR */ - { pre_RI, NULL }, /* RI */ - { NULL, NULL }, /* na */ - { pre_I, NULL }, /* i */ - { pre_sp, NULL }, /* sp */ - { pre_nf, NULL }, /* nf */ - { pre_fi, NULL }, /* fi */ - { NULL, NULL }, /* r */ - { NULL, NULL }, /* RE */ - { pre_RS, post_RS }, /* RS */ - { pre_ign, NULL }, /* DT */ - { pre_ign, NULL }, /* UC */ - { pre_ign, NULL }, /* PD */ + { pre_br, NULL, MAN_NOTEXT }, /* br */ + { NULL, NULL, 0 }, /* TH */ + { pre_SH, post_SH, 0 }, /* SH */ + { pre_SS, post_SS, 0 }, /* SS */ + { pre_TP, post_TP, 0 }, /* TP */ + { pre_PP, NULL, 0 }, /* LP */ + { pre_PP, NULL, 0 }, /* PP */ + { pre_PP, NULL, 0 }, /* P */ + { pre_IP, post_IP, 0 }, /* IP */ + { pre_HP, post_HP, 0 }, /* HP */ + { NULL, NULL, 0 }, /* SM */ + { pre_B, NULL, 0 }, /* SB */ + { pre_BI, NULL, 0 }, /* BI */ + { pre_BI, NULL, 0 }, /* IB */ + { pre_RB, NULL, 0 }, /* BR */ + { pre_RB, NULL, 0 }, /* RB */ + { NULL, NULL, 0 }, /* R */ + { pre_B, NULL, 0 }, /* B */ + { pre_I, NULL, 0 }, /* I */ + { pre_RI, NULL, 0 }, /* IR */ + { pre_RI, NULL, 0 }, /* RI */ + { NULL, NULL, MAN_NOTEXT }, /* na */ + { pre_I, NULL, 0 }, /* i */ + { pre_sp, NULL, MAN_NOTEXT }, /* sp */ + { pre_nf, NULL, 0 }, /* nf */ + { pre_fi, NULL, 0 }, /* fi */ + { NULL, NULL, 0 }, /* r */ + { NULL, NULL, 0 }, /* RE */ + { pre_RS, post_RS, 0 }, /* RS */ + { pre_ign, NULL, 0 }, /* DT */ + { pre_ign, NULL, 0 }, /* UC */ + { pre_ign, NULL, 0 }, /* PD */ }; @@ -574,10 +576,13 @@ pre_TP(DECL_ARGS) /* Calculate offset. */ - if (NULL != (nn = n->parent->head->child)) - if (NULL != nn->next) + if (NULL != (nn = n->parent->head->child)) { + while (nn && MAN_TEXT != nn->type) + nn = nn->next; + if (nn && nn->next) if ((ival = a2width(nn)) >= 0) len = (size_t)ival; + } switch (n->type) { case (MAN_HEAD): @@ -803,7 +808,8 @@ print_man_node(DECL_ARGS) } break; default: - term_fontrepl(p, TERMFONT_NONE); + if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) + term_fontrepl(p, TERMFONT_NONE); if (termacts[n->tok].pre) c = (*termacts[n->tok].pre)(p, mt, n, m); break; @@ -815,7 +821,8 @@ print_man_node(DECL_ARGS) if (MAN_TEXT != n->type) { if (termacts[n->tok].post) (*termacts[n->tok].post)(p, mt, n, m); - term_fontrepl(p, TERMFONT_NONE); + if ( ! (MAN_NOTEXT & termacts[n->tok].flags)) + term_fontrepl(p, TERMFONT_NONE); } } diff --git a/man_validate.c b/man_validate.c index 85cc763f..16320064 100644 --- a/man_validate.c +++ b/man_validate.c @@ -59,7 +59,7 @@ static v_check posts_sp[] = { check_le1, NULL }; static v_check pres_bline[] = { check_bline, NULL }; static const struct man_valid man_valids[MAN_MAX] = { - { pres_bline, posts_eq0 }, /* br */ + { NULL, posts_eq0 }, /* br */ { pres_bline, posts_ge2_le5 }, /* TH */ /* FIXME: make sure capitalised. */ { pres_bline, posts_sec }, /* SH */ { pres_bline, posts_sec }, /* SS */ @@ -80,9 +80,9 @@ static const struct man_valid man_valids[MAN_MAX] = { { NULL, NULL }, /* I */ { NULL, NULL }, /* IR */ { NULL, NULL }, /* RI */ - { pres_bline, posts_eq0 }, /* na */ + { NULL, posts_eq0 }, /* na */ { NULL, NULL }, /* i */ - { pres_bline, posts_sp }, /* sp */ + { NULL, posts_sp }, /* sp */ { pres_bline, posts_eq0 }, /* nf */ { pres_bline, posts_eq0 }, /* fi */ { NULL, NULL }, /* r */ |