summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c123
1 files changed, 81 insertions, 42 deletions
diff --git a/roff.c b/roff.c
index 1cb12301..52182bf0 100644
--- a/roff.c
+++ b/roff.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -46,6 +46,7 @@
#define ROFFDEF_STD (1 << 4) /* mdoc(7) or man(7) macro. */
#define ROFFDEF_ANY (ROFFDEF_USER | ROFFDEF_PRE | \
ROFFDEF_REN | ROFFDEF_STD)
+#define ROFFDEF_UNDEF (1 << 5) /* Completely undefined. */
/* --- data types --------------------------------------------------------- */
@@ -185,7 +186,7 @@ static int roff_getregn(const struct roff *,
const char *, size_t);
static int roff_getregro(const struct roff *,
const char *name);
-static const char *roff_getstrn(const struct roff *,
+static const char *roff_getstrn(struct roff *,
const char *, size_t, int *);
static int roff_hasregn(const struct roff *,
const char *, size_t);
@@ -1639,6 +1640,11 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
}
if (t != TOKEN_NONE)
*pos = cp - buf;
+ else if (deftype == ROFFDEF_UNDEF) {
+ /* Using an undefined macro defines it to be empty. */
+ roff_setstrn(&r->strtab, mac, maclen, "", 0, 0);
+ roff_setstrn(&r->rentab, mac, maclen, NULL, 0, 0);
+ }
return t;
}
@@ -3537,62 +3543,95 @@ roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
}
static const char *
-roff_getstrn(const struct roff *r, const char *name, size_t len,
+roff_getstrn(struct roff *r, const char *name, size_t len,
int *deftype)
{
const struct roffkv *n;
- int i;
+ int found, i;
enum roff_tok tok;
- if (*deftype & ROFFDEF_USER) {
- for (n = r->strtab; n != NULL; n = n->next) {
- if (strncmp(name, n->key.p, len) == 0 &&
- n->key.p[len] == '\0' &&
- n->val.p != NULL) {
- *deftype = ROFFDEF_USER;
- return n->val.p;
- }
+ found = 0;
+ for (n = r->strtab; n != NULL; n = n->next) {
+ if (strncmp(name, n->key.p, len) != 0 ||
+ n->key.p[len] != '\0' || n->val.p == NULL)
+ continue;
+ if (*deftype & ROFFDEF_USER) {
+ *deftype = ROFFDEF_USER;
+ return n->val.p;
+ } else {
+ found = 1;
+ break;
}
}
- if (*deftype & ROFFDEF_PRE) {
- for (i = 0; i < PREDEFS_MAX; i++) {
- if (strncmp(name, predefs[i].name, len) == 0 &&
- predefs[i].name[len] == '\0') {
- *deftype = ROFFDEF_PRE;
- return predefs[i].str;
- }
+ for (n = r->rentab; n != NULL; n = n->next) {
+ if (strncmp(name, n->key.p, len) != 0 ||
+ n->key.p[len] != '\0' || n->val.p == NULL)
+ continue;
+ if (*deftype & ROFFDEF_REN) {
+ *deftype = ROFFDEF_REN;
+ return n->val.p;
+ } else {
+ found = 1;
+ break;
}
}
- if (*deftype & ROFFDEF_REN) {
- for (n = r->rentab; n != NULL; n = n->next) {
- if (strncmp(name, n->key.p, len) == 0 &&
- n->key.p[len] == '\0' &&
- n->val.p != NULL) {
- *deftype = ROFFDEF_REN;
- return n->val.p;
- }
+ for (i = 0; i < PREDEFS_MAX; i++) {
+ if (strncmp(name, predefs[i].name, len) != 0 ||
+ predefs[i].name[len] != '\0')
+ continue;
+ if (*deftype & ROFFDEF_PRE) {
+ *deftype = ROFFDEF_PRE;
+ return predefs[i].str;
+ } else {
+ found = 1;
+ break;
}
}
- if (*deftype & ROFFDEF_STD) {
- if (r->man->macroset != MACROSET_MAN) {
- for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {
- if (strncmp(name, roff_name[tok], len) == 0 &&
- roff_name[tok][len] == '\0') {
- *deftype = ROFFDEF_STD;
- return NULL;
- }
+ if (r->man->macroset != MACROSET_MAN) {
+ for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) {
+ if (strncmp(name, roff_name[tok], len) != 0 ||
+ roff_name[tok][len] != '\0')
+ continue;
+ if (*deftype & ROFFDEF_STD) {
+ *deftype = ROFFDEF_STD;
+ return NULL;
+ } else {
+ found = 1;
+ break;
}
}
- if (r->man->macroset != MACROSET_MDOC) {
- for (tok = MAN_TH; tok < MAN_MAX; tok++) {
- if (strncmp(name, roff_name[tok], len) == 0 &&
- roff_name[tok][len] == '\0') {
- *deftype = ROFFDEF_STD;
- return NULL;
- }
+ }
+ if (r->man->macroset != MACROSET_MDOC) {
+ for (tok = MAN_TH; tok < MAN_MAX; tok++) {
+ if (strncmp(name, roff_name[tok], len) != 0 ||
+ roff_name[tok][len] != '\0')
+ continue;
+ if (*deftype & ROFFDEF_STD) {
+ *deftype = ROFFDEF_STD;
+ return NULL;
+ } else {
+ found = 1;
+ break;
}
}
}
+
+ if (found == 0 && *deftype != ROFFDEF_ANY) {
+ if (*deftype & ROFFDEF_REN) {
+ /*
+ * This might still be a request,
+ * so do not treat it as undefined yet.
+ */
+ *deftype = ROFFDEF_UNDEF;
+ return NULL;
+ }
+
+ /* Using an undefined string defines it to be empty. */
+
+ roff_setstrn(&r->strtab, name, len, "", 0, 0);
+ roff_setstrn(&r->rentab, name, len, NULL, 0, 0);
+ }
+
*deftype = 0;
return NULL;
}