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
This commit is contained in:
parent
c448f58f45
commit
88497f0c68
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=269162
@ -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$
|
# $FreeBSD$
|
||||||
|
|
||||||
# -DEXTENDED
|
# -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
|
SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y tokenizer.l
|
||||||
.PATH: ${.CURDIR}/lib
|
.PATH: ${.CURDIR}/lib
|
||||||
SRCS+= ohash_create_entry.c ohash_delete.c ohash_do.c ohash_entries.c \
|
SRCS+= ohash.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
|
|
||||||
|
|
||||||
tokenizer.o: parser.h
|
tokenizer.o: parser.h
|
||||||
|
|
||||||
|
@ -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 $ */
|
/* $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]);
|
doesyscmd(argv[2]);
|
||||||
break;
|
break;
|
||||||
case INCLTYPE:
|
case INCLTYPE:
|
||||||
if (argc > 2)
|
if (argc > 2) {
|
||||||
if (!doincl(argv[2])) {
|
if (!doincl(argv[2])) {
|
||||||
if (mimic_gnu) {
|
if (mimic_gnu) {
|
||||||
warn("%s at line %lu: include(%s)",
|
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)",
|
err(1, "%s at line %lu: include(%s)",
|
||||||
CURRENT_NAME, CURRENT_LINE, argv[2]);
|
CURRENT_NAME, CURRENT_LINE, argv[2]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SINCTYPE:
|
case SINCTYPE:
|
||||||
@ -794,7 +795,7 @@ dom4wrap(const char *text)
|
|||||||
maxwraps = 16;
|
maxwraps = 16;
|
||||||
else
|
else
|
||||||
maxwraps *= 2;
|
maxwraps *= 2;
|
||||||
m4wraps = xrealloc(m4wraps, maxwraps * sizeof(*m4wraps),
|
m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
|
||||||
"too many m4wraps");
|
"too many m4wraps");
|
||||||
}
|
}
|
||||||
m4wraps[wrapindex++] = xstrdup(text);
|
m4wraps[wrapindex++] = xstrdup(text);
|
||||||
@ -821,11 +822,10 @@ dodiv(int n)
|
|||||||
if (outfile[n] == NULL) {
|
if (outfile[n] == NULL) {
|
||||||
char fname[] = _PATH_DIVNAME;
|
char fname[] = _PATH_DIVNAME;
|
||||||
|
|
||||||
if ((fd = mkstemp(fname)) < 0 ||
|
if ((fd = mkstemp(fname)) < 0 ||
|
||||||
(outfile[n] = fdopen(fd, "w+")) == NULL)
|
unlink(fname) == -1 ||
|
||||||
err(1, "%s: cannot divert", fname);
|
(outfile[n] = fdopen(fd, "w+")) == NULL)
|
||||||
if (unlink(fname) == -1)
|
err(1, "%s: cannot divert", fname);
|
||||||
err(1, "%s: cannot unlink", fname);
|
|
||||||
}
|
}
|
||||||
active = outfile[n];
|
active = outfile[n];
|
||||||
}
|
}
|
||||||
|
@ -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 $ */
|
/* $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 pbunsigned(unsigned long);
|
||||||
extern void pbstr(const char *);
|
extern void pbstr(const char *);
|
||||||
extern void pushback(int);
|
extern void pushback(int);
|
||||||
extern void *xalloc(size_t, const char *fmt, ...);
|
extern void *xalloc(size_t, const char *, ...);
|
||||||
extern void *xrealloc(void *, size_t, const char *fmt, ...);
|
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 char *xstrdup(const char *);
|
||||||
extern void usage(void);
|
extern void usage(void);
|
||||||
extern void resizedivs(int);
|
extern void resizedivs(int);
|
||||||
|
@ -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
|
* Copyright (c) 1999 Marc Espie
|
||||||
@ -196,10 +196,12 @@ static void addchars(const char *, size_t);
|
|||||||
static void addchar(int);
|
static void addchar(int);
|
||||||
static char *twiddle(const char *);
|
static char *twiddle(const char *);
|
||||||
static char *getstring(void);
|
static char *getstring(void);
|
||||||
static void exit_regerror(int, regex_t *);
|
static void exit_regerror(int, regex_t *, const char *);
|
||||||
static void do_subst(const char *, regex_t *, const char *, regmatch_t *);
|
static void do_subst(const char *, regex_t *, const char *, const char *,
|
||||||
static void do_regexpindex(const char *, regex_t *, regmatch_t *);
|
regmatch_t *);
|
||||||
static void do_regexp(const char *, regex_t *, 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_sub(int, const char *, regex_t *, regmatch_t *);
|
||||||
static void add_replace(const char *, regex_t *, const char *, regmatch_t *);
|
static void add_replace(const char *, regex_t *, const char *, regmatch_t *);
|
||||||
#define addconstantstring(s) addchars((s), sizeof(s)-1)
|
#define addconstantstring(s) addchars((s), sizeof(s)-1)
|
||||||
@ -243,7 +245,7 @@ getstring(void)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
exit_regerror(int er, regex_t *re)
|
exit_regerror(int er, regex_t *re, const char *source)
|
||||||
{
|
{
|
||||||
size_t errlen;
|
size_t errlen;
|
||||||
char *errbuf;
|
char *errbuf;
|
||||||
@ -252,7 +254,7 @@ exit_regerror(int er, regex_t *re)
|
|||||||
errbuf = xalloc(errlen,
|
errbuf = xalloc(errlen,
|
||||||
"malloc in regerror: %lu", (unsigned long)errlen);
|
"malloc in regerror: %lu", (unsigned long)errlen);
|
||||||
regerror(er, re, errbuf, 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
|
static void
|
||||||
@ -296,7 +298,7 @@ add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm
|
|||||||
p++;
|
p++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isdigit(p[1])) {
|
if (isdigit((unsigned char)p[1])) {
|
||||||
add_sub(*(++p) - '0', string, re, pm);
|
add_sub(*(++p) - '0', string, re, pm);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -306,7 +308,8 @@ add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 error;
|
||||||
int flags = 0;
|
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;
|
string += pm[0].rm_eo;
|
||||||
}
|
}
|
||||||
if (error != REG_NOMATCH)
|
if (error != REG_NOMATCH)
|
||||||
exit_regerror(error, re);
|
exit_regerror(error, re, source);
|
||||||
pbstr(string);
|
pbstr(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
int error;
|
||||||
|
|
||||||
@ -358,12 +362,13 @@ do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm)
|
|||||||
case REG_NOMATCH:
|
case REG_NOMATCH:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
exit_regerror(error, re);
|
exit_regerror(error, re, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
int error;
|
||||||
|
|
||||||
@ -375,7 +380,7 @@ do_regexpindex(const char *string, regex_t *re, regmatch_t *pm)
|
|||||||
pbnum(-1);
|
pbnum(-1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
exit_regerror(error, re);
|
exit_regerror(error, re, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,6 +464,7 @@ dopatsubst(const char *argv[], int argc)
|
|||||||
regex_t re;
|
regex_t re;
|
||||||
regmatch_t *pmatch;
|
regmatch_t *pmatch;
|
||||||
int mode = REG_EXTENDED;
|
int mode = REG_EXTENDED;
|
||||||
|
const char *source;
|
||||||
size_t l = strlen(argv[3]);
|
size_t l = strlen(argv[3]);
|
||||||
|
|
||||||
if (!mimic_gnu ||
|
if (!mimic_gnu ||
|
||||||
@ -466,13 +472,14 @@ dopatsubst(const char *argv[], int argc)
|
|||||||
(l > 0 && argv[3][l-1] == '$'))
|
(l > 0 && argv[3][l-1] == '$'))
|
||||||
mode |= REG_NEWLINE;
|
mode |= REG_NEWLINE;
|
||||||
|
|
||||||
error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3],
|
source = mimic_gnu ? twiddle(argv[3]) : argv[3];
|
||||||
mode);
|
error = regcomp(&re, source, mode);
|
||||||
if (error != 0)
|
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),
|
||||||
do_subst(argv[2], &re,
|
NULL);
|
||||||
|
do_subst(argv[2], &re, source,
|
||||||
argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch);
|
argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch);
|
||||||
free(pmatch);
|
free(pmatch);
|
||||||
regfree(&re);
|
regfree(&re);
|
||||||
@ -486,6 +493,7 @@ doregexp(const char *argv[], int argc)
|
|||||||
int error;
|
int error;
|
||||||
regex_t re;
|
regex_t re;
|
||||||
regmatch_t *pmatch;
|
regmatch_t *pmatch;
|
||||||
|
const char *source;
|
||||||
|
|
||||||
if (argc <= 3) {
|
if (argc <= 3) {
|
||||||
warnx("Too few arguments to regexp");
|
warnx("Too few arguments to regexp");
|
||||||
@ -498,16 +506,16 @@ doregexp(const char *argv[], int argc)
|
|||||||
else
|
else
|
||||||
pbstr(argv[4]);
|
pbstr(argv[4]);
|
||||||
}
|
}
|
||||||
error = regcomp(&re, mimic_gnu ? twiddle(argv[3]) : argv[3],
|
source = mimic_gnu ? twiddle(argv[3]) : argv[3];
|
||||||
REG_EXTENDED|REG_NEWLINE);
|
error = regcomp(&re, source, REG_EXTENDED|REG_NEWLINE);
|
||||||
if (error != 0)
|
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)
|
if (argc == 4 || argv[4] == NULL)
|
||||||
do_regexpindex(argv[2], &re, pmatch);
|
do_regexpindex(argv[2], &re, source, pmatch);
|
||||||
else
|
else
|
||||||
do_regexp(argv[2], &re, argv[4], pmatch);
|
do_regexp(argv[2], &re, source, argv[4], pmatch);
|
||||||
free(pmatch);
|
free(pmatch);
|
||||||
regfree(&re);
|
regfree(&re);
|
||||||
}
|
}
|
||||||
|
330
usr.bin/m4/lib/ohash.c
Normal file
330
usr.bin/m4/lib/ohash.c
Normal file
@ -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);
|
||||||
|
}
|
@ -1,8 +1,4 @@
|
|||||||
#ifndef OHASH_H
|
/* $OpenBSD: src/lib/libutil/ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */
|
||||||
#define OHASH_H
|
|
||||||
/* $OpenBSD: ohash.h,v 1.8 2005/12/29 18:54:47 jaredy Exp $ */
|
|
||||||
/* ex:ts=8 sw=4:
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
|
/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
|
||||||
*
|
*
|
||||||
@ -21,21 +17,26 @@
|
|||||||
* $FreeBSD$
|
* $FreeBSD$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef OHASH_H
|
||||||
|
#define OHASH_H
|
||||||
|
|
||||||
/* Open hashing support.
|
/* Open hashing support.
|
||||||
* Open hashing was chosen because it is much lighter than other hash
|
* Open hashing was chosen because it is much lighter than other hash
|
||||||
* techniques, and more efficient in most cases.
|
* techniques, and more efficient in most cases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* user-visible data structure */
|
||||||
struct ohash_info {
|
struct ohash_info {
|
||||||
ptrdiff_t key_offset;
|
ptrdiff_t key_offset;
|
||||||
void *data; /* user data */
|
void *data; /* user data */
|
||||||
void *(*halloc)(size_t, void *);
|
void *(*calloc)(size_t, size_t, void *);
|
||||||
void (*hfree)(void *, size_t, void *);
|
void (*free)(void *, void *);
|
||||||
void *(*alloc)(size_t, void *);
|
void *(*alloc)(size_t, void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ohash_record;
|
struct _ohash_record;
|
||||||
|
|
||||||
|
/* private structure. It's there just so you can do a sizeof */
|
||||||
struct ohash {
|
struct ohash {
|
||||||
struct _ohash_record *t;
|
struct _ohash_record *t;
|
||||||
struct ohash_info info;
|
struct ohash_info info;
|
||||||
@ -55,9 +56,10 @@ void ohash_init(struct ohash *, unsigned, struct ohash_info *);
|
|||||||
void ohash_delete(struct ohash *);
|
void ohash_delete(struct ohash *);
|
||||||
|
|
||||||
unsigned int ohash_lookup_interval(struct ohash *, const char *,
|
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 *,
|
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_find(struct ohash *, unsigned int);
|
||||||
void *ohash_remove(struct ohash *, unsigned int);
|
void *ohash_remove(struct ohash *, unsigned int);
|
||||||
void *ohash_insert(struct ohash *, unsigned int, void *);
|
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 *);
|
unsigned int ohash_entries(struct ohash *);
|
||||||
|
|
||||||
void *ohash_create_entry(struct ohash_info *, const char *, const char **);
|
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_qlookupi(struct ohash *, const char *, const char **);
|
||||||
unsigned int ohash_qlookup(struct ohash *, const char *);
|
unsigned int ohash_qlookup(struct ohash *, const char *);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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>
|
.\" Copyright (c) 1999 Marc Espie <espie@openbsd.org>
|
||||||
.\"
|
.\"
|
||||||
.\" Permission to use, copy, modify, and distribute this software for any
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
@ -15,8 +15,8 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: May 31 2007 $
|
.Dd May 12 2014
|
||||||
.Dt OPEN_HASH 3
|
.Dt OHASH_INIT 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ohash_init ,
|
.Nm ohash_init ,
|
||||||
@ -71,11 +71,46 @@ initializes the table to store roughly 2 to the power
|
|||||||
.Fa size
|
.Fa size
|
||||||
elements.
|
elements.
|
||||||
.Fa info
|
.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
|
.Xr calloc 3
|
||||||
and
|
and
|
||||||
.Xr free 3 Ns -like
|
.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
|
.Pp
|
||||||
.Fn ohash_delete
|
.Fn ohash_delete
|
||||||
frees storage internal to
|
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
|
points to an auxiliary unsigned integer used to record the current position
|
||||||
in the ohash table.
|
in the ohash table.
|
||||||
Those functions are safe to use even while entries are added to/removed
|
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.
|
will be returned.
|
||||||
As a special case, they can safely be used to free elements in the table.
|
As a special case, they can safely be used to free elements in the table.
|
||||||
.Pp
|
.Pp
|
||||||
@ -179,7 +214,13 @@ Only
|
|||||||
.Fn ohash_remove
|
.Fn ohash_remove
|
||||||
and
|
and
|
||||||
.Fn ohash_delete
|
.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
|
It is the responsibility of the user memory allocation code to verify
|
||||||
that those calls did not fail.
|
that those calls did not fail.
|
||||||
.Pp
|
.Pp
|
||||||
@ -213,6 +254,7 @@ call.
|
|||||||
.Pp
|
.Pp
|
||||||
Multi-threaded applications should explicitly protect ohash table access.
|
Multi-threaded applications should explicitly protect ohash table access.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
.Xr hcreate 3 ,
|
||||||
.Xr ohash_interval 3
|
.Xr ohash_interval 3
|
||||||
.Rs
|
.Rs
|
||||||
.%A Donald E. Knuth
|
.%A Donald E. Knuth
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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>
|
.\" Copyright (c) 2001 Marc Espie <espie@openbsd.org>
|
||||||
.\"
|
.\"
|
||||||
.\" Permission to use, copy, modify, and distribute this software for any
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
@ -15,8 +15,8 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: May 31 2007 $
|
.Dd June 5 2013
|
||||||
.Dt OPEN_HASH_HELPER 3
|
.Dt OHASH_INTERVAL 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ohash_interval ,
|
.Nm ohash_interval ,
|
||||||
@ -68,7 +68,10 @@ the alloc field of
|
|||||||
.Fa info
|
.Fa info
|
||||||
should point to a
|
should point to a
|
||||||
.Xr malloc 3 Ns -like
|
.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
|
.Pp
|
||||||
.Fn ohash_qlookupi
|
.Fn ohash_qlookupi
|
||||||
is a wrapper function that simply calls
|
is a wrapper function that simply calls
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
* Copyright (c) 1989, 1993
|
||||||
@ -51,36 +51,34 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "stdd.h"
|
#include "stdd.h"
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
|
|
||||||
static void *hash_alloc(size_t, void *);
|
static void *hash_calloc(size_t, size_t, void *);
|
||||||
static void hash_free(void *, size_t, void *);
|
static void hash_free(void *, void *);
|
||||||
static void *element_alloc(size_t, void *);
|
static void *element_alloc(size_t, void *);
|
||||||
static void setup_definition(struct macro_definition *, const char *,
|
static void setup_definition(struct macro_definition *, const char *,
|
||||||
const char *);
|
const char *);
|
||||||
|
|
||||||
static struct ohash_info macro_info = {
|
static struct ohash_info macro_info = {
|
||||||
offsetof(struct ndblock, name),
|
offsetof(struct ndblock, name),
|
||||||
NULL, hash_alloc, hash_free, element_alloc };
|
NULL, hash_calloc, hash_free, element_alloc };
|
||||||
|
|
||||||
struct ohash macros;
|
struct ohash macros;
|
||||||
|
|
||||||
/* Support routines for hash tables. */
|
/* Support routines for hash tables. */
|
||||||
void *
|
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");
|
void *storage = xcalloc(n, s, "hash alloc");
|
||||||
if (storage)
|
|
||||||
memset(storage, 0, s);
|
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hash_free(void *p, __unused size_t s, __unused void *u)
|
hash_free(void *p, void *u __unused)
|
||||||
{
|
{
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
element_alloc(size_t s, __unused void *u)
|
element_alloc(size_t s, void *u __unused)
|
||||||
{
|
{
|
||||||
return xalloc(s, "element alloc");
|
return xalloc(s, "element alloc");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" $NetBSD: m4.1,v 1.23 2012/04/08 22:00:39 wiz Exp $
|
.\" $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
|
.\" Copyright (c) 1989, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
@ -33,7 +33,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd October 21, 2010
|
.Dd January 12 2014 $
|
||||||
.Dt M4 1
|
.Dt M4 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -88,9 +88,7 @@ In arguments to macros, leading unquoted space, tab, and newline
|
|||||||
.Pq Sq \en
|
.Pq Sq \en
|
||||||
characters are ignored.
|
characters are ignored.
|
||||||
To quote strings, use left and right single quotes
|
To quote strings, use left and right single quotes
|
||||||
.Po e.g.,\ \&
|
.Pq e.g., Sq \ \&this is a string with a leading space .
|
||||||
.Sq "\ this is a string with a leading space"
|
|
||||||
.Pc .
|
|
||||||
You can change the quote characters with the
|
You can change the quote characters with the
|
||||||
.Ic changequote
|
.Ic changequote
|
||||||
built-in macro.
|
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.
|
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
|
Note that the shell shares its standard input and standard error with
|
||||||
.Nm .
|
.Nm .
|
||||||
.It Fn eval expr
|
.It Fn eval expr[,radix[,minimum]]
|
||||||
Computes the first argument as an arithmetic expression using 32-bit
|
Computes the first argument as an arithmetic expression using 32-bit
|
||||||
arithmetic.
|
arithmetic.
|
||||||
Operators are the standard C ternary, arithmetic, logical,
|
Operators are the standard C ternary, arithmetic, logical,
|
||||||
shift, relational, bitwise, and parentheses operators.
|
shift, relational, bitwise, and parentheses operators.
|
||||||
You can specify
|
You can specify
|
||||||
octal, decimal, and hexadecimal numbers as in C.
|
octal, decimal, and hexadecimal numbers as in C.
|
||||||
The second argument (if any)
|
The optional second argument
|
||||||
specifies the radix for the result and the third argument (if any)
|
.Fa radix
|
||||||
|
specifies the radix for the result and the optional third argument
|
||||||
|
.Fa minimum
|
||||||
specifies the minimum number of digits in the result.
|
specifies the minimum number of digits in the result.
|
||||||
.It Fn expr expr
|
.It Fn expr expr
|
||||||
This is an alias for
|
This is an alias for
|
||||||
@ -441,12 +441,12 @@ macro can modify the exit status.
|
|||||||
.Sh STANDARDS
|
.Sh STANDARDS
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
utility is mostly compliant with the
|
utility is compliant with the
|
||||||
.St -p1003.1-2008
|
.St -p1003.1-2008
|
||||||
specification.
|
specification.
|
||||||
.Pp
|
.Pp
|
||||||
The flags
|
The flags
|
||||||
.Op Fl dgIot
|
.Op Fl dgIPot
|
||||||
and the macros
|
and the macros
|
||||||
.Ic builtin ,
|
.Ic builtin ,
|
||||||
.Ic esyscmd ,
|
.Ic esyscmd ,
|
||||||
@ -467,9 +467,13 @@ are extensions to that specification.
|
|||||||
is not supposed to be a synonym for
|
is not supposed to be a synonym for
|
||||||
.Ic mkstemp ,
|
.Ic mkstemp ,
|
||||||
but instead to be an insecure temporary file name creation function.
|
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
|
.Pp
|
||||||
The output format of tracing and of
|
The output format of
|
||||||
|
.Ic traceon
|
||||||
|
and
|
||||||
.Ic dumpdef
|
.Ic dumpdef
|
||||||
are not specified in any standard,
|
are not specified in any standard,
|
||||||
are likely to change and should not be relied upon.
|
are likely to change and should not be relied upon.
|
||||||
|
@ -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 $ */
|
/* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
@ -180,8 +180,8 @@ main(int argc, char *argv[])
|
|||||||
initspaces();
|
initspaces();
|
||||||
STACKMAX = INITSTACKMAX;
|
STACKMAX = INITSTACKMAX;
|
||||||
|
|
||||||
mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL);
|
mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL);
|
||||||
sstack = (char *)xalloc(STACKMAX, NULL);
|
sstack = xalloc(STACKMAX, NULL);
|
||||||
|
|
||||||
maxout = 0;
|
maxout = 0;
|
||||||
outfile = NULL;
|
outfile = NULL;
|
||||||
@ -415,7 +415,8 @@ macro(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (t == EOF) {
|
} 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:");
|
warnx( "unexpected end of input, unclosed parenthesis:");
|
||||||
dump_stack(paren, PARLEV);
|
dump_stack(paren, PARLEV);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -625,7 +626,7 @@ static void
|
|||||||
enlarge_stack(void)
|
enlarge_stack(void)
|
||||||
{
|
{
|
||||||
STACKMAX += STACKMAX/2;
|
STACKMAX += STACKMAX/2;
|
||||||
mstack = xrealloc(mstack, sizeof(stae) * STACKMAX,
|
mstack = xreallocarray(mstack, STACKMAX, sizeof(stae),
|
||||||
"Evaluation stack overflow (%lu)",
|
"Evaluation stack overflow (%lu)",
|
||||||
(unsigned long)STACKMAX);
|
(unsigned long)STACKMAX);
|
||||||
sstack = xrealloc(sstack, STACKMAX,
|
sstack = xrealloc(sstack, STACKMAX,
|
||||||
|
@ -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 $ */
|
/* $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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -165,7 +167,7 @@ initspaces(void)
|
|||||||
strspace = xalloc(strsize+1, NULL);
|
strspace = xalloc(strsize+1, NULL);
|
||||||
ep = strspace;
|
ep = strspace;
|
||||||
endest = strspace+strsize;
|
endest = strspace+strsize;
|
||||||
buf = (unsigned char *)xalloc(bufsize, NULL);
|
buf = xalloc(bufsize, NULL);
|
||||||
bufbase = buf;
|
bufbase = buf;
|
||||||
bp = buf;
|
bp = buf;
|
||||||
endpbb = buf + bufsize;
|
endpbb = buf + bufsize;
|
||||||
@ -239,7 +241,7 @@ getdiv(int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
onintr(__unused int signo)
|
onintr(int signo __unused)
|
||||||
{
|
{
|
||||||
#define intrmessage "m4: interrupted.\n"
|
#define intrmessage "m4: interrupted.\n"
|
||||||
write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
|
write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
|
||||||
@ -263,7 +265,7 @@ killdiv(void)
|
|||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
void
|
void
|
||||||
m4errx(int evaluation, const char *fmt, ...)
|
m4errx(int eval, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: ", __progname);
|
fprintf(stderr, "%s: ", __progname);
|
||||||
fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE);
|
fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE);
|
||||||
@ -275,7 +277,7 @@ m4errx(int evaluation, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
exit(evaluation);
|
exit(eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -285,7 +287,7 @@ resizedivs(int n)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
outfile = (FILE **)xrealloc(outfile, sizeof(FILE *) * n,
|
outfile = xreallocarray(outfile, n, sizeof(FILE *),
|
||||||
"too many diverts %d", n);
|
"too many diverts %d", n);
|
||||||
for (i = maxout; i < n; i++)
|
for (i = maxout; i < n; i++)
|
||||||
outfile[i] = NULL;
|
outfile[i] = NULL;
|
||||||
@ -311,6 +313,25 @@ xalloc(size_t n, const char *fmt, ...)
|
|||||||
return p;
|
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 *
|
void *
|
||||||
xrealloc(void *old, size_t n, const char *fmt, ...)
|
xrealloc(void *old, size_t n, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -331,6 +352,43 @@ xrealloc(void *old, size_t n, const char *fmt, ...)
|
|||||||
return p;
|
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 *
|
char *
|
||||||
xstrdup(const char *s)
|
xstrdup(const char *s)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user