summaryrefslogtreecommitdiffstats
path: root/usr.bin/m4
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2014-07-27 22:54:13 +0000
committerbapt <bapt@FreeBSD.org>2014-07-27 22:54:13 +0000
commit4d9c8bc174f1c23d46ad231ae6e152ddc11dfffa (patch)
treebaccaebeb197c2b665518fe1a74fa0902fbf5d98 /usr.bin/m4
parentdee9ff96585a6d4e00149c564fc7e6b0776d8ae8 (diff)
downloadFreeBSD-src-4d9c8bc174f1c23d46ad231ae6e152ddc11dfffa.zip
FreeBSD-src-4d9c8bc174f1c23d46ad231ae6e152ddc11dfffa.tar.gz
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
Diffstat (limited to 'usr.bin/m4')
-rw-r--r--usr.bin/m4/Makefile7
-rw-r--r--usr.bin/m4/eval.c16
-rw-r--r--usr.bin/m4/extern.h8
-rw-r--r--usr.bin/m4/gnum4.c58
-rw-r--r--usr.bin/m4/lib/ohash.c330
-rw-r--r--usr.bin/m4/lib/ohash.h23
-rw-r--r--usr.bin/m4/lib/ohash_create_entry.c40
-rw-r--r--usr.bin/m4/lib/ohash_delete.c33
-rw-r--r--usr.bin/m4/lib/ohash_do.c113
-rw-r--r--usr.bin/m4/lib/ohash_entries.c28
-rw-r--r--usr.bin/m4/lib/ohash_enum.c38
-rw-r--r--usr.bin/m4/lib/ohash_init.356
-rw-r--r--usr.bin/m4/lib/ohash_init.c43
-rw-r--r--usr.bin/m4/lib/ohash_interval.311
-rw-r--r--usr.bin/m4/lib/ohash_interval.c38
-rw-r--r--usr.bin/m4/lib/ohash_lookup_interval.c70
-rw-r--r--usr.bin/m4/lib/ohash_lookup_memory.c66
-rw-r--r--usr.bin/m4/lib/ohash_qlookup.c29
-rw-r--r--usr.bin/m4/lib/ohash_qlookupi.c31
-rw-r--r--usr.bin/m4/look.c18
-rw-r--r--usr.bin/m4/m4.128
-rw-r--r--usr.bin/m4/main.c11
-rw-r--r--usr.bin/m4/misc.c70
23 files changed, 540 insertions, 625 deletions
diff --git a/usr.bin/m4/Makefile b/usr.bin/m4/Makefile
index 13b99c8..7691b2e 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 fbd42aa..b4b025e 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 7753c32..fd2d3ae 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 342751a..cac01ec 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 0000000..3a0f5dd
--- /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 <espie@openbsd.org>
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#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 9880102..698f02e 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 <espie@openbsd.org>
*
@@ -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 b0959dd..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 b0ec7b5..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 dffe6b6..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 c6c5d3e..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 85a3bbc..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 e0b2320..56ece40 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 <espie@openbsd.org>
.\"
.\" 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 a98673d..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 8abe7a8..3a930f5 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 <espie@openbsd.org>
.\"
.\" 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 f6884c0..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 196f5fa..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 0c448e0..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 81e7d55..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 ab90fe3..0000000
--- 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 <espie@openbsd.org>
- *
- * 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/cdefs.h>
-__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 904c055..70497e0 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 a32dc62..c72ffac 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 1cb0340..ced881b 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 c5bcfbf..ebf0198 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -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;
@@ -312,6 +314,25 @@ xalloc(size_t n, const char *fmt, ...)
}
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, ...)
{
char *p = realloc(old, n);
@@ -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)
{
OpenPOWER on IntegriCloud