From 4d9c8bc174f1c23d46ad231ae6e152ddc11dfffa Mon Sep 17 00:00:00 2001 From: bapt Date: Sun, 27 Jul 2014 22:54:13 +0000 Subject: [PATCH] Sync with OpenBSD This brings: - check for integer overflows in custom allocs - fix potential integer overflows in memory allocation - annotate regexp error messages with source string - better error handling in mkstemp/unlink/fdopen logic --- usr.bin/m4/Makefile | 7 +- usr.bin/m4/eval.c | 16 +- usr.bin/m4/extern.h | 8 +- usr.bin/m4/gnum4.c | 58 +++-- usr.bin/m4/lib/ohash.c | 330 +++++++++++++++++++++++++ usr.bin/m4/lib/ohash.h | 23 +- usr.bin/m4/lib/ohash_create_entry.c | 40 --- usr.bin/m4/lib/ohash_delete.c | 33 --- usr.bin/m4/lib/ohash_do.c | 113 --------- usr.bin/m4/lib/ohash_entries.c | 28 --- usr.bin/m4/lib/ohash_enum.c | 38 --- usr.bin/m4/lib/ohash_init.3 | 56 ++++- usr.bin/m4/lib/ohash_init.c | 43 ---- usr.bin/m4/lib/ohash_interval.3 | 11 +- usr.bin/m4/lib/ohash_interval.c | 38 --- usr.bin/m4/lib/ohash_lookup_interval.c | 70 ------ usr.bin/m4/lib/ohash_lookup_memory.c | 66 ----- usr.bin/m4/lib/ohash_qlookup.c | 29 --- usr.bin/m4/lib/ohash_qlookupi.c | 31 --- usr.bin/m4/look.c | 18 +- usr.bin/m4/m4.1 | 28 ++- usr.bin/m4/main.c | 11 +- usr.bin/m4/misc.c | 70 +++++- 23 files changed, 540 insertions(+), 625 deletions(-) create mode 100644 usr.bin/m4/lib/ohash.c delete mode 100644 usr.bin/m4/lib/ohash_create_entry.c delete mode 100644 usr.bin/m4/lib/ohash_delete.c delete mode 100644 usr.bin/m4/lib/ohash_do.c delete mode 100644 usr.bin/m4/lib/ohash_entries.c delete mode 100644 usr.bin/m4/lib/ohash_enum.c delete mode 100644 usr.bin/m4/lib/ohash_init.c delete mode 100644 usr.bin/m4/lib/ohash_interval.c delete mode 100644 usr.bin/m4/lib/ohash_lookup_interval.c delete mode 100644 usr.bin/m4/lib/ohash_lookup_memory.c delete mode 100644 usr.bin/m4/lib/ohash_qlookup.c delete mode 100644 usr.bin/m4/lib/ohash_qlookupi.c diff --git a/usr.bin/m4/Makefile b/usr.bin/m4/Makefile index 13b99c8d0269..7691b2ed23be 100644 --- a/usr.bin/m4/Makefile +++ b/usr.bin/m4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.10 2002/04/26 13:13:41 espie Exp $ +# $OpenBSD: Makefile,v 1.13 2014/05/12 19:11:19 espie Exp $ # $FreeBSD$ # -DEXTENDED @@ -15,10 +15,7 @@ NO_WMISSING_VARIABLE_DECLARATIONS= SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y tokenizer.l .PATH: ${.CURDIR}/lib -SRCS+= ohash_create_entry.c ohash_delete.c ohash_do.c ohash_entries.c \ - ohash_enum.c ohash_init.c ohash_int.h ohash_interval.c \ - ohash_lookup_interval.c ohash_lookup_memory.c ohash_qlookup.c \ - ohash_qlookupi.c +SRCS+= ohash.c tokenizer.o: parser.h diff --git a/usr.bin/m4/eval.c b/usr.bin/m4/eval.c index fbd42aa9e796..b4b025e642c3 100644 --- a/usr.bin/m4/eval.c +++ b/usr.bin/m4/eval.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eval.c,v 1.70 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: eval.c,v 1.73 2014/07/11 21:04:17 espie Exp $ */ /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ /* @@ -267,7 +267,7 @@ expand_builtin(const char *argv[], int argc, int td) doesyscmd(argv[2]); break; case INCLTYPE: - if (argc > 2) + if (argc > 2) { if (!doincl(argv[2])) { if (mimic_gnu) { warn("%s at line %lu: include(%s)", @@ -277,6 +277,7 @@ expand_builtin(const char *argv[], int argc, int td) err(1, "%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); } + } break; case SINCTYPE: @@ -794,7 +795,7 @@ dom4wrap(const char *text) maxwraps = 16; else maxwraps *= 2; - m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps), + m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps), "too many m4wraps"); } m4wraps[wrapindex++] = xstrdup(text); @@ -821,11 +822,10 @@ dodiv(int n) if (outfile[n] == NULL) { char fname[] = _PATH_DIVNAME; - if ((fd = mkstemp(fname)) < 0 || - (outfile[n] = fdopen(fd, "w+")) == NULL) - err(1, "%s: cannot divert", fname); - if (unlink(fname) == -1) - err(1, "%s: cannot unlink", fname); + if ((fd = mkstemp(fname)) < 0 || + unlink(fname) == -1 || + (outfile[n] = fdopen(fd, "w+")) == NULL) + err(1, "%s: cannot divert", fname); } active = outfile[n]; } diff --git a/usr.bin/m4/extern.h b/usr.bin/m4/extern.h index 7753c32c8a0e..fd2d3ae57099 100644 --- a/usr.bin/m4/extern.h +++ b/usr.bin/m4/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.52 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: extern.h,v 1.54 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */ /*- @@ -104,8 +104,10 @@ extern void pbnumbase(int, int, int); extern void pbunsigned(unsigned long); extern void pbstr(const char *); extern void pushback(int); -extern void *xalloc(size_t, const char *fmt, ...); -extern void *xrealloc(void *, size_t, const char *fmt, ...); +extern void *xalloc(size_t, const char *, ...); +extern void *xcalloc(size_t, size_t, const char *, ...); +extern void *xrealloc(void *, size_t, const char *, ...); +extern void *xreallocarray(void *, size_t, size_t, const char *, ...); extern char *xstrdup(const char *); extern void usage(void); extern void resizedivs(int); diff --git a/usr.bin/m4/gnum4.c b/usr.bin/m4/gnum4.c index 342751a15215..cac01ece6818 100644 --- a/usr.bin/m4/gnum4.c +++ b/usr.bin/m4/gnum4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gnum4.c,v 1.42 2011/11/06 12:25:43 espie Exp $ */ +/* $OpenBSD: gnum4.c,v 1.46 2014/07/10 14:12:31 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie @@ -196,10 +196,12 @@ static void addchars(const char *, size_t); static void addchar(int); static char *twiddle(const char *); static char *getstring(void); -static void exit_regerror(int, regex_t *); -static void do_subst(const char *, regex_t *, const char *, regmatch_t *); -static void do_regexpindex(const char *, regex_t *, regmatch_t *); -static void do_regexp(const char *, regex_t *, const char *, regmatch_t *); +static void exit_regerror(int, regex_t *, const char *); +static void do_subst(const char *, regex_t *, const char *, const char *, + regmatch_t *); +static void do_regexpindex(const char *, regex_t *, const char *, regmatch_t *); +static void do_regexp(const char *, regex_t *, const char *, const char *, + regmatch_t *); static void add_sub(int, const char *, regex_t *, regmatch_t *); static void add_replace(const char *, regex_t *, const char *, regmatch_t *); #define addconstantstring(s) addchars((s), sizeof(s)-1) @@ -243,7 +245,7 @@ getstring(void) static void -exit_regerror(int er, regex_t *re) +exit_regerror(int er, regex_t *re, const char *source) { size_t errlen; char *errbuf; @@ -252,7 +254,7 @@ exit_regerror(int er, regex_t *re) errbuf = xalloc(errlen, "malloc in regerror: %lu", (unsigned long)errlen); regerror(er, re, errbuf, errlen); - m4errx(1, "regular expression error: %s.", errbuf); + m4errx(1, "regular expression error in %s: %s.", source, errbuf); } static void @@ -296,7 +298,7 @@ add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm p++; continue; } - if (isdigit(p[1])) { + if (isdigit((unsigned char)p[1])) { add_sub(*(++p) - '0', string, re, pm); continue; } @@ -306,7 +308,8 @@ add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm } static void -do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) +do_subst(const char *string, regex_t *re, const char *source, + const char *replace, regmatch_t *pm) { int error; int flags = 0; @@ -341,12 +344,13 @@ do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) string += pm[0].rm_eo; } if (error != REG_NOMATCH) - exit_regerror(error, re); + exit_regerror(error, re, source); pbstr(string); } static void -do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) +do_regexp(const char *string, regex_t *re, const char *source, + const char *replace, regmatch_t *pm) { int error; @@ -358,12 +362,13 @@ do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) case REG_NOMATCH: break; default: - exit_regerror(error, re); + exit_regerror(error, re, source); } } static void -do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) +do_regexpindex(const char *string, regex_t *re, const char *source, + regmatch_t *pm) { int error; @@ -375,7 +380,7 @@ do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) pbnum(-1); break; default: - exit_regerror(error, re); + exit_regerror(error, re, source); } } @@ -459,6 +464,7 @@ dopatsubst(const char *argv[], int argc) regex_t re; regmatch_t *pmatch; int mode = REG_EXTENDED; + const char *source; size_t l = strlen(argv[3]); if (!mimic_gnu || @@ -466,13 +472,14 @@ dopatsubst(const char *argv[], int argc) (l > 0 && argv[3][l-1] == '$')) mode |= REG_NEWLINE; - error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], - mode); + source = mimic_gnu ? twiddle(argv[3]) : argv[3]; + error = regcomp(&re, source, mode); if (error != 0) - exit_regerror(error, &re); + exit_regerror(error, &re, source); - pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); - do_subst(argv[2], &re, + pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), + NULL); + do_subst(argv[2], &re, source, argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch); free(pmatch); regfree(&re); @@ -486,6 +493,7 @@ doregexp(const char *argv[], int argc) int error; regex_t re; regmatch_t *pmatch; + const char *source; if (argc <= 3) { warnx("Too few arguments to regexp"); @@ -498,16 +506,16 @@ doregexp(const char *argv[], int argc) else pbstr(argv[4]); } - error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3], - REG_EXTENDED|REG_NEWLINE); + source = mimic_gnu ? twiddle(argv[3]) : argv[3]; + error = regcomp(&re, source, REG_EXTENDED|REG_NEWLINE); if (error != 0) - exit_regerror(error, &re); + exit_regerror(error, &re, source); - pmatch = xalloc(sizeof(regmatch_t) * (re.re_nsub+1), NULL); + pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), NULL); if (argc == 4 || argv[4] == NULL) - do_regexpindex(argv[2], &re, pmatch); + do_regexpindex(argv[2], &re, source, pmatch); else - do_regexp(argv[2], &re, argv[4], pmatch); + do_regexp(argv[2], &re, source, argv[4], pmatch); free(pmatch); regfree(&re); } diff --git a/usr.bin/m4/lib/ohash.c b/usr.bin/m4/lib/ohash.c new file mode 100644 index 000000000000..3a0f5dde449c --- /dev/null +++ b/usr.bin/m4/lib/ohash.c @@ -0,0 +1,330 @@ +/* $OpenBSD: src/lib/libutil/ohash.c,v 1.1 2014/06/02 18:52:03 deraadt Exp $ */ + +/* Copyright (c) 1999, 2004 Marc Espie + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include "ohash.h" + +struct _ohash_record { + uint32_t hv; + const char *p; +}; + +#define DELETED ((const char *)h) +#define NONE (h->size) + +/* Don't bother changing the hash table if the change is small enough. */ +#define MINSIZE (1UL << 4) +#define MINDELETED 4 + +static void ohash_resize(struct ohash *); + + +/* This handles the common case of variable length keys, where the + * key is stored at the end of the record. + */ +void * +ohash_create_entry(struct ohash_info *i, const char *start, const char **end) +{ + char *p; + + if (!*end) + *end = start + strlen(start); + p = (i->alloc)(i->key_offset + (*end - start) + 1, i->data); + if (p) { + memcpy(p+i->key_offset, start, *end-start); + p[i->key_offset + (*end - start)] = '\0'; + } + return (void *)p; +} + +/* hash_delete only frees the hash structure. Use hash_first/hash_next + * to free entries as well. */ +void +ohash_delete(struct ohash *h) +{ + (h->info.free)(h->t, h->info.data); +#ifndef NDEBUG + h->t = NULL; +#endif +} + +static void +ohash_resize(struct ohash *h) +{ + struct _ohash_record *n; + size_t ns; + unsigned int j; + unsigned int i, incr; + + if (4 * h->deleted < h->total) { + if (h->size >= (UINT_MAX >> 1U)) + ns = UINT_MAX; + else + ns = h->size << 1U; + } else if (3 * h->deleted > 2 * h->total) + ns = h->size >> 1U; + else + ns = h->size; + if (ns < MINSIZE) + ns = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_EXPAND++; + STAT_HASH_SIZE += ns - h->size; +#endif + + n = (h->info.calloc)(ns, sizeof(struct _ohash_record), h->info.data); + if (!n) + return; + + for (j = 0; j < h->size; j++) { + if (h->t[j].p != NULL && h->t[j].p != DELETED) { + i = h->t[j].hv % ns; + incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1; + while (n[i].p != NULL) { + i += incr; + if (i >= ns) + i -= ns; + } + n[i].hv = h->t[j].hv; + n[i].p = h->t[j].p; + } + } + (h->info.free)(h->t, h->info.data); + h->t = n; + h->size = ns; + h->total -= h->deleted; + h->deleted = 0; +} + +void * +ohash_remove(struct ohash *h, unsigned int i) +{ + void *result = (void *)h->t[i].p; + + if (result == NULL || result == DELETED) + return NULL; + +#ifdef STATS_HASH + STAT_HASH_ENTRIES--; +#endif + h->t[i].p = DELETED; + h->deleted++; + if (h->deleted >= MINDELETED && 4 * h->deleted > h->total) + ohash_resize(h); + return result; +} + +void * +ohash_find(struct ohash *h, unsigned int i) +{ + if (h->t[i].p == DELETED) + return NULL; + else + return (void *)h->t[i].p; +} + +void * +ohash_insert(struct ohash *h, unsigned int i, void *p) +{ +#ifdef STATS_HASH + STAT_HASH_ENTRIES++; +#endif + if (h->t[i].p == DELETED) { + h->deleted--; + h->t[i].p = p; + } else { + h->t[i].p = p; + /* Arbitrary resize boundary. Tweak if not efficient enough. */ + if (++h->total * 4 > h->size * 3) + ohash_resize(h); + } + return p; +} + +unsigned int +ohash_entries(struct ohash *h) +{ + return h->total - h->deleted; +} + +void * +ohash_first(struct ohash *h, unsigned int *pos) +{ + *pos = 0; + return ohash_next(h, pos); +} + +void * +ohash_next(struct ohash *h, unsigned int *pos) +{ + for (; *pos < h->size; (*pos)++) + if (h->t[*pos].p != DELETED && h->t[*pos].p != NULL) + return (void *)h->t[(*pos)++].p; + return NULL; +} + +void +ohash_init(struct ohash *h, unsigned int size, struct ohash_info *info) +{ + h->size = 1UL << size; + if (h->size < MINSIZE) + h->size = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_CREATION++; + STAT_HASH_SIZE += h->size; +#endif + /* Copy info so that caller may free it. */ + h->info.key_offset = info->key_offset; + h->info.calloc = info->calloc; + h->info.free = info->free; + h->info.alloc = info->alloc; + h->info.data = info->data; + h->t = (h->info.calloc)(h->size, sizeof(struct _ohash_record), + h->info.data); + h->total = h->deleted = 0; +} + +uint32_t +ohash_interval(const char *s, const char **e) +{ + uint32_t k; + + if (!*e) + *e = s + strlen(s); + if (s == *e) + k = 0; + else + k = *s++; + while (s != *e) + k = ((k << 2) | (k >> 30)) ^ *s++; + return k; +} + +unsigned int +ohash_lookup_interval(struct ohash *h, const char *start, const char *end, + uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + strncmp(h->t[i].p+h->info.key_offset, start, + end - start) == 0 && + (h->t[i].p+h->info.key_offset)[end-start] == '\0') { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + return i; + } + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_lookup_memory(struct ohash *h, const char *k, size_t size, uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + memcmp(h->t[i].p+h->info.key_offset, k, size) == 0) { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + } return i; + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_qlookup(struct ohash *h, const char *s) +{ + const char *e = NULL; + return ohash_qlookupi(h, s, &e); +} + +unsigned int +ohash_qlookupi(struct ohash *h, const char *s, const char **e) +{ + uint32_t hv; + + hv = ohash_interval(s, e); + return ohash_lookup_interval(h, s, *e, hv); +} diff --git a/usr.bin/m4/lib/ohash.h b/usr.bin/m4/lib/ohash.h index 98801022fb84..698f02e4a1d1 100644 --- a/usr.bin/m4/lib/ohash.h +++ b/usr.bin/m4/lib/ohash.h @@ -1,8 +1,4 @@ -#ifndef OHASH_H -#define OHASH_H -/* $OpenBSD: ohash.h,v 1.8 2005/12/29 18:54:47 jaredy Exp $ */ -/* ex:ts=8 sw=4: - */ +/* $OpenBSD: src/lib/libutil/ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */ /* Copyright (c) 1999, 2004 Marc Espie * @@ -21,21 +17,26 @@ * $FreeBSD$ */ +#ifndef OHASH_H +#define OHASH_H + /* Open hashing support. * Open hashing was chosen because it is much lighter than other hash * techniques, and more efficient in most cases. */ +/* user-visible data structure */ struct ohash_info { ptrdiff_t key_offset; void *data; /* user data */ - void *(*halloc)(size_t, void *); - void (*hfree)(void *, size_t, void *); + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); void *(*alloc)(size_t, void *); }; struct _ohash_record; +/* private structure. It's there just so you can do a sizeof */ struct ohash { struct _ohash_record *t; struct ohash_info info; @@ -55,9 +56,10 @@ void ohash_init(struct ohash *, unsigned, struct ohash_info *); void ohash_delete(struct ohash *); unsigned int ohash_lookup_interval(struct ohash *, const char *, - const char *, u_int32_t); + const char *, uint32_t); unsigned int ohash_lookup_memory(struct ohash *, const char *, - size_t, u_int32_t); + size_t, uint32_t) + __attribute__ ((__bounded__(__string__,2,3))); void *ohash_find(struct ohash *, unsigned int); void *ohash_remove(struct ohash *, unsigned int); void *ohash_insert(struct ohash *, unsigned int, void *); @@ -66,10 +68,9 @@ void *ohash_next(struct ohash *, unsigned int *); unsigned int ohash_entries(struct ohash *); void *ohash_create_entry(struct ohash_info *, const char *, const char **); -u_int32_t ohash_interval(const char *, const char **); +uint32_t ohash_interval(const char *, const char **); unsigned int ohash_qlookupi(struct ohash *, const char *, const char **); unsigned int ohash_qlookup(struct ohash *, const char *); __END_DECLS #endif - diff --git a/usr.bin/m4/lib/ohash_create_entry.c b/usr.bin/m4/lib/ohash_create_entry.c deleted file mode 100644 index b0959dd5a312..000000000000 --- a/usr.bin/m4/lib/ohash_create_entry.c +++ /dev/null @@ -1,40 +0,0 @@ -/* $OpenBSD: ohash_create_entry.c,v 1.2 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -/* This handles the common case of variable length keys, where the - * key is stored at the end of the record. - */ -void * -ohash_create_entry(struct ohash_info *i, const char *start, const char **end) -{ - char *p; - - if (!*end) - *end = start + strlen(start); - p = (i->alloc)(i->key_offset + (*end - start) + 1, i->data); - if (p) { - memcpy(p+i->key_offset, start, *end-start); - p[i->key_offset + (*end - start)] = '\0'; - } - return (void *)p; -} diff --git a/usr.bin/m4/lib/ohash_delete.c b/usr.bin/m4/lib/ohash_delete.c deleted file mode 100644 index b0ec7b546ee8..000000000000 --- a/usr.bin/m4/lib/ohash_delete.c +++ /dev/null @@ -1,33 +0,0 @@ -/* $OpenBSD: ohash_delete.c,v 1.2 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" -/* hash_delete only frees the hash structure. Use hash_first/hash_next - * to free entries as well. */ -void -ohash_delete(struct ohash *h) -{ - (h->info.hfree)(h->t, sizeof(struct _ohash_record) * h->size, - h->info.data); -#ifndef NDEBUG - h->t = NULL; -#endif -} diff --git a/usr.bin/m4/lib/ohash_do.c b/usr.bin/m4/lib/ohash_do.c deleted file mode 100644 index dffe6b614880..000000000000 --- a/usr.bin/m4/lib/ohash_do.c +++ /dev/null @@ -1,113 +0,0 @@ -/* $OpenBSD: ohash_do.c,v 1.4 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -static void ohash_resize(struct ohash *); - -static void -ohash_resize(struct ohash *h) -{ - struct _ohash_record *n; - unsigned int ns, j; - unsigned int i, incr; - - if (4 * h->deleted < h->total) - ns = h->size << 1; - else if (3 * h->deleted > 2 * h->total) - ns = h->size >> 1; - else - ns = h->size; - if (ns < MINSIZE) - ns = MINSIZE; -#ifdef STATS_HASH - STAT_HASH_EXPAND++; - STAT_HASH_SIZE += ns - h->size; -#endif - n = (h->info.halloc)(sizeof(struct _ohash_record) * ns, h->info.data); - if (!n) - return; - - for (j = 0; j < h->size; j++) { - if (h->t[j].p != NULL && h->t[j].p != DELETED) { - i = h->t[j].hv % ns; - incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1; - while (n[i].p != NULL) { - i += incr; - if (i >= ns) - i -= ns; - } - n[i].hv = h->t[j].hv; - n[i].p = h->t[j].p; - } - } - (h->info.hfree)(h->t, sizeof(struct _ohash_record) * h->size, - h->info.data); - h->t = n; - h->size = ns; - h->total -= h->deleted; - h->deleted = 0; -} - -void * -ohash_remove(struct ohash *h, unsigned int i) -{ - void *result = __DECONST(void *, h->t[i].p); - - if (result == NULL || result == DELETED) - return NULL; - -#ifdef STATS_HASH - STAT_HASH_ENTRIES--; -#endif - h->t[i].p = DELETED; - h->deleted++; - if (h->deleted >= MINDELETED && 4 * h->deleted > h->total) - ohash_resize(h); - return result; -} - -void * -ohash_find(struct ohash *h, unsigned int i) -{ - if (h->t[i].p == DELETED) - return NULL; - else - return __DECONST(void *, h->t[i].p); -} - -void * -ohash_insert(struct ohash *h, unsigned int i, void *p) -{ -#ifdef STATS_HASH - STAT_HASH_ENTRIES++; -#endif - if (h->t[i].p == DELETED) { - h->deleted--; - h->t[i].p = p; - } else { - h->t[i].p = p; - /* Arbitrary resize boundary. Tweak if not efficient enough. */ - if (++h->total * 4 > h->size * 3) - ohash_resize(h); - } - return p; -} diff --git a/usr.bin/m4/lib/ohash_entries.c b/usr.bin/m4/lib/ohash_entries.c deleted file mode 100644 index c6c5d3e5ee23..000000000000 --- a/usr.bin/m4/lib/ohash_entries.c +++ /dev/null @@ -1,28 +0,0 @@ -/* $OpenBSD: ohash_entries.c,v 1.2 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -unsigned int -ohash_entries(struct ohash *h) -{ - return h->total - h->deleted; -} diff --git a/usr.bin/m4/lib/ohash_enum.c b/usr.bin/m4/lib/ohash_enum.c deleted file mode 100644 index 85a3bbc4fb8a..000000000000 --- a/usr.bin/m4/lib/ohash_enum.c +++ /dev/null @@ -1,38 +0,0 @@ -/* $OpenBSD: ohash_enum.c,v 1.3 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -void * -ohash_first(struct ohash *h, unsigned int *pos) -{ - *pos = 0; - return ohash_next(h, pos); -} - -void * -ohash_next(struct ohash *h, unsigned int *pos) -{ - for (; *pos < h->size; (*pos)++) - if (h->t[*pos].p != DELETED && h->t[*pos].p != NULL) - return __DECONST(void *, h->t[(*pos)++].p); - return NULL; -} diff --git a/usr.bin/m4/lib/ohash_init.3 b/usr.bin/m4/lib/ohash_init.3 index e0b232077465..56ece40f4cff 100644 --- a/usr.bin/m4/lib/ohash_init.3 +++ b/usr.bin/m4/lib/ohash_init.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ohash_init.3,v 1.14 2007/05/31 19:19:30 jmc Exp $ +.\" $OpenBSD: ohash_init.3,v 1.2 2014/05/13 14:01:41 jmc Exp $ .\" Copyright (c) 1999 Marc Espie .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -15,8 +15,8 @@ .\" .\" $FreeBSD$ .\" -.Dd $Mdocdate: May 31 2007 $ -.Dt OPEN_HASH 3 +.Dd May 12 2014 +.Dt OHASH_INIT 3 .Os .Sh NAME .Nm ohash_init , @@ -71,11 +71,46 @@ initializes the table to store roughly 2 to the power .Fa size elements. .Fa info -holds the position of the key in each record, and two pointers to +is a pointer to a +.Fa struct ohash_info . +.Bd -literal -offset indent +struct ohash_info { + ptrdiff_t key_offset; + void *data; /* user data */ + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); + void *(*alloc)(size_t, void *); +}; +.Ed +.Pp +The +.Va offset +field holds the position of the key in each record; +the +.Va calloc +and +.Va free +fields are pointers to .Xr calloc 3 and .Xr free 3 Ns -like -functions, to use for managing the table internal storage. +functions, used for managing the table internal storage; +the +.Va alloc +field is only used by the utility function +.Xr ohash_create_entry 3 . +.Pp +Each of these functions are called similarly to their standard counterpart, +but with an extra +.Ft void * +parameter corresponding to the content of the field +.Fa data , +which can be used to communicate specific information to the functions. +.Pp +.Fn ohash_init +stores a copy of those fields internally, so +.Fa info +can be reclaimed after initialization. .Pp .Fn ohash_delete frees storage internal to @@ -166,7 +201,7 @@ for (n = ohash_first(h, &i); n != NULL; n = ohash_next(h, &i)) points to an auxiliary unsigned integer used to record the current position in the ohash table. Those functions are safe to use even while entries are added to/removed -from the table, but in such a case they do not guarantee that new entries +from the table, but in such a case they don't guarantee that new entries will be returned. As a special case, they can safely be used to free elements in the table. .Pp @@ -179,7 +214,13 @@ Only .Fn ohash_remove and .Fn ohash_delete -may call the user-supplied memory functions. +may call the user-supplied memory functions: +.Bd -literal -offset indent +p = (*info->calloc)(n, sizeof_record, info->data); +/* copy data from old to p */ +(*info->free)(old, info->data); +.Ed +.Pp It is the responsibility of the user memory allocation code to verify that those calls did not fail. .Pp @@ -213,6 +254,7 @@ call. .Pp Multi-threaded applications should explicitly protect ohash table access. .Sh SEE ALSO +.Xr hcreate 3 , .Xr ohash_interval 3 .Rs .%A Donald E. Knuth diff --git a/usr.bin/m4/lib/ohash_init.c b/usr.bin/m4/lib/ohash_init.c deleted file mode 100644 index a98673d4f0d2..000000000000 --- a/usr.bin/m4/lib/ohash_init.c +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: ohash_init.c,v 1.2 2004/06/22 20:00:16 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -void -ohash_init(struct ohash *h, unsigned int size, struct ohash_info *info) -{ - h->size = 1UL << size; - if (h->size < MINSIZE) - h->size = MINSIZE; -#ifdef STATS_HASH - STAT_HASH_CREATION++; - STAT_HASH_SIZE += h->size; -#endif - /* Copy info so that caller may free it. */ - h->info.key_offset = info->key_offset; - h->info.halloc = info->halloc; - h->info.hfree = info->hfree; - h->info.alloc = info->alloc; - h->info.data = info->data; - h->t = (h->info.halloc)(sizeof(struct _ohash_record) * h->size, - h->info.data); - h->total = h->deleted = 0; -} diff --git a/usr.bin/m4/lib/ohash_interval.3 b/usr.bin/m4/lib/ohash_interval.3 index 8abe7a842bf8..3a930f57d06c 100644 --- a/usr.bin/m4/lib/ohash_interval.3 +++ b/usr.bin/m4/lib/ohash_interval.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ohash_interval.3,v 1.11 2007/05/31 19:19:30 jmc Exp $ +.\" $OpenBSD: ohash_interval.3,v 1.1 2014/05/12 19:09:00 espie Exp $ .\" Copyright (c) 2001 Marc Espie .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -15,8 +15,8 @@ .\" .\" $FreeBSD$ .\" -.Dd $Mdocdate: May 31 2007 $ -.Dt OPEN_HASH_HELPER 3 +.Dd June 5 2013 +.Dt OHASH_INTERVAL 3 .Os .Sh NAME .Nm ohash_interval , @@ -68,7 +68,10 @@ the alloc field of .Fa info should point to a .Xr malloc 3 Ns -like -function to allocate the storage. +function to allocate the storage: +.Bd -literal -offset indent +p = (*info->alloc)(sz, info->data); +.Ed .Pp .Fn ohash_qlookupi is a wrapper function that simply calls diff --git a/usr.bin/m4/lib/ohash_interval.c b/usr.bin/m4/lib/ohash_interval.c deleted file mode 100644 index f6884c08e836..000000000000 --- a/usr.bin/m4/lib/ohash_interval.c +++ /dev/null @@ -1,38 +0,0 @@ -/* $OpenBSD: ohash_interval.c,v 1.3 2006/01/16 15:52:25 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -uint32_t -ohash_interval(const char *s, const char **e) -{ - uint32_t k; - - if (!*e) - *e = s + strlen(s); - if (s == *e) - k = 0; - else - k = *s++; - while (s != *e) - k = ((k << 2) | (k >> 30)) ^ *s++; - return k; -} diff --git a/usr.bin/m4/lib/ohash_lookup_interval.c b/usr.bin/m4/lib/ohash_lookup_interval.c deleted file mode 100644 index 196f5fa47902..000000000000 --- a/usr.bin/m4/lib/ohash_lookup_interval.c +++ /dev/null @@ -1,70 +0,0 @@ -/* $OpenBSD: ohash_lookup_interval.c,v 1.3 2006/01/16 15:52:25 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -unsigned int -ohash_lookup_interval(struct ohash *h, const char *start, const char *end, - uint32_t hv) -{ - unsigned int i, incr; - unsigned int empty; - -#ifdef STATS_HASH - STAT_HASH_LOOKUP++; -#endif - empty = NONE; - i = hv % h->size; - incr = ((hv % (h->size-2)) & ~1) + 1; - while (h->t[i].p != NULL) { -#ifdef STATS_HASH - STAT_HASH_LENGTH++; -#endif - if (h->t[i].p == DELETED) { - if (empty == NONE) - empty = i; - } else if (h->t[i].hv == hv && - strncmp(h->t[i].p+h->info.key_offset, start, - end - start) == 0 && - (h->t[i].p+h->info.key_offset)[end-start] == '\0') { - if (empty != NONE) { - h->t[empty].hv = hv; - h->t[empty].p = h->t[i].p; - h->t[i].p = DELETED; - return empty; - } else { -#ifdef STATS_HASH - STAT_HASH_POSITIVE++; -#endif - return i; - } - } - i += incr; - if (i >= h->size) - i -= h->size; - } - - /* Found an empty position. */ - if (empty != NONE) - i = empty; - h->t[i].hv = hv; - return i; -} diff --git a/usr.bin/m4/lib/ohash_lookup_memory.c b/usr.bin/m4/lib/ohash_lookup_memory.c deleted file mode 100644 index 0c448e03a3b6..000000000000 --- a/usr.bin/m4/lib/ohash_lookup_memory.c +++ /dev/null @@ -1,66 +0,0 @@ -/* $OpenBSD: ohash_lookup_memory.c,v 1.3 2006/01/16 15:52:25 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -unsigned int -ohash_lookup_memory(struct ohash *h, const char *k, size_t size, uint32_t hv) -{ - unsigned int i, incr; - unsigned int empty; - -#ifdef STATS_HASH - STAT_HASH_LOOKUP++; -#endif - empty = NONE; - i = hv % h->size; - incr = ((hv % (h->size-2)) & ~1) + 1; - while (h->t[i].p != NULL) { -#ifdef STATS_HASH - STAT_HASH_LENGTH++; -#endif - if (h->t[i].p == DELETED) { - if (empty == NONE) - empty = i; - } else if (h->t[i].hv == hv && - memcmp(h->t[i].p+h->info.key_offset, k, size) == 0) { - if (empty != NONE) { - h->t[empty].hv = hv; - h->t[empty].p = h->t[i].p; - h->t[i].p = DELETED; - return empty; - } else { -#ifdef STATS_HASH - STAT_HASH_POSITIVE++; -#endif - } return i; - } - i += incr; - if (i >= h->size) - i -= h->size; - } - - /* Found an empty position. */ - if (empty != NONE) - i = empty; - h->t[i].hv = hv; - return i; -} diff --git a/usr.bin/m4/lib/ohash_qlookup.c b/usr.bin/m4/lib/ohash_qlookup.c deleted file mode 100644 index 81e7d55474aa..000000000000 --- a/usr.bin/m4/lib/ohash_qlookup.c +++ /dev/null @@ -1,29 +0,0 @@ -/* $OpenBSD: ohash_qlookup.c,v 1.2 2004/06/22 20:00:17 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -unsigned int -ohash_qlookup(struct ohash *h, const char *s) -{ - const char *e = NULL; - return ohash_qlookupi(h, s, &e); -} diff --git a/usr.bin/m4/lib/ohash_qlookupi.c b/usr.bin/m4/lib/ohash_qlookupi.c deleted file mode 100644 index ab90fe30cf73..000000000000 --- a/usr.bin/m4/lib/ohash_qlookupi.c +++ /dev/null @@ -1,31 +0,0 @@ -/* $OpenBSD: ohash_qlookupi.c,v 1.2 2004/06/22 20:00:17 espie Exp $ */ -/* ex:ts=8 sw=4: - */ - -/* Copyright (c) 1999, 2004 Marc Espie - * - * 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 -__FBSDID("$FreeBSD$"); - -#include "ohash_int.h" - -unsigned int -ohash_qlookupi(struct ohash *h, const char *s, const char **e) -{ - u_int32_t hv; - - hv = ohash_interval(s, e); - return ohash_lookup_interval(h, s, *e, hv); -} diff --git a/usr.bin/m4/look.c b/usr.bin/m4/look.c index 904c05545198..70497e01e593 100644 --- a/usr.bin/m4/look.c +++ b/usr.bin/m4/look.c @@ -1,4 +1,4 @@ -/* $OpenBSD: look.c,v 1.22 2010/09/07 19:58:09 marco Exp $ */ +/* $OpenBSD: look.c,v 1.23 2014/05/12 19:11:19 espie Exp $ */ /* * Copyright (c) 1989, 1993 @@ -51,36 +51,34 @@ __FBSDID("$FreeBSD$"); #include "stdd.h" #include "extern.h" -static void *hash_alloc(size_t, void *); -static void hash_free(void *, size_t, void *); +static void *hash_calloc(size_t, size_t, void *); +static void hash_free(void *, void *); static void *element_alloc(size_t, void *); static void setup_definition(struct macro_definition *, const char *, const char *); static struct ohash_info macro_info = { offsetof(struct ndblock, name), - NULL, hash_alloc, hash_free, element_alloc }; + NULL, hash_calloc, hash_free, element_alloc }; struct ohash macros; /* Support routines for hash tables. */ void * -hash_alloc(size_t s, __unused void *u) +hash_calloc(size_t n, size_t s, void *u __unused) { - void *storage = xalloc(s, "hash alloc"); - if (storage) - memset(storage, 0, s); + void *storage = xcalloc(n, s, "hash alloc"); return storage; } void -hash_free(void *p, __unused size_t s, __unused void *u) +hash_free(void *p, void *u __unused) { free(p); } void * -element_alloc(size_t s, __unused void *u) +element_alloc(size_t s, void *u __unused) { return xalloc(s, "element alloc"); } diff --git a/usr.bin/m4/m4.1 b/usr.bin/m4/m4.1 index a32dc62ff1ce..c72ffac85828 100644 --- a/usr.bin/m4/m4.1 +++ b/usr.bin/m4/m4.1 @@ -1,5 +1,5 @@ .\" $NetBSD: m4.1,v 1.23 2012/04/08 22:00:39 wiz Exp $ -.\" @(#) $OpenBSD: m4.1,v 1.59 2010/10/21 13:20:51 jmc Exp $ +.\" @(#) $OpenBSD: m4.1,v 1.62 2014/04/14 07:00:47 jmc Exp $ .\" .\" Copyright (c) 1989, 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 21, 2010 +.Dd January 12 2014 $ .Dt M4 1 .Os .Sh NAME @@ -88,9 +88,7 @@ In arguments to macros, leading unquoted space, tab, and newline .Pq Sq \en characters are ignored. To quote strings, use left and right single quotes -.Po e.g.,\ \& -.Sq "\ this is a string with a leading space" -.Pc . +.Pq e.g., Sq \ \&this is a string with a leading space . You can change the quote characters with the .Ic changequote built-in macro. @@ -258,15 +256,17 @@ Prints the first argument on the standard error output stream. Passes its first argument to a shell and returns the shell's standard output. Note that the shell shares its standard input and standard error with .Nm . -.It Fn eval expr +.It Fn eval expr[,radix[,minimum]] Computes the first argument as an arithmetic expression using 32-bit arithmetic. Operators are the standard C ternary, arithmetic, logical, shift, relational, bitwise, and parentheses operators. You can specify octal, decimal, and hexadecimal numbers as in C. -The second argument (if any) -specifies the radix for the result and the third argument (if any) +The optional second argument +.Fa radix +specifies the radix for the result and the optional third argument +.Fa minimum specifies the minimum number of digits in the result. .It Fn expr expr This is an alias for @@ -441,12 +441,12 @@ macro can modify the exit status. .Sh STANDARDS The .Nm -utility is mostly compliant with the +utility is compliant with the .St -p1003.1-2008 specification. .Pp The flags -.Op Fl dgIot +.Op Fl dgIPot and the macros .Ic builtin , .Ic esyscmd , @@ -467,9 +467,13 @@ are extensions to that specification. is not supposed to be a synonym for .Ic mkstemp , but instead to be an insecure temporary file name creation function. -The change causes no known compatibility issues. +It is marked by +.St -p1003.1-2008 +as being obsolescent and should not be used if portability is a concern. .Pp -The output format of tracing and of +The output format of +.Ic traceon +and .Ic dumpdef are not specified in any standard, are likely to change and should not be relied upon. diff --git a/usr.bin/m4/main.c b/usr.bin/m4/main.c index 1cb0340fbdd4..ced881b2ca91 100644 --- a/usr.bin/m4/main.c +++ b/usr.bin/m4/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.81 2012/04/12 17:00:11 espie Exp $ */ +/* $OpenBSD: main.c,v 1.83 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- @@ -180,8 +180,8 @@ main(int argc, char *argv[]) initspaces(); STACKMAX = INITSTACKMAX; - mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL); - sstack = (char *)xalloc(STACKMAX, NULL); + mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL); + sstack = xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; @@ -415,7 +415,8 @@ macro(void) } } } else if (t == EOF) { - if (sp > -1 && ilevel <= 0) { + if (!mimic_gnu /* you can puke right there */ + && sp > -1 && ilevel <= 0) { warnx( "unexpected end of input, unclosed parenthesis:"); dump_stack(paren, PARLEV); exit(1); @@ -625,7 +626,7 @@ static void enlarge_stack(void) { STACKMAX += STACKMAX/2; - mstack = xrealloc(mstack, sizeof(stae) * STACKMAX, + mstack = xreallocarray(mstack, STACKMAX, sizeof(stae), "Evaluation stack overflow (%lu)", (unsigned long)STACKMAX); sstack = xrealloc(sstack, STACKMAX, diff --git a/usr.bin/m4/misc.c b/usr.bin/m4/misc.c index c5bcfbf4fce1..ebf0198d4efa 100644 --- a/usr.bin/m4/misc.c +++ b/usr.bin/m4/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.42 2010/09/07 19:58:09 marco Exp $ */ +/* $OpenBSD: misc.c,v 1.44 2014/05/12 19:11:19 espie Exp $ */ /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */ /* @@ -32,6 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #include __FBSDID("$FreeBSD$"); @@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -165,7 +167,7 @@ initspaces(void) strspace = xalloc(strsize+1, NULL); ep = strspace; endest = strspace+strsize; - buf = (unsigned char *)xalloc(bufsize, NULL); + buf = xalloc(bufsize, NULL); bufbase = buf; bp = buf; endpbb = buf + bufsize; @@ -239,7 +241,7 @@ getdiv(int n) } void -onintr(__unused int signo) +onintr(int signo __unused) { #define intrmessage "m4: interrupted.\n" write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1); @@ -263,7 +265,7 @@ killdiv(void) extern char *__progname; void -m4errx(int evaluation, const char *fmt, ...) +m4errx(int eval, const char *fmt, ...) { fprintf(stderr, "%s: ", __progname); fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE); @@ -275,7 +277,7 @@ m4errx(int evaluation, const char *fmt, ...) va_end(ap); } fprintf(stderr, "\n"); - exit(evaluation); + exit(eval); } /* @@ -285,7 +287,7 @@ resizedivs(int n) { int i; - outfile = (FILE **)xrealloc(outfile, sizeof(FILE *) * n, + outfile = xreallocarray(outfile, n, sizeof(FILE *), "too many diverts %d", n); for (i = maxout; i < n; i++) outfile[i] = NULL; @@ -311,6 +313,25 @@ xalloc(size_t n, const char *fmt, ...) return p; } +void * +xcalloc(size_t n, size_t s, const char *fmt, ...) +{ + void *p = calloc(n, s); + + if (p == NULL) { + if (fmt == NULL) + err(1, "calloc"); + else { + va_list va; + + va_start(va, fmt); + verr(1, fmt, va); + va_end(va); + } + } + return p; +} + void * xrealloc(void *old, size_t n, const char *fmt, ...) { @@ -331,6 +352,43 @@ xrealloc(void *old, size_t n, const char *fmt, ...) return p; } +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) + +static void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} + +void * +xreallocarray(void *old, size_t s1, size_t s2, const char *fmt, ...) +{ + void *p = reallocarray(old, s1, s2); + + if (p == NULL) { + free(old); + if (fmt == NULL) + err(1, "reallocarray"); + else { + va_list va; + + va_start(va, fmt); + verr(1, fmt, va); + va_end(va); + } + } + return p; +} + char * xstrdup(const char *s) {