2
0
Эх сурвалжийг харах

Fix import/export rules for #import as .

Ginger Bill 8 жил өмнө
parent
commit
fb45287e9e
5 өөрчлөгдсөн 164 нэмэгдсэн , 121 устгасан
  1. 1 4
      LICENSE
  2. 2 2
      build.bat
  3. 29 34
      code/demo.odin
  4. 2 3
      src/gb/gb.h
  5. 130 78
      src/map.c

+ 1 - 4
LICENSE

@@ -1,7 +1,4 @@
-BSD 2-Clause License
-
-Copyright (c) 2016, Ginger Bill
-All rights reserved.
+Copyright (c) 2016 Ginger Bill. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

+ 2 - 2
build.bat

@@ -25,8 +25,8 @@ set compiler_warnings= ^
 
 set compiler_includes=
 set libs= ^
-	kernel32.lib ^
-	"src\dyncall\lib\*.lib"
+	kernel32.lib
+	rem "src\dyncall\lib\*.lib"
 
 set linker_flags= -incremental:no -opt:ref -subsystem:console
 

+ 29 - 34
code/demo.odin

@@ -1,5 +1,4 @@
 #import "fmt.odin"
-#import "game.odin"
 
 variadic :: proc(args: ..any) {
 	for i := 0; i < args.count; i++ {
@@ -15,37 +14,33 @@ variadic :: proc(args: ..any) {
 main :: proc() {
 	fmt.println("Hellope, everybody!")
 
-
-
-	variadic(1 as u128,
-	         1 as i128,
-	         )
-
-	x: i128 = 321312321
-	y: i128 = 123123123
-	z: i128
-	x *= x; x *= x
-	y *= y; y *= y
-	fmt.println("x =", x)
-	fmt.println("y =", y)
-	z = x + y; fmt.println("x + y", z)
-	z = x - y; fmt.println("x - y", z)
-	z = x * y; fmt.println("x * y", z)
-	z = x / y; fmt.println("x / y", z)
-	z = x % y; fmt.println("x % y", z)
-	z = x & y; fmt.println("x & y", z)
-	z = x ~ y; fmt.println("x ~ y", z)
-	z = x | y; fmt.println("x | y", z)
-	z = x &~ y; fmt.println("x &~ y", z)
-
-	z = -x
-	z = ~x
-
-	b: bool
-	b = x == y; fmt.println("x == y", b)
-	b = x != y; fmt.println("x != y", b)
-	b = x <  y; fmt.println("x <  y", b)
-	b = x <= y; fmt.println("x <= y", b)
-	b = x >  y; fmt.println("x >  y", b)
-	b = x >= y; fmt.println("x >= y", b)
+	variadic(1 as u128, 1 as i128)
+
+	// x: i128 = 321312321
+	// y: i128 = 123123123
+	// z: i128
+	// x *= x; x *= x
+	// y *= y; y *= y
+	// fmt.println("x =", x)
+	// fmt.println("y =", y)
+	// z = x + y; fmt.println("x + y", z)
+	// z = x - y; fmt.println("x - y", z)
+	// z = x * y; fmt.println("x * y", z)
+	// z = x / y; fmt.println("x / y", z)
+	// z = x % y; fmt.println("x % y", z)
+	// z = x & y; fmt.println("x & y", z)
+	// z = x ~ y; fmt.println("x ~ y", z)
+	// z = x | y; fmt.println("x | y", z)
+	// z = x &~ y; fmt.println("x &~ y", z)
+
+	// z = -x
+	// z = ~x
+
+	// b: bool
+	// b = x == y; fmt.println("x == y", b)
+	// b = x != y; fmt.println("x != y", b)
+	// b = x <  y; fmt.println("x <  y", b)
+	// b = x <= y; fmt.println("x <= y", b)
+	// b = x >  y; fmt.println("x >  y", b)
+	// b = x >= y; fmt.println("x >= y", b)
 }

+ 2 - 3
src/gb/gb.h

@@ -412,21 +412,20 @@ typedef i32 Rune; // NOTE(bill): Unicode codepoint
 #define GB_RUNE_EOF     cast(Rune)(-1)
 
 
-// NOTE(bill): I think C99 and C++ `bool` is stupid for numerous reasons but there are too many
-// to write in this small comment.
 typedef i8  b8;
 typedef i16 b16;
 typedef i32 b32; // NOTE(bill): Prefer this!!!
 
 // NOTE(bill): Get true and false
 #if !defined(__cplusplus)
-	#if (defined(_MSC_VER) && _MSC_VER <= 1800) || !defined(__STDC_VERSION__)
+	#if (defined(_MSC_VER) && _MSC_VER <= 1800) || (!defined(_MSC_VER) && !defined(__STDC_VERSION__))
 		#ifndef true
 		#define true  (0 == 0)
 		#endif
 		#ifndef false
 		#define false (0 != 0)
 		#endif
+		typedef b8 bool;
 	#else
 		#include <stdbool.h>
 	#endif

+ 130 - 78
src/map.c

@@ -2,26 +2,79 @@
 	Example of usage:
 
 	#define MAP_TYPE String
-	#define MAP_FUNC map_string_
+	#define MAP_PROC map_string_
 	#define MAP_NAME MapString
 	#include "map.c"
 */
 
-#ifndef MAP_FIND_RESULT
-#define MAP_FIND_RESULT
-// NOTE(bill): This is the same for every `Map`
+#ifndef MAP_UTIL_STUFF
+#define MAP_UTIL_STUFF
+// NOTE(bill): This util stuff is the same for every `Map`
 typedef struct MapFindResult {
 	isize hash_index;
 	isize entry_prev;
 	isize entry_index;
 } MapFindResult;
+
+typedef enum HashKeyKind {
+	HashKey_Default,
+	HashKey_String,
+	HashKey_Pointer,
+} HashKeyKind;
+
+typedef struct HashKey {
+	HashKeyKind kind;
+	u64         key;
+	union {
+		String string; // if String, s.len > 0
+		void * ptr;
+	};
+} HashKey;
+
+gb_inline HashKey hashing_proc(void const *data, isize len) {
+	HashKey h = {HashKey_Default};
+	h.kind = HashKey_Default;
+	// h.key = gb_murmur64(data, len);
+	h.key = gb_fnv64a(data, len);
+	return h;
+}
+
+gb_inline HashKey hash_string(String s) {
+	HashKey h = hashing_proc(s.text, s.len);
+	h.kind = HashKey_String;
+	h.string = s;
+	return h;
+}
+
+gb_inline HashKey hash_pointer(void *ptr) {
+	HashKey h = {HashKey_Default};
+	h.key = cast(u64)cast(uintptr)ptr;
+	h.ptr = ptr;
+	h.kind = HashKey_Default;
+	return h;
+}
+
+bool hash_key_equal(HashKey a, HashKey b) {
+	if (a.key == b.key) {
+		// NOTE(bill): If two string's hashes collide, compare the strings themselves
+		if (a.kind == HashKey_String) {
+			if (b.kind == HashKey_String) {
+				return str_eq(a.string, b.string);
+			}
+			return false;
+		}
+		return true;
+	}
+	return false;
+}
 #endif
 
-#define _J2(a,b) GB_JOIN2(a,b)
+#define _J2_IND(a, b) a##b
+#define _J2(a, b) _J2_IND(a, b)
 
 /*
 MAP_TYPE - Entry type
-MAP_FUNC - Function prefix (e.g. entity_map_)
+MAP_PROC - Function prefix (e.g. entity_map_)
 MAP_NAME - Name of Map (e.g. EntityMap)
 */
 #define MAP_ENTRY _J2(MAP_NAME,Entry)
@@ -37,45 +90,44 @@ typedef struct MAP_NAME {
 	Array(MAP_ENTRY) entries;
 } MAP_NAME;
 
-void      _J2(MAP_FUNC,init)             (MAP_NAME *h, gbAllocator a);
-void      _J2(MAP_FUNC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity);
-void      _J2(MAP_FUNC,destroy)          (MAP_NAME *h);
-MAP_TYPE *_J2(MAP_FUNC,get)              (MAP_NAME *h, HashKey key);
-void      _J2(MAP_FUNC,set)              (MAP_NAME *h, HashKey key, MAP_TYPE value);
-void      _J2(MAP_FUNC,remove)           (MAP_NAME *h, HashKey key);
-void      _J2(MAP_FUNC,clear)            (MAP_NAME *h);
-void      _J2(MAP_FUNC,grow)             (MAP_NAME *h);
-void      _J2(MAP_FUNC,rehash)           (MAP_NAME *h, isize new_count);
+void      _J2(MAP_PROC,init)             (MAP_NAME *h, gbAllocator a);
+void      _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity);
+void      _J2(MAP_PROC,destroy)          (MAP_NAME *h);
+MAP_TYPE *_J2(MAP_PROC,get)              (MAP_NAME *h, HashKey key);
+void      _J2(MAP_PROC,set)              (MAP_NAME *h, HashKey key, MAP_TYPE value);
+void      _J2(MAP_PROC,remove)           (MAP_NAME *h, HashKey key);
+void      _J2(MAP_PROC,clear)            (MAP_NAME *h);
+void      _J2(MAP_PROC,grow)             (MAP_NAME *h);
+void      _J2(MAP_PROC,rehash)           (MAP_NAME *h, isize new_count);
 
-#if 1
-MAP_ENTRY *_J2(MAP_FUNC,multi_find_first)(MAP_NAME *h, HashKey key);
-MAP_ENTRY *_J2(MAP_FUNC,multi_find_next) (MAP_NAME *h, MAP_ENTRY *e);
-
-isize _J2(MAP_FUNC,multi_count)     (MAP_NAME *h, HashKey key);
-void  _J2(MAP_FUNC,multi_get_all)   (MAP_NAME *h, HashKey key, MAP_TYPE *items);
-void  _J2(MAP_FUNC,multi_insert)    (MAP_NAME *h, HashKey key, MAP_TYPE value);
-void  _J2(MAP_FUNC,multi_remove)    (MAP_NAME *h, HashKey key, MAP_ENTRY *e);
-void  _J2(MAP_FUNC,multi_remove_all)(MAP_NAME *h, HashKey key);
-#endif
+// Mutlivalued map procedure
+MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key);
+MAP_ENTRY *_J2(MAP_PROC,multi_find_next) (MAP_NAME *h, MAP_ENTRY *e);
+
+isize _J2(MAP_PROC,multi_count)     (MAP_NAME *h, HashKey key);
+void  _J2(MAP_PROC,multi_get_all)   (MAP_NAME *h, HashKey key, MAP_TYPE *items);
+void  _J2(MAP_PROC,multi_insert)    (MAP_NAME *h, HashKey key, MAP_TYPE value);
+void  _J2(MAP_PROC,multi_remove)    (MAP_NAME *h, HashKey key, MAP_ENTRY *e);
+void  _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key);
 
 
 
-gb_inline void _J2(MAP_FUNC,init)(MAP_NAME *h, gbAllocator a) {
+gb_inline void _J2(MAP_PROC,init)(MAP_NAME *h, gbAllocator a) {
 	array_init(&h->hashes,  a);
 	array_init(&h->entries, a);
 }
 
-gb_inline void _J2(MAP_FUNC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity) {
+gb_inline void _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity) {
 	array_init_reserve(&h->hashes,  a, capacity);
 	array_init_reserve(&h->entries, a, capacity);
 }
 
-gb_inline void _J2(MAP_FUNC,destroy)(MAP_NAME *h) {
+gb_inline void _J2(MAP_PROC,destroy)(MAP_NAME *h) {
 	array_free(&h->entries);
 	array_free(&h->hashes);
 }
 
-gb_internal isize _J2(MAP_FUNC,_add_entry)(MAP_NAME *h, HashKey key) {
+gb_internal isize _J2(MAP_PROC,_add_entry)(MAP_NAME *h, HashKey key) {
 	MAP_ENTRY e = {0};
 	e.key = key;
 	e.next = -1;
@@ -83,7 +135,7 @@ gb_internal isize _J2(MAP_FUNC,_add_entry)(MAP_NAME *h, HashKey key) {
 	return h->entries.count-1;
 }
 
-gb_internal MapFindResult _J2(MAP_FUNC,_find)(MAP_NAME *h, HashKey key) {
+gb_internal MapFindResult _J2(MAP_PROC,_find)(MAP_NAME *h, HashKey key) {
 	MapFindResult fr = {-1, -1, -1};
 	if (h->hashes.count > 0) {
 		fr.hash_index  = key.key % h->hashes.count;
@@ -99,7 +151,7 @@ gb_internal MapFindResult _J2(MAP_FUNC,_find)(MAP_NAME *h, HashKey key) {
 	return fr;
 }
 
-gb_internal MapFindResult _J2(MAP_FUNC,_find_from_entry)(MAP_NAME *h, MAP_ENTRY *e) {
+gb_internal MapFindResult _J2(MAP_PROC,_find_from_entry)(MAP_NAME *h, MAP_ENTRY *e) {
 	MapFindResult fr = {-1, -1, -1};
 	if (h->hashes.count > 0) {
 		fr.hash_index  = e->key.key % h->hashes.count;
@@ -116,19 +168,19 @@ gb_internal MapFindResult _J2(MAP_FUNC,_find_from_entry)(MAP_NAME *h, MAP_ENTRY
 }
 
 
-gb_internal b32 _J2(MAP_FUNC,_full)(MAP_NAME *h) {
+gb_internal b32 _J2(MAP_PROC,_full)(MAP_NAME *h) {
 	return 0.75f * h->hashes.count <= h->entries.count;
 }
 
-gb_inline void _J2(MAP_FUNC,grow)(MAP_NAME *h) {
+gb_inline void _J2(MAP_PROC,grow)(MAP_NAME *h) {
 	isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
-	_J2(MAP_FUNC,rehash)(h, new_count);
+	_J2(MAP_PROC,rehash)(h, new_count);
 }
 
-void _J2(MAP_FUNC,rehash)(MAP_NAME *h, isize new_count) {
+void _J2(MAP_PROC,rehash)(MAP_NAME *h, isize new_count) {
 	isize i, j;
 	MAP_NAME nh = {0};
-	_J2(MAP_FUNC,init)(&nh, h->hashes.allocator);
+	_J2(MAP_PROC,init)(&nh, h->hashes.allocator);
 	array_resize(&nh.hashes, new_count);
 	array_reserve(&nh.entries, h->entries.count);
 	for (i = 0; i < new_count; i++) {
@@ -138,10 +190,10 @@ void _J2(MAP_FUNC,rehash)(MAP_NAME *h, isize new_count) {
 		MAP_ENTRY *e = &h->entries.e[i];
 		MapFindResult fr;
 		if (nh.hashes.count == 0) {
-			_J2(MAP_FUNC,grow)(&nh);
+			_J2(MAP_PROC,grow)(&nh);
 		}
-		fr = _J2(MAP_FUNC,_find)(&nh, e->key);
-		j = _J2(MAP_FUNC,_add_entry)(&nh, e->key);
+		fr = _J2(MAP_PROC,_find)(&nh, e->key);
+		j = _J2(MAP_PROC,_add_entry)(&nh, e->key);
 		if (fr.entry_prev < 0) {
 			nh.hashes.e[fr.hash_index] = j;
 		} else {
@@ -149,32 +201,32 @@ void _J2(MAP_FUNC,rehash)(MAP_NAME *h, isize new_count) {
 		}
 		nh.entries.e[j].next = fr.entry_index;
 		nh.entries.e[j].value = e->value;
-		if (_J2(MAP_FUNC,_full)(&nh)) {
-			_J2(MAP_FUNC,grow)(&nh);
+		if (_J2(MAP_PROC,_full)(&nh)) {
+			_J2(MAP_PROC,grow)(&nh);
 		}
 	}
-	_J2(MAP_FUNC,destroy)(h);
+	_J2(MAP_PROC,destroy)(h);
 	*h = nh;
 }
 
-gb_inline MAP_TYPE *_J2(MAP_FUNC,get)(MAP_NAME *h, HashKey key) {
-	isize index = _J2(MAP_FUNC,_find)(h, key).entry_index;
+gb_inline MAP_TYPE *_J2(MAP_PROC,get)(MAP_NAME *h, HashKey key) {
+	isize index = _J2(MAP_PROC,_find)(h, key).entry_index;
 	if (index >= 0) {
 		return &h->entries.e[index].value;
 	}
 	return NULL;
 }
 
-void _J2(MAP_FUNC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
+void _J2(MAP_PROC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
 	isize index;
 	MapFindResult fr;
 	if (h->hashes.count == 0)
-		_J2(MAP_FUNC,grow)(h);
-	fr = _J2(MAP_FUNC,_find)(h, key);
+		_J2(MAP_PROC,grow)(h);
+	fr = _J2(MAP_PROC,_find)(h, key);
 	if (fr.entry_index >= 0) {
 		index = fr.entry_index;
 	} else {
-		index = _J2(MAP_FUNC,_add_entry)(h, key);
+		index = _J2(MAP_PROC,_add_entry)(h, key);
 		if (fr.entry_prev >= 0) {
 			h->entries.e[fr.entry_prev].next = index;
 		} else {
@@ -183,14 +235,14 @@ void _J2(MAP_FUNC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
 	}
 	h->entries.e[index].value = value;
 
-	if (_J2(MAP_FUNC,_full)(h)) {
-		_J2(MAP_FUNC,grow)(h);
+	if (_J2(MAP_PROC,_full)(h)) {
+		_J2(MAP_PROC,grow)(h);
 	}
 }
 
 
 
-void _J2(MAP_FUNC,_erase)(MAP_NAME *h, MapFindResult fr) {
+void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
 	if (fr.entry_prev < 0) {
 		h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
 	} else {
@@ -201,7 +253,7 @@ void _J2(MAP_FUNC,_erase)(MAP_NAME *h, MapFindResult fr) {
 		return;
 	}
 	h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
-	MapFindResult last = _J2(MAP_FUNC,_find)(h, h->entries.e[fr.entry_index].key);
+	MapFindResult last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
 	if (last.entry_prev >= 0) {
 		h->entries.e[last.entry_prev].next = fr.entry_index;
 	} else {
@@ -209,29 +261,29 @@ void _J2(MAP_FUNC,_erase)(MAP_NAME *h, MapFindResult fr) {
 	}
 }
 
-void _J2(MAP_FUNC,remove)(MAP_NAME *h, HashKey key) {
-	MapFindResult fr = _J2(MAP_FUNC,_find)(h, key);
+void _J2(MAP_PROC,remove)(MAP_NAME *h, HashKey key) {
+	MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
 	if (fr.entry_index >= 0) {
-		_J2(MAP_FUNC,_erase)(h, fr);
+		_J2(MAP_PROC,_erase)(h, fr);
 	}
 }
 
-gb_inline void _J2(MAP_FUNC,clear)(MAP_NAME *h) {
+gb_inline void _J2(MAP_PROC,clear)(MAP_NAME *h) {
 	array_clear(&h->hashes);
 	array_clear(&h->entries);
 }
 
 
 #if 1
-MAP_ENTRY *_J2(MAP_FUNC,multi_find_first)(MAP_NAME *h, HashKey key) {
-	isize i = _J2(MAP_FUNC,_find)(h, key).entry_index;
+MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key) {
+	isize i = _J2(MAP_PROC,_find)(h, key).entry_index;
 	if (i < 0) {
 		return NULL;
 	}
 	return &h->entries.e[i];
 }
 
-MAP_ENTRY *_J2(MAP_FUNC,multi_find_next)(MAP_NAME *h, MAP_ENTRY *e) {
+MAP_ENTRY *_J2(MAP_PROC,multi_find_next)(MAP_NAME *h, MAP_ENTRY *e) {
 	isize i = e->next;
 	while (i >= 0) {
 		if (hash_key_equal(h->entries.e[i].key, e->key)) {
@@ -242,31 +294,31 @@ MAP_ENTRY *_J2(MAP_FUNC,multi_find_next)(MAP_NAME *h, MAP_ENTRY *e) {
 	return NULL;
 }
 
-isize _J2(MAP_FUNC,multi_count)(MAP_NAME *h, HashKey key) {
+isize _J2(MAP_PROC,multi_count)(MAP_NAME *h, HashKey key) {
 	isize count = 0;
-	MAP_ENTRY *e = _J2(MAP_FUNC,multi_find_first)(h, key);
+	MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
 	while (e != NULL) {
 		count++;
-		e = _J2(MAP_FUNC,multi_find_next)(h, e);
+		e = _J2(MAP_PROC,multi_find_next)(h, e);
 	}
 	return count;
 }
 
-void _J2(MAP_FUNC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
+void _J2(MAP_PROC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
 	isize i = 0;
-	MAP_ENTRY *e = _J2(MAP_FUNC,multi_find_first)(h, key);
+	MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
 	while (e != NULL) {
 		items[i++] = e->value;
-		e = _J2(MAP_FUNC,multi_find_next)(h, e);
+		e = _J2(MAP_PROC,multi_find_next)(h, e);
 	}
 }
 
-void _J2(MAP_FUNC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
+void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
 	if (h->hashes.count == 0) {
-		_J2(MAP_FUNC,grow)(h);
+		_J2(MAP_PROC,grow)(h);
 	}
-	MapFindResult fr = _J2(MAP_FUNC,_find)(h, key);
-	isize i = _J2(MAP_FUNC,_add_entry)(h, key);
+	MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
+	isize i = _J2(MAP_PROC,_add_entry)(h, key);
 	if (fr.entry_prev < 0) {
 		h->hashes.e[fr.hash_index] = i;
 	} else {
@@ -274,21 +326,21 @@ void _J2(MAP_FUNC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
 	}
 	h->entries.e[i].next = fr.entry_index;
 	h->entries.e[i].value = value;
-	if (_J2(MAP_FUNC,_full)(h)) {
-		_J2(MAP_FUNC,grow)(h);
+	if (_J2(MAP_PROC,_full)(h)) {
+		_J2(MAP_PROC,grow)(h);
 	}
 }
 
-void _J2(MAP_FUNC,multi_remove)(MAP_NAME *h, HashKey key, MAP_ENTRY *e) {
-	MapFindResult fr = _J2(MAP_FUNC,_find_from_entry)(h, e);
+void _J2(MAP_PROC,multi_remove)(MAP_NAME *h, HashKey key, MAP_ENTRY *e) {
+	MapFindResult fr = _J2(MAP_PROC,_find_from_entry)(h, e);
 	if (fr.entry_index >= 0) {
-		_J2(MAP_FUNC,_erase)(h, fr);
+		_J2(MAP_PROC,_erase)(h, fr);
 	}
 }
 
-void _J2(MAP_FUNC,multi_remove_all)(MAP_NAME *h, HashKey key) {
-	while (_J2(MAP_FUNC,get)(h, key) != NULL) {
-		_J2(MAP_FUNC,remove)(h, key);
+void _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key) {
+	while (_J2(MAP_PROC,get)(h, key) != NULL) {
+		_J2(MAP_PROC,remove)(h, key);
 	}
 }
 #endif
@@ -296,6 +348,6 @@ void _J2(MAP_FUNC,multi_remove_all)(MAP_NAME *h, HashKey key) {
 
 #undef _J2
 #undef MAP_TYPE
-#undef MAP_FUNC
+#undef MAP_PROC
 #undef MAP_NAME
 #undef MAP_ENTRY