File: DynamicLoader.cc

package info (click to toggle)
thepeg 1.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 9,312 kB
  • ctags: 11,509
  • sloc: cpp: 57,129; sh: 11,315; java: 3,212; lisp: 1,402; makefile: 830; ansic: 58; perl: 3
file content (156 lines) | stat: -rw-r--r-- 4,036 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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
// -*- C++ -*-
//
// DynamicLoader.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DynamicLoader class.
//

// macro is passed in from -D compile flag
#ifndef THEPEG_PKGLIBDIR
#error Makefile.am needs to define THEPEG_PKGLIBDIR
#endif

#include "DynamicLoader.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Config/algorithm.h"
#include "config.h"

#ifdef ThePEG_HAS_DLOPEN
#include <dlfcn.h>
#endif

#include <cstdlib>

#ifdef ThePEG_HAS_FENV
#include <fenv.h>
#endif

using namespace ThePEG;

void DynamicLoader::dlname(string sofile) {
  if ( StringUtils::suffix(sofile) == "so" ) {
    string lafile = StringUtils::remsuf(sofile) + ".la";
    ifstream is(lafile.c_str());
    string line;
    while ( getline(is, line) ) {
      if ( line.find("dlname='") != string::npos ) {
	int pos = line.find('\'') + 1;
	int l = line.rfind('\'') - pos;
	sofile = StringUtils::basename(sofile);
	versionMap[sofile] = line.substr(pos, l);
      }
    }
  } else if ( StringUtils::suffix(StringUtils::remsuf(sofile)) == "so" ) {
    versionMap[StringUtils::basename(StringUtils::remsuf(sofile))] =
      StringUtils::basename(sofile);
  }

}

string DynamicLoader::dlnameversion(string libs) {
  string ret;
  do {
    string soname = StringUtils::car(libs);
    string dir = StringUtils::dirname(soname);
    if ( dir.length() ) dir += '/';
    libs = StringUtils::cdr(libs);
    if ( versionMap.find(StringUtils::basename(soname)) != versionMap.end() )
      ret += dir + versionMap[StringUtils::basename(soname)] + " ";
    else
      ret += soname + " ";
  } while ( libs.length() );
  return StringUtils::stripws(ret);
}

bool DynamicLoader::loadcmd(string file) {
#ifdef ThePEG_HAS_DLOPEN
  dlname(file);
#ifdef ThePEG_HAS_FENV
  int oldfpe = fegetexcept();
#endif
  bool ret = dlopen(file.c_str(), RTLD_LAZY|RTLD_GLOBAL) != 0;
#ifdef ThePEG_HAS_FENV
  feenableexcept(oldfpe);
#endif
  if ( !ret ) lastErrorMessage += string(dlerror()) + string("\n");
  return ret;
#else
#error ThePEG can only be run on platforms which support
#error dynamic loading.
  return false;
#endif
}

void DynamicLoader::appendPath(string path) {
  if ( path[path.size()-1] != '/' ) path += '/';
  paths.push_back(path);
  apppaths.push_back(path);
}

void DynamicLoader::prependPath(string path) {
  if ( path[path.size()-1] != '/' ) path += '/';
  paths.insert(paths.begin(), path);
  prepaths.push_back(path);
}

bool DynamicLoader::load(string name) {
  lastErrorMessage = "";
  static set<string> loaded;
  if ( loaded.find(name) != loaded.end() ) return true;
  loaded.insert(name);
  bool success = false;
  if ( name[0] == '/' ) success = loadcmd(name);
  else {
    for ( unsigned i = 0; i < paths.size(); ++i ) {
      string path = paths[i];
      if ( path[path.size() - 1] != '/' ) path += '/';
      if ( loadcmd(path + name) ) {
	success = true;
	break;
      }
    }
  }
  if ( success || loadcmd(name) ) {
    lastErrorMessage = "";
    return true;
  }
  loaded.erase(name);
  return false;
}

const vector<string> & DynamicLoader::appendedPaths() {
  return apppaths;
}

const vector<string> & DynamicLoader::prependedPaths() {
  return prepaths;
}

const vector<string> & DynamicLoader::allPaths() {
  return paths;
}

vector<string> DynamicLoader::paths = DynamicLoader::defaultPaths();

vector<string> DynamicLoader::prepaths = vector<string>();

vector<string> DynamicLoader::apppaths = vector<string>();

string DynamicLoader::lastErrorMessage;

map<string,string> DynamicLoader::versionMap;

vector<string> DynamicLoader::defaultPaths() {
  vector<string> vpaths;
  // macro is passed in from -D compile flag
  string instpath = THEPEG_PKGLIBDIR;
  vpaths.push_back(instpath);
  vpaths.push_back(".");
  return vpaths;
}