-/* $Id: man.c,v 1.6 2009/03/25 16:07:36 kristaps Exp $ */
+/* $Id: man.c,v 1.13 2009/03/27 14:56:15 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
*
"TP", "LP", "PP", "P",
"IP", "HP", "SM", "SB",
"BI", "IB", "BR", "RB",
- "R", "B", "I", "IR"
+ "R", "B", "I", "IR",
+ "RI", "br"
};
const char * const *man_macronames = __man_macronames;
struct man *
-man_alloc(void *data, const struct man_cb *cb)
+man_alloc(void *data, int pflags, const struct man_cb *cb)
{
struct man *p;
p->htab = man_hash_alloc();
p->data = data;
+ p->pflags = pflags;
+
return(p);
}
if ( ! man_word_alloc(m, line, 0, buf))
return(0);
m->next = MAN_NEXT_SIBLING;
+
+ /*
+ * If this is one of the zany NLINE macros that consumes the
+ * next line of input as being influenced, then close out the
+ * existing macro "scope" and continue processing.
+ */
+
+ if ( ! (MAN_NLINE & m->flags))
+ return(1);
+
+ m->flags &= ~MAN_NLINE;
+ m->last = m->last->parent;
+
+ assert(MAN_ROOT != m->last->type);
+ if ( ! man_valid_post(m))
+ return(0);
+ if ( ! man_action_post(m))
+ return(0);
+
return(1);
}
int
man_pmacro(struct man *m, int ln, char *buf)
{
- int i, c;
+ int i, j, c, ppos, fl;
char mac[5];
+ struct man_node *n;
/* Comments and empties are quickly ignored. */
+ n = m->last;
+ fl = MAN_NLINE & m->flags;
+
if (0 == buf[1])
- return(1);
+ goto out;
+
+ i = 1;
- if (' ' == buf[1]) {
- i = 2;
+ if (' ' == buf[i]) {
+ i++;
while (buf[i] && ' ' == buf[i])
i++;
if (0 == buf[i])
- return(1);
- warnx("invalid syntax");
- return(0);
+ goto out;
}
- if (buf[1] && '\\' == buf[1])
- if (buf[2] && '\"' == buf[2])
- return(1);
+ ppos = i;
+
+ if (buf[i] && '\\' == buf[i])
+ if (buf[i + 1] && '\"' == buf[i + 1])
+ goto out;
/* Copy the first word into a nil-terminated buffer. */
- for (i = 1; i < 5; i++) {
- if (0 == (mac[i - 1] = buf[i]))
+ for (j = 0; j < 4; j++, i++) {
+ if (0 == (mac[j] = buf[i]))
break;
else if (' ' == buf[i])
break;
}
- mac[i - 1] = 0;
-
- if (i == 5 || i <= 1) {
- warnx("unknown macro: %s", mac);
- goto err;
- }
+ mac[j] = 0;
+
+ if (j == 4 || j < 1) {
+ if ( ! (MAN_IGN_MACRO & m->pflags)) {
+ (void)man_verr(m, ln, ppos,
+ "ill-formed macro: %s", mac);
+ goto err;
+ }
+ if ( ! man_vwarn(m, ln, ppos,
+ "ill-formed macro: %s", mac))
+ goto err;
+ return(1);
+ }
if (MAN_MAX == (c = man_hash_find(m->htab, mac))) {
- warnx("unknown macro: %s", mac);
- goto err;
+ if ( ! (MAN_IGN_MACRO & m->pflags)) {
+ (void)man_verr(m, ln, ppos,
+ "unknown macro: %s", mac);
+ goto err;
+ }
+ if ( ! man_vwarn(m, ln, ppos,
+ "unknown macro: %s", mac))
+ goto err;
+ return(1);
}
/* The macro is sane. Jump to the next word. */
/* Begin recursive parse sequence. */
- if ( ! man_macro(m, c, ln, 1, &i, buf))
+ if ( ! man_macro(m, c, ln, ppos, &i, buf))
goto err;
+out:
+ if (fl) {
+ /*
+ * A NLINE macro has been immediately followed with
+ * another. Close out the preceeding macro's scope, and
+ * continue.
+ */
+ assert(MAN_ROOT != m->last->type);
+ assert(m->last->parent);
+ assert(MAN_ROOT != m->last->parent->type);
+
+ if (n != m->last)
+ m->last = m->last->parent;
+
+ if ( ! man_valid_post(m))
+ return(0);
+ if ( ! man_action_post(m))
+ return(0);
+ m->next = MAN_NEXT_SIBLING;
+ m->flags &= ~MAN_NLINE;
+ }
+
return(1);
err: /* Error out. */