bringing SDL 1.2.14 from vendor into the main branch
[AROS-Contrib.git] / regina / library.c
blobdb98565e890b2cc6b0fb27cb478529582cae8966
1 #ifndef lint
2 static char *RCSid = "$Id$";
3 #endif
5 /*
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 * Sigh, let's live dangerously. We need to remove the definition of
26 * _POSIX_SOURCE, in order to get defined some extenstions to POSIX,
27 * since dynamic loading is not a part of POSIX.
30 #include "rexx.h"
31 #include "rxiface.h"
32 #include <assert.h>
33 #include <string.h>
36 typedef struct { /* lib_tsd: static variables of this module (thread-safe) */
37 struct library * first_library ;
38 #ifdef DYNAMIC
39 struct library_func *libfuncs[133] ;
40 #endif
41 streng * err_message ;
42 } lib_tsd_t; /* thread-specific but only needed by this module. see
43 * init_library
45 #define LIBFUNCS_COUNT (sizeof(((lib_tsd_t*)0)->libfuncs) / \
46 sizeof(((lib_tsd_t*)0)->libfuncs[0]))
48 /* init_library initializes the module.
49 * Currently, we set up the thread specific data.
50 * The function returns 1 on success, 0 if memory is short.
52 int init_library( tsd_t *TSD )
54 lib_tsd_t *lt;
56 if (TSD->lib_tsd != NULL)
57 return(1);
59 if ((lt = TSD->lib_tsd = MallocTSD(sizeof(lib_tsd_t))) == NULL)
60 return(0);
61 memset(lt,0,sizeof(lib_tsd_t)); /* correct for all values */
62 return(1);
65 #ifdef DYNAMIC
67 /* Operations on the library and library_func structures */
69 static void insert_library( const tsd_t *TSD, struct library *ptr )
71 lib_tsd_t *lt;
73 lt = TSD->lib_tsd;
74 ptr->prev = NULL ;
75 ptr->next = lt->first_library ;
76 if ((lt->first_library=ptr)->next)
77 ptr->next->prev = ptr ;
80 static void remove_function( const tsd_t *TSD, const struct library_func *fptr )
82 lib_tsd_t *lt;
84 lt = TSD->lib_tsd;
85 if (fptr->next)
86 fptr->next->prev = fptr->prev ;
87 if (fptr->prev)
88 fptr->prev->next = fptr->next ;
89 else
90 lt->libfuncs[fptr->hash % LIBFUNCS_COUNT] = fptr->next ;
92 if (fptr->forw)
93 fptr->forw->backw = fptr->backw ;
94 if (fptr->backw)
95 fptr->backw->forw = fptr->forw ;
96 else
97 fptr->lib->first = fptr->forw ;
100 static void remove_library( const tsd_t *TSD, struct library *ptr )
102 lib_tsd_t *lt;
104 lt = TSD->lib_tsd;
105 if (ptr->next)
106 ptr->next->prev = ptr->prev ;
108 if (ptr->prev)
109 ptr->prev->next = ptr->next ;
110 else
111 lt->first_library = ptr->next ;
113 assert( ptr->name ) ;
114 Free_stringTSD( ptr->name ) ;
115 FreeTSD( ptr ) ;
118 void purge_library( const tsd_t *TSD )
120 struct library_func *lptr, *save_lptr ;
121 struct library *ptr, *save_ptr ;
122 lib_tsd_t *lt;
124 lt = TSD->lib_tsd;
125 for (ptr = lt->first_library; ptr != NULL; )
127 save_ptr = ptr->next ;
128 for ( lptr = ptr->first; lptr; )
130 save_lptr = lptr->next ;
131 remove_function( TSD, lptr ) ;
132 Free_stringTSD( lptr->name );
133 lptr = save_lptr ;
135 remove_library( TSD, ptr );
136 ptr = save_ptr;
138 lt->first_library = NULL;
139 memset( lt->libfuncs, 0, sizeof(lt->libfuncs) ) ;
143 static struct library *find_library( const tsd_t *TSD, const streng *name )
145 struct library *lptr=NULL ;
146 lib_tsd_t *lt;
148 lt = TSD->lib_tsd;
149 lptr = lt->first_library ;
150 for (;lptr; lptr=lptr->next)
152 if (!Str_cmp(name,lptr->name))
153 return lptr ;
156 return NULL ;
159 static void add_function( const tsd_t *TSD, struct library_func *fptr )
161 int hash0=0 ;
162 lib_tsd_t *lt;
164 lt = TSD->lib_tsd;
165 hash0 = fptr->hash % LIBFUNCS_COUNT;
166 fptr->next = lt->libfuncs[hash0] ;
167 lt->libfuncs[hash0] = fptr ;
168 fptr->prev = NULL ;
169 if (fptr->next)
170 fptr->next->prev = fptr ;
172 fptr->forw = fptr->lib->first ;
173 fptr->backw = NULL ;
174 fptr->lib->first = fptr ;
175 if (fptr->forw)
176 fptr->forw->backw = fptr ;
179 static struct library_func *find_library_func( const tsd_t *TSD, const streng *name )
181 struct library_func *lptr=NULL ;
182 unsigned hash, hash0 ;
183 lib_tsd_t *lt;
185 lt = TSD->lib_tsd;
186 hash = hashvalue( name->value, name->len ) ;
187 hash0 = hash % LIBFUNCS_COUNT ;
188 for (lptr=lt->libfuncs[hash0]; lptr; lptr=lptr->next)
190 if (hash == lptr->hash)
191 if (Str_cmp(name,lptr->name) == 0)
192 return lptr ;
195 return NULL ;
198 void set_err_message( const tsd_t *TSD, const char *message1, const char *message2 )
200 lib_tsd_t *lt;
201 int size;
203 lt = TSD->lib_tsd;
204 if (lt->err_message)
205 Free_stringTSD( lt->err_message ) ;
207 #if 0
208 lt->err_message = Str_creTSD( message ) ;
209 #else
210 size = strlen(message1)+strlen(message2);
211 lt->err_message = MallocTSD(size+1);
212 if ( lt->err_message )
214 strcpy( lt->err_message->value, message1 );
215 strcat( lt->err_message->value, message2 );
216 lt->err_message->len = size;
218 #endif
221 int loadrxfunc( const tsd_t *TSD, struct library *lptr, const streng *rxname, const streng *objnam )
223 int result=1 ;
224 PFN addr=NULL ;
225 struct library_func *fptr=NULL ;
227 if (lptr)
229 fptr = find_library_func( TSD, rxname ) ;
230 if (!fptr || fptr->lib!=lptr)
232 addr = wrapper_get_addr( TSD, lptr, objnam ) ;
233 if (addr)
235 fptr = MallocTSD( sizeof( struct library_func )) ;
236 fptr->name = Str_upper( Str_dupstrTSD( rxname ) );
237 fptr->hash = hashvalue(fptr->name->value, fptr->name->len);
238 fptr->addr = addr ;
239 fptr->lib = lptr ;
240 add_function( TSD, fptr ) ;
241 result = 0 ;
243 else
245 result = 30 ;
248 else
250 result = 10;
253 else
255 result = 30;
257 return result ;
261 * This loads a module as a result of a RexxRegisterFunctionDll() call
263 * parameters:
264 * 1) name of the function to be added (in Rexx)
265 * 2) name of object file to link in
266 * 3) name of the function to be added (in the object file)
268 static int rex_rxfuncdlladd( const tsd_t *TSD, const streng* rxname,
269 const streng* module, const streng* objnam )
271 struct library *lptr=NULL ;
272 void *handle=NULL ;
273 int rc=0;
275 if ((lptr=find_library(TSD, module)) == NULL)
277 handle = wrapper_load( TSD, module ) ;
278 if (handle)
280 lptr = MallocTSD( sizeof( struct library )) ;
281 lptr->name = Str_dupTSD( module ) ;
282 lptr->handle = handle ;
283 lptr->funcs = NULL ;
284 lptr->first = NULL ;
286 else
288 return 1;
290 insert_library( TSD, lptr ) ;
292 rc = loadrxfunc( TSD, lptr, rxname, objnam ) ;
293 return ( rc );
295 #endif /* DYNAMIC */
297 streng *rex_rxfuncerrmsg( tsd_t *TSD, cparamboxptr parms )
299 #ifdef DYNAMIC
300 lib_tsd_t *lt;
301 #endif
303 checkparam( parms, 0, 0 , "RXFUNCERRMSG" ) ;
305 #ifdef DYNAMIC
306 lt = TSD->lib_tsd;
307 if (lt->err_message)
308 return Str_dupTSD( lt->err_message ) ;
309 else
310 return nullstringptr() ;
311 #else
312 return Str_creTSD( "Platform doesn't support dynamic linking" ) ;
313 #endif
316 streng *rex_rxfuncquery( tsd_t *TSD, cparamboxptr parms )
318 streng *name=NULL;
319 #ifdef DYNAMIC
320 struct library_func *fptr=NULL ;
321 #endif
323 checkparam( parms, 1, 1 , "RXFUNCQUERY" ) ;
324 name = Str_upper( parms->value ) ;
325 #ifdef DYNAMIC
326 fptr = find_library_func( TSD, name ) ;
328 if (fptr)
329 return int_to_streng( TSD, 0 ) ;
331 *... otherwise fall through and try to find the function
332 * loaded via RexxRegisterFunctionExe()
334 #endif
335 return int_to_streng( TSD,(external_func( TSD, name ) ) ? 0 : 1);
340 * parameters:
341 * 1) name of the function to be added (in Rexx)
342 * 2) name of object file to link in
343 * 3) name of the function to be added (in the object file)
345 streng *rex_rxfuncadd( tsd_t *TSD, cparamboxptr parms )
347 #ifdef DYNAMIC
348 streng *rxname=NULL ;
349 streng *module=NULL, *objnam=NULL ;
350 int rc;
352 if ( TSD->restricted )
353 exiterror( ERR_RESTRICTED, 1, "RXFUNCADD" ) ;
355 checkparam( parms, 3, 3 , "RXFUNCADD" ) ;
357 rxname = Str_upper (Str_dupTSD(parms->value) ) ;
358 module = (parms=parms->next)->value ;
359 objnam = parms->next->value ;
361 rc = rex_rxfuncdlladd( TSD, rxname, module, objnam ) ;
362 Free_stringTSD( rxname );
363 return int_to_streng( TSD, rc ) ;
364 #else
365 checkparam( parms, 3, 3 , "RXFUNCADD" ) ;
366 return int_to_streng( TSD, 1 ) ;
367 #endif
370 int IfcRegDllFunc( const tsd_t *TSD, const char* rxname, const char* module, const char* objnam )
372 #ifdef DYNAMIC
373 int rc;
374 streng *ext;
375 streng *intr;
376 streng *lib;
378 ext = Str_upper( Str_creTSD( rxname ) ) ;
379 intr = Str_creTSD( objnam ) ;
380 lib = Str_creTSD( module ) ;
382 rc = rex_rxfuncdlladd( TSD, ext, lib, intr ) ;
383 Free_stringTSD( ext );
384 Free_stringTSD( intr );
385 Free_stringTSD( lib );
386 return ( rc ) ;
387 #else
388 TSD = TSD; /* keep compiler happy */
389 rxname = rxname; /* keep compiler happy */
390 module = module; /* keep compiler happy */
391 objnam = objnam; /* keep compiler happy */
392 return 1;
393 #endif
397 streng *rex_rxfuncdrop( tsd_t *TSD, cparamboxptr parms )
399 streng *name=NULL;
400 int rc=0;
401 #ifdef DYNAMIC
402 struct library_func *fptr=NULL ;
403 #endif
405 checkparam( parms, 1, 1 , "RXFUNCDROP" ) ;
406 name = Str_upper( parms->value ) ;
407 #ifdef DYNAMIC
408 fptr = find_library_func( TSD, name ) ;
410 if (fptr)
413 * if found OK, remove the function...
415 remove_function( TSD, fptr ) ;
416 FreeTSD( fptr );
417 return int_to_streng( TSD, 0 ) ;
420 *... otherwise fall through and try to remove from function
421 * loaded via RexxRegisterFunctionExe()
423 #endif
424 if (external_func( TSD, name ) )
425 rc = delfunc ( TSD, name ) ;
426 else
427 rc = 1;
428 return int_to_streng( TSD, rc ) ; /* value of 1 indicates failure */
431 int rex_rxfuncdlldrop( tsd_t *TSD, const streng* objnam )
433 int rc=0;
434 #ifdef DYNAMIC
435 struct library_func *fptr=NULL ;
437 * try to find the function loaded from a dynamic library
439 fptr=find_library_func(TSD, objnam);
440 if (fptr)
443 * if found OK, remove the function...
445 remove_function( TSD, fptr );
446 FreeTSD( fptr );
447 return(0);
450 *... otherwise fall through and try to remove from function
451 * loaded via RexxRegisterFunctionExe()
453 #endif
454 if (external_func( TSD, objnam ) )
455 rc = delfunc ( TSD, objnam );
456 else
457 rc = 1;
458 return rc; /* value of 0 indicates failure */
461 int rex_rxfuncdllquery( tsd_t *TSD, const streng* objnam )
463 #ifdef DYNAMIC
464 struct library_func *fptr=NULL ;
466 * try to find the function loaded from a dynamic library
468 fptr=find_library_func(TSD, objnam);
469 if (fptr)
470 return(0);
472 *... otherwise fall through and try to find the function
473 * loaded via RexxRegisterFunctionExe()
475 #endif
476 return((external_func( TSD, objnam )) ? 0 : 1 );
479 void *loaded_lib_func( const tsd_t *TSD, const streng *name )
481 #ifdef DYNAMIC
482 struct library_func *box=NULL ;
484 box = find_library_func( TSD, name ) ;
485 return (void*)(box) ;
486 #else
487 TSD = TSD; /* keep compiler happy */
488 name = name; /* keep compiler happy */
489 return NULL ;
490 #endif