2
// Copyright (C) 1997 - 2001, Paul C. Gregory // // Contact: pgregory@aqsis.org //
3
// This library is free software; you can redistribute it and/or
4
// modify it under the terms of the GNU General Public
5
// License as published by the Free Software Foundation; either
6
// version 2 of the License, or (at your option) any later version.
8
// This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
// General Public License for more details.
12
// You should have received a copy of the GNU General Public
13
// License along with this library; if not, write to the Free Software
14
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
\brief Implements the classes and support structures for DSO shadeops
18
\author Tristan Colgate <tristan@inuxtech.co.uk>
21
#include <aqsis/aqsis.h>
25
#include <boost/filesystem.hpp>
27
#include "dsoshadeops.h"
28
#include <aqsis/util/file.h>
29
#include <aqsis/util/logging.h>
33
//---------------------------------------------------------------------
35
CqDSORepository::strPrototype(CqString *strFuncName, SqDSOExternalCall *pExtCall)
40
type = pExtCall->return_type;
41
m_itTypeNameMap = m_TypeNameMap.begin();
42
while (m_itTypeNameMap != m_TypeNameMap.end() &&
43
(*m_itTypeNameMap).second != type)
47
if(m_itTypeNameMap != m_TypeNameMap.end())
49
strProt = (*m_itTypeNameMap).first + " ";
56
strProt += *strFuncName + " ( ";
58
std::list<EqVariableType>::iterator it = pExtCall->arg_types.begin();
59
while( it != pExtCall->arg_types.end())
62
m_itTypeNameMap = m_TypeNameMap.begin();
63
while (m_itTypeNameMap != m_TypeNameMap.end() &&
64
(*m_itTypeNameMap).second != type)
68
if(m_itTypeNameMap != m_TypeNameMap.end())
70
strProt += (*m_itTypeNameMap).first + " ";
85
//---------------------------------------------------------------------
86
void CqDSORepository::SetDSOPath(const char* pathStr)
88
if ( pathStr == NULL )
91
// Scan through all the paths in the search path
92
std::string pathString = pathStr;
93
TqPathsTokenizer paths(pathString);
94
for(TqPathsTokenizer::iterator path = paths.begin(), end = paths.end();
99
if(boost::filesystem::is_directory(*path))
101
// If the path points to a directory, we add each library in the
102
// named directory to the list of DSO candidates.
103
std::vector<std::string> files = Glob(
104
((*path)/"*" SHARED_LIBRARY_SUFFIX).file_string() );
105
m_DSOPathList.insert(m_DSOPathList.end(), files.begin(), files.end());
109
// else add the file itself.
110
m_DSOPathList.push_back(path->file_string());
113
catch(boost::filesystem::filesystem_error& /*e*/)
115
// ignore any errors.
121
//---------------------------------------------------------------------
122
/** This returns a list of descriptors of calls to external DSO functions that
123
* implement a named shadeop, entries are returned for each polymorphic function
125
std::list<SqDSOExternalCall*>*
126
CqDSORepository::getShadeOpMethods(CqString* pShadeOpName)
128
CqString strTableSymbol = *pShadeOpName + "_shadeops" ;
130
std::list<SqDSOExternalCall*>* oplist = new (std::list<SqDSOExternalCall*>);
131
std::list<CqString>::iterator itPathEntry;
132
SqShadeOp *pTableSymbol = NULL;
134
Aqsis::log() << debug << "Looking for DSO candidates for shadeop \"" << pShadeOpName->c_str() << "\"" << std::endl;
135
for ( itPathEntry = m_DSOPathList.begin() ; itPathEntry != m_DSOPathList.end() ; itPathEntry++ )
137
Aqsis::log() << debug << "Looking in shared library : " << itPathEntry->c_str() << std::endl;
138
void *handle = DLOpen( &(*itPathEntry) );
142
pTableSymbol = (SqShadeOp*) DLSym( handle, &strTableSymbol );
144
if ( pTableSymbol != NULL )
146
//We have an appropriate named shadeop table
147
SqShadeOp *pShadeOp = (SqShadeOp*) pTableSymbol;
148
while( ( pShadeOp->m_opspec )[0] != (char) NULL )
150
SqDSOExternalCall *pDSOCall = NULL;
151
pDSOCall = parseShadeOpTableEntry( handle, pShadeOp );
152
if ( pDSOCall != NULL )
153
oplist->push_back( pDSOCall );
159
// Failure here does not neccesarily mean anything since
163
CqString strError = DLError();
164
Aqsis::log() << error << "DLOpen: " << strError.c_str() << std::endl;
167
std::stringstream resultStr;
169
resultStr << "(none found)";
171
resultStr << "(found " << oplist->size() << " possibilities)";
172
Aqsis::log() << debug << "Finished looking for DSO candidates "<< resultStr.str().c_str() << std::endl;
173
return ( oplist->empty() ? NULL : oplist );
176
//---------------------------------------------------------------------
177
/** We have found a plugins with the desried shadeop table in it
178
* For each shaeop table entry we parse the prototype and validate all
179
* symbols that are named by the shadeop entry.
183
CqDSORepository::parseShadeOpTableEntry(void* handle, SqShadeOp* pShadeOpEntry)
186
TqInt length = strlen(pShadeOpEntry->m_opspec)+1;
188
strncpy(temp, pShadeOpEntry->m_opspec,length);
190
// We remove all the '(),' charachters, so we are left with
191
// returntype name argtype ...
192
for (int x = 0; x < length; x++)
193
if(temp[x]=='('||temp[x]==')'||temp[x]==',')
196
CqString strSpec(temp);
198
// Get the return type of the function
199
std::string strRetType;
202
strRetType = strtok(temp, " ");
203
m_itTypeNameMap = m_TypeNameMap.find(strRetType.c_str());
205
// ERROR if we cant find this types name;
206
if (m_itTypeNameMap == m_TypeNameMap.end())
208
Aqsis::log() << warning << "Discarding DSO Table entry due to unsupported return type: \"" << strRetType.c_str() << "\"" << std::endl;
211
EqVariableType rettype = (*m_itTypeNameMap).second;
215
std::string strMethodName;
217
strMethodName = strtok(NULL, " ");
218
CqString s = strMethodName.c_str();
219
DSOMethod method = (DSOMethod) DLSym (handle,&s);
222
Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for method: \"" << strMethodName.c_str() << "\"" << std::endl;
227
// Parse each arg type, presumably we need to handle arrays here
228
std::list<EqVariableType> arglist;
229
char *nextarg = NULL;
232
// Get the next arguments type
233
std::string strArgType;
235
nextarg = strtok(NULL, " ");
238
strArgType = nextarg;
239
m_itTypeNameMap = m_TypeNameMap.find(strArgType.c_str());
241
// ERROR if we cant find this arguments type name;
242
if (m_itTypeNameMap == m_TypeNameMap.end())
244
Aqsis::log() << warning << "Discarding DSO Table entry due to unsupported argument type: \"" << strArgType.c_str() << "\"" << std::endl;
247
arglist.push_back((*m_itTypeNameMap).second);
252
// Check if there is a valid init function
253
CqString strInit = pShadeOpEntry->m_init;
254
DSOInit initfunc = NULL;
255
if (strcmp(pShadeOpEntry->m_init,""))
257
initfunc = (DSOInit) DLSym(handle,&strInit);
258
if (initfunc == NULL)
260
Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for init: \"" << strInit.c_str() << "\"" << std::endl;
261
return NULL; // ERROR ;
265
// Check if there is a valid shutdown function
266
CqString strShutdown = pShadeOpEntry->m_shutdown;
267
DSOShutdown shutdownfunc = NULL;
268
if (strcmp(pShadeOpEntry->m_shutdown,""))
270
shutdownfunc = (DSOShutdown) DLSym(handle,&strShutdown);
271
if (shutdownfunc == NULL)
273
Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for shutdown: \"" << strShutdown.c_str() << "\"" << std::endl;
274
return NULL; // ERROR ;
279
// We have a valid shadeop implementation
280
SqDSOExternalCall *ret = new SqDSOExternalCall;
281
ret->method = method;
282
ret->init = initfunc;
283
ret->shutdown = shutdownfunc;
284
ret->return_type = rettype;
285
ret->arg_types = arglist;
286
ret->initData = NULL;
287
ret->initialised = false;
294
//---------------------------------------------------------------------