Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.
(This day shall henceforth be known as the Eighty Column Massacre of '07)
3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
34 #include "sp_vm_function.h"
40 void CFunction::Set(uint32_t code_addr, IPluginContext *plugin)
42 m_codeaddr = code_addr;
45 m_errorstate = SP_ERROR_NONE;
47 m_pCtx = plugin ? plugin->GetContext() : NULL;
50 bool CFunction::IsRunnable()
52 return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED);
55 int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
59 return SP_ERROR_NOT_RUNNABLE;
64 m_pContext->PushCell(params[num_params]);
67 return m_pContext->Execute(m_codeaddr, result);
70 IPluginContext *CFunction::GetParentContext()
75 CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin) :
76 m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
77 m_errorstate(SP_ERROR_NONE)
82 m_pCtx = plugin->GetContext();
86 int CFunction::PushCell(cell_t cell)
88 if (m_curparam >= SP_MAX_EXEC_PARAMS)
90 return SetError(SP_ERROR_PARAMS_MAX);
93 m_info[m_curparam].marked = false;
94 m_params[m_curparam] = cell;
100 int CFunction::PushCellByRef(cell_t *cell, int flags)
102 return PushArray(cell, 1, flags);
105 int CFunction::PushFloat(float number)
107 cell_t val = *(cell_t *)&number;
109 return PushCell(val);
112 int CFunction::PushFloatByRef(float *number, int flags)
114 return PushCellByRef((cell_t *)number, flags);
117 int CFunction::PushArray(cell_t *inarray, unsigned int cells, int copyback)
119 if (m_curparam >= SP_MAX_EXEC_PARAMS)
121 return SetError(SP_ERROR_PARAMS_MAX);
124 ParamInfo *info = &m_info[m_curparam];
126 info->flags = inarray ? copyback : 0;
129 info->str.is_sz = false;
130 info->orig_addr = inarray;
134 return SP_ERROR_NONE;
137 int CFunction::PushString(const char *string)
139 return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
142 int CFunction::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
144 return _PushString(buffer, sz_flags, cp_flags, length);
147 int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
149 if (m_curparam >= SP_MAX_EXEC_PARAMS)
151 return SetError(SP_ERROR_PARAMS_MAX);
154 ParamInfo *info = &m_info[m_curparam];
157 info->orig_addr = (cell_t *)string;
158 info->flags = cp_flags;
160 info->str.sz_flags = sz_flags;
161 info->str.is_sz = true;
165 return SP_ERROR_NONE;
168 void CFunction::Cancel()
175 m_errorstate = SP_ERROR_NONE;
179 int CFunction::Execute(cell_t *result)
181 int err = SP_ERROR_NONE;
184 m_errorstate = SP_ERROR_NOT_RUNNABLE;
186 if (m_errorstate != SP_ERROR_NONE)
193 //This is for re-entrancy!
194 cell_t temp_params[SP_MAX_EXEC_PARAMS];
195 ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
196 unsigned int numparams = m_curparam;
198 bool docopies = true;
202 //Save the info locally, then reset it for re-entrant calls.
203 memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
207 /* Browse the parameters and build arrays */
208 for (i=0; i<numparams; i++)
210 /* Is this marked as an array? */
211 if (temp_info[i].marked)
213 if (!temp_info[i].str.is_sz)
215 /* Allocate a normal/generic array */
216 if ((err=m_pContext->HeapAlloc(temp_info[i].size,
217 &(temp_info[i].local_addr),
218 &(temp_info[i].phys_addr)))
223 if (temp_info[i].orig_addr)
225 memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
228 /* Calculate cells required for the string */
229 size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
231 /* Allocate the buffer */
232 if ((err=m_pContext->HeapAlloc(cells,
233 &(temp_info[i].local_addr),
234 &(temp_info[i].phys_addr)))
239 /* Copy original string if necessary */
240 if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
242 if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
244 if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr,
246 (const char *)temp_info[i].orig_addr,
253 if ((err=m_pContext->StringToLocal(temp_info[i].local_addr,
255 (const char *)temp_info[i].orig_addr))
262 } /* End array/string calculation */
263 /* Update the pushed parameter with the byref local address */
264 temp_params[i] = temp_info[i].local_addr;
266 /* Just copy the value normally */
267 temp_params[i] = m_params[i];
271 /* Make the call if we can */
272 if (err == SP_ERROR_NONE)
274 if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
282 /* i should be equal to the last valid parameter + 1 */
285 if (!temp_info[i].marked)
289 if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
291 if (temp_info[i].orig_addr)
293 if (temp_info[i].str.is_sz)
295 memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
297 if (temp_info[i].size == 1)
299 *temp_info[i].orig_addr = *(temp_info[i].phys_addr);
301 memcpy(temp_info[i].orig_addr,
302 temp_info[i].phys_addr,
303 temp_info[i].size * sizeof(cell_t));
308 if ((err=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)