dvander@177: #include dvander@177: #include "PluginSys.h" dvander@177: dvander@177: /******************** dvander@177: * FUNCTION CALLING * dvander@177: ********************/ dvander@177: dvander@177: void CFunction::Set(funcid_t funcid, CPlugin *plugin) dvander@177: { dvander@177: m_funcid = funcid; dvander@177: m_pPlugin = plugin; dvander@177: m_curparam = 0; dvander@177: m_errorstate = SP_ERROR_NONE; dvander@177: } dvander@177: dvander@177: int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) dvander@177: { dvander@209: IPluginContext *ctx = m_pPlugin->m_ctx.base; dvander@177: dvander@177: while (num_params--) dvander@177: { dvander@177: ctx->PushCell(params[num_params]); dvander@177: } dvander@177: dvander@177: return ctx->Execute(m_funcid, result); dvander@177: } dvander@177: dvander@177: IPlugin *CFunction::GetParentPlugin() dvander@177: { dvander@177: return m_pPlugin; dvander@177: } dvander@177: dvander@177: CFunction::CFunction(funcid_t funcid, CPlugin *plugin) : dvander@177: m_funcid(funcid), m_pPlugin(plugin), m_curparam(0), dvander@177: m_errorstate(SP_ERROR_NONE) dvander@177: { dvander@177: } dvander@177: dvander@177: int CFunction::PushCell(cell_t cell) dvander@177: { dvander@177: if (m_curparam >= SP_MAX_EXEC_PARAMS) dvander@177: { dvander@177: return SetError(SP_ERROR_PARAMS_MAX); dvander@177: } dvander@177: dvander@177: m_info[m_curparam].marked = false; dvander@177: m_params[m_curparam] = cell; dvander@177: m_curparam++; dvander@177: dvander@177: return SP_ERROR_NONE; dvander@177: } dvander@177: dvander@177: int CFunction::PushCellByRef(cell_t *cell, int flags) dvander@177: { dvander@177: if (m_curparam >= SP_MAX_EXEC_PARAMS) dvander@177: { dvander@177: return SetError(SP_ERROR_PARAMS_MAX); dvander@177: } dvander@177: dvander@177: return PushArray(cell, 1, NULL, flags); dvander@177: } dvander@177: dvander@177: int CFunction::PushFloat(float number) dvander@177: { dvander@177: cell_t val = *(cell_t *)&number; dvander@177: dvander@177: return PushCell(val); dvander@177: } dvander@177: dvander@177: int CFunction::PushFloatByRef(float *number, int flags) dvander@177: { dvander@177: return PushCellByRef((cell_t *)number, flags); dvander@177: } dvander@177: dvander@177: int CFunction::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int copyback) dvander@177: { dvander@177: if (m_curparam >= SP_MAX_EXEC_PARAMS) dvander@177: { dvander@177: return SetError(SP_ERROR_PARAMS_MAX); dvander@177: } dvander@177: dvander@209: IPluginContext *ctx = m_pPlugin->m_ctx.base; dvander@177: ParamInfo *info = &m_info[m_curparam]; dvander@177: int err; dvander@177: dvander@177: if ((err=ctx->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE) dvander@177: { dvander@177: return SetError(err); dvander@177: } dvander@177: dvander@183: info->flags = inarray ? copyback : 0; dvander@177: info->marked = true; dvander@296: info->size = cells * sizeof(cell_t); dvander@177: m_params[m_curparam] = info->local_addr; dvander@177: m_curparam++; dvander@177: dvander@177: if (inarray) dvander@177: { dvander@183: memcpy(info->phys_addr, inarray, sizeof(cell_t) * cells); dvander@177: info->orig_addr = inarray; dvander@177: } else { dvander@177: info->orig_addr = info->phys_addr; dvander@177: } dvander@177: dvander@177: if (phys_addr) dvander@177: { dvander@177: *phys_addr = info->phys_addr; dvander@177: } dvander@177: dvander@177: return true; dvander@177: } dvander@177: dvander@177: int CFunction::PushString(const char *string) dvander@177: { dvander@211: return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1); dvander@177: } dvander@177: faluco@192: int CFunction::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) dvander@177: { faluco@192: return _PushString(buffer, sz_flags, cp_flags, length); dvander@177: } dvander@177: faluco@192: int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_t len) dvander@177: { dvander@177: if (m_curparam >= SP_MAX_EXEC_PARAMS) dvander@177: { dvander@177: return SetError(SP_ERROR_PARAMS_MAX); dvander@177: } dvander@177: dvander@209: IPluginContext *base = m_pPlugin->m_ctx.base; dvander@177: ParamInfo *info = &m_info[m_curparam]; faluco@192: size_t cells = (len + sizeof(cell_t) - 1) / sizeof(cell_t); dvander@177: int err; dvander@177: dvander@177: if ((err=base->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE) dvander@177: { dvander@177: return SetError(err); dvander@177: } dvander@177: dvander@177: info->marked = true; dvander@177: m_params[m_curparam] = info->local_addr; dvander@177: m_curparam++; /* Prevent a leak */ dvander@177: dvander@211: if (!(sz_flags & SM_PARAM_STRING_COPY)) dvander@177: { faluco@192: goto skip_localtostr; dvander@177: } dvander@177: dvander@211: if (sz_flags & SM_PARAM_STRING_UTF8) faluco@192: { faluco@192: if ((err=base->StringToLocalUTF8(info->local_addr, len, string, NULL)) != SP_ERROR_NONE) faluco@192: { faluco@192: return SetError(err); faluco@192: } faluco@192: } else { faluco@192: if ((err=base->StringToLocal(info->local_addr, len, string)) != SP_ERROR_NONE) faluco@192: { faluco@192: return SetError(err); faluco@192: } faluco@192: } faluco@192: faluco@192: skip_localtostr: faluco@192: info->flags = cp_flags; dvander@177: info->orig_addr = (cell_t *)string; dvander@296: info->size = len; dvander@177: dvander@177: return SP_ERROR_NONE; dvander@177: } dvander@177: dvander@177: void CFunction::Cancel() dvander@177: { dvander@177: if (!m_curparam) dvander@177: { dvander@177: return; dvander@177: } dvander@177: dvander@209: IPluginContext *base = m_pPlugin->m_ctx.base; dvander@177: dvander@177: while (m_curparam--) dvander@177: { dvander@177: if (m_info[m_curparam].marked) dvander@177: { dvander@177: base->HeapRelease(m_info[m_curparam].local_addr); dvander@177: m_info[m_curparam].marked = false; dvander@177: } dvander@177: } dvander@177: dvander@177: m_errorstate = SP_ERROR_NONE; dvander@177: } dvander@177: dvander@183: int CFunction::Execute(cell_t *result) dvander@177: { dvander@177: int err; dvander@177: if (m_errorstate != SP_ERROR_NONE) dvander@177: { dvander@177: err = m_errorstate; dvander@177: Cancel(); dvander@177: return err; dvander@177: } dvander@177: dvander@177: //This is for re-entrancy! dvander@177: cell_t temp_params[SP_MAX_EXEC_PARAMS]; dvander@177: ParamInfo temp_info[SP_MAX_EXEC_PARAMS]; dvander@177: unsigned int numparams = m_curparam; dvander@177: bool docopies = true; dvander@177: dvander@177: if (numparams) dvander@177: { dvander@177: //Save the info locally, then reset it for re-entrant calls. dvander@177: memcpy(temp_params, m_params, numparams * sizeof(cell_t)); dvander@177: memcpy(temp_info, m_info, numparams * sizeof(ParamInfo)); dvander@177: } dvander@177: m_curparam = 0; dvander@177: dvander@177: if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE) dvander@177: { dvander@177: docopies = false; dvander@177: } dvander@177: dvander@209: IPluginContext *base = m_pPlugin->m_ctx.base; dvander@177: dvander@177: while (numparams--) dvander@177: { dvander@177: if (!temp_info[numparams].marked) dvander@177: { dvander@177: continue; dvander@177: } dvander@177: if (docopies && temp_info[numparams].flags) dvander@177: { dvander@177: if (temp_info[numparams].orig_addr) dvander@177: { dvander@296: if (temp_info[numparams].size == sizeof(cell_t)) dvander@180: { dvander@180: *temp_info[numparams].orig_addr = *temp_info[numparams].phys_addr; dvander@180: } else { dvander@180: memcpy(temp_info[numparams].orig_addr, dvander@180: temp_info[numparams].phys_addr, dvander@296: temp_info[numparams].size); dvander@180: } dvander@177: } dvander@177: } dvander@181: base->HeapPop(temp_info[numparams].local_addr); dvander@177: temp_info[numparams].marked = false; dvander@177: } dvander@177: dvander@177: return err; dvander@177: } dvander@177: dvander@177: cell_t *CFunction::GetAddressOfPushedParam(unsigned int param) dvander@177: { dvander@177: if (m_errorstate != SP_ERROR_NONE dvander@177: || param >= m_curparam dvander@177: || !m_info[param].marked) dvander@177: { dvander@177: return NULL; dvander@177: } dvander@177: dvander@177: return m_info[param].phys_addr; dvander@177: }