/*
 *  The Regina Rexx Interpreter
 *  Copyright (C) 1993-1994  Anders Christensen <anders@pvv.unit.no>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * $Id:$
 */

/*
 * This file is 'a hell of a file'. It contain _anything_ that is neither
 * POSIX nor ANSI. The meaning is that when these things are needed in 
 * the code, they are located in a wrapper in this file. Thus, if you need 
 * to hack the code, it's likely that you only need to hack this file. 
 * 
 * At least, that's the theory ...
 */

#ifdef _POSIX_SOURCE
# undef _POSIX_SOURCE
#endif
#define _ALL_SOURCE

#include "rexx.h"


#ifdef DYNAMIC


#if defined(DYNAMIC_DLOPEN)
# include <dlfcn.h>
  typedef void *handle_type ;
# ifndef RTLD_LAZY
#  define RTLD_LAZY 1
# endif

#elif defined(DYNAMIC_AIXLOAD)
# define _ALL_SOURCE
# include <sys/types.h>
# include <sys/ldr.h>
  typedef void *handle_type ;

#elif defined(DYNAMIC_HPSHLOAD)
# include <dl.h>
  typedef shl_t handle_type ;
#endif

#include <errno.h>
#include <string.h>

#ifdef DYNAMIC_HPSHLOAD
/* 
 * HP/UX doesn't find symbols unless they are 'true data'; entrypoints
 * for functions are not sufficient! Thus, we need to force it to 
 * 'release' that these symbols are defined. There's no need to do 
 * anything more, once it sets some flag somewhere ... it'll find'em
 * later. Weird!
 *
 * Datatype char only used to save space ... this is never used, so 
 * there is no reason to waste space.
 */

char Food_For_Fuzzy_HP_Linkers[] = {
   (char)exiterror, (char)get_a_chunk, (char)getonechar,
   (char)nullstringptr, (char)get_a_streng, (char)Str_cre,
   (char)atozpos, (char)checkparam, (char)loadrxfunc, (char)Str_cmp,
   (char)Str_cat, (char)give_a_chunk } ;
#endif

void *wrapper_load( streng *module ) 
{
   streng *new_module ;
   handle_type handle ;

   new_module = Str_ify( module ) ;

#if defined(DYNAMIC_DLOPEN)
   handle = dlopen( new_module->value, RTLD_LAZY ) ;
   if (handle==NULL)
      set_err_message( dlerror()) ;
#elif defined(DYNAMIC_HPSHLOAD)
   handle = shl_load( new_module->value, BIND_IMMEDIATE | BIND_VERBOSE, 0L ) ;
   if (handle==NULL)
      set_err_message( strerror(errno)) ;
#elif defined(DYNAMIC_AIXLOAD)
   handle = load( new_module->value, 1, NULL ) ;
   if (handle)
   {
      int rc=loadbind( 0, wrapper_load, handle ) ;
      if (rc!=0)
         handle = NULL ;
   }
   else
      set_err_message( strerror( errno )) ;
#endif

   if (new_module != module)
      Free_string( new_module ) ;

   return handle ;
}

struct entrypt *wrapper_getentries( handle_type handle )
{
   struct entrypt *((*addr)()) ;

#if defined(DYNAMIC_DLOPEN) 
   /*
    * Note, the following assignment is not allowed by ANSI, but SVR4.2 
    * includes it as an example, so it is probably safe in this context
    */
   addr = (struct entrypt *((*)()))(dlsym( handle, "initial" )) ;
   if (addr==NULL)
      set_err_message( dlerror()) ;
#elif defined(DYNAMIC_HPSHLOAD)
   {
      long eaddr ;
      if (shl_findsym( &handle, "initial", TYPE_PROCEDURE, &eaddr ))
      {
         addr = NULL ;
         set_err_message( strerror(errno)) ;
      }
      else 
         addr = (struct entrypt *((*)()))eaddr ;
   }
#elif defined(DYNAMIC_AIXLOAD) 
   addr = handle ;
#endif
   if (addr)
      return (*addr)() ;
   else
      return NULL ;
}

#endif /* DYNAMIC */
