libSupport.c 6.32 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/**CFile****************************************************************

  FileName    [libSupport.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [The main package.]

  Synopsis    [Support for external libaries.]

  Author      [Mike Case]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $]

***********************************************************************/

#include <stdio.h>
#include <string.h>
23

24
#include "base/abc/abc.h"
Alan Mishchenko committed
25
#include "mainInt.h"
26 27 28

ABC_NAMESPACE_IMPL_START

29 30 31
#if defined(ABC_NO_DYNAMIC_LINKING)
#define WIN32
#endif
Alan Mishchenko committed
32 33 34 35 36 37 38

#ifndef WIN32
# include <sys/types.h>
# include <dirent.h>
# include <dlfcn.h>
#endif

39 40 41 42 43 44 45 46
// fix by Paddy O'Brien  on Sep 22, 2009
#ifdef __CYGWIN__
#ifndef RTLD_LOCAL
#define RTLD_LOCAL 0
#endif
#endif 


Alan Mishchenko committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#define MAX_LIBS 256
static void* libHandles[MAX_LIBS+1]; // will be null terminated

typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc);

////////////////////////////////////////////////////////////////////////////////////////////////////
// This will find all the ABC library extensions in the current directory and load them all.
////////////////////////////////////////////////////////////////////////////////////////////////////
void open_libs() {
    int curr_lib = 0;

#ifdef WIN32
//    printf("Warning: open_libs WIN32 not implemented.\n");
#else
    DIR* dirp;
    struct dirent* dp;
    char *env, *init_p, *p;
    int done;

    env = getenv ("ABC_LIB_PATH");
    if (env == NULL) {
//    printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n");
Alan Mishchenko committed
69
      init_p = ABC_ALLOC( char, (2*sizeof(char)) );
Alan Mishchenko committed
70 71
      init_p[0]='.'; init_p[1] = 0;
    } else {
Alan Mishchenko committed
72
      init_p = ABC_ALLOC( char, ((strlen(env)+1)*sizeof(char)) );
Alan Mishchenko committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
      strcpy (init_p, env);
    }

    // Extract directories and read libraries
    done = 0;
    p = init_p;
    while (!done) {
      char *endp = strchr (p,':');
      if (endp == NULL) done = 1; // last directory in the list
      else *endp = 0; // end of string

      dirp = opendir(p);
      if (dirp == NULL) {
//      printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p);
        continue;
      }

      while ((dp = readdir(dirp)) != NULL) {
        if ((strncmp("libabc_", dp->d_name, 7) == 0) &&
            (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) {

          // make sure we don't overflow the handle array
          if (curr_lib >= MAX_LIBS) {
            printf("Warning: maximum number of ABC libraries (%d) exceeded.  Not loading %s.\n",
                   MAX_LIBS,
                   dp->d_name);
          }
          
          // attempt to load it
          else {
Alan Mishchenko committed
103 104
            char* szPrefixed = ABC_ALLOC( char, ((strlen(dp->d_name) + strlen(p) + 2) * 
                                      sizeof(char)) );
Alan Mishchenko committed
105 106 107 108 109 110 111 112 113 114 115 116
            sprintf(szPrefixed, "%s/", p);
            strcat(szPrefixed, dp->d_name);
            libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL);
            
            // did the load succeed?
            if (libHandles[curr_lib] != 0) {
              printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib);
              curr_lib++;
            } else {
              printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror());
            }
            
Alan Mishchenko committed
117
            ABC_FREE(szPrefixed);
Alan Mishchenko committed
118 119 120 121 122 123 124
          }
        }
      }
      closedir(dirp);
      p = endp+1;
    }

Alan Mishchenko committed
125
    ABC_FREE(init_p);
Alan Mishchenko committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
#endif
    
    // null terminate the list of handles
    libHandles[curr_lib] = 0;    
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// This will close all open ABC library extensions
////////////////////////////////////////////////////////////////////////////////////////////////////
void close_libs() {
#ifdef WIN32
    printf("Warning: close_libs WIN32 not implemented.\n");
#else
    int i;
    for (i = 0; libHandles[i] != 0; i++) {
        if (dlclose(libHandles[i]) != 0) {
            printf("Warning: failed to close library %d\n", i);
        }
        libHandles[i] = 0;
    }
#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// This will get a pointer to a function inside of an open library
////////////////////////////////////////////////////////////////////////////////////////////////////
void* get_fnct_ptr(int lib_num, char* sym_name) {
#ifdef WIN32
    printf("Warning: get_fnct_ptr WIN32 not implemented.\n");
    return 0;
#else
    return dlsym(libHandles[lib_num], sym_name);
#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// This will call an initialization function in every open library.
////////////////////////////////////////////////////////////////////////////////////////////////////
void call_inits(Abc_Frame_t* pAbc) {
    int i;
    lib_init_end_func init_func;
    for (i = 0; libHandles[i] != 0; i++) {
        init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init");
        if (init_func == 0) {
            printf("Warning: Failed to initialize library %d.\n", i);
        } else {
            (*init_func)(pAbc);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// This will call a shutdown function in every open library.
////////////////////////////////////////////////////////////////////////////////////////////////////
void call_ends(Abc_Frame_t* pAbc) {
    int i;
    lib_init_end_func end_func;
    for (i = 0; libHandles[i] != 0; i++) {
        end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end");
        if (end_func == 0) {
            printf("Warning: Failed to end library %d.\n", i);
        } else {
            (*end_func)(pAbc);
        }
    }
}

void Libs_Init(Abc_Frame_t * pAbc)
{
    open_libs();
    call_inits(pAbc);
}

void Libs_End(Abc_Frame_t * pAbc)
{
    call_ends(pAbc);

    // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind.
    //    close_libs();
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////
210 211
ABC_NAMESPACE_IMPL_END