diff options
-rw-r--r-- | macro.c | 86 | ||||
-rw-r--r-- | mdoc.c | 6 | ||||
-rw-r--r-- | mdoc.h | 19 | ||||
-rw-r--r-- | mdocml.c | 9 | ||||
-rw-r--r-- | private.h | 2 | ||||
-rw-r--r-- | strings.c | 41 | ||||
-rw-r--r-- | xstd.c | 84 |
7 files changed, 241 insertions, 6 deletions
@@ -21,6 +21,9 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#ifdef __linux__ +#include <time.h> +#endif #include "private.h" @@ -189,11 +192,33 @@ append_const(struct mdoc *mdoc, int tok, int pos, int sz, char *args[]) { - assert(sz >= 0); - args[sz] = NULL; - switch (tok) { /* ======= ADD MORE MACRO CHECKS BELOW. ======= */ + case (MDOC_At): + /* This needs special handling. */ + if (0 == sz) + break; + else if (sz > 2) + return(mdoc_err(mdoc, tok, pos, ERR_ARGS_LE2)); + + if (ATT_DEFAULT != mdoc_atoatt(args[0])) { + mdoc_elem_alloc(mdoc, pos, tok, 0, + NULL, 1, _CC(&args[0])); + } else { + mdoc_elem_alloc(mdoc, pos, tok, + 0, NULL, 0, NULL); + if (mdoc_isdelim(args[0])) + return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT)); + mdoc_word_alloc(mdoc, pos, args[0]); + } + + if (1 == sz) + return(1); + if (mdoc_isdelim(args[1])) + return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT)); + mdoc_word_alloc(mdoc, pos, args[1]); + return(1); + case (MDOC_Bx): /* FALLTHROUGH */ case (MDOC_Bsx): @@ -210,6 +235,13 @@ append_const(struct mdoc *mdoc, int tok, assert(0 == sz); break; + case (MDOC_Bt): + /* FALLTHROUGH */ + case (MDOC_Ud): + if (0 == sz) + break; + return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ0)); + /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */ default: abort(); @@ -929,6 +961,8 @@ macro_constant_delimited(MACRO_PROT_ARGS) lastarg = ppos; flushed = 0; + /* Token pre-processing. */ + switch (tok) { case (MDOC_Ux): maxargs = 0; @@ -961,6 +995,8 @@ again: /* NOTREACHED */ } + /* Accepts no arguments: flush out symbol and continue. */ + if (0 == maxargs) { pp = p; if ( ! append_const(mdoc, tok, ppos, 0, &p)) @@ -979,6 +1015,11 @@ again: return(append_delims(mdoc, tok, pos, buf)); } + /* + * We only accept one argument; subsequent tokens are considered + * as literal words (until a macro). + */ + if ( ! flushed && ! mdoc_isdelim(p)) { if ( ! append_const(mdoc, tok, ppos, 1, &p)) return(0); @@ -996,3 +1037,42 @@ again: goto again; /* NOTREACHED */ } + + +int +macro_constant(MACRO_PROT_ARGS) +{ + int lastarg, j; + char *args[MDOC_LINEARG_MAX]; + + if (SEC_PROLOGUE == mdoc->sec_lastn) + return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE)); + + j = 0; + +again: + if (j == MDOC_LINEARG_MAX) + return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY)); + + lastarg = *pos; + + switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) { + case (ARGS_ERROR): + return(0); + case (ARGS_WORD): + break; + case (ARGS_EOLN): + return(append_const(mdoc, tok, ppos, j, args)); + default: + abort(); + /* NOTREACHED */ + } + + if (MDOC_MAX != mdoc_find(mdoc, args[j])) + if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE)) + return(0); + + j++; + goto again; + /* NOTREACHED */ +} @@ -138,7 +138,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { NULL, 0 }, /* Ac */ { NULL, 0 }, /* Ao */ { macro_scoped_pline, MDOC_CALLABLE }, /* Aq */ - { NULL, 0 }, /* At */ + { macro_constant, 0 }, /* At */ { NULL, 0 }, /* Bc */ { NULL, 0 }, /* Bf */ { NULL, 0 }, /* Bo */ @@ -185,10 +185,10 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { NULL, 0 }, /* Oc */ { NULL, 0 }, /* Bk */ { NULL, 0 }, /* Ek */ - { NULL, 0 }, /* Bt */ + { macro_constant, 0 }, /* Bt */ { NULL, 0 }, /* Hf */ { NULL, 0 }, /* Fr */ - { NULL, 0 }, /* Ud */ + { macro_constant, 0 }, /* Ud */ }; const char * const *mdoc_macronames = __mdoc_macronames; @@ -194,6 +194,7 @@ enum mdoc_err { ERR_SYNTAX_QUOTE, /* NOTUSED */ ERR_SYNTAX_UNQUOTE, + ERR_SYNTAX_NOPUNCT, ERR_SYNTAX_WS, ERR_SYNTAX_ARG, ERR_SYNTAX_ARGFORM, @@ -210,10 +211,28 @@ enum mdoc_err { ERR_SEC_PROLOGUE_OO, ERR_SEC_PROLOGUE_REP, ERR_SEC_NAME, + ERR_ARGS_EQ0, ERR_ARGS_GE1, + ERR_ARGS_LE2, ERR_ARGS_MANY }; +enum mdoc_att { + ATT_DEFAULT = 0, + ATT_v1, + ATT_v2, + ATT_v3, + ATT_v4, + ATT_v5, + ATT_v6, + ATT_v7, + ATT_32v, + ATT_V1, + ATT_V2, + ATT_V3, + ATT_V4 +}; + enum mdoc_warn { WARN_SYNTAX_WS_EOLN, WARN_SYNTAX_MACLIKE, @@ -339,6 +339,9 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type) case (ERR_SYNTAX_ARGFORM): fmt = "syntax: macro `%s' arguments malformed"; break; + case (ERR_SYNTAX_NOPUNCT): + fmt = "syntax: macro `%s' doesn't understand punctuation"; + break; case (ERR_SYNTAX_ARG): fmt = "syntax: unknown argument for macro `%s'"; break; @@ -364,9 +367,15 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type) case (ERR_SEC_NPROLOGUE): fmt = "macro `%s' called outside of prologue"; break; + case (ERR_ARGS_EQ0): + fmt = "macro `%s' expects zero arguments"; + break; case (ERR_ARGS_GE1): fmt = "macro `%s' expects one or more arguments"; break; + case (ERR_ARGS_LE2): + fmt = "macro `%s' expects two or fewer arguments"; + break; case (ERR_ARGS_MANY): fmt = "macro `%s' has too many arguments"; break; @@ -73,6 +73,7 @@ enum mdoc_sec mdoc_atosec(size_t, const char **); enum mdoc_msec mdoc_atomsec(const char *); enum mdoc_vol mdoc_atovol(const char *); enum mdoc_arch mdoc_atoarch(const char *); +enum mdoc_att mdoc_atoatt(const char *); time_t mdoc_atotime(const char *); int mdoc_argv(struct mdoc *, int, @@ -94,6 +95,7 @@ int xstrcmp(const char *, const char *); void *xcalloc(size_t, size_t); char *xstrdup(const char *); +int macro_constant(MACRO_PROT_ARGS); int macro_constant_delimited(MACRO_PROT_ARGS); int macro_text(MACRO_PROT_ARGS); int macro_scoped_implicit(MACRO_PROT_ARGS); @@ -21,9 +21,16 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#ifdef __linux__ +#include <time.h> +#endif #include "private.h" +#ifdef __linux__ +extern char *strptime(const char *, const char *, struct tm *); +#endif + int mdoc_iscdelim(char p) { @@ -264,3 +271,37 @@ mdoc_atoarch(const char *p) return(ARCH_DEFAULT); } + + +enum mdoc_att +mdoc_atoatt(const char *p) +{ + + assert(p); + if (0 == strcmp(p, "v1")) + return(ATT_v1); + else if (0 == strcmp(p, "v2")) + return(ATT_v2); + else if (0 == strcmp(p, "v3")) + return(ATT_v3); + else if (0 == strcmp(p, "v4")) + return(ATT_v4); + else if (0 == strcmp(p, "v5")) + return(ATT_v5); + else if (0 == strcmp(p, "v6")) + return(ATT_v6); + else if (0 == strcmp(p, "v7")) + return(ATT_v7); + else if (0 == strcmp(p, "32v")) + return(ATT_32v); + else if (0 == strcmp(p, "V.1")) + return(ATT_V1); + else if (0 == strcmp(p, "V.2")) + return(ATT_V2); + else if (0 == strcmp(p, "V.3")) + return(ATT_V3); + else if (0 == strcmp(p, "V.4")) + return(ATT_V4); + + return(ATT_DEFAULT); +} @@ -22,6 +22,11 @@ #include "private.h" +#ifdef __linux__ +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); +#endif + int xstrcmp(const char *p1, const char *p2) @@ -69,3 +74,82 @@ xstrdup(const char *p) return(pp); } + +#ifdef __linux__ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <string.h> + + +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + + +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif |