=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.33 retrieving revision 1.42 diff -u -p -r1.33 -r1.42 --- mandoc/roff.c 2008/12/02 13:20:24 1.33 +++ mandoc/roff.c 2008/12/05 22:34:30 1.42 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.33 2008/12/02 13:20:24 kristaps Exp $ */ +/* $Id: roff.c,v 1.42 2008/12/05 22:34:30 kristaps Exp $ */ /* * Copyright (c) 2008 Kristaps Dzonsons * @@ -40,9 +40,9 @@ /* TODO: (warn) NAME section has particular order. */ /* TODO: unify empty-content tags a la
. */ /* TODO: macros with a set number of arguments? */ +/* TODO: validate Dt macro arguments. */ +/* FIXME: Bl -diag ignore callable children. */ -#define ROFF_MAXARG 32 - enum roffd { ROFF_ENTER = 0, ROFF_EXIT @@ -68,18 +68,13 @@ struct rofftok { const int *children; /* Limit to kids. */ int ctx; /* Blk-close node. */ enum rofftype type; /* Type of macro. */ - int flags; + int flags; #define ROFF_PARSED (1 << 0) /* "Parsed". */ #define ROFF_CALLABLE (1 << 1) /* "Callable". */ #define ROFF_SHALLOW (1 << 2) /* Nesting block. */ #define ROFF_LSCOPE (1 << 3) /* Line scope. */ }; -struct roffarg { - int flags; -#define ROFF_VALUE (1 << 0) /* Has a value. */ -}; - struct roffnode { int tok; /* Token id. */ struct roffnode *parent; /* Parent (or NULL). */ @@ -89,6 +84,7 @@ struct rofftree { struct roffnode *last; /* Last parsed node. */ char *cur; /* Line start. */ struct tm tm; /* `Dd' results. */ + char name[64]; /* `Nm' results. */ char os[64]; /* `Os' results. */ char title[64]; /* `Dt' results. */ char section[64]; /* `Dt' results. */ @@ -103,15 +99,16 @@ struct rofftree { void *arg; /* Callbacks' arg. */ }; -static int roff_Dd(ROFFCALL_ARGS); -static int roff_Dt(ROFFCALL_ARGS); -static int roff_Os(ROFFCALL_ARGS); -static int roff_Ns(ROFFCALL_ARGS); -static int roff_Sm(ROFFCALL_ARGS); +static int roff_Dd(ROFFCALL_ARGS); /* FIXME: deprecate. */ +static int roff_Dt(ROFFCALL_ARGS); /* FIXME: deprecate. */ +static int roff_Os(ROFFCALL_ARGS); /* FIXME: deprecate. */ +static int roff_Ns(ROFFCALL_ARGS); /* FIXME: deprecate. */ +static int roff_Sm(ROFFCALL_ARGS); /* FIXME: deprecate. */ static int roff_layout(ROFFCALL_ARGS); static int roff_text(ROFFCALL_ARGS); static int roff_noop(ROFFCALL_ARGS); static int roff_depr(ROFFCALL_ARGS); +static int roff_ordered(ROFFCALL_ARGS); static struct roffnode *roffnode_new(int, struct rofftree *); static void roffnode_free(struct rofftree *); static void roff_warn(const struct rofftree *, @@ -132,11 +129,16 @@ static int roffparseopts(struct rofftree *, int, char ***, int *, char **); static int roffcall(struct rofftree *, int, char **); static int roffparse(struct rofftree *, char *); -static int textparse(const struct rofftree *, char *); +static int textparse(struct rofftree *, char *); +static int roffdata(struct rofftree *, int, char *); +static int roffspecial(struct rofftree *, int, char **); +static int roffsetname(struct rofftree *, char **); +static int roffgetname(struct rofftree *, char **, + const char *); -#ifdef __linux__ -static size_t strlcat(char *, const char *, size_t); -static size_t strlcpy(char *, const char *, size_t); +#ifdef __linux__ +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); extern int vsnprintf(char *, size_t, const char *, va_list); extern char *strptime(const char *, const char *, @@ -203,13 +205,13 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fa */ /* XXX needs arg */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Fd */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fl */ - { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fn */ /* XXX needs arg */ /* FIXME */ + {roff_ordered, NULL, NULL, NULL, 0, ROFF_TEXT, /*XXX*/ -1 }, /* Fn */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ft */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ic */ /* XXX needs arg */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* In */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Li */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Nd */ - { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Nm */ /* FIXME */ + {roff_ordered, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Nm */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Op */ { roff_depr, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Ot */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pa */ @@ -217,7 +219,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, roffarg_St, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* St */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Va */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Vt */ /* XXX needs arg */ - { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xr */ /* XXX needs arg */ + {roff_ordered, NULL, NULL, NULL, 0, ROFF_TEXT, /*XXX*/ -1 }, /* Xr */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* %A */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE}, /* %B */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* %D */ @@ -249,7 +251,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Eo */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Fx */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ms */ - { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* No */ + { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* No */ { roff_Ns, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ns */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Nx */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ox */ @@ -271,8 +273,8 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */ - { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */ - { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ + { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */ + { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ { roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ { roff_noop, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ { roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ @@ -285,12 +287,15 @@ static const struct rofftok tokens[ROFF_MAX] = { { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Ud */ }; +#define ROFF_VALUE (1 << 0) + static const int tokenargs[ROFF_ARGMAX] = { 0, 0, 0, 0, 0, ROFF_VALUE, ROFF_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ROFF_VALUE, 0, + 0, ROFF_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -300,7 +305,6 @@ static const int tokenargs[ROFF_ARGMAX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, }; const char *const toknamesp[ROFF_MAX] = { @@ -449,14 +453,43 @@ roff_engine(struct rofftree *tree, char *buf) static int -textparse(const struct rofftree *tree, char *buf) +textparse(struct rofftree *tree, char *buf) { + char *bufp; + /* TODO: literal parsing. */ + if ( ! (ROFF_BODY & tree->state)) { roff_err(tree, buf, "data not in body"); return(0); } - return((*tree->cb.roffdata)(tree->arg, 1, buf)); + + /* LINTED */ + while (*buf) { + while (*buf && isspace(*buf)) + buf++; + + if (0 == *buf) + break; + + bufp = buf++; + + while (*buf && ! isspace(*buf)) + buf++; + + if (0 != *buf) { + *buf++ = 0; + if ( ! roffdata(tree, 1, bufp)) + return(0); + continue; + } + + if ( ! roffdata(tree, 1, bufp)) + return(0); + break; + } + + return(1); } @@ -472,8 +505,15 @@ roffargs(const struct rofftree *tree, p = buf; + /* + * This is an ugly little loop. It parses a line into + * space-delimited tokens. If a quote mark is encountered, a + * token is alloted the entire quoted text. If whitespace is + * escaped, it's included in the prior alloted token. + */ + /* LINTED */ - for (i = 0; *buf && i < ROFF_MAXARG; i++) { + for (i = 0; *buf && i < ROFF_MAXLINEARG; i++) { if ('\"' == *buf) { argv[i] = ++buf; while (*buf && '\"' != *buf) @@ -487,8 +527,17 @@ roffargs(const struct rofftree *tree, } } else { argv[i] = buf++; - while (*buf && ! isspace(*buf)) - buf++; + while (*buf) { + if ( ! isspace(*buf)) { + buf++; + continue; + } + if (*(buf - 1) == '\\') { + buf++; + continue; + } + break; + } if (0 == *buf) continue; } @@ -496,9 +545,9 @@ roffargs(const struct rofftree *tree, while (*buf && isspace(*buf)) buf++; } - + assert(i > 0); - if (ROFF_MAXARG == i && *buf) { + if (ROFF_MAXLINEARG == i && *buf) { roff_err(tree, p, "too many arguments for `%s'", toknames [tok]); return(0); @@ -529,7 +578,7 @@ roffparse(struct rofftree *tree, char *buf) { int tok, t; struct roffnode *n; - char *argv[ROFF_MAXARG]; + char *argv[ROFF_MAXLINEARG]; char **argvp; if (0 != *buf && 0 != *(buf + 1) && 0 != *(buf + 2)) @@ -832,6 +881,15 @@ roffnode_free(struct rofftree *tree) static int +roffspecial(struct rofftree *tree, int tok, char **ordp) +{ + + return((*tree->cb.roffspecial)(tree->arg, tok, + tree->cur, ordp)); +} + + +static int roffcall(struct rofftree *tree, int tok, char **argv) { @@ -906,7 +964,7 @@ roffpurgepunct(struct rofftree *tree, char **argv) /* LINTED */ while (argv[i]) - if ( ! (*tree->cb.roffdata)(tree->arg, 0, argv[i++])) + if ( ! roffdata(tree, 0, argv[i++])) return(0); return(1); } @@ -937,6 +995,17 @@ roffparseopts(struct rofftree *tree, int tok, } +static int +roffdata(struct rofftree *tree, int space, char *buf) +{ + + if (0 == *buf) + return(1); + return((*tree->cb.roffdata)(tree->arg, + space != 0, tree->cur, buf)); +} + + /* ARGSUSED */ static int roff_Dd(ROFFCALL_ARGS) @@ -965,7 +1034,7 @@ roff_Dd(ROFFCALL_ARGS) argv++; - if (0 == strcmp(*argv, "$Mdocdate: December 2 2008 $")) { + if (0 == strcmp(*argv, "$Mdocdate: December 5 2008 $")) { t = time(NULL); if (NULL == localtime_r(&t, &tree->tm)) err(1, "localtime_r"); @@ -1080,17 +1149,50 @@ roff_Dt(ROFFCALL_ARGS) } +static int +roffgetname(struct rofftree *tree, char **ordp, const char *start) +{ + if (0 == tree->name[0]) { + roff_err(tree, start, "`Nm' name not set"); + return(0); + } + *ordp++ = tree->name; + *ordp = NULL; + return(1); +} + + +static int +roffsetname(struct rofftree *tree, char **ordp) +{ + + assert(*ordp); + + /* FIXME: not all sections can set this. */ + + if (NULL != *(ordp + 1)) { + roff_err(tree, *ordp, "too many `Nm' args"); + return(0); + } + + if (strlcpy(tree->name, *ordp, sizeof(tree->name)) + >= sizeof(tree->name)) { + roff_err(tree, *ordp, "`Nm' arg too long"); + return(0); + } + + return(1); +} + + /* ARGSUSED */ -static int +static int roff_Sm(ROFFCALL_ARGS) { - int argcp[1]; - char *argvp[1], *morep[1], *p; + char *morep[1], *p; p = *argv++; - argcp[0] = ROFF_ARGMAX; - argvp[0] = NULL; if (NULL == (morep[0] = *argv++)) { roff_err(tree, p, "`Sm' expects an argument"); return(0); @@ -1103,15 +1205,12 @@ roff_Sm(ROFFCALL_ARGS) if (*argv) roff_warn(tree, *argv, "`Sm' shouldn't have arguments"); - if ( ! (*tree->cb.roffspecial)(tree->arg, - tok, argcp, argvp, morep)) + if ( ! roffspecial(tree, tok, morep)) return(0); - while (*argv) { - if ((*tree->cb.roffdata)(tree->arg, 1, *argv++)) - continue; - return(0); - } + while (*argv) + if ( ! roffdata(tree, 1, *argv++)) + return(0); return(1); } @@ -1122,16 +1221,12 @@ static int roff_Ns(ROFFCALL_ARGS) { int j, c, first; - int argcp[1]; - char *argvp[1], *morep[1]; + char *morep[1]; first = (*argv++ == tree->cur); + morep[0] = NULL; - argcp[0] = ROFF_ARGMAX; - argvp[0] = morep[0] = NULL; - - if ( ! (*tree->cb.roffspecial)(tree->arg, - tok, argcp, argvp, morep)) + if ( ! roffspecial(tree, tok, morep)) return(0); while (*argv) { @@ -1142,18 +1237,19 @@ roff_Ns(ROFFCALL_ARGS) } if ( ! roffispunct(*argv)) { - if ((*tree->cb.roffdata)(tree->arg, 1, *argv++)) - continue; - return(0); + if ( ! roffdata(tree, 1, *argv++)) + return(0); + continue; } + for (j = 0; argv[j]; j++) if ( ! roffispunct(argv[j])) break; if (argv[j]) { - if ((*tree->cb.roffdata)(tree->arg, 0, *argv++)) - continue; - return(0); + if ( ! roffdata(tree, 0, *argv++)) + return(0); + continue; } break; @@ -1210,7 +1306,9 @@ roff_Os(ROFFCALL_ARGS) assert(NULL == tree->last); - return((*tree->cb.roffhead)(tree->arg)); + return((*tree->cb.roffhead)(tree->arg, &tree->tm, + tree->os, tree->title, tree->section, + tree->volume)); } @@ -1218,8 +1316,8 @@ roff_Os(ROFFCALL_ARGS) static int roff_layout(ROFFCALL_ARGS) { - int i, c, argcp[ROFF_MAXARG]; - char *argvp[ROFF_MAXARG]; + int i, c, argcp[ROFF_MAXLINEARG]; + char *argvp[ROFF_MAXLINEARG]; if (ROFF_PRELUDE & tree->state) { roff_err(tree, *argv, "bad `%s' in prelude", @@ -1227,6 +1325,8 @@ roff_layout(ROFFCALL_ARGS) return(0); } else if (ROFF_EXIT == type) { roffnode_free(tree); + if ( ! (*tree->cb.roffblkbodyout)(tree->arg, tok)) + return(0); return((*tree->cb.roffblkout)(tree->arg, tok)); } @@ -1248,8 +1348,10 @@ roff_layout(ROFFCALL_ARGS) if ( ! (*tree->cb.roffblkin)(tree->arg, tok, argcp, argvp)) return(0); if (NULL == *argv) - return(1); - if ( ! (*tree->cb.roffin)(tree->arg, tok, argcp, argvp)) + return((*tree->cb.roffblkbodyin) + (tree->arg, tok, argcp, argvp)); + + if ( ! (*tree->cb.roffblkheadin)(tree->arg, tok, argcp, argvp)) return(0); /* @@ -1259,12 +1361,14 @@ roff_layout(ROFFCALL_ARGS) if ( ! (ROFF_PARSED & tokens[tok].flags)) { i = 0; - while (*argv) { - if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) + while (*argv) + if ( ! roffdata(tree, i++, *argv++)) return(0); - i = 1; - } - return((*tree->cb.roffout)(tree->arg, tok)); + + if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) + return(0); + return((*tree->cb.roffblkbodyin) + (tree->arg, tok, argcp, argvp)); } /* @@ -1276,10 +1380,8 @@ roff_layout(ROFFCALL_ARGS) while (*argv) { if (ROFF_MAX == (c = rofffindcallable(*argv))) { assert(tree->arg); - if ( ! (*tree->cb.roffdata) - (tree->arg, i, *argv++)) + if ( ! roffdata(tree, i++, *argv++)) return(0); - i = 1; continue; } if ( ! roffcall(tree, c, argv)) @@ -1293,8 +1395,12 @@ roff_layout(ROFFCALL_ARGS) * macro. */ - if (NULL == *argv) - return((*tree->cb.roffout)(tree->arg, tok)); + if (NULL == *argv) { + if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) + return(0); + return((*tree->cb.roffblkbodyin) + (tree->arg, tok, argcp, argvp)); + } /* * Expensive. Scan to the end of line then work backwards until @@ -1304,16 +1410,101 @@ roff_layout(ROFFCALL_ARGS) if ( ! roffpurgepunct(tree, argv)) return(0); - return((*tree->cb.roffout)(tree->arg, tok)); + if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) + return(0); + return((*tree->cb.roffblkbodyin) + (tree->arg, tok, argcp, argvp)); } /* ARGSUSED */ static int +roff_ordered(ROFFCALL_ARGS) +{ + int i, first, c; + char *ordp[ROFF_MAXLINEARG]; + + if (ROFF_PRELUDE & tree->state) { + roff_err(tree, *argv, "`%s' disallowed in prelude", + toknames[tok]); + return(0); + } + + first = (*argv == tree->cur); + argv++; + + if (NULL == *argv) { + switch (tok) { + case (ROFF_Nm): + if ( ! roffgetname(tree, ordp, *(argv - 1))) + return(0); + break; + default: + *ordp = NULL; + break; + } + + return(roffspecial(tree, tok, ordp)); + } + + i = 0; + while (*argv && i < ROFF_MAXLINEARG) { + c = rofffindcallable(*argv); + + if (ROFF_MAX == c && ! roffispunct(*argv)) { + ordp[i++] = *argv++; + continue; + } + ordp[i] = NULL; + + if (ROFF_MAX == c) + break; + + switch (tok) { + case (ROFF_Nm): + if ( ! roffsetname(tree, ordp)) + return(0); + break; + default: + break; + } + + if ( ! roffspecial(tree, tok, ordp)) + return(0); + + return(roffcall(tree, c, ordp)); + } + + assert(i != ROFF_MAXLINEARG); + ordp[i] = NULL; + + switch (tok) { + case (ROFF_Nm): + if ( ! roffsetname(tree, ordp)) + return(0); + break; + default: + break; + } + + if ( ! roffspecial(tree, tok, ordp)) + return(0); + + /* FIXME: error if there's stuff after the punctuation. */ + + if ( ! first || NULL == *argv) + return(1); + + return(roffpurgepunct(tree, argv)); +} + + +/* ARGSUSED */ +static int roff_text(ROFFCALL_ARGS) { - int i, j, first, c, argcp[ROFF_MAXARG]; - char *argvp[ROFF_MAXARG]; + int i, j, first, c, argcp[ROFF_MAXLINEARG]; + char *argvp[ROFF_MAXLINEARG]; if (ROFF_PRELUDE & tree->state) { roff_err(tree, *argv, "`%s' disallowed in prelude", @@ -1333,11 +1524,10 @@ roff_text(ROFFCALL_ARGS) if ( ! (ROFF_PARSED & tokens[tok].flags)) { i = 0; - while (*argv) { - if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) + while (*argv) + if ( ! roffdata(tree, i++, *argv++)) return(0); - i = 1; - } + return((*tree->cb.roffout)(tree->arg, tok)); } @@ -1366,9 +1556,8 @@ roff_text(ROFFCALL_ARGS) } if ( ! roffispunct(*argv)) { - if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) + if ( ! roffdata(tree, i++, *argv++)) return(0); - i = 1; continue; } @@ -1378,7 +1567,7 @@ roff_text(ROFFCALL_ARGS) break; if (argv[j]) { - if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++)) + if ( ! roffdata(tree, 0, *argv++)) return(0); continue; } @@ -1445,80 +1634,3 @@ roff_err(const struct rofftree *tree, const char *pos, ROFF_ERROR, tree->cur, pos, buf); } - -#ifdef __linux -/* $OpenBSD: roff.c,v 1.33 2008/12/02 13:20:24 kristaps Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller - * - * 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. - */ -static 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 */ -} - - -static 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 /*__linux__*/