8 void CFunction::Set(funcid_t funcid, CPlugin *plugin)
13 m_errorstate = SP_ERROR_NONE;
16 int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
18 IPluginContext *ctx = m_pPlugin->m_ctx_current.base;
22 ctx->PushCell(params[num_params]);
25 return ctx->Execute(m_funcid, result);
28 IPlugin *CFunction::GetParentPlugin()
33 CFunction::CFunction(funcid_t funcid, CPlugin *plugin) :
34 m_funcid(funcid), m_pPlugin(plugin), m_curparam(0),
35 m_errorstate(SP_ERROR_NONE)
39 int CFunction::PushCell(cell_t cell)
41 if (m_curparam >= SP_MAX_EXEC_PARAMS)
43 return SetError(SP_ERROR_PARAMS_MAX);
46 m_info[m_curparam].marked = false;
47 m_params[m_curparam] = cell;
53 int CFunction::PushCellByRef(cell_t *cell, int flags)
55 if (m_curparam >= SP_MAX_EXEC_PARAMS)
57 return SetError(SP_ERROR_PARAMS_MAX);
60 return PushArray(cell, 1, NULL, flags);
63 int CFunction::PushFloat(float number)
65 cell_t val = *(cell_t *)&number;
70 int CFunction::PushFloatByRef(float *number, int flags)
72 return PushCellByRef((cell_t *)number, flags);
75 int CFunction::PushCells(cell_t array[], unsigned int numcells, bool each)
79 return PushArray(array, numcells, NULL, SMFUNC_COPYBACK_NONE);
82 for (unsigned int i=0; i<numcells; i++)
84 if ((err=PushCell(array[i])) != SP_ERROR_NONE)
93 int CFunction::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int copyback)
95 if (m_curparam >= SP_MAX_EXEC_PARAMS)
97 return SetError(SP_ERROR_PARAMS_MAX);
100 IPluginContext *ctx = m_pPlugin->m_ctx_current.base;
101 ParamInfo *info = &m_info[m_curparam];
104 if ((err=ctx->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
106 return SetError(err);
109 info->flags = (inarray || (copyback & SMFUNC_COPYBACK_ALWAYS)) ? copyback : SMFUNC_COPYBACK_NONE;
112 m_params[m_curparam] = info->local_addr;
117 if (!(copyback & SMFUNC_ARRAY_NOINIT))
119 memcpy(info->phys_addr, inarray, sizeof(cell_t) * cells);
121 info->orig_addr = inarray;
123 info->orig_addr = info->phys_addr;
128 *phys_addr = info->phys_addr;
134 int CFunction::PushString(const char *string)
136 return _PushString(string, SMFUNC_COPYBACK_NONE);
139 int CFunction::PushStringByRef(char *string, int flags)
141 return _PushString(string, flags);
144 int CFunction::_PushString(const char *string, int flags)
146 if (m_curparam >= SP_MAX_EXEC_PARAMS)
148 return SetError(SP_ERROR_PARAMS_MAX);
151 IPluginContext *base = m_pPlugin->m_ctx_current.base;
152 ParamInfo *info = &m_info[m_curparam];
153 size_t len = strlen(string);
154 size_t cells = (len + sizeof(cell_t) - 1) / sizeof(cell_t);
157 if ((err=base->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
159 return SetError(err);
163 m_params[m_curparam] = info->local_addr;
164 m_curparam++; /* Prevent a leak */
166 //:TODO: Use UTF-8 version
167 if ((err=base->StringToLocal(info->local_addr, len, string)) != SP_ERROR_NONE)
169 return SetError(err);
173 info->orig_addr = (cell_t *)string;
176 return SP_ERROR_NONE;
179 void CFunction::Cancel()
186 IPluginContext *base = m_pPlugin->m_ctx_current.base;
190 if (m_info[m_curparam].marked)
192 base->HeapRelease(m_info[m_curparam].local_addr);
193 m_info[m_curparam].marked = false;
197 m_errorstate = SP_ERROR_NONE;
200 int CFunction::Execute(cell_t *result, IFunctionCopybackReader *reader)
203 if (m_errorstate != SP_ERROR_NONE)
210 //This is for re-entrancy!
211 cell_t temp_params[SP_MAX_EXEC_PARAMS];
212 ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
213 unsigned int numparams = m_curparam;
214 bool docopies = true;
218 //Save the info locally, then reset it for re-entrant calls.
219 memcpy(temp_params, m_params, numparams * sizeof(cell_t));
220 memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
224 if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
229 IPluginContext *base = m_pPlugin->m_ctx_current.base;
233 if (!temp_info[numparams].marked)
237 if (docopies && temp_info[numparams].flags)
241 if (!reader->OnCopybackArray(numparams,
242 temp_info[numparams].size,
243 temp_info[numparams].phys_addr,
244 temp_info[numparams].orig_addr,
245 temp_info[numparams].flags))
250 if (temp_info[numparams].orig_addr)
252 if (temp_info[numparams].size == 1)
254 *temp_info[numparams].orig_addr = *temp_info[numparams].phys_addr;
256 memcpy(temp_info[numparams].orig_addr,
257 temp_info[numparams].phys_addr,
258 temp_info[numparams].size * sizeof(cell_t));
263 base->HeapPop(temp_info[numparams].local_addr);
264 temp_info[numparams].marked = false;
270 cell_t *CFunction::GetAddressOfPushedParam(unsigned int param)
272 if (m_errorstate != SP_ERROR_NONE
273 || param >= m_curparam
274 || !m_info[param].marked)
279 return m_info[param].phys_addr;