version 1.3, 2009/03/20 15:14:01 |
version 1.8, 2009/03/25 21:46:24 |
Line 29 extern size_t strlcpy(char *, const char *, size_t) |
|
Line 29 extern size_t strlcpy(char *, const char *, size_t) |
|
extern size_t strlcat(char *, const char *, size_t); |
extern size_t strlcat(char *, const char *, size_t); |
#endif |
#endif |
|
|
static struct termp *termp_alloc(enum termenc); |
static struct termp *term_alloc(enum termenc); |
static void termp_free(struct termp *); |
static void term_free(struct termp *); |
static void termp_body(struct termp *, struct termpair *, |
static void term_body(struct termp *, struct termpair *, |
const struct mdoc_meta *, |
const struct mdoc_meta *, |
const struct mdoc_node *); |
const struct mdoc_node *); |
static void termp_head(struct termp *, |
static void term_head(struct termp *, |
const struct mdoc_meta *); |
const struct mdoc_meta *); |
static void termp_foot(struct termp *, |
static void term_foot(struct termp *, |
const struct mdoc_meta *); |
const struct mdoc_meta *); |
static void termp_pword(struct termp *, const char *, int); |
static void term_pword(struct termp *, const char *, int); |
static void termp_pescape(struct termp *, |
static void term_pescape(struct termp *, |
const char *, int *, int); |
const char *, int *, int); |
static void termp_nescape(struct termp *, |
static void term_nescape(struct termp *, |
const char *, size_t); |
const char *, size_t); |
static void termp_chara(struct termp *, char); |
static void term_chara(struct termp *, char); |
static void termp_stringa(struct termp *, |
static void term_stringa(struct termp *, |
const char *, size_t); |
const char *, size_t); |
|
static int term_isopendelim(const char *, int); |
|
static int term_isclosedelim(const char *, int); |
static void sanity(const struct mdoc_node *); /* XXX */ |
static void sanity(const struct mdoc_node *); /* XXX */ |
|
|
|
|
void * |
void * |
latin1_alloc(void) |
|
{ |
|
|
|
return(termp_alloc(TERMENC_LATIN1)); |
|
} |
|
|
|
|
|
void * |
|
utf8_alloc(void) |
|
{ |
|
|
|
return(termp_alloc(TERMENC_UTF8)); |
|
} |
|
|
|
|
|
void * |
|
ascii_alloc(void) |
ascii_alloc(void) |
{ |
{ |
|
|
return(termp_alloc(TERMENC_ASCII)); |
return(term_alloc(TERMENC_ASCII)); |
} |
} |
|
|
|
|
int |
int |
terminal_run(void *arg, const struct mdoc *mdoc) |
terminal_run(void *arg, const struct man *man, |
|
const struct mdoc *mdoc) |
{ |
{ |
struct termp *p; |
struct termp *p; |
|
|
|
if (NULL == mdoc) |
|
return(1); |
|
|
p = (struct termp *)arg; |
p = (struct termp *)arg; |
|
|
if (NULL == p->symtab) |
if (NULL == p->symtab) |
p->symtab = term_ascii2htab(); |
p->symtab = term_ascii2htab(); |
|
|
termp_head(p, mdoc_meta(mdoc)); |
term_head(p, mdoc_meta(mdoc)); |
termp_body(p, NULL, mdoc_meta(mdoc), mdoc_node(mdoc)); |
term_body(p, NULL, mdoc_meta(mdoc), mdoc_node(mdoc)); |
termp_foot(p, mdoc_meta(mdoc)); |
term_foot(p, mdoc_meta(mdoc)); |
|
|
return(1); |
return(1); |
} |
} |
|
|
terminal_free(void *arg) |
terminal_free(void *arg) |
{ |
{ |
|
|
termp_free((struct termp *)arg); |
term_free((struct termp *)arg); |
} |
} |
|
|
|
|
static void |
static void |
termp_free(struct termp *p) |
term_free(struct termp *p) |
{ |
{ |
|
|
if (p->buf) |
if (p->buf) |
Line 113 termp_free(struct termp *p) |
|
Line 103 termp_free(struct termp *p) |
|
|
|
|
|
static struct termp * |
static struct termp * |
termp_alloc(enum termenc enc) |
term_alloc(enum termenc enc) |
{ |
{ |
struct termp *p; |
struct termp *p; |
|
|
Line 126 termp_alloc(enum termenc enc) |
|
Line 116 termp_alloc(enum termenc enc) |
|
} |
} |
|
|
|
|
|
static int |
|
term_isclosedelim(const char *p, int len) |
|
{ |
|
|
|
if (1 != len) |
|
return(0); |
|
|
|
switch (*p) { |
|
case('.'): |
|
/* FALLTHROUGH */ |
|
case(','): |
|
/* FALLTHROUGH */ |
|
case(';'): |
|
/* FALLTHROUGH */ |
|
case(':'): |
|
/* FALLTHROUGH */ |
|
case('?'): |
|
/* FALLTHROUGH */ |
|
case('!'): |
|
/* FALLTHROUGH */ |
|
case(')'): |
|
/* FALLTHROUGH */ |
|
case(']'): |
|
/* FALLTHROUGH */ |
|
case('}'): |
|
return(1); |
|
default: |
|
break; |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
|
|
static int |
|
term_isopendelim(const char *p, int len) |
|
{ |
|
|
|
if (1 != len) |
|
return(0); |
|
|
|
switch (*p) { |
|
case('('): |
|
/* FALLTHROUGH */ |
|
case('['): |
|
/* FALLTHROUGH */ |
|
case('{'): |
|
return(1); |
|
default: |
|
break; |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
|
/* |
/* |
* Flush a line of text. A "line" is loosely defined as being something |
* Flush a line of text. A "line" is loosely defined as being something |
* that should be followed by a newline, regardless of whether it's |
* that should be followed by a newline, regardless of whether it's |
Line 222 term_flushln(struct termp *p) |
|
Line 268 term_flushln(struct termp *p) |
|
for (j = 0; j < (int)p->offset; j++) |
for (j = 0; j < (int)p->offset; j++) |
putchar(' '); |
putchar(' '); |
vis = 0; |
vis = 0; |
} else if (vis + vsz > bp) |
} |
warnx("word breaks right margin"); |
} else if (vis && vis + vsz > bp) { |
|
putchar('\n'); |
/* TODO: hyphenate. */ |
for (j = 0; j < (int)p->rmargin; j++) |
|
putchar(' '); |
} else { |
vis = p->rmargin - p->offset; |
if (vis && vis + vsz > bp) { |
|
putchar('\n'); |
|
for (j = 0; j < (int)p->rmargin; j++) |
|
putchar(' '); |
|
vis = p->rmargin - p->offset; |
|
} else if (vis + vsz > bp) |
|
warnx("word breaks right margin"); |
|
|
|
/* TODO: hyphenate. */ |
|
} |
} |
|
|
/* |
/* |
Line 336 term_word(struct termp *p, const char *word) |
|
Line 373 term_word(struct termp *p, const char *word) |
|
len = (int)strlen(word); |
len = (int)strlen(word); |
|
|
if (p->flags & TERMP_LITERAL) { |
if (p->flags & TERMP_LITERAL) { |
termp_pword(p, word, len); |
term_pword(p, word, len); |
return; |
return; |
} |
} |
|
|
if (mdoc_isdelim(word)) { |
|
if ( ! (p->flags & TERMP_IGNDELIM)) |
|
p->flags |= TERMP_NOSPACE; |
|
p->flags &= ~TERMP_IGNDELIM; |
|
} |
|
|
|
/* LINTED */ |
/* LINTED */ |
for (j = i = 0; i < len; i++) { |
for (j = i = 0; i < len; i++) { |
if (' ' != word[i]) { |
if (' ' != word[i]) { |
Line 362 term_word(struct termp *p, const char *word) |
|
Line 393 term_word(struct termp *p, const char *word) |
|
if (0 == j) |
if (0 == j) |
continue; |
continue; |
assert(i >= j); |
assert(i >= j); |
termp_pword(p, &word[i - j], j); |
term_pword(p, &word[i - j], j); |
j = 0; |
j = 0; |
} |
} |
if (j > 0) { |
if (j > 0) { |
assert(i >= j); |
assert(i >= j); |
termp_pword(p, &word[i - j], j); |
term_pword(p, &word[i - j], j); |
} |
} |
} |
} |
|
|
|
|
static void |
static void |
termp_body(struct termp *p, struct termpair *ppair, |
term_body(struct termp *p, struct termpair *ppair, |
const struct mdoc_meta *meta, |
const struct mdoc_meta *meta, |
const struct mdoc_node *node) |
const struct mdoc_node *node) |
{ |
{ |
|
|
term_node(p, ppair, meta, node); |
term_node(p, ppair, meta, node); |
if (node->next) |
if (node->next) |
termp_body(p, ppair, meta, node->next); |
term_body(p, ppair, meta, node->next); |
} |
} |
|
|
|
|
Line 424 term_node(struct termp *p, struct termpair *ppair, |
|
Line 455 term_node(struct termp *p, struct termpair *ppair, |
|
p->flags |= pair.flag; |
p->flags |= pair.flag; |
|
|
if (dochild && node->child) |
if (dochild && node->child) |
termp_body(p, &pair, meta, node->child); |
term_body(p, &pair, meta, node->child); |
|
|
if (TERMPAIR_FLAG & pair.type) |
if (TERMPAIR_FLAG & pair.type) |
p->flags &= ~pair.flag; |
p->flags &= ~pair.flag; |
Line 438 term_node(struct termp *p, struct termpair *ppair, |
|
Line 469 term_node(struct termp *p, struct termpair *ppair, |
|
|
|
|
|
static void |
static void |
termp_foot(struct termp *p, const struct mdoc_meta *meta) |
term_foot(struct termp *p, const struct mdoc_meta *meta) |
{ |
{ |
struct tm *tm; |
struct tm *tm; |
char *buf, *os; |
char *buf, *os; |
Line 489 termp_foot(struct termp *p, const struct mdoc_meta *me |
|
Line 520 termp_foot(struct termp *p, const struct mdoc_meta *me |
|
|
|
|
|
static void |
static void |
termp_head(struct termp *p, const struct mdoc_meta *meta) |
term_head(struct termp *p, const struct mdoc_meta *meta) |
{ |
{ |
char *buf, *title; |
char *buf, *title; |
|
|
Line 563 termp_head(struct termp *p, const struct mdoc_meta *me |
|
Line 594 termp_head(struct termp *p, const struct mdoc_meta *me |
|
* output buffer by way of the symbol table. |
* output buffer by way of the symbol table. |
*/ |
*/ |
static void |
static void |
termp_nescape(struct termp *p, const char *word, size_t len) |
term_nescape(struct termp *p, const char *word, size_t len) |
{ |
{ |
const char *rhs; |
const char *rhs; |
size_t sz; |
size_t sz; |
|
|
if (NULL == (rhs = term_a2ascii(p->symtab, word, len, &sz))) |
if (NULL == (rhs = term_a2ascii(p->symtab, word, len, &sz))) |
return; |
return; |
termp_stringa(p, rhs, sz); |
term_stringa(p, rhs, sz); |
} |
} |
|
|
|
|
Line 580 termp_nescape(struct termp *p, const char *word, size_ |
|
Line 611 termp_nescape(struct termp *p, const char *word, size_ |
|
* the escape sequence (we assert upon badly-formed escape sequences). |
* the escape sequence (we assert upon badly-formed escape sequences). |
*/ |
*/ |
static void |
static void |
termp_pescape(struct termp *p, const char *word, int *i, int len) |
term_pescape(struct termp *p, const char *word, int *i, int len) |
{ |
{ |
int j; |
int j; |
|
|
Line 592 termp_pescape(struct termp *p, const char *word, int * |
|
Line 623 termp_pescape(struct termp *p, const char *word, int * |
|
if (*i + 1 >= len) |
if (*i + 1 >= len) |
return; |
return; |
|
|
termp_nescape(p, &word[*i], 2); |
term_nescape(p, &word[*i], 2); |
(*i)++; |
(*i)++; |
return; |
return; |
|
|
Line 607 termp_pescape(struct termp *p, const char *word, int * |
|
Line 638 termp_pescape(struct termp *p, const char *word, int * |
|
if (*i + 1 >= len) |
if (*i + 1 >= len) |
return; |
return; |
|
|
termp_nescape(p, &word[*i], 2); |
term_nescape(p, &word[*i], 2); |
(*i)++; |
(*i)++; |
return; |
return; |
case ('['): |
case ('['): |
break; |
break; |
default: |
default: |
termp_nescape(p, &word[*i], 1); |
term_nescape(p, &word[*i], 1); |
return; |
return; |
} |
} |
|
|
} else if ('[' != word[*i]) { |
} else if ('[' != word[*i]) { |
termp_nescape(p, &word[*i], 1); |
term_nescape(p, &word[*i], 1); |
return; |
return; |
} |
} |
|
|
Line 629 termp_pescape(struct termp *p, const char *word, int * |
|
Line 660 termp_pescape(struct termp *p, const char *word, int * |
|
if (0 == word[*i]) |
if (0 == word[*i]) |
return; |
return; |
|
|
termp_nescape(p, &word[*i - j], (size_t)j); |
term_nescape(p, &word[*i - j], (size_t)j); |
} |
} |
|
|
|
|
Line 639 termp_pescape(struct termp *p, const char *word, int * |
|
Line 670 termp_pescape(struct termp *p, const char *word, int * |
|
* handles word styling. |
* handles word styling. |
*/ |
*/ |
static void |
static void |
termp_pword(struct termp *p, const char *word, int len) |
term_pword(struct termp *p, const char *word, int len) |
{ |
{ |
int i; |
int i; |
|
|
|
if (term_isclosedelim(word, len)) |
|
if ( ! (TERMP_IGNDELIM & p->flags)) |
|
p->flags |= TERMP_NOSPACE; |
|
|
if ( ! (TERMP_NOSPACE & p->flags)) |
if ( ! (TERMP_NOSPACE & p->flags)) |
termp_chara(p, ' '); |
term_chara(p, ' '); |
|
|
if ( ! (p->flags & TERMP_NONOSPACE)) |
if ( ! (p->flags & TERMP_NONOSPACE)) |
p->flags &= ~TERMP_NOSPACE; |
p->flags &= ~TERMP_NOSPACE; |
Line 656 termp_pword(struct termp *p, const char *word, int len |
|
Line 691 termp_pword(struct termp *p, const char *word, int len |
|
|
|
for (i = 0; i < len; i++) { |
for (i = 0; i < len; i++) { |
if ('\\' == word[i]) { |
if ('\\' == word[i]) { |
termp_pescape(p, word, &i, len); |
term_pescape(p, word, &i, len); |
continue; |
continue; |
} |
} |
|
|
if (TERMP_STYLE & p->flags) { |
if (TERMP_STYLE & p->flags) { |
if (TERMP_BOLD & p->flags) { |
if (TERMP_BOLD & p->flags) { |
termp_chara(p, word[i]); |
term_chara(p, word[i]); |
termp_chara(p, 8); |
term_chara(p, 8); |
} |
} |
if (TERMP_UNDER & p->flags) { |
if (TERMP_UNDER & p->flags) { |
termp_chara(p, '_'); |
term_chara(p, '_'); |
termp_chara(p, 8); |
term_chara(p, 8); |
} |
} |
} |
} |
|
|
termp_chara(p, word[i]); |
term_chara(p, word[i]); |
} |
} |
|
|
|
if (term_isopendelim(word, len)) |
|
p->flags |= TERMP_NOSPACE; |
} |
} |
|
|
|
|
/* |
/* |
* Like termp_chara() but for arbitrary-length buffers. Resize the |
* Like term_chara() but for arbitrary-length buffers. Resize the |
* buffer by a factor of two (if the buffer is less than that) or the |
* buffer by a factor of two (if the buffer is less than that) or the |
* buffer's size. |
* buffer's size. |
*/ |
*/ |
static void |
static void |
termp_stringa(struct termp *p, const char *c, size_t sz) |
term_stringa(struct termp *p, const char *c, size_t sz) |
{ |
{ |
size_t s; |
size_t s; |
|
|
Line 711 termp_stringa(struct termp *p, const char *c, size_t s |
|
Line 749 termp_stringa(struct termp *p, const char *c, size_t s |
|
* size. |
* size. |
*/ |
*/ |
static void |
static void |
termp_chara(struct termp *p, char c) |
term_chara(struct termp *p, char c) |
{ |
{ |
size_t s; |
size_t s; |
|
|