diff --git a/acconfig.h b/acconfig.h index 92eac2d..bfef1cb 100644 --- a/acconfig.h +++ b/acconfig.h @@ -97,5 +97,8 @@ /* Define this if fnmatch is prototyped in fnmatch.h */ #undef HAVE_FNMATCH_PROTO +/* Define this to something appropriate for declaring 0 length arrays */ +#undef ZERO_LENGTH_ARRAY + @BOTTOM@ #endif // __config_h_ diff --git a/configure.in b/configure.in index c2f078c..57421c5 100644 --- a/configure.in +++ b/configure.in @@ -152,6 +152,13 @@ AC_TRY_COMPILE( AC_MSG_RESULT(no) ) +AC_MSG_CHECKING(for zero length array syntax) +AC_TRY_COMPILE( + [], + [int foo[0];], + AC_DEFINE(ZERO_LENGTH_ARRAY,0) AC_MSG_RESULT([0]), + AC_DEFINE(ZERO_LENGTH_ARRAY,) AC_MSG_RESULT([]) +) dnl ================================================================== dnl Checks for library functions. diff --git a/include/cvar.h b/include/cvar.h index ff7d392..08b8fed 100644 --- a/include/cvar.h +++ b/include/cvar.h @@ -118,6 +118,7 @@ void Cvar_WriteVariables (QFile *f); // Returns a pointer to the Cvar, NULL if not found cvar_t *Cvar_FindVar (char *var_name); +void Cvar_Init_Hash (void); void Cvar_Init(); void Cvar_Shutdown(); diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 0000000..2450501 --- /dev/null +++ b/include/hash.h @@ -0,0 +1,54 @@ +/* + hash.h + + hash tables + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Marcus Sundberg + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __hash_h +#define __hash_h + +#include // should be sys/types.h, but bc is stupid + +typedef struct hashlink_s { + struct hashlink_s *next; + struct hashlink_s **prev; + void *data; +} hashlink_t; + +typedef struct hashtab_s { + size_t tab_size; + char *(*get_key)(void*); + void (*free_ele)(void*); + hashlink_t *tab[ZERO_LENGTH_ARRAY]; +} hashtab_t; + +hashtab_t *Hash_NewTable (int tsize, char *(*gk)(void*), void (*f)(void*)); +void Hash_DelTable (hashtab_t *tab); +int Hash_Add (hashtab_t *tab, void *ele); +void *Hash_Find (hashtab_t *tab, const char *key); +int Hash_Del (hashtab_t *tab, const char *key); + +#endif // __hash_h diff --git a/source/Makefile.am b/source/Makefile.am index b9ba4b0..bd51df3 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -45,7 +45,8 @@ noinst_LIBRARIES= libqfcd.a libqfjs.a libqfsnd.a libqfsys_cl.a libqfsys_sv.a if ASM_ARCH math_ASM = math.S sys_x86.S endif -common_SOURCES= buildnum.c checksum.c cmd.c com.c crc.c cvar.c info.c link.c \ +common_SOURCES= buildnum.c checksum.c cmd.c com.c crc.c cvar.c hash.c \ + info.c link.c \ locs.c mathlib.c mdfour.c model.c model_brush.c msg.c \ net_chan.c net_com.c net_udp.c pmove.c pmovetst.c qargs.c \ qendian.c quakefs.c quakeio.c sizebuf.c va.c zone.c \ diff --git a/source/cl_main.c b/source/cl_main.c index 0d3d248..3b9d96c 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -1641,6 +1641,7 @@ Host_Init (void) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", host_parms.memsize / (float) 0x100000); + Cvar_Init_Hash (); Memory_Init (host_parms.membase, host_parms.memsize); Cvar_Init (); Sys_Init_Cvars (); diff --git a/source/cvar.c b/source/cvar.c index c42e64f..9e0f84f 100644 --- a/source/cvar.c +++ b/source/cvar.c @@ -45,6 +45,7 @@ #include "commdef.h" #include "cvar.h" #include "console.h" +#include "hash.h" #include "qargs.h" #include "cmd.h" #include "commdef.h" @@ -53,6 +54,8 @@ cvar_t *cvar_vars; char *cvar_null_string = ""; extern cvar_t *developer; cvar_alias_t *calias_vars; +hashtab_t *cvar_hash; +hashtab_t *calias_hash; /* ============ @@ -62,13 +65,7 @@ Cvar_FindVar cvar_t * Cvar_FindVar (char *var_name) { - cvar_t *var; - - for (var = cvar_vars; var; var = var->next) - if (!strcmp (var_name, var->name)) - return var; - - return NULL; + return (cvar_t*)Hash_Find (cvar_hash, var_name); } cvar_t * @@ -76,10 +73,10 @@ Cvar_FindAlias (char *alias_name) { cvar_alias_t *alias; - for (alias = calias_vars; alias; alias = alias->next) - if (!strcmp (alias_name, alias->name)) - return alias->cvar; - return NULL; + alias = (cvar_alias_t*)Hash_Find (calias_hash, alias_name); + if (alias) + return alias->cvar; + return 0; } void @@ -104,6 +101,7 @@ Cvar_Alias_Get (char *name, cvar_t *cvar) calias_vars = alias; alias->name = strdup (name); alias->cvar = cvar; + Hash_Add (calias_hash, alias); } } @@ -206,8 +204,7 @@ Cvar_Set (cvar_t *var, char *value) free (var->string); // free the old value string - var->string = malloc (strlen (value) + 1); - strcpy (var->string, value); + var->string = strdup (value); var->value = atof (var->string); var->int_val = atoi (var->string); @@ -228,8 +225,7 @@ Cvar_SetROM (cvar_t *var, char *value) free (var->string); // free the old value string - var->string = malloc (strlen (value) + 1); - strcpy (var->string, value); + var->string = strdup (value); var->value = atof (var->string); var->int_val = atoi (var->string); @@ -430,6 +426,44 @@ Cvar_CvarList_f (void) Con_Printf ("------------\n%d variables\n", i); } +static void +cvar_free (void *c) +{ + cvar_t *cvar = (cvar_t*)c; + free (cvar->name); + free (cvar->string); + free (cvar); +} + +static char * +cvar_get_key (void *c) +{ + cvar_t *cvar = (cvar_t*)c; + return cvar->name; +} + +static void +calias_free (void *c) +{ + cvar_alias_t *calias = (cvar_alias_t*)c; + free (calias->name); + free (calias); +} + +static char * +calias_get_key (void *c) +{ + cvar_alias_t *calias = (cvar_alias_t*)c; + return calias->name; +} + +void +Cvar_Init_Hash (void) +{ + cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free); + calias_hash = Hash_NewTable (1021, calias_get_key, calias_free); +} + void Cvar_Init (void) { @@ -486,12 +520,12 @@ Cvar_Get (char *name, char *string, int cvarflags, char *description) v->next = cvar_vars; cvar_vars = v; v->name = strdup (name); - v->string = malloc (strlen (string) + 1); - strcpy (v->string, string); + v->string = strdup (string); v->flags = cvarflags; v->description = description; v->value = atof (v->string); v->int_val = atoi (v->string); + Hash_Add (cvar_hash, v); } else { // Cvar does exist, so we update the flags and return. v->flags &= ~CVAR_USER_CREATED; diff --git a/source/hash.c b/source/hash.c new file mode 100644 index 0000000..8cdd9bc --- /dev/null +++ b/source/hash.c @@ -0,0 +1,129 @@ +/* + hash.h + + hash tables + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Marcus Sundberg + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "compat.h" +#include "hash.h" + +static unsigned long +hash (const char *str) +{ + unsigned long h = 0; + while (*str) { + h = (h << 4) + (unsigned char)*str++; + if (h&0xf0000000) + h = (h ^ (h >> 24)) & 0xfffffff; + } + return h; +} + +hashtab_t * +Hash_NewTable (int tsize, char *(*gk)(void*), void (*f)(void*)) +{ + hashtab_t *tab = calloc (1, (size_t)&((hashtab_t*)0)->tab[tsize]); + if (!tab) + return 0; + tab->tab_size = tsize; + tab->get_key = gk; + tab->free_ele = f; + return tab; +} + +void +Hash_DelTable (hashtab_t *tab) +{ + int i; + + for (i = 0; i < tab->tab_size; i++) { + while (tab->tab[i]) { + hashlink_t *t = tab->tab[i]->next; + if (tab->free_ele) + tab->free_ele (&tab->tab[i]->data); + free (tab->tab[i]); + tab->tab[i] = t; + } + } + free (tab); +} + +int +Hash_Add (hashtab_t *tab, void *ele) +{ + unsigned long h = hash (tab->get_key(ele)); + size_t ind = h % tab->tab_size; + hashlink_t *lnk = malloc (sizeof (hashlink_t)); + + if (!lnk) + return -1; + if (tab->tab[ind]) + tab->tab[ind]->prev = &lnk->next; + lnk->next = tab->tab[ind]; + lnk->prev = &tab->tab[ind]; + lnk->data = ele; + tab->tab[ind] = lnk; + return 0; +} + +void * +Hash_Find (hashtab_t *tab, const char *key) +{ + unsigned long h = hash (key); + size_t ind = h % tab->tab_size; + hashlink_t *lnk = tab->tab[ind]; + + while (lnk) { + if (strequal (key, tab->get_key (lnk->data))) + return lnk->data; + lnk = lnk->next; + } + return 0; +} + +int +Hash_Del (hashtab_t *tab, const char *key) +{ + unsigned long h = hash (key); + size_t ind = h % tab->tab_size; + hashlink_t *lnk = tab->tab[ind]; + + while (lnk) { + if (strequal (key, tab->get_key (lnk->data))) { + if (lnk->next) + lnk->next->prev = lnk->prev; + *lnk->prev = lnk->next; + free (lnk); + return 0; + } + lnk = lnk->next; + } + return -1; +} diff --git a/source/sv_main.c b/source/sv_main.c index 931f197..53671b7 100644 --- a/source/sv_main.c +++ b/source/sv_main.c @@ -1867,6 +1867,7 @@ SV_Init (void) SV_Error ("Only %4.1f megs of memory reported, can't execute game", host_parms.memsize / (float) 0x100000); + Cvar_Init_Hash (); Memory_Init (host_parms.membase, host_parms.memsize); Cvar_Init (); Sys_Init_Cvars ();