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:
Baptiste Daroussin 2014-07-27 22:54:13 +00:00
parent c448f58f45
commit 88497f0c68
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=269162
23 changed files with 540 additions and 625 deletions

View File

@ -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

View File

@ -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];
}

View File

@ -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);

View File

@ -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);
}

330
usr.bin/m4/lib/ohash.c Normal file
View 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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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.

View File

@ -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,

View File

@ -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;
@ -311,6 +313,25 @@ xalloc(size_t n, const char *fmt, ...)
return p;
}
void *
xcalloc(size_t n, size_t s, const char *fmt, ...)
{
void *p = calloc(n, s);
if (p == NULL) {
if (fmt == NULL)
err(1, "calloc");
else {
va_list va;
va_start(va, fmt);
verr(1, fmt, va);
va_end(va);
}
}
return p;
}
void *
xrealloc(void *old, size_t n, const char *fmt, ...)
{
@ -331,6 +352,43 @@ xrealloc(void *old, size_t n, const char *fmt, ...)
return p;
}
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
static void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}
void *
xreallocarray(void *old, size_t s1, size_t s2, const char *fmt, ...)
{
void *p = reallocarray(old, s1, s2);
if (p == NULL) {
free(old);
if (fmt == NULL)
err(1, "reallocarray");
else {
va_list va;
va_start(va, fmt);
verr(1, fmt, va);
va_end(va);
}
}
return p;
}
char *
xstrdup(const char *s)
{