version 1.324, 2017/07/14 17:16:16 |
version 1.326, 2018/04/09 22:27:04 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* 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 |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
#define ROFFDEF_STD (1 << 4) /* mdoc(7) or man(7) macro. */ |
#define ROFFDEF_STD (1 << 4) /* mdoc(7) or man(7) macro. */ |
#define ROFFDEF_ANY (ROFFDEF_USER | ROFFDEF_PRE | \ |
#define ROFFDEF_ANY (ROFFDEF_USER | ROFFDEF_PRE | \ |
ROFFDEF_REN | ROFFDEF_STD) |
ROFFDEF_REN | ROFFDEF_STD) |
|
#define ROFFDEF_UNDEF (1 << 5) /* Completely undefined. */ |
|
|
/* --- data types --------------------------------------------------------- */ |
/* --- data types --------------------------------------------------------- */ |
|
|
Line 181 static void roff_freestr(struct roffkv *); |
|
Line 182 static void roff_freestr(struct roffkv *); |
|
static size_t roff_getname(struct roff *, char **, int, int); |
static size_t roff_getname(struct roff *, char **, int, int); |
static int roff_getnum(const char *, int *, int *, int); |
static int roff_getnum(const char *, int *, int *, int); |
static int roff_getop(const char *, int *, char *); |
static int roff_getop(const char *, int *, char *); |
static int roff_getregn(const struct roff *, |
static int roff_getregn(struct roff *, const char *, size_t); |
const char *, size_t); |
|
static int roff_getregro(const struct roff *, |
static int roff_getregro(const struct roff *, |
const char *name); |
const char *name); |
static const char *roff_getstrn(const struct roff *, |
static const char *roff_getstrn(struct roff *, |
const char *, size_t, int *); |
const char *, size_t, int *); |
static int roff_hasregn(const struct roff *, |
static int roff_hasregn(const struct roff *, |
const char *, size_t); |
const char *, size_t); |
Line 206 static enum rofferr roff_res(struct roff *, struct bu |
|
Line 206 static enum rofferr roff_res(struct roff *, struct bu |
|
static enum rofferr roff_rm(ROFF_ARGS); |
static enum rofferr roff_rm(ROFF_ARGS); |
static enum rofferr roff_rn(ROFF_ARGS); |
static enum rofferr roff_rn(ROFF_ARGS); |
static enum rofferr roff_rr(ROFF_ARGS); |
static enum rofferr roff_rr(ROFF_ARGS); |
|
static void roff_setregn(struct roff *, const char *, |
|
size_t, int, char); |
static void roff_setstr(struct roff *, |
static void roff_setstr(struct roff *, |
const char *, const char *, int); |
const char *, const char *, int); |
static void roff_setstrn(struct roffkv **, const char *, |
static void roff_setstrn(struct roffkv **, const char *, |
Line 1639 roff_parse(struct roff *r, char *buf, int *pos, int ln |
|
Line 1641 roff_parse(struct roff *r, char *buf, int *pos, int ln |
|
} |
} |
if (t != TOKEN_NONE) |
if (t != TOKEN_NONE) |
*pos = cp - buf; |
*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; |
return t; |
} |
} |
|
|
Line 2515 roff_evalnum(struct roff *r, int ln, const char *v, |
|
Line 2522 roff_evalnum(struct roff *r, int ln, const char *v, |
|
void |
void |
roff_setreg(struct roff *r, const char *name, int val, char sign) |
roff_setreg(struct roff *r, const char *name, int val, char sign) |
{ |
{ |
|
roff_setregn(r, name, strlen(name), val, sign); |
|
} |
|
|
|
static void |
|
roff_setregn(struct roff *r, const char *name, size_t len, |
|
int val, char sign) |
|
{ |
struct roffreg *reg; |
struct roffreg *reg; |
|
|
/* Search for an existing register with the same name. */ |
/* Search for an existing register with the same name. */ |
reg = r->regtab; |
reg = r->regtab; |
|
|
while (reg && strcmp(name, reg->key.p)) |
while (reg != NULL && (reg->key.sz != len || |
|
strncmp(reg->key.p, name, len) != 0)) |
reg = reg->next; |
reg = reg->next; |
|
|
if (NULL == reg) { |
if (NULL == reg) { |
/* Create a new register. */ |
/* Create a new register. */ |
reg = mandoc_malloc(sizeof(struct roffreg)); |
reg = mandoc_malloc(sizeof(struct roffreg)); |
reg->key.p = mandoc_strdup(name); |
reg->key.p = mandoc_strndup(name, len); |
reg->key.sz = strlen(name); |
reg->key.sz = len; |
reg->val = 0; |
reg->val = 0; |
reg->next = r->regtab; |
reg->next = r->regtab; |
r->regtab = reg; |
r->regtab = reg; |
Line 2572 roff_getregro(const struct roff *r, const char *name) |
|
Line 2587 roff_getregro(const struct roff *r, const char *name) |
|
} |
} |
|
|
int |
int |
roff_getreg(const struct roff *r, const char *name) |
roff_getreg(struct roff *r, const char *name) |
{ |
{ |
struct roffreg *reg; |
return roff_getregn(r, name, strlen(name)); |
int val; |
|
|
|
if ('.' == name[0] && '\0' != name[1] && '\0' == name[2]) { |
|
val = roff_getregro(r, name + 1); |
|
if (-1 != val) |
|
return val; |
|
} |
|
|
|
for (reg = r->regtab; reg; reg = reg->next) |
|
if (0 == strcmp(name, reg->key.p)) |
|
return reg->val; |
|
|
|
return 0; |
|
} |
} |
|
|
static int |
static int |
roff_getregn(const struct roff *r, const char *name, size_t len) |
roff_getregn(struct roff *r, const char *name, size_t len) |
{ |
{ |
struct roffreg *reg; |
struct roffreg *reg; |
int val; |
int val; |
Line 2607 roff_getregn(const struct roff *r, const char *name, s |
|
Line 2609 roff_getregn(const struct roff *r, const char *name, s |
|
0 == strncmp(name, reg->key.p, len)) |
0 == strncmp(name, reg->key.p, len)) |
return reg->val; |
return reg->val; |
|
|
|
roff_setregn(r, name, len, 0, '\0'); |
return 0; |
return 0; |
} |
} |
|
|
Line 2658 roff_nr(ROFF_ARGS) |
|
Line 2661 roff_nr(ROFF_ARGS) |
|
keysz = roff_getname(r, &val, ln, pos); |
keysz = roff_getname(r, &val, ln, pos); |
if (key[keysz] == '\\') |
if (key[keysz] == '\\') |
return ROFF_IGN; |
return ROFF_IGN; |
key[keysz] = '\0'; |
|
|
|
sign = *val; |
sign = *val; |
if (sign == '+' || sign == '-') |
if (sign == '+' || sign == '-') |
val++; |
val++; |
|
|
if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE)) |
if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE)) |
roff_setreg(r, key, iv, sign); |
roff_setregn(r, key, keysz, iv, sign); |
|
|
return ROFF_IGN; |
return ROFF_IGN; |
} |
} |
Line 3537 roff_setstrn(struct roffkv **r, const char *name, size |
|
Line 3539 roff_setstrn(struct roffkv **r, const char *name, size |
|
} |
} |
|
|
static const char * |
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) |
int *deftype) |
{ |
{ |
const struct roffkv *n; |
const struct roffkv *n; |
int i; |
int found, i; |
enum roff_tok tok; |
enum roff_tok tok; |
|
|
if (*deftype & ROFFDEF_USER) { |
found = 0; |
for (n = r->strtab; n != NULL; n = n->next) { |
for (n = r->strtab; n != NULL; n = n->next) { |
if (strncmp(name, n->key.p, len) == 0 && |
if (strncmp(name, n->key.p, len) != 0 || |
n->key.p[len] == '\0' && |
n->key.p[len] != '\0' || n->val.p == NULL) |
n->val.p != NULL) { |
continue; |
*deftype = ROFFDEF_USER; |
if (*deftype & ROFFDEF_USER) { |
return n->val.p; |
*deftype = ROFFDEF_USER; |
} |
return n->val.p; |
|
} else { |
|
found = 1; |
|
break; |
} |
} |
} |
} |
if (*deftype & ROFFDEF_PRE) { |
for (n = r->rentab; n != NULL; n = n->next) { |
for (i = 0; i < PREDEFS_MAX; i++) { |
if (strncmp(name, n->key.p, len) != 0 || |
if (strncmp(name, predefs[i].name, len) == 0 && |
n->key.p[len] != '\0' || n->val.p == NULL) |
predefs[i].name[len] == '\0') { |
continue; |
*deftype = ROFFDEF_PRE; |
if (*deftype & ROFFDEF_REN) { |
return predefs[i].str; |
*deftype = ROFFDEF_REN; |
} |
return n->val.p; |
|
} else { |
|
found = 1; |
|
break; |
} |
} |
} |
} |
if (*deftype & ROFFDEF_REN) { |
for (i = 0; i < PREDEFS_MAX; i++) { |
for (n = r->rentab; n != NULL; n = n->next) { |
if (strncmp(name, predefs[i].name, len) != 0 || |
if (strncmp(name, n->key.p, len) == 0 && |
predefs[i].name[len] != '\0') |
n->key.p[len] == '\0' && |
continue; |
n->val.p != NULL) { |
if (*deftype & ROFFDEF_PRE) { |
*deftype = ROFFDEF_REN; |
*deftype = ROFFDEF_PRE; |
return n->val.p; |
return predefs[i].str; |
} |
} else { |
|
found = 1; |
|
break; |
} |
} |
} |
} |
if (*deftype & ROFFDEF_STD) { |
if (r->man->macroset != MACROSET_MAN) { |
if (r->man->macroset != MACROSET_MAN) { |
for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) { |
for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) { |
if (strncmp(name, roff_name[tok], len) != 0 || |
if (strncmp(name, roff_name[tok], len) == 0 && |
roff_name[tok][len] != '\0') |
roff_name[tok][len] == '\0') { |
continue; |
*deftype = ROFFDEF_STD; |
if (*deftype & ROFFDEF_STD) { |
return NULL; |
*deftype = ROFFDEF_STD; |
} |
return NULL; |
|
} else { |
|
found = 1; |
|
break; |
} |
} |
} |
} |
if (r->man->macroset != MACROSET_MDOC) { |
} |
for (tok = MAN_TH; tok < MAN_MAX; tok++) { |
if (r->man->macroset != MACROSET_MDOC) { |
if (strncmp(name, roff_name[tok], len) == 0 && |
for (tok = MAN_TH; tok < MAN_MAX; tok++) { |
roff_name[tok][len] == '\0') { |
if (strncmp(name, roff_name[tok], len) != 0 || |
*deftype = ROFFDEF_STD; |
roff_name[tok][len] != '\0') |
return NULL; |
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; |
*deftype = 0; |
return NULL; |
return NULL; |
} |
} |