-/* $Id: mdoc_macro.c,v 1.20 2009/07/17 10:56:57 kristaps Exp $ */
+/* $Id: mdoc_macro.c,v 1.30 2009/08/13 11:43:24 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
static int rew_expblock(struct mdoc *, int, int, int);
static int rew_subblock(enum mdoc_type,
struct mdoc *, int, int, int);
-static int rew_last(struct mdoc *, struct mdoc_node *);
+static int rew_last(struct mdoc *, struct mdoc_node *); /* FIXME: make const */
static int append_delims(struct mdoc *, int, int *, char *);
-static int lookup(struct mdoc *, int, int, int, const char *);
+static int lookup(struct mdoc *, int, const char *);
+static int lookup_raw(struct mdoc *, const char *);
static int swarn(struct mdoc *, enum mdoc_type, int, int,
const struct mdoc_node *);
{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
{ blk_full, 0 }, /* Sh */
{ blk_full, 0 }, /* Ss */
- { in_line, 0 }, /* Pp */
+ { in_line_eoln, 0 }, /* Pp */
{ blk_part_imp, MDOC_PARSED }, /* D1 */
{ blk_part_imp, MDOC_PARSED }, /* Dl */
{ blk_full, MDOC_EXPLICIT }, /* Bd */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
- { in_line_eoln, MDOC_CALLABLE }, /* Cd */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
{ obsolete, 0 }, /* Fr */
{ in_line_eoln, 0 }, /* Ud */
{ in_line_eoln, 0 }, /* Lb */
- { in_line, 0 }, /* Lp */
+ { in_line_eoln, 0 }, /* Lp */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
}
static int
-lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
+lookup(struct mdoc *mdoc, int from, const char *p)
+{
+
+ if ( ! (MDOC_PARSED & mdoc_macros[from].flags))
+ return(MDOC_MAX);
+ return(lookup_raw(mdoc, p));
+}
+
+
+static int
+lookup_raw(struct mdoc *mdoc, const char *p)
{
int res;
- res = mdoc_hash_find(mdoc->htab, p);
- if (MDOC_PARSED & mdoc_macros[from].flags)
- return(res);
- if (MDOC_MAX == res)
+ if (MDOC_MAX == (res = mdoc_hash_find(mdoc->htab, p)))
+ return(MDOC_MAX);
+ if (MDOC_CALLABLE & mdoc_macros[res].flags)
return(res);
- if ( ! mdoc_pwarn(mdoc, line, pos, EMACPARM))
- return(-1);
return(MDOC_MAX);
}
}
+/* FIXME: can this be merged with subblock? */
static int
rew_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
{
}
if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
- if (0 == buf[*pos]) {
- if ( ! rew_subblock(MDOC_BODY, mdoc,
- tok, line, ppos))
+ if (buf[*pos])
+ if ( ! mdoc_pwarn(mdoc, line, ppos, ENOLINE))
return(0);
- return(rew_expblock(mdoc, tok, line, ppos));
- }
- return(mdoc_perr(mdoc, line, ppos, ENOLINE));
+
+ if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
+ return(0);
+ return(rew_expblock(mdoc, tok, line, ppos));
}
if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
mdoc->next = MDOC_NEXT_CHILD;
}
- for (lastarg = ppos, flushed = j = 0; ; j++) {
+ for (flushed = j = 0; ; j++) {
lastarg = *pos;
if (j == maxargs && ! flushed) {
if (ARGS_EOLN == c)
break;
- if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
- return(0);
- else if (MDOC_MAX != c) {
+ if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
if ( ! flushed) {
if ( ! rew_expblock(mdoc, tok,
line, ppos))
* usually because of reserved words) to squeak by.
*/
switch (tok) {
- case (MDOC_Lp):
- /* FALLTHROUGH */
- case (MDOC_Pp):
+ case (MDOC_An):
/* FALLTHROUGH */
- case (MDOC_Nm):
+ case (MDOC_Ar):
/* FALLTHROUGH */
case (MDOC_Fl):
/* FALLTHROUGH */
case (MDOC_Lk):
/* FALLTHROUGH */
- case (MDOC_Ar):
+ case (MDOC_Nm):
+ /* FALLTHROUGH */
+ case (MDOC_Pa):
nc = 1;
break;
default:
break;
}
- for (la = ppos, arg = NULL;; ) {
+ for (arg = NULL;; ) {
la = *pos;
c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
/* Quoted words shouldn't be looked-up. */
- c = ARGS_QWORD == w ? MDOC_MAX :
- lookup(mdoc, line, la, tok, p);
+ c = ARGS_QWORD == w ? MDOC_MAX : lookup(mdoc, tok, p);
/*
* In this case, we've located a submacro and must
* or raise a warning.
*/
- if (MDOC_MAX != c && -1 != c) {
+ if (MDOC_MAX != c) {
if (0 == lastpunct && ! rew_elem(mdoc, tok))
return(0);
if (nc && 0 == cnt) {
if (ppos > 1)
return(1);
return(append_delims(mdoc, line, pos, buf));
- } else if (-1 == c)
- return(0);
+ }
/*
* Non-quote-enclosed punctuation. Set up our scope, if
continue;
}
- if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
- return(0);
-
- if (MDOC_MAX == c) {
+ if (MDOC_MAX == (c = lookup(mdoc, tok, p))) {
if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
return(0);
mdoc->next = MDOC_NEXT_SIBLING;
/* XXX - no known argument macros. */
- for (lastarg = ppos;; ) {
+ for (;;) {
lastarg = *pos;
c = mdoc_args(mdoc, line, pos, buf, tok, &p);
assert(ARGS_PHRASE != c);
if (ARGS_EOLN == c)
break;
- if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
- return(0);
- else if (MDOC_MAX == c) {
+ if (MDOC_MAX == (c = lookup(mdoc, tok, p))) {
if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
return(0);
mdoc->next = MDOC_NEXT_SIBLING;
int lastarg, flushed, j, c, maxargs;
char *p;
- lastarg = ppos;
flushed = 0;
/*
if (ARGS_EOLN == c)
break;
- if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
- return(0);
- else if (MDOC_MAX != c) {
+ if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
if ( ! flushed) {
if ( ! rew_subblock(MDOC_HEAD, mdoc,
tok, line, ppos))
break;
}
- for (lastarg = ppos, arg = NULL;; ) {
+ for (arg = NULL;; ) {
lastarg = *pos;
c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
if (ARGS_EOLN == c)
break;
- if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
- return(0);
- else if (MDOC_MAX != c) {
+ if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
if ( ! flushed && ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
if (ARGS_EOLN == w)
break;
- c = ARGS_QWORD == w ? MDOC_MAX :
- lookup(mdoc, line, la, tok, p);
+ c = ARGS_QWORD == w ? MDOC_MAX : lookup(mdoc, tok, p);
- if (MDOC_MAX != c && -1 != c) {
+ if (MDOC_MAX != c) {
if ( ! rew_elem(mdoc, tok))
return(0);
return(mdoc_macro(mdoc, c, line, la, pos, buf));
- } else if (-1 == c)
- return(0);
+ }
if ( ! mdoc_word_alloc(mdoc, line, la, p))
return(0);
}
+/*
+ * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
+ * They're unusual because they're basically free-form text until a
+ * macro is encountered.
+ */
static int
phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
{
- int i, la, c, quoted;
-
- /*
- * Parse over words in a phrase. We have to handle this
- * specially because we assume no calling context -- in normal
- * circumstances, we switch argument parsing based on whether
- * the parent macro accepts quotes, tabs, etc. Here, anything
- * goes.
- */
+ int c, w, la, pos;
+ char *p;
- for (i = ppos; buf[i]; ) {
- assert(' ' != buf[i]);
- la = i;
- quoted = 0;
+ for (pos = ppos; ; ) {
+ la = pos;
- /*
- * Read to next token. If quoted (check not escaped),
- * scan ahead to next unescaped quote. If not quoted or
- * escape-quoted, then scan ahead to next space.
- */
+ /* Note: no calling context! */
+ w = mdoc_zargs(mdoc, line, &pos, buf, &p);
- if ((i && '\"' == buf[i] && '\\' != buf[i - 1]) ||
- (0 == i && '\"' == buf[i])) {
- for (la = ++i; buf[i]; i++)
- if ('\"' != buf[i])
- continue;
- else if ('\\' != buf[i - 1])
- break;
- if (0 == buf[i])
- return(mdoc_perr(mdoc, line, la, EQUOTPHR));
- quoted = 1;
- } else
- for ( ; buf[i]; i++)
- if (i && ' ' == buf[i]) {
- if ('\\' != buf[i - 1])
- break;
- } else if (' ' == buf[i])
- break;
-
- /* If not end-of-line, terminate argument. */
-
- if (buf[i])
- buf[i++] = 0;
-
- /* Read to next argument. */
-
- for ( ; buf[i] && ' ' == buf[i]; i++)
- /* Spin. */ ;
-
- /*
- * If we're a non-quoted string, try to look up the
- * value as a macro and execute it, if found.
- */
+ if (ARGS_ERROR == w)
+ return(0);
+ if (ARGS_EOLN == w)
+ break;
- c = quoted ? MDOC_MAX :
- mdoc_hash_find(mdoc->htab, &buf[la]);
+ c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(mdoc, p);
if (MDOC_MAX != c) {
- if ( ! mdoc_macro(mdoc, c, line, la, &i, buf))
+ if ( ! mdoc_macro(mdoc, c, line, la, &pos, buf))
return(0);
- return(append_delims(mdoc, line, &i, buf));
- }
-
- /* A regular word or quoted string. */
+ return(append_delims(mdoc, line, &pos, buf));
+ }
- if ( ! mdoc_word_alloc(mdoc, line, la, &buf[la]))
+ if ( ! mdoc_word_alloc(mdoc, line, la, p))
return(0);
mdoc->next = MDOC_NEXT_SIBLING;
}
return(1);
}
+
+