"make update" + stripping the type-specific stack functions out of
[openssl.git] / crypto / objects / o_names.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <openssl/lhash.h>
6 #include <openssl/objects.h>
7 #include <openssl/safestack.h>
8
9 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
10  * that applications may define.  I only really use the free function field.
11  */
12 static LHASH *names_lh=NULL;
13 static int names_type_num=OBJ_NAME_TYPE_NUM;
14
15 typedef struct name_funcs_st
16         {
17         unsigned long (*hash_func)();
18         int (*cmp_func)();
19         void (*free_func)();
20         } NAME_FUNCS;
21
22 DECLARE_STACK_OF(NAME_FUNCS)
23 /* This block of defines is updated by a perl script, please do not touch! */
24 #ifndef DEBUG_SAFESTACK
25         #define sk_NAME_FUNCS_new(a) sk_new((int (*) \
26                 (const char * const *, const char * const *))(a))
27         #define sk_NAME_FUNCS_new_null() sk_new_null()
28         #define sk_NAME_FUNCS_free(a) sk_free(a)
29         #define sk_NAME_FUNCS_num(a) sk_num(a)
30         #define sk_NAME_FUNCS_value(a,b) ((NAME_FUNCS *) \
31                 sk_value((a),(b)))
32         #define sk_NAME_FUNCS_set(a,b,c) ((NAME_FUNCS *) \
33                 sk_set((a),(b),(char *)(c)))
34         #define sk_NAME_FUNCS_zero(a) sk_zero(a)
35         #define sk_NAME_FUNCS_push(a,b) sk_push((a),(char *)(b))
36         #define sk_NAME_FUNCS_unshift(a,b) sk_unshift((a),(b))
37         #define sk_NAME_FUNCS_find(a,b) sk_find((a), (char *)(b))
38         #define sk_NAME_FUNCS_delete(a,b) ((NAME_FUNCS *) \
39                 sk_delete((a),(b)))
40         #define sk_NAME_FUNCS_delete_ptr(a,b) ((NAME_FUNCS *) \
41                 sk_delete_ptr((a),(char *)(b)))
42         #define sk_NAME_FUNCS_insert(a,b,c) sk_insert((a),(char *)(b),(c))
43         #define sk_NAME_FUNCS_set_cmp_func(a,b) ((int (*) \
44                 (const NAME_FUNCS * const *,const NAME_FUNCS * const *)) \
45                 sk_set_cmp_func((a),(int (*) \
46                 (const char * const *, const char * const *))(b)))
47         #define sk_NAME_FUNCS_dup(a) sk_dup(a)
48         #define sk_NAME_FUNCS_pop_free(a,b) sk_pop_free((a),(void (*)(void *))(b))
49         #define sk_NAME_FUNCS_shift(a) ((NAME_FUNCS *)sk_shift(a))
50         #define sk_NAME_FUNCS_pop(a) ((NAME_FUNCS *)sk_pop(a))
51         #define sk_NAME_FUNCS_sort(a) sk_sort(a)
52 #endif /* !DEBUG_SAFESTACK */
53 /* End of perl script block, you may now edit :-) */
54 IMPLEMENT_STACK_OF(NAME_FUNCS)
55
56 static STACK_OF(NAME_FUNCS) *name_funcs_stack;
57
58 static unsigned long obj_name_hash(OBJ_NAME *a);
59 static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
60
61 int OBJ_NAME_init(void)
62         {
63         if (names_lh != NULL) return(1);
64         MemCheck_off();
65         names_lh=lh_new(obj_name_hash,obj_name_cmp);
66         MemCheck_on();
67         return(names_lh != NULL);
68         }
69
70 int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(),
71              void (*free_func)())
72         {
73         int ret;
74         int i;
75         NAME_FUNCS *name_funcs;
76
77         if (name_funcs_stack == NULL)
78                 {
79                 MemCheck_off();
80                 name_funcs_stack=sk_NAME_FUNCS_new_null();
81                 MemCheck_on();
82                 }
83         if ((name_funcs_stack == NULL))
84                 {
85                 /* ERROR */
86                 return(0);
87                 }
88         ret=names_type_num;
89         names_type_num++;
90         for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
91                 {
92                 MemCheck_off();
93                 name_funcs = Malloc(sizeof(NAME_FUNCS));
94                 name_funcs->hash_func = lh_strhash;
95                 name_funcs->cmp_func = (int (*)())strcmp;
96                 name_funcs->free_func = 0; /* NULL is often declared to
97                                             * ((void *)0), which according
98                                             * to Compaq C is not really
99                                             * compatible with a function
100                                             * pointer.  -- Richard Levitte*/
101                 sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
102                 MemCheck_on();
103                 }
104         name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
105         if (hash_func != NULL)
106                 name_funcs->hash_func = hash_func;
107         if (cmp_func != NULL)
108                 name_funcs->cmp_func = cmp_func;
109         if (free_func != NULL)
110                 name_funcs->free_func = free_func;
111         return(ret);
112         }
113
114 static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b)
115         {
116         int ret;
117
118         ret=a->type-b->type;
119         if (ret == 0)
120                 {
121                 if ((name_funcs_stack != NULL)
122                         && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
123                         {
124                         ret=sk_NAME_FUNCS_value(name_funcs_stack,a->type)
125                                 ->cmp_func(a->name,b->name);
126                         }
127                 else
128                         ret=strcmp(a->name,b->name);
129                 }
130         return(ret);
131         }
132
133 static unsigned long obj_name_hash(OBJ_NAME *a)
134         {
135         unsigned long ret;
136
137         if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
138                 {
139                 ret=sk_NAME_FUNCS_value(name_funcs_stack,a->type)
140                         ->hash_func(a->name);
141                 }
142         else
143                 {
144                 ret=lh_strhash(a->name);
145                 }
146         ret^=a->type;
147         return(ret);
148         }
149
150 const char *OBJ_NAME_get(const char *name, int type)
151         {
152         OBJ_NAME on,*ret;
153         int num=0,alias;
154
155         if (name == NULL) return(NULL);
156         if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
157
158         alias=type&OBJ_NAME_ALIAS;
159         type&= ~OBJ_NAME_ALIAS;
160
161         on.name=name;
162         on.type=type;
163
164         for (;;)
165                 {
166                 ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
167                 if (ret == NULL) return(NULL);
168                 if ((ret->alias) && !alias)
169                         {
170                         if (++num > 10) return(NULL);
171                         on.name=ret->data;
172                         }
173                 else
174                         {
175                         return(ret->data);
176                         }
177                 }
178         }
179
180 int OBJ_NAME_add(const char *name, int type, const char *data)
181         {
182         OBJ_NAME *onp,*ret;
183         int alias;
184
185         if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
186
187         alias=type&OBJ_NAME_ALIAS;
188         type&= ~OBJ_NAME_ALIAS;
189
190         onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
191         if (onp == NULL)
192                 {
193                 /* ERROR */
194                 return(0);
195                 }
196
197         onp->name=name;
198         onp->alias=alias;
199         onp->type=type;
200         onp->data=data;
201
202         ret=(OBJ_NAME *)lh_insert(names_lh,onp);
203         if (ret != NULL)
204                 {
205                 /* free things */
206                 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
207                         {
208                         /* XXX: I'm not sure I understand why the free
209                          * function should get three arguments...
210                          * -- Richard Levitte
211                          */
212                         sk_NAME_FUNCS_value(name_funcs_stack,ret->type)
213                                 ->free_func(ret->name,ret->type,ret->data);
214                         }
215                 Free(ret);
216                 }
217         else
218                 {
219                 if (lh_error(names_lh))
220                         {
221                         /* ERROR */
222                         return(0);
223                         }
224                 }
225         return(1);
226         }
227
228 int OBJ_NAME_remove(const char *name, int type)
229         {
230         OBJ_NAME on,*ret;
231
232         if (names_lh == NULL) return(0);
233
234         type&= ~OBJ_NAME_ALIAS;
235         on.name=name;
236         on.type=type;
237         ret=(OBJ_NAME *)lh_delete(names_lh,&on);
238         if (ret != NULL)
239                 {
240                 /* free things */
241                 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
242                         {
243                         /* XXX: I'm not sure I understand why the free
244                          * function should get three arguments...
245                          * -- Richard Levitte
246                          */
247                         sk_NAME_FUNCS_value(name_funcs_stack,ret->type)
248                                 ->free_func(ret->name,ret->type,ret->data);
249                         }
250                 Free(ret);
251                 return(1);
252                 }
253         else
254                 return(0);
255         }
256
257 static int free_type;
258
259 static void names_lh_free(OBJ_NAME *onp, int type)
260 {
261         if(onp == NULL)
262             return;
263
264         if ((free_type < 0) || (free_type == onp->type))
265                 {
266                 OBJ_NAME_remove(onp->name,onp->type);
267                 }
268         }
269
270 static void name_funcs_free(NAME_FUNCS *ptr)
271         {
272         Free(ptr);
273         }
274
275 void OBJ_NAME_cleanup(int type)
276         {
277         unsigned long down_load;
278
279         if (names_lh == NULL) return;
280
281         free_type=type;
282         down_load=names_lh->down_load;
283         names_lh->down_load=0;
284
285         lh_doall(names_lh,names_lh_free);
286         if (type < 0)
287                 {
288                 lh_free(names_lh);
289                 sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
290                 names_lh=NULL;
291                 name_funcs_stack = NULL;
292                 }
293         else
294                 names_lh->down_load=down_load;
295         }
296