Patch title: Release 87 bulk changes
Abstract:
File: /pliant/language/os/dll.c
Key:
    Removed line
    Added line
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation.
// 
// This program 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 General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// version 2 along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/*
abstract
  text "The OS native DLLs interface"
doc
  text "It's used to implement 'external' attribute in Pliant functions and enable Pliant to call a function of a DLL just as if it was a Pliant function."
*/


#if (defined(_LINUX_API_) || defined(_POSIX_API_)) && defined(_GCC_) && !defined(_STATIC_)

  void * _EXTERNAL_ dlopen(const char *filename,int flag);
  #define RTLD_LAZY 1
  #define RTLD_NOW 2
  #define RTLD_GLOBAL 0x100
  void * _EXTERNAL_ dlsym(void *,const char *);
  int _EXTERNAL_ dlclose(void *);
  #if defined(_SO1_) && !defined(_DLL_)
    void * _EXTERNAL_ malloc(unsigned int size) { return memory_allocate(size,null); }
    void  _EXTERNAL_ free(void *adr) { memory_free(adr); }
  #endif

  FUNCTION Address external_function_address(struct Str *dllname,struct Str *funname) {
    struct Str namez;
    void *handle; void *fn;
    Str_build(&namez); Str_concat(&namez,S,dllname,EOS);
    handle=dlopen(namez.chars,RTLD_LAZY);
    // handle=dlopen(namez.chars,RTLD_LAZY);
    handle=dlopen(namez.chars,RTLD_NOW|RTLD_GLOBAL);
    Str_destroy(&namez);
    if(handle==null) {
  #if defined(_OpenBSD_)  /* don't lie */
      error_notifyn(error_id_missing,Z,"Failed to load shared object ",S,dllname,END); 
  #else
      error_notifyn(error_id_missing,Z,"Failed to load ELF DLL ",S,dllname,END);
  #endif
      return null; }
    Str_build(&namez);
  #if defined(_OpenBSD_)
    Str_concat(&namez,Z,"_",S,funname,EOS);
  #else
    Str_concat(&namez,S,funname,EOS);
  #endif
    fn=dlsym(handle,namez.chars);
    Str_destroy(&namez);
    if(fn==null) {
  #if defined(_OpenBSD_)  /* don't lie */
      error_notifyn(error_id_missing,Z,"Could not find function ",S,funname,Z," in shared object ",S,dllname,END);
  #else
      error_notifyn(error_id_missing,Z,"Could not find function ",S,funname,Z," in ELF DLL ",S,dllname,END);
  #endif
      return null; }
    return fn; }

#endif

#ifdef _WIN32_API_

  FUNCTION Address external_function_address(struct Str *dllname,struct Str *funname) {
    struct Str namez;
    HINSTANCE handle; void *fn;
    Str_build(&namez);
    Str_concat(&namez,S,dllname,EOS);
    handle=LoadLibrary(namez.chars);
    Str_destroy(&namez);
    if(handle==null) {
      error_notifyn(error_id_missing,Z,"Failed to load Win32 DLL ",S,dllname,END);
      return null; }
    Str_build(&namez); Str_concat(&namez,S,funname,EOS);
    fn=GetProcAddress(handle,namez.chars);
    Str_destroy(&namez);
    if(fn==null) {
      error_notifyn(error_id_missing,Z,"Could not find function ",S,funname,Z," in Win32 DLL ",S,dllname,END);
      return null; }
    return fn; }

#endif

#ifdef _OS2_API_

  FUNCTION Address external_function_address(struct Str *dllname,struct Str *funname) {
    struct Str namez; Int num;
    UCHAR buffer[256]; HMODULE handle; PFN fn; APIRET err;
    Int i;
    Str_build(&namez);
    Str_concat(&namez,S,dllname,EOS);
    err=DosLoadModule(buffer,sizeof(buffer),namez.chars,&handle);
    Str_destroy(&namez);
    if(err!=0) {
      error_notifyn(error_id_missing,Z,"Failed to load OS/2 DLL ",S,dllname,END);
      return null; }
    if(Str_len(funname)==0 || funname->chars[0]<'0' || funname->chars[0]>'9') {
      Str_build(&namez);
      Str_concat(&namez,S,funname,EOS);
      err=DosQueryProcAddr(handle,0,namez.chars,&fn);
      Str_destroy(&namez);
    other
      for(i=0,num=0; i<Str_len(funname); i++) num=num*10+(Int)(funname->chars[i]-'0');
      err=DosQueryProcAddr(handle,num,null,&fn); }
    if(err!=0) {
      error_notifyn(error_id_missing,Z,"Could not find function ",S,funname,Z," in OS/2 DLL ",S,dllname,END);
      return null; }
    return (Address)fn; }

#endif

#if defined(_LINUX_API_) && defined(_WATCOM_)

  FUNCTION Address external_function_address(struct Str *dllname,struct Str *funname) {
    compile_errorz(module,"DLLs are not available when Watcom compiler is used");
    return null; }

#endif