/*=====================================================================*/
/*    serrano/prgm/project/bigloo/runtime/Clib/cdlopen.c               */
/*    -------------------------------------------------------------    */
/*    Author      :  Manuel Serrano                                    */
/*    Creation    :  Thu Feb 17 14:34:53 2000                          */
/*    Last change :  Sun Nov 16 13:52:47 2003 (serrano)                */
/*    -------------------------------------------------------------    */
/*    The dlopen interface.                                            */
/*=====================================================================*/
#include <string.h>
#include <bigloo.h>

/*---------------------------------------------------------------------*/
/*    static char *bgl_error;                                          */
/*---------------------------------------------------------------------*/
#define DLOAD_ERROR_LEN 256
static char dload_error[ DLOAD_ERROR_LEN + 1 ];

/*---------------------------------------------------------------------*/
/*    char *                                                           */
/*    bgl_dload_error ...                                              */
/*---------------------------------------------------------------------*/
char *
bgl_dload_error() {
   dload_error[ DLOAD_ERROR_LEN ] = 0;
   return dload_error;
}

#ifndef _MSC_VER
#   if HAVE_DLOPEN
#   include <dlfcn.h>
#   ifndef RTLD_GLOBAL
#      define RTLD_GLOBAL 0
#   endif
#endif

/*---------------------------------------------------------------------*/
/*    int                                                              */
/*    bgl_dload ...                                                    */
/*---------------------------------------------------------------------*/
int
bgl_dload( char *filename, char *init_sym ) {
#if !HAVE_DLOPEN
   strcpy( dload_error, "Feature not supported" );

   return 3;
#else
   void *handle = dlopen( filename, RTLD_LAZY | RTLD_GLOBAL );

   if( !handle ) {
      char *error;
      
      if( (error = dlerror()) != NULL ) {
	 strncpy( dload_error, error, DLOAD_ERROR_LEN );
      } else {
	 strcpy( dload_error, "dlopen error" );
      }
      return 1;
   } else {
      void (*init)() = dlsym( handle, init_sym );
      char *error;

      if( (error = dlerror()) != NULL ) {
	 strncpy( dload_error, error, DLOAD_ERROR_LEN );
	 
	 return 2;
      } else {
	 init();
	 return 0;
      }
   }
#endif
}
#else
#include <windows.h>
/*---------------------------------------------------------------------*/
/*    int                                                              */
/*    bgl_dload ...                                                    */
/*---------------------------------------------------------------------*/
int
bgl_dload( char *filename, char *init_sym ) {
   HMODULE hLibrary= LoadLibrary( filename );

   if( !hLibrary ) {
      /* failed */
      char *error;

      if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
			 | FORMAT_MESSAGE_FROM_SYSTEM,
                         NULL,
			 GetLastError(),
			 0,
			 (LPTSTR)&error,
			 0,
			 NULL ) > 0 ) {
         strncpy( dload_error, error, DLOAD_ERROR_LEN );
         LocalFree( error );
      } else {
         strcpy( dload_error, "dlopen error" );
      }
      return 1;
   } else {
      /* LoadLibrary succeeded */
      void (*init)() = (void (*)())GetProcAddress( hLibrary, init_sym );
      char *error;

      if( !init ) {
         /* failed */
         char *error;

         if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
			    | FORMAT_MESSAGE_FROM_SYSTEM,
                            NULL,
			    GetLastError(),
			    0,
			    (LPTSTR)&error,
			    0,
			    NULL ) > 0) {
            strncpy( dload_error, error, DLOAD_ERROR_LEN );
            LocalFree( error );
         } else {
            strcpy( dload_error, "dlopen error" );
         }
         FreeLibrary( hLibrary );
         return 1;
      } else {
         init();
         FreeLibrary( hLibrary );
         return 0;
      }
   }
}
#endif
