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)