diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-07-03 15:59:06 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-07-03 15:59:06 +0000 |
commit | 2f67ad630f9663c8b0396b020057b985d1b36011 (patch) | |
tree | 3cd39b9305ace47b07a396a31e817ca802b9eb1f | |
parent | c61d37e9d6ca98b286e1f3eeeaab720c35e91996 (diff) |
Rudimentary implementation of user-defined strings;
no time for more refinement right now.
In particular, fixes terminfo(3) and mdoc.samples(7).
ok kristaps@, who will add the HTML frontend bits
-rw-r--r-- | usr.bin/mandoc/regs.h | 7 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.3 | 71 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 117 | ||||
-rw-r--r-- | usr.bin/mandoc/term.c | 8 |
4 files changed, 197 insertions, 6 deletions
diff --git a/usr.bin/mandoc/regs.h b/usr.bin/mandoc/regs.h index b41ceaca585..b06f981689f 100644 --- a/usr.bin/mandoc/regs.h +++ b/usr.bin/mandoc/regs.h @@ -1,4 +1,4 @@ -/* $Id: regs.h,v 1.1 2010/06/27 21:58:57 schwarze Exp $ */ +/* $Id: regs.h,v 1.2 2010/07/03 15:59:05 schwarze Exp $ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -41,6 +41,11 @@ struct regset { struct reg regs[REG__MAX]; }; +char *roff_setstr(const char *, const char *); +char *roff_getstr(const char *); +char *roff_getstrn(const char *, size_t); +void roff_freestr(void); + __END_DECLS #endif /*!REGS_H*/ diff --git a/usr.bin/mandoc/roff.3 b/usr.bin/mandoc/roff.3 index 0c5a092668b..85e558fbe8c 100644 --- a/usr.bin/mandoc/roff.3 +++ b/usr.bin/mandoc/roff.3 @@ -1,4 +1,4 @@ -.\" $Id: roff.3,v 1.2 2010/06/27 21:54:42 schwarze Exp $ +.\" $Id: roff.3,v 1.3 2010/07/03 15:59:05 schwarze Exp $ .\" .\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 27 2010 $ +.Dd $Mdocdate: July 3 2010 $ .Dt ROFF 3 .Os .Sh NAME @@ -50,6 +50,15 @@ .Fc .Ft void .Fn roff_reset "struct roff *roff" +.In regs.h +.Ft "char *" +.Fn roff_setstr "const char *name" "const char *string" +.Ft "char *" +.Fn roff_getstr "const char *name" +.Ft "char *" +.Fn roff_getstrn "const char *name" "size_t len" +.Ft void +.Fn roff_freestr void .Sh DESCRIPTION The .Nm @@ -145,6 +154,52 @@ Returns 0 on failure, 1 on success. Signals that the parse is complete. Returns 0 on failure, 1 on success. .El +.Sh USER-DEFINED STRINGS +Strings defined by the +.Xr roff 7 +.Sx \&ds +instruction are saved using the +.Fn roff_setstr +function and retrieved using the +.Fn roff_getstr +and +.Fn roff_getstrn +functions. +.Pp +These functions take the name of the string to be accessed +as their first argument. +While +.Fn roff_getstr +requires the name to be null-terminated, +.Fn roff_getstrn +accepts non-terminated strings, but requires the length of the name +to be specified. +.Pp +The second argument to +.Fn roff_setstr +is the new value of the string. +It will be copied to internal storage, so both pointers to constant +strings and pointers to volatile storage are acceptable. +.Pp +All of these functions return a pointer to the new value of the string +in internal storage, which should be considered read-only, so use +.Xr strdup 3 +on it as appropriate. +The read functions return NULL when a string of the specified name +is not available or empty, and +.Fn roff_setstr +returns NULL when memory allocation fails. +In the latter case, the string will remain unset. +.Pp +The function +.Fn roff_freestr +clears all user-defined strings. +It always succeeds. +Both +.Fn roff_reset +and +.Fn roff_free +call it. .Sh EXAMPLES See .Pa main.c @@ -159,3 +214,15 @@ The .Nm library was written by .An Kristaps Dzonsons Aq kristaps@bsd.lv . +.Sh BUGS +The implementation of user-defined strings needs improvement: +.Bl -dash +.It +String values are taken literally and are not interpreted. +.It +Parsing of quoted strings is incomplete. +.It +The stings are stored internally using a singly linked list, +which is fine for small numbers of strings, +but ineffient when handling many strings. +.El diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 8bd10dd7050..32cd7423de3 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.6 2010/06/27 21:54:42 schwarze Exp $ */ +/* $Id: roff.c,v 1.7 2010/07/03 15:59:05 schwarze Exp $ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -100,6 +100,12 @@ struct roffmac { struct roffmac *next; }; +struct roffstr { + char *name; + char *string; + struct roffstr *next; +} *first_string; + static enum rofferr roff_block(ROFF_ARGS); static enum rofferr roff_block_text(ROFF_ARGS); static enum rofferr roff_block_sub(ROFF_ARGS); @@ -108,6 +114,7 @@ static enum rofferr roff_ccond(ROFF_ARGS); static enum rofferr roff_cond(ROFF_ARGS); static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); +static enum rofferr roff_ds(ROFF_ARGS); static enum rofferr roff_line(ROFF_ARGS); static enum rofferr roff_nr(ROFF_ARGS); static enum roffrule roff_evalcond(const char *, int *); @@ -127,7 +134,7 @@ static struct roffmac roffs[ROFF_MAX] = { { "de", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "ds", roff_line, NULL, NULL, 0, NULL }, + { "ds", roff_ds, NULL, NULL, 0, NULL }, { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, @@ -260,6 +267,7 @@ roff_free1(struct roff *r) while (r->last) roffnode_pop(r); + roff_freestr(); } @@ -846,6 +854,39 @@ roff_cond(ROFF_ARGS) /* ARGSUSED */ static enum rofferr +roff_ds(ROFF_ARGS) +{ + char *name, *string, *end; + + name = *bufp + pos; + if ('\0' == *name) + return(ROFF_IGN); + + string = name; + while (*string && ' ' != *string) + string++; + if (*string) + *(string++) = NULL; + if (*string && '"' == *string) + string++; + while (*string && ' ' == *string) + string++; + end = string; + while (*end) + end++; + if (string < end) { + end--; + if (*end == '"') + *end = '\0'; + } + + roff_setstr(name, string); + return(ROFF_IGN); +} + + +/* ARGSUSED */ +static enum rofferr roff_nr(ROFF_ARGS) { const char *key, *val; @@ -881,3 +922,75 @@ roff_nr(ROFF_ARGS) return(ROFF_IGN); } + + +char * +roff_setstr(const char *name, const char *string) +{ + struct roffstr *n; + char *namecopy; + + n = first_string; + while (n && strcmp(name, n->name)) + n = n->next; + if (n) { + free(n->string); + } else { + if (NULL == (namecopy = strdup(name))) + return(NULL); + if (NULL == (n = malloc(sizeof(struct roffstr)))) { + free(n); + return(NULL); + } + n->name = namecopy; + n->next = first_string; + first_string = n; + } + if (string) + n->string = strdup(string); + else + n->string = NULL; + return(n->string); +} + +char * +roff_getstr(const char *name) +{ + struct roffstr *n; + + n = first_string; + while (n && strcmp(name, n->name)) + n = n->next; + if (n) + return(n->string); + else + return(NULL); +} + +char * +roff_getstrn(const char *name, size_t len) +{ + struct roffstr *n; + + n = first_string; + while (n && (strncmp(name, n->name, len) || '\0' != n->name[len])) + n = n->next; + if (n) + return(n->string); + else + return(NULL); +} + +void +roff_freestr(void) +{ + struct roffstr *n, *nn; + + for (n = first_string; n; n = nn) { + free(n->name); + free(n->string); + nn = n->next; + free(n); + } + first_string = NULL; +} diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index df88fa918dc..45b603616af 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.42 2010/06/29 14:41:28 schwarze Exp $ */ +/* $Id: term.c,v 1.43 2010/07/03 15:59:05 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -26,6 +26,7 @@ #include "mandoc.h" #include "chars.h" #include "out.h" +#include "regs.h" #include "term.h" #include "main.h" @@ -373,6 +374,11 @@ res(struct termp *p, const char *word, size_t len) size_t sz; rhs = chars_a2res(p->symtab, word, len, &sz); + if (NULL == rhs) { + rhs = roff_getstrn(word, len); + if (rhs) + sz = strlen(rhs); + } if (rhs) encode(p, rhs, sz); } |