1 /* 2 * Copyright (C) 2010 Dan Carpenter. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 16 */ 17 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include "smatch.h" 22 #include "cwchash/hashtable.h" 23 24 static inline unsigned int djb2_hash(void *ky) 25 { 26 char *str = (char *)ky; 27 unsigned long hash = 5381; 28 int c; 29 30 while ((c = *str++)) 31 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 32 33 return hash; 34 } 35 36 static inline int equalkeys(void *k1, void *k2) 37 { 38 return !strcmp((char *)k1, (char *)k2); 39 } 40 41 #define DEFINE_FUNCTION_ADD_HOOK(_name, _item_type, _list_type) \ 42 void add_##_name(struct hashtable *table, const char *look_for, _item_type *value) \ 43 { \ 44 _list_type *list; \ 45 char *key; \ 46 \ 47 key = alloc_string(look_for); \ 48 list = search_##_name(table, key); \ 49 if (!list) { \ 50 add_ptr_list(&list, value); \ 51 } else { \ 52 remove_##_name(table, key); \ 53 add_ptr_list(&list, value); \ 54 } \ 55 insert_##_name(table, key, list); \ 56 } 57 58 static inline struct hashtable *create_function_hashtable(int size) 59 { 60 return create_hashtable(size, djb2_hash, equalkeys); 61 } 62 63 static inline void destroy_function_hashtable(struct hashtable *table) 64 { 65 hashtable_destroy(table, 0); 66 } 67 68 #define DEFINE_FUNCTION_HASHTABLE(_name, _item_type, _list_type) \ 69 DEFINE_HASHTABLE_INSERT(insert_##_name, char, _list_type); \ 70 DEFINE_HASHTABLE_SEARCH(search_##_name, char, _list_type); \ 71 DEFINE_HASHTABLE_REMOVE(remove_##_name, char, _list_type); \ 72 DEFINE_FUNCTION_ADD_HOOK(_name, _item_type, _list_type); 73 74 #define DEFINE_FUNCTION_HASHTABLE_STATIC(_name, _item_type, _list_type) \ 75 static DEFINE_HASHTABLE_INSERT(insert_##_name, char, _list_type); \ 76 static DEFINE_HASHTABLE_SEARCH(search_##_name, char, _list_type); \ 77 static DEFINE_HASHTABLE_REMOVE(remove_##_name, char, _list_type); \ 78 static DEFINE_FUNCTION_ADD_HOOK(_name, _item_type, _list_type); 79 80 #define DEFINE_STRING_HASHTABLE_STATIC(_name) \ 81 static DEFINE_HASHTABLE_INSERT(insert_##_name, char, int); \ 82 static DEFINE_HASHTABLE_SEARCH(search_##_name, char, int); \ 83 static struct hashtable *_name 84 85 static inline void load_hashtable_helper(const char *file, int (*insert_func)(struct hashtable *, char *, int *), struct hashtable *table) 86 { 87 char filename[256]; 88 struct token *token; 89 char *name; 90 91 snprintf(filename, sizeof(filename), "%s.%s", option_project_str, file); 92 token = get_tokens_file(filename); 93 if (!token) 94 return; 95 if (token_type(token) != TOKEN_STREAMBEGIN) 96 return; 97 token = token->next; 98 while (token_type(token) != TOKEN_STREAMEND) { 99 if (token_type(token) != TOKEN_IDENT) 100 return; 101 name = alloc_string(show_ident(token->ident)); 102 insert_func(table, name, (void *)1); 103 token = token->next; 104 } 105 clear_token_alloc(); 106 } 107 108 #define load_strings(file, _table) load_hashtable_helper(file, insert_##_table, _table) 109