- add hash table support.
- make use of __UNCONST() instead of LINTED.
This commit is contained in:
parent
ef820af6db
commit
29be49b448
@ -1,9 +1,9 @@
|
||||
# $NetBSD: Makefile,v 1.3 2004/01/18 08:40:40 yamt Exp $
|
||||
# $NetBSD: Makefile,v 1.4 2004/09/23 16:44:26 tshiozak Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIB= intl
|
||||
SRCS= gettext.c textdomain.c gettext_iconv.c gettext_dummy.c
|
||||
SRCS= gettext.c textdomain.c gettext_iconv.c gettext_dummy.c strhash.c
|
||||
INCS= libintl.h
|
||||
INCSDIR=/usr/include
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: gettext.c,v 1.18 2004/01/18 08:40:40 yamt Exp $ */
|
||||
/* $NetBSD: gettext.c,v 1.19 2004/09/23 16:44:26 tshiozak Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2001 Citrus Project,
|
||||
@ -29,13 +29,14 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: gettext.c,v 1.18 2004/01/18 08:40:40 yamt Exp $");
|
||||
__RCSID("$NetBSD: gettext.c,v 1.19 2004/09/23 16:44:26 tshiozak Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -189,25 +190,25 @@ fail:
|
||||
if (t) {
|
||||
if (c) {
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s.%s@%s",
|
||||
l, t, c, m);
|
||||
l, t, c, m);
|
||||
strlcat(result, tmp, sizeof(result));
|
||||
strlcat(result, ":", sizeof(result));
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s@%s", l, t, m);
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s@%s", l, t, m);
|
||||
strlcat(result, tmp, sizeof(result));
|
||||
strlcat(result, ":", sizeof(result));
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%s@%s", l, m);
|
||||
snprintf(tmp, sizeof(tmp), "%s@%s", l, m);
|
||||
strlcat(result, tmp, sizeof(result));
|
||||
strlcat(result, ":", sizeof(result));
|
||||
}
|
||||
if (t) {
|
||||
if (c) {
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s.%s", l, t, c);
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s.%s", l, t, c);
|
||||
strlcat(result, tmp, sizeof(result));
|
||||
strlcat(result, ":", sizeof(result));
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s", l, t);
|
||||
snprintf(tmp, sizeof(tmp), "%s_%s", l, t);
|
||||
strlcat(result, tmp, sizeof(result));
|
||||
strlcat(result, ":", sizeof(result));
|
||||
}
|
||||
@ -309,6 +310,7 @@ mapit(path, db)
|
||||
char *base;
|
||||
u_int32_t magic, revision;
|
||||
struct moentry *otable, *ttable;
|
||||
const u_int32_t *htable;
|
||||
struct moentry_h *p;
|
||||
struct mo *mo;
|
||||
size_t l;
|
||||
@ -338,8 +340,18 @@ mapit(path, db)
|
||||
close(fd);
|
||||
goto fail;
|
||||
}
|
||||
if (read(fd, &revision, sizeof(revision)) != sizeof(revision) ||
|
||||
flip(revision, magic) != MO_REVISION) {
|
||||
if (read(fd, &revision, sizeof(revision)) != sizeof(revision)) {
|
||||
close(fd);
|
||||
goto fail;
|
||||
}
|
||||
switch (flip(revision, magic)) {
|
||||
case MO_MAKE_REV(0, 0):
|
||||
#if 0
|
||||
case MO_MAKE_REV(0, 1):
|
||||
case MO_MAKE_REV(1, 1):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
close(fd);
|
||||
goto fail;
|
||||
}
|
||||
@ -359,9 +371,12 @@ mapit(path, db)
|
||||
mohandle->mo.mo_magic = mo->mo_magic;
|
||||
mohandle->mo.mo_revision = flip(mo->mo_revision, magic);
|
||||
mohandle->mo.mo_nstring = flip(mo->mo_nstring, magic);
|
||||
mohandle->mo.mo_hsize = flip(mo->mo_hsize, magic);
|
||||
|
||||
/* validate otable/ttable */
|
||||
/* LINTED: ignore the alignment problem. */
|
||||
otable = (struct moentry *)(base + flip(mo->mo_otable, magic));
|
||||
/* LINTED: ignore the alignment problem. */
|
||||
ttable = (struct moentry *)(base + flip(mo->mo_ttable, magic));
|
||||
if (!validate(otable, mohandle) ||
|
||||
!validate(&otable[mohandle->mo.mo_nstring], mohandle)) {
|
||||
@ -408,7 +423,26 @@ mapit(path, db)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate htable, and convert it to the host order. */
|
||||
if (mohandle->mo.mo_hsize > 2) {
|
||||
l = sizeof(u_int32_t) * mohandle->mo.mo_hsize;
|
||||
mohandle->mo.mo_htable = (u_int32_t *)malloc(l);
|
||||
if (!mohandle->mo.mo_htable) {
|
||||
unmapit(db);
|
||||
goto fail;
|
||||
}
|
||||
/* LINTED: ignore the alignment problem. */
|
||||
htable = (const u_int32_t *)(base+flip(mo->mo_hoffset, magic));
|
||||
for (i=0; i < mohandle->mo.mo_hsize; i++) {
|
||||
mohandle->mo.mo_htable[i] = flip(htable[i], magic);
|
||||
if (mohandle->mo.mo_htable[i] >=
|
||||
mohandle->mo.mo_nstring+1) {
|
||||
/* illegal string number. */
|
||||
unmapit(db);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* grab MIME-header and charset field */
|
||||
mohandle->mo.mo_header = lookup("", db);
|
||||
if (mohandle->mo.mo_header)
|
||||
@ -454,22 +488,63 @@ unmapit(db)
|
||||
free(mohandle->mo.mo_ttable);
|
||||
if (mohandle->mo.mo_charset)
|
||||
free(mohandle->mo.mo_charset);
|
||||
if (mohandle->mo.mo_htable)
|
||||
free(mohandle->mo.mo_htable);
|
||||
memset(&mohandle->mo, 0, sizeof(mohandle->mo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate the step value if the hash value is conflicted.
|
||||
*/
|
||||
static __inline u_int32_t
|
||||
calc_collision_step(u_int32_t hashval, u_int32_t hashsize)
|
||||
{
|
||||
_DIAGASSERT(hashsize>2);
|
||||
return (hashval % (hashsize - 2)) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate the next index while conflicting.
|
||||
*/
|
||||
static __inline u_int32_t
|
||||
calc_next_index(u_int32_t curidx, u_int32_t hashsize, u_int32_t step)
|
||||
{
|
||||
return curidx+step - (curidx >= hashsize-step ? hashsize : 0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static const char *
|
||||
lookup_hash(msgid, db)
|
||||
const char *msgid;
|
||||
struct domainbinding *db;
|
||||
{
|
||||
struct mohandle *mohandle = &db->mohandle;
|
||||
u_int32_t idx, hashval, step, strno;
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* XXX should try a hashed lookup here, but to do so, we need to
|
||||
* look inside the GPL'ed *.c and re-implement...
|
||||
*/
|
||||
return NULL;
|
||||
if (mohandle->mo.mo_hsize <= 2 || mohandle->mo.mo_htable == NULL)
|
||||
return NULL;
|
||||
|
||||
hashval = __intl_string_hash(msgid);
|
||||
step = calc_collision_step(hashval, mohandle->mo.mo_hsize);
|
||||
idx = hashval % mohandle->mo.mo_hsize;
|
||||
len = strlen(msgid);
|
||||
while (/*CONSTCOND*/1) {
|
||||
strno = mohandle->mo.mo_htable[idx];
|
||||
if (strno == 0) {
|
||||
/* unexpected miss */
|
||||
return NULL;
|
||||
}
|
||||
strno--;
|
||||
if (len <= mohandle->mo.mo_otable[strno].len &&
|
||||
!strcmp(msgid, mohandle->mo.mo_otable[strno].off)) {
|
||||
/* hit */
|
||||
return mohandle->mo.mo_ttable[strno].off;
|
||||
}
|
||||
idx = calc_next_index(idx, mohandle->mo.mo_hsize, step);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
static const char *
|
||||
@ -576,7 +651,7 @@ dcngettext(domainname, msgid1, msgid2, n, category)
|
||||
lpath = get_lang_env(cname);
|
||||
if (!lpath)
|
||||
goto fail;
|
||||
|
||||
|
||||
for (db = __bindings; db; db = db->next)
|
||||
if (strcmp(db->domainname, domainname) == 0)
|
||||
break;
|
||||
@ -650,6 +725,5 @@ found:
|
||||
}
|
||||
|
||||
fail:
|
||||
/* LINTED const cast */
|
||||
return (char *)msgid;
|
||||
return (char *)__UNCONST(msgid);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: libintl_local.h,v 1.7 2004/01/18 08:40:40 yamt Exp $ */
|
||||
/* $NetBSD: libintl_local.h,v 1.8 2004/09/23 16:44:26 tshiozak Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2001 Citrus Project,
|
||||
@ -30,7 +30,9 @@
|
||||
|
||||
#define MO_MAGIC 0x950412de
|
||||
#define MO_MAGIC_SWAPPED 0xde120495
|
||||
#define MO_REVISION 0
|
||||
#define MO_GET_REV_MAJOR(r) (((r) >> 16) & 0xFFFF)
|
||||
#define MO_GET_REV_MINOR(r) ((r) & 0xFFFF)
|
||||
#define MO_MAKE_REV(maj, min) (((maj) << 16) | (min))
|
||||
|
||||
#define GETTEXT_MMAP_MAX (1024 * 1024) /*XXX*/
|
||||
|
||||
@ -45,6 +47,13 @@ struct mo {
|
||||
u_int32_t mo_ttable; /* T: translated text table offset */
|
||||
u_int32_t mo_hsize; /* S: size of hashing table */
|
||||
u_int32_t mo_hoffset; /* H: offset of hashing table */
|
||||
/* rev 0.1 / 1.1 */
|
||||
/* system dependent string support */
|
||||
u_int32_t mo_sysdep_nsegs; /* number of sysdep segments */
|
||||
u_int32_t mo_sysdep_segoff; /* offset of sysdep segment table */
|
||||
u_int32_t mo_sysdep_nstring; /* number of strings */
|
||||
u_int32_t mo_sysdep_otable; /* offset of original text table */
|
||||
u_int32_t mo_sysdep_ttable; /* offset of translated text table */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct moentry {
|
||||
@ -52,6 +61,12 @@ struct moentry {
|
||||
u_int32_t off; /* offset of \0-terminated string */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct mosysdepstr
|
||||
{
|
||||
u_int32_t off; /* offset of seed text */
|
||||
struct moentry segs[1]; /* text segments */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* libintl internal data format */
|
||||
struct moentry_h {
|
||||
size_t len; /* strlen(str), so region will be len + 1 */
|
||||
@ -66,6 +81,8 @@ struct mo_h {
|
||||
struct moentry_h *mo_ttable; /* T: translated text table offset */
|
||||
const char *mo_header;
|
||||
char *mo_charset;
|
||||
u_int32_t mo_hsize; /* S: size of hashing table */
|
||||
u_int32_t *mo_htable; /* H: hashing table */
|
||||
};
|
||||
|
||||
struct mohandle {
|
||||
@ -85,4 +102,7 @@ struct domainbinding {
|
||||
extern struct domainbinding *__bindings;
|
||||
extern char __current_domainname[PATH_MAX];
|
||||
|
||||
__BEGIN_DECLS
|
||||
const char *__gettext_iconv __P((const char *, struct domainbinding *));
|
||||
u_int32_t __intl_string_hash __P((const char *));
|
||||
__END_DECLS
|
||||
|
63
lib/libintl/strhash.c
Normal file
63
lib/libintl/strhash.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* $NetBSD: strhash.c,v 1.1 2004/09/23 16:44:26 tshiozak Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c)2003, 2004 Citrus Project,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: strhash.c,v 1.1 2004/09/23 16:44:26 tshiozak Exp $");
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libintl_local.h"
|
||||
|
||||
/*
|
||||
* string hash function by P.J.Weinberger.
|
||||
* this implementation is derived from src/lib/libc/citrus/citrus_db_hash.c.
|
||||
*/
|
||||
u_int32_t
|
||||
/*ARGSUSED*/
|
||||
__intl_string_hash(const char *str)
|
||||
{
|
||||
const u_int8_t *p;
|
||||
u_int32_t hash = 0, tmp;
|
||||
|
||||
for (p = (const u_int8_t *)str; *p; p++) {
|
||||
hash <<= 4;
|
||||
hash += *p;
|
||||
tmp = hash & 0xF0000000;
|
||||
if (tmp != 0) {
|
||||
hash ^= tmp;
|
||||
hash ^= tmp >> 24;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: textdomain.c,v 1.10 2004/01/18 08:40:40 yamt Exp $ */
|
||||
/* $NetBSD: textdomain.c,v 1.11 2004/09/23 16:44:26 tshiozak Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2001 Citrus Project,
|
||||
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: textdomain.c,v 1.10 2004/01/18 08:40:40 yamt Exp $");
|
||||
__RCSID("$NetBSD: textdomain.c,v 1.11 2004/09/23 16:44:26 tshiozak Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
@ -98,7 +98,7 @@ bindtextdomain(domainname, dirname)
|
||||
if (p)
|
||||
return (p->path);
|
||||
else
|
||||
return _PATH_TEXTDOMAIN;
|
||||
return (char *)__UNCONST(_PATH_TEXTDOMAIN);
|
||||
}
|
||||
|
||||
strlcpy(p->path, dirname, sizeof(p->path));
|
||||
|
Loading…
Reference in New Issue
Block a user