2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory // // Contact: pgregory@aqsis.com //
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>
25
#include "irenderer.h"
26
#include "ishaderdata.h"
27
#include "dsoshadeops.h"
31
START_NAMESPACE( Aqsis )
33
//---------------------------------------------------------------------
34
/** This does replicate effort from CqFile and at present doesnt handle NT either
35
** There is a distinction in that we would like to handle directories here which CqFile doesnt
39
CqDSORepository::strPrototype(CqString *strFuncName, SqDSOExternalCall *pExtCall)
44
type = pExtCall->return_type;
45
m_itTypeNameMap = m_TypeNameMap.begin();
46
while (m_itTypeNameMap != m_TypeNameMap.end() &&
47
(*m_itTypeNameMap).second != type)
51
if(m_itTypeNameMap != m_TypeNameMap.end()){
52
strProt = (*m_itTypeNameMap).first + " ";
57
strProt += *strFuncName + " ( ";
59
std::list<EqVariableType>::iterator it = pExtCall->arg_types.begin();
60
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()){
69
strProt += (*m_itTypeNameMap).first + " ";
82
//---------------------------------------------------------------------
83
/** This does replicate effort from CqFile and at present doesnt handle NT either
84
** There is a distinction in that we would like to handle directories here which CqFile doesnt
87
CqDSORepository::SetDSOPath(const CqString* pPath)
89
CqString::size_type iLeft = 0;
90
CqString::size_type iRight = iLeft ;
92
if ( pPath == NULL ) return;
94
// Split the string up into the components of the path;
95
while(iRight <= pPath->length())
97
if ( ( *pPath)[iRight] == ';' || // completed a path element with ';'
98
( ( *pPath)[iRight] == ':' && ( iRight - iLeft ) > 1) || // completed a path element ':'
99
( iRight+1 > pPath->length() && iLeft != iRight) ) // hit end of list
101
CqString *element = new CqString(pPath->substr(iLeft,iRight - iLeft));
102
// Here, if element points to a directory, we can add each library in the
103
// named directory which is not already in the path list
106
if (!stat( element->c_str(), &s ))
108
if ( S_ISDIR(s.st_mode) )
110
// We have a directory, list all the libraries in that directory and add them to the path
111
CqString wild = *element + CqString( DIRSEP ) + CqString( "*" ) + CqString ( SHARED_LIBRARY_SUFFIX );
112
std::list<CqString*> files = Aqsis::CqFile::Glob(wild);
113
if ( !files.empty() )
115
m_pDSOPathList.splice(m_pDSOPathList.end(), files);
121
m_pDSOPathList.push_back(element);
128
if ( ( *pPath)[iRight] == ';' || // completed a path element with ';'
129
( ( *pPath)[iRight] == ':' && ( iRight - iLeft ) > 1) ) // completed a path element ':'
136
//---------------------------------------------------------------------
137
/** This returns a list of descriptors of calls to external DSO functions that
138
* implement a named shadeop, entries are returned for each polymorphic function
140
std::list<SqDSOExternalCall*>*
141
CqDSORepository::getShadeOpMethods(CqString* pShadeOpName)
143
CqString strTableSymbol = *pShadeOpName + "_shadeops" ;
145
std::list<SqDSOExternalCall*>* oplist = new (std::list<SqDSOExternalCall*>);
146
std::list<CqString*>::iterator itPathEntry;
147
SqShadeOp *pTableSymbol = NULL;
150
for ( itPathEntry = m_pDSOPathList.begin() ; itPathEntry != m_pDSOPathList.end() ; itPathEntry++ )
152
void *handle = DLOpen( (*itPathEntry) );
156
pTableSymbol = (SqShadeOp*) DLSym( handle, &strTableSymbol );
158
if ( pTableSymbol != NULL )
160
//We have an appropriate named shadeop table
161
SqShadeOp *pShadeOp = (SqShadeOp*) pTableSymbol;
162
while( ( pShadeOp->m_opspec )[0] != (char) NULL )
164
SqDSOExternalCall *pDSOCall = NULL;
165
pDSOCall = parseShadeOpTableEntry( handle, pShadeOp );
166
if ( pDSOCall != NULL )
167
oplist->push_back( pDSOCall );
173
// Failure here does not neccesarily mean anything since
177
CqString strError = DLError();
178
std::cerr << error << "DLOpen: " << strError.c_str() << std::endl;
181
return ( oplist->empty() ? NULL : oplist );
184
//---------------------------------------------------------------------
185
/** We have found a plugins with the desried shadeop table in it
186
* For each shaeop table entry we parse the prototype and validate all
187
* symbols that are named by the shadeop entry.
191
CqDSORepository::parseShadeOpTableEntry(void* handle, SqShadeOp* pShadeOpEntry){
193
TqInt length = strlen(pShadeOpEntry->m_opspec)+1;
195
strncpy(temp, pShadeOpEntry->m_opspec,length);
197
// We remove all the '(),' charachters, so we are left with
198
// returntype name argtype ...
199
for (int x = 0; x < length; x++)
200
if(temp[x]=='('||temp[x]==')'||temp[x]==',')temp[x]=' ';
202
CqString strSpec(temp);
204
// Get the return type of the function
205
std::string strRetType;
208
strRetType = strtok(temp, " ");
209
m_itTypeNameMap = m_TypeNameMap.find(strRetType.c_str());
211
// ERROR if we cant find this types name;
212
if (m_itTypeNameMap == m_TypeNameMap.end())
214
std::cerr << warning << "Discarding DSO Table entry due to unsupported return type: \"" << strRetType.c_str() << "\"" << std::endl;
217
EqVariableType rettype = (*m_itTypeNameMap).second;
221
std::string strMethodName;
223
strMethodName = strtok(NULL, " ");
224
CqString s = strMethodName.c_str();
225
DSOMethod method = (DSOMethod) DLSym (handle,&s);
228
std::cerr << warning << "Discarding DSO Table entry due to unknown symbol for method: \"" << strMethodName.c_str() << "\"" << std::endl;
233
// Parse each arg type, presumably we need to handle arrays here
234
std::list<EqVariableType> arglist;
235
char *nextarg = NULL;
238
// Get the next arguments type
239
std::string strArgType;
241
nextarg = strtok(NULL, " ");
242
if (nextarg == NULL) break;
243
strArgType = nextarg;
244
m_itTypeNameMap = m_TypeNameMap.find(strArgType.c_str());
246
// ERROR if we cant find this arguments type name;
247
if (m_itTypeNameMap == m_TypeNameMap.end())
249
std::cerr << warning << "Discarding DSO Table entry due to unsupported argument type: \"" << strArgType.c_str() << "\"" << std::endl;
252
arglist.push_back((*m_itTypeNameMap).second);
256
// Check if there is a valid init function
257
CqString strInit = pShadeOpEntry->m_init;
258
DSOInit initfunc = NULL;
259
if (strcmp(pShadeOpEntry->m_init,""))
261
initfunc = (DSOInit) DLSym(handle,&strInit);
262
if (initfunc == NULL)
264
std::cerr << warning << "Discarding DSO Table entry due to unknown symbol for init: \"" << strInit.c_str() << "\"" << std::endl;
265
return NULL; // ERROR ;
269
// Check if there is a valid shutdown function
270
CqString strShutdown = pShadeOpEntry->m_shutdown;
271
DSOShutdown shutdownfunc = NULL;
272
if (strcmp(pShadeOpEntry->m_shutdown,""))
274
shutdownfunc = (DSOShutdown) DLSym(handle,&strShutdown);
275
if (shutdownfunc == NULL)
277
std::cerr << warning << "Discarding DSO Table entry due to unknown symbol for shutdown: \"" << strShutdown.c_str() << "\"" << std::endl;
278
return NULL; // ERROR ;
283
// We have a valid shadeop implementation
284
SqDSOExternalCall *ret = new SqDSOExternalCall;
285
ret->method = method;
286
ret->init = initfunc;
287
ret->shutdown = shutdownfunc;
288
ret->return_type = rettype;
289
ret->arg_types = arglist;
290
ret->initData = NULL;
291
ret->initialised = false;
297
END_NAMESPACE( Aqsis )
298
//---------------------------------------------------------------------