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 
djb2_hash(void * ky)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 
equalkeys(void * k1,void * k2)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 
create_function_hashtable(int size)58 static inline struct hashtable *create_function_hashtable(int size)
59 {
60 	return create_hashtable(size, djb2_hash, equalkeys);
61 }
62 
destroy_function_hashtable(struct hashtable * table)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 
load_hashtable_helper(const char * file,int (* insert_func)(struct hashtable *,char *,int *),struct hashtable * table)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