// ---------------------------------------------------------------------------
// - cshl.cxx                                                                -
// - standard system library - c dynamic library implementation              -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - 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.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2008 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "cshl.hpp"
#include "cstr.hpp"
#include "cshl.hxx"

namespace afnix {

  // open the main program as a shared object

  void* c_dlmain (void) {
    return dlopen (nilp, RTLD_NOW);
  }

  // get the version name of a library
  static char* get_shl_name (const char* name, bool vflag) {
    // standard check
    long nlen = c_strlen (name);
    if (nlen == 0) return nilp;
    // build name with version
    char buffer[512];
    if (vflag == true) {
      sprintf (buffer, "lib%s.%s.%d.%d", name, AFNIX_LIBRARY_EXT,
	       AFNIX_VERSION_MAJOR, AFNIX_VERSION_MINOR);
    } else {
      sprintf (buffer, "lib%s.%s", name, AFNIX_LIBRARY_EXT);
    }
    return c_strdup (buffer);
  }

  // open a dynamic library by name
 
  void* c_dlopen (const char* name) {
    // get the version name first
    char* lname = get_shl_name (name, true);
    if (lname == nilp) return nilp;
    void* library = dlopen (lname, RTLD_LAZY);
    delete [] lname;
    if (library != nilp) return library;
    // fallback with regular name
    lname = get_shl_name (name, false);
    if (lname == nilp) return nilp;
    library = dlopen (lname, RTLD_LAZY);
    delete [] lname;
    return library;
  }
  
  // query a symbol by name
  
  void* c_dlsym (const char* name, void* lptr) {
    // standard check as usual
    if ((c_strlen (name) == 0) || (lptr == nilp)) return nilp;
    return dlsym (lptr, name);
  }
  
  // close the library
  
  void c_dlclose (void* lptr) {
    // standard chech again
    if (lptr == nilp) return;  
    dlclose (lptr);
  }
}

// define a symbol for test purpose only
extern "C" {
  char cshl_test_symbol = 0;
}
