Compaq C 6.2 for VMS will complain when we want to convert
[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
8 union cmp_fn_to_char_u
9         {
10         char *char_p;
11         int (*fn_p)(const char *, const char *);
12         };
13
14 union hash_fn_to_char_u
15         {
16         char *char_p;
17         unsigned long (*fn_p)(const char *);
18         };
19
20 union int_fn_to_char_u
21         {
22         char *char_p;
23         int (*fn_p)();
24         };
25
26 union ulong_fn_to_char_u
27         {
28         char *char_p;
29         unsigned long (*fn_p)();
30         };
31
32 union void_fn_to_char_u
33         {
34         char *char_p;
35         void (*fn_p)();
36         };
37
38 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
39  * that applications may define.  I only really use the free function field.
40  */
41 static LHASH *names_lh=NULL;
42 static int names_type_num=OBJ_NAME_TYPE_NUM;
43 static STACK *names_cmp=NULL;
44 static STACK *names_hash=NULL;
45 static STACK *names_free=NULL;
46
47 static unsigned long obj_name_hash(OBJ_NAME *a);
48 static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
49
50 int OBJ_NAME_init(void)
51         {
52         if (names_lh != NULL) return(1);
53         MemCheck_off();
54         names_lh=lh_new(obj_name_hash,obj_name_cmp);
55         MemCheck_on();
56         return(names_lh != NULL);
57         }
58
59 int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(),
60              void (*free_func)())
61         {
62         int ret;
63         int i;
64         union ulong_fn_to_char_u tmp_hash_func;
65         union int_fn_to_char_u tmp_cmp_func;
66         union void_fn_to_char_u tmp_free_func;
67         union cmp_fn_to_char_u tmp_strcmp;
68         union hash_fn_to_char_u tmp_lh_strhash;
69
70         tmp_hash_func.fn_p = hash_func;
71         tmp_cmp_func.fn_p = cmp_func;
72         tmp_free_func.fn_p = free_func;
73         tmp_strcmp.fn_p = (int (*)(const char *, const char *))strcmp;
74         tmp_lh_strhash.fn_p = lh_strhash;
75
76         if (names_free == NULL)
77                 {
78                 MemCheck_off();
79                 names_hash=sk_new_null();
80                 names_cmp=sk_new_null();
81                 names_free=sk_new_null();
82                 MemCheck_on();
83                 }
84         if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL))
85                 {
86                 /* ERROR */
87                 return(0);
88                 }
89         ret=names_type_num;
90         names_type_num++;
91         for (i=sk_num(names_free); i<names_type_num; i++)
92                 {
93                 MemCheck_off();
94                 sk_push(names_hash,tmp_strcmp.char_p);
95                 sk_push(names_cmp,tmp_lh_strhash.char_p);
96                 sk_push(names_free,NULL);
97                 MemCheck_on();
98                 }
99         if (hash_func != NULL)
100                 sk_set(names_hash,ret,tmp_hash_func.char_p);
101         if (cmp_func != NULL)
102                 sk_set(names_cmp,ret,tmp_cmp_func.char_p);
103         if (free_func != NULL)
104                 sk_set(names_free,ret,tmp_free_func.char_p);
105         return(ret);
106         }
107
108 static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b)
109         {
110         int ret;
111         union int_fn_to_char_u cmp;
112
113         ret=a->type-b->type;
114         if (ret == 0)
115                 {
116                 if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type))
117                         {
118                         cmp.char_p=sk_value(names_cmp,a->type);
119                         ret=cmp.fn_p(a->name,b->name);
120                         }
121                 else
122                         ret=strcmp(a->name,b->name);
123                 }
124         return(ret);
125         }
126
127 static unsigned long obj_name_hash(OBJ_NAME *a)
128         {
129         unsigned long ret;
130         union ulong_fn_to_char_u hash;
131
132         if ((names_hash != NULL) && (sk_num(names_hash) > a->type))
133                 {
134                 hash.char_p=sk_value(names_hash,a->type);
135                 ret=hash.fn_p(a->name);
136                 }
137         else
138                 {
139                 ret=lh_strhash(a->name);
140                 }
141         ret^=a->type;
142         return(ret);
143         }
144
145 const char *OBJ_NAME_get(const char *name, int type)
146         {
147         OBJ_NAME on,*ret;
148         int num=0,alias;
149
150         if (name == NULL) return(NULL);
151         if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
152
153         alias=type&OBJ_NAME_ALIAS;
154         type&= ~OBJ_NAME_ALIAS;
155
156         on.name=name;
157         on.type=type;
158
159         for (;;)
160                 {
161                 ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on);
162                 if (ret == NULL) return(NULL);
163                 if ((ret->alias) && !alias)
164                         {
165                         if (++num > 10) return(NULL);
166                         on.name=ret->data;
167                         }
168                 else
169                         {
170                         return(ret->data);
171                         }
172                 }
173         }
174
175 int OBJ_NAME_add(const char *name, int type, const char *data)
176         {
177         union void_fn_to_char_u f;
178         OBJ_NAME *onp,*ret;
179         int alias;
180
181         if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
182
183         alias=type&OBJ_NAME_ALIAS;
184         type&= ~OBJ_NAME_ALIAS;
185
186         onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
187         if (onp == NULL)
188                 {
189                 /* ERROR */
190                 return(0);
191                 }
192
193         onp->name=name;
194         onp->alias=alias;
195         onp->type=type;
196         onp->data=data;
197
198         ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp);
199         if (ret != NULL)
200                 {
201                 /* free things */
202                 if ((names_free != NULL) && (sk_num(names_free) > ret->type))
203                         {
204                         f.char_p=sk_value(names_free,ret->type);
205                         f.fn_p(ret->name,ret->type,ret->data);
206                         }
207                 Free((char *)ret);
208                 }
209         else
210                 {
211                 if (lh_error(names_lh))
212                         {
213                         /* ERROR */
214                         return(0);
215                         }
216                 }
217         return(1);
218         }
219
220 int OBJ_NAME_remove(const char *name, int type)
221         {
222         OBJ_NAME on,*ret;
223         union void_fn_to_char_u f;
224
225         if (names_lh == NULL) return(0);
226
227         type&= ~OBJ_NAME_ALIAS;
228         on.name=name;
229         on.type=type;
230         ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on);
231         if (ret != NULL)
232                 {
233                 /* free things */
234                 if ((names_free != NULL) && (sk_num(names_free) > type))
235                         {
236                         f.char_p=sk_value(names_free,type);
237                         f.fn_p(ret->name,ret->type,ret->data);
238                         }
239                 Free((char *)ret);
240                 return(1);
241                 }
242         else
243                 return(0);
244         }
245
246 static int free_type;
247
248 static void names_lh_free(OBJ_NAME *onp, int type)
249 {
250         if(onp == NULL)
251             return;
252
253         if ((free_type < 0) || (free_type == onp->type))
254                 {
255                 OBJ_NAME_remove(onp->name,onp->type);
256                 }
257         }
258
259 void OBJ_NAME_cleanup(int type)
260         {
261         unsigned long down_load;
262
263         if (names_lh == NULL) return;
264
265         free_type=type;
266         down_load=names_lh->down_load;
267         names_lh->down_load=0;
268
269         lh_doall(names_lh,names_lh_free);
270         if (type < 0)
271                 {
272                 lh_free(names_lh);
273                 sk_free(names_hash);
274                 sk_free(names_cmp);
275                 sk_free(names_free);
276                 names_lh=NULL;
277                 names_hash=NULL;
278                 names_cmp=NULL;
279                 names_free=NULL;
280                 }
281         else
282                 names_lh->down_load=down_load;
283         }
284