summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmdoc.h1
-rw-r--r--mdoc_argv.c33
-rw-r--r--mdoc_validate.c15
3 files changed, 33 insertions, 16 deletions
diff --git a/libmdoc.h b/libmdoc.h
index 0d64e8a9..054e0350 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -167,6 +167,7 @@ int mdoc_argv(struct mdoc *, int, enum mdoct,
#define ARGV_ARG (1)
#define ARGV_WORD (2)
void mdoc_argv_free(struct mdoc_arg *);
+void mdoc_argn_free(struct mdoc_arg *, int);
int mdoc_args(struct mdoc *, int,
int *, char *, enum mdoct, char **);
int mdoc_zargs(struct mdoc *, int,
diff --git a/mdoc_argv.c b/mdoc_argv.c
index f1be3755..2aaa8a61 100644
--- a/mdoc_argv.c
+++ b/mdoc_argv.c
@@ -288,7 +288,7 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
void
mdoc_argv_free(struct mdoc_arg *p)
{
- int i, j;
+ int i;
if (NULL == p)
return;
@@ -300,23 +300,28 @@ mdoc_argv_free(struct mdoc_arg *p)
}
assert(p->argc);
- /* LINTED */
- for (i = 0; i < (int)p->argc; i++) {
- if (0 == p->argv[i].sz)
- continue;
- if (NULL == p->argv[i].value)
- continue;
+ for (i = (int)p->argc - 1; i >= 0; i--)
+ mdoc_argn_free(p, i);
+
+ free(p->argv);
+ free(p);
+}
+
- /* LINTED */
- for (j = 0; j < (int)p->argv[i].sz; j++)
- if (p->argv[i].value[j])
- free(p->argv[i].value[j]);
+void
+mdoc_argn_free(struct mdoc_arg *p, int iarg)
+{
+ struct mdoc_argv *arg = &p->argv[iarg];
+ int j;
- free(p->argv[i].value);
+ if (arg->sz && arg->value) {
+ for (j = (int)arg->sz - 1; j >= 0; j--)
+ free(arg->value[j]);
+ free(arg->value);
}
- free(p->argv);
- free(p);
+ for (--p->argc; iarg < (int)p->argc; iarg++)
+ p->argv[iarg] = p->argv[iarg+1];
}
diff --git a/mdoc_validate.c b/mdoc_validate.c
index e67286a5..af5d5ad1 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -621,8 +621,19 @@ pre_bl(PRE_ARGS)
case (MDOC_Inset):
/* FALLTHROUGH */
case (MDOC_Column):
- if (type >= 0)
- return(mdoc_nerr(mdoc, n, EMULTILIST));
+ /*
+ * Note that if a duplicate is detected, we
+ * remove the duplicate instead of passing it
+ * over. If we don't do this, mdoc_action will
+ * become confused when it scans over multiple
+ * types whilst setting its bitmasks.
+ */
+ if (type >= 0) {
+ if ( ! mdoc_nwarn(mdoc, n, EMULTILIST))
+ return(0);
+ mdoc_argn_free(n->args, pos);
+ break;
+ }
type = n->args->argv[pos].arg;
break;
case (MDOC_Compact):