version 1.118, 2010/03/31 07:42:04 |
version 1.123, 2010/04/08 07:53:01 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
#include <time.h> |
|
|
#include "libmdoc.h" |
#include "libmdoc.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
Line 83 const char *const __mdoc_merrnames[MERRMAX] = { |
|
Line 84 const char *const __mdoc_merrnames[MERRMAX] = { |
|
"no description found for library", /* ELIB */ |
"no description found for library", /* ELIB */ |
"bad child for parent context", /* EBADCHILD */ |
"bad child for parent context", /* EBADCHILD */ |
"list arguments preceding type", /* ENOTYPE */ |
"list arguments preceding type", /* ENOTYPE */ |
|
"deprecated comment style", /* EBADCOMMENT */ |
}; |
}; |
|
|
const char *const __mdoc_macronames[MDOC_MAX] = { |
const char *const __mdoc_macronames[MDOC_MAX] = { |
Line 140 const char *const __mdoc_argnames[MDOC_ARG_MAX] = { |
|
Line 142 const char *const __mdoc_argnames[MDOC_ARG_MAX] = { |
|
const char * const *mdoc_macronames = __mdoc_macronames; |
const char * const *mdoc_macronames = __mdoc_macronames; |
const char * const *mdoc_argnames = __mdoc_argnames; |
const char * const *mdoc_argnames = __mdoc_argnames; |
|
|
|
static void mdoc_node_free(struct mdoc_node *); |
|
static void mdoc_node_unlink(struct mdoc *, |
|
struct mdoc_node *); |
static void mdoc_free1(struct mdoc *); |
static void mdoc_free1(struct mdoc *); |
static void mdoc_alloc1(struct mdoc *); |
static void mdoc_alloc1(struct mdoc *); |
static struct mdoc_node *node_alloc(struct mdoc *, int, int, |
static struct mdoc_node *node_alloc(struct mdoc *, int, int, |
enum mdoct, enum mdoc_type); |
enum mdoct, enum mdoc_type); |
static int node_append(struct mdoc *, |
static int node_append(struct mdoc *, |
struct mdoc_node *); |
struct mdoc_node *); |
static int parsetext(struct mdoc *, int, char *); |
static int mdoc_ptext(struct mdoc *, int, char *); |
static int parsemacro(struct mdoc *, int, char *); |
static int mdoc_pmacro(struct mdoc *, int, char *); |
static int macrowarn(struct mdoc *, int, const char *); |
static int macrowarn(struct mdoc *, int, const char *); |
static int pstring(struct mdoc *, int, int, |
static int pstring(struct mdoc *, int, int, |
const char *, size_t); |
const char *, size_t); |
Line 176 mdoc_free1(struct mdoc *mdoc) |
|
Line 181 mdoc_free1(struct mdoc *mdoc) |
|
{ |
{ |
|
|
if (mdoc->first) |
if (mdoc->first) |
mdoc_node_freelist(mdoc->first); |
mdoc_node_delete(mdoc, mdoc->first); |
if (mdoc->meta.title) |
if (mdoc->meta.title) |
free(mdoc->meta.title); |
free(mdoc->meta.title); |
if (mdoc->meta.os) |
if (mdoc->meta.os) |
Line 276 mdoc_endparse(struct mdoc *m) |
|
Line 281 mdoc_endparse(struct mdoc *m) |
|
|
|
/* |
/* |
* Main parse routine. Parses a single line -- really just hands off to |
* Main parse routine. Parses a single line -- really just hands off to |
* the macro (parsemacro()) or text parser (parsetext()). |
* the macro (mdoc_pmacro()) or text parser (mdoc_ptext()). |
*/ |
*/ |
int |
int |
mdoc_parseln(struct mdoc *m, int ln, char *buf) |
mdoc_parseln(struct mdoc *m, int ln, char *buf) |
Line 285 mdoc_parseln(struct mdoc *m, int ln, char *buf) |
|
Line 290 mdoc_parseln(struct mdoc *m, int ln, char *buf) |
|
if (MDOC_HALT & m->flags) |
if (MDOC_HALT & m->flags) |
return(0); |
return(0); |
|
|
return('.' == *buf ? parsemacro(m, ln, buf) : |
return('.' == *buf ? mdoc_pmacro(m, ln, buf) : |
parsetext(m, ln, buf)); |
mdoc_ptext(m, ln, buf)); |
} |
} |
|
|
|
|
|
|
mdoc_macro(struct mdoc *m, enum mdoct tok, |
mdoc_macro(struct mdoc *m, enum mdoct tok, |
int ln, int pp, int *pos, char *buf) |
int ln, int pp, int *pos, char *buf) |
{ |
{ |
|
|
assert(tok < MDOC_MAX); |
assert(tok < MDOC_MAX); |
/* |
|
* If we're in the prologue, deny "body" macros. Similarly, if |
/* If we're in the body, deny prologue calls. */ |
* we're in the body, deny prologue calls. |
|
*/ |
|
if (MDOC_PROLOGUE & mdoc_macros[tok].flags && |
if (MDOC_PROLOGUE & mdoc_macros[tok].flags && |
MDOC_PBODY & m->flags) |
MDOC_PBODY & m->flags) |
return(mdoc_perr(m, ln, pp, EPROLBODY)); |
return(mdoc_perr(m, ln, pp, EPROLBODY)); |
|
|
|
/* If we're in the prologue, deny "body" macros. */ |
|
|
if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && |
if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && |
! (MDOC_PBODY & m->flags)) |
! (MDOC_PBODY & m->flags)) { |
return(mdoc_perr(m, ln, pp, EBODYPROL)); |
if ( ! mdoc_pwarn(m, ln, pp, EBODYPROL)) |
|
return(0); |
|
if (NULL == m->meta.title) |
|
m->meta.title = mandoc_strdup("unknown"); |
|
if (NULL == m->meta.vol) |
|
m->meta.vol = mandoc_strdup("local"); |
|
if (NULL == m->meta.os) |
|
m->meta.os = mandoc_strdup("local"); |
|
if (0 == m->meta.date) |
|
m->meta.date = time(NULL); |
|
m->flags |= MDOC_PBODY; |
|
} |
|
|
return((*mdoc_macros[tok].fp)(m, tok, ln, pp, pos, buf)); |
return((*mdoc_macros[tok].fp)(m, tok, ln, pp, pos, buf)); |
} |
} |
|
|
mdoc_node_free(struct mdoc_node *p) |
mdoc_node_free(struct mdoc_node *p) |
{ |
{ |
|
|
if (p->parent) |
|
p->parent->nchild--; |
|
if (p->string) |
if (p->string) |
free(p->string); |
free(p->string); |
if (p->args) |
if (p->args) |
Line 560 mdoc_node_free(struct mdoc_node *p) |
|
Line 575 mdoc_node_free(struct mdoc_node *p) |
|
} |
} |
|
|
|
|
void |
static void |
mdoc_node_freelist(struct mdoc_node *p) |
mdoc_node_unlink(struct mdoc *m, struct mdoc_node *n) |
{ |
{ |
|
|
if (p->child) |
/* Adjust siblings. */ |
mdoc_node_freelist(p->child); |
|
if (p->next) |
|
mdoc_node_freelist(p->next); |
|
|
|
|
if (n->prev) |
|
n->prev->next = n->next; |
|
if (n->next) |
|
n->next->prev = n->prev; |
|
|
|
/* Adjust parent. */ |
|
|
|
if (n->parent) { |
|
n->parent->nchild--; |
|
if (n->parent->child == n) |
|
n->parent->child = n->prev ? n->prev : n->next; |
|
} |
|
|
|
/* Adjust parse point, if applicable. */ |
|
|
|
if (m && m->last == n) { |
|
if (n->prev) { |
|
m->last = n->prev; |
|
m->next = MDOC_NEXT_SIBLING; |
|
} else { |
|
m->last = n->parent; |
|
m->next = MDOC_NEXT_CHILD; |
|
} |
|
} |
|
|
|
if (m && m->first == n) |
|
m->first = NULL; |
|
} |
|
|
|
|
|
void |
|
mdoc_node_delete(struct mdoc *m, struct mdoc_node *p) |
|
{ |
|
|
|
while (p->child) { |
|
assert(p->nchild); |
|
mdoc_node_delete(m, p->child); |
|
} |
assert(0 == p->nchild); |
assert(0 == p->nchild); |
|
|
|
mdoc_node_unlink(m, p); |
mdoc_node_free(p); |
mdoc_node_free(p); |
} |
} |
|
|
Line 579 mdoc_node_freelist(struct mdoc_node *p) |
|
Line 631 mdoc_node_freelist(struct mdoc_node *p) |
|
* control character. |
* control character. |
*/ |
*/ |
static int |
static int |
parsetext(struct mdoc *m, int line, char *buf) |
mdoc_ptext(struct mdoc *m, int line, char *buf) |
{ |
{ |
int i, j; |
int i, j; |
char sv; |
char sv; |
|
|
|
/* Ignore bogus comments. */ |
|
|
|
if ('\\' == buf[0] && '.' == buf[1] && '\"' == buf[2]) |
|
return(mdoc_pwarn(m, line, 0, EBADCOMMENT)); |
|
|
if (SEC_NONE == m->lastnamed) |
if (SEC_NONE == m->lastnamed) |
return(mdoc_perr(m, line, 0, ETEXTPROL)); |
return(mdoc_perr(m, line, 0, ETEXTPROL)); |
|
|
Line 600 parsetext(struct mdoc *m, int line, char *buf) |
|
Line 657 parsetext(struct mdoc *m, int line, char *buf) |
|
for (i = 0; ' ' == buf[i]; i++) |
for (i = 0; ' ' == buf[i]; i++) |
/* Skip leading whitespace. */ ; |
/* Skip leading whitespace. */ ; |
|
|
if ('\0' == buf[i]) |
if ('\0' == buf[i]) { |
return(mdoc_perr(m, line, 0, ENOBLANK)); |
if ( ! mdoc_pwarn(m, line, 0, ENOBLANK)) |
|
return(0); |
|
/* |
|
* Assume that a `Pp' should be inserted in the case of |
|
* a blank line. Technically, blank lines aren't |
|
* allowed, but enough manuals assume this behaviour |
|
* that we want to work around it. |
|
*/ |
|
if ( ! mdoc_elem_alloc(m, line, 0, MDOC_Pp, NULL)) |
|
return(0); |
|
} |
|
|
/* |
/* |
* Break apart a free-form line into tokens. Spaces are |
* Break apart a free-form line into tokens. Spaces are |
Line 669 macrowarn(struct mdoc *m, int ln, const char *buf) |
|
Line 736 macrowarn(struct mdoc *m, int ln, const char *buf) |
|
* character. |
* character. |
*/ |
*/ |
int |
int |
parsemacro(struct mdoc *m, int ln, char *buf) |
mdoc_pmacro(struct mdoc *m, int ln, char *buf) |
{ |
{ |
int i, j, c; |
int i, j, c; |
char mac[5]; |
char mac[5]; |