core/systems/ForwardSys.cpp
author David Anderson <dvander@alliedmods.net>
Wed Aug 15 20:18:15 2007 +0000 (2007-08-15)
changeset 1339 02e8f2c0f8af
parent 1330 ab94316bb52b
child 1947 e73a1e51833b
permissions -rw-r--r--
SourceMod will now spit out errors for scripts that become corrupt and would otherwise be crashing Core. if you get these errors contact the dev team.
ds@730
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
dvander@180
    32
#include <assert.h>
dvander@351
    33
#include <stdarg.h>
dvander@351
    34
#include <string.h>
dvander@180
    35
#include "ForwardSys.h"
dvander@180
    36
#include "PluginSys.h"
dvander@336
    37
#include "ShareSys.h"
dvander@1339
    38
#include "DebugReporter.h"
dvander@180
    39
dvander@186
    40
CForwardManager g_Forwards;
dvander@186
    41
dvander@183
    42
/**
ds@729
    43
 * Genesis turns to its source, reduction occurs stepwise although the essence is all one.
dvander@183
    44
 * End of line.  FTL system check.
dvander@183
    45
 *
dvander@282
    46
 * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
dvander@183
    47
 * VARARG FUNCTIONS:
dvander@183
    48
 * - Pushing no varargs
dvander@183
    49
 */
dvander@183
    50
faluco@226
    51
// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
faluco@226
    52
// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
faluco@226
    53
faluco@641
    54
CForwardManager::~CForwardManager()
faluco@641
    55
{
faluco@641
    56
	CStack<CForward *>::iterator iter;
faluco@641
    57
	for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
faluco@641
    58
	{
faluco@641
    59
		delete (*iter);
faluco@641
    60
	}
faluco@641
    61
	m_FreeForwards.popall();
faluco@641
    62
}
faluco@641
    63
dvander@211
    64
void CForwardManager::OnSourceModAllInitialized()
dvander@211
    65
{
dvander@211
    66
	g_PluginSys.AddPluginsListener(this);
dvander@336
    67
	g_ShareSys.AddInterface(NULL, this);
dvander@211
    68
}
dvander@211
    69
ds@559
    70
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
dvander@186
    71
{
dvander@186
    72
	CForward *fwd;
dvander@186
    73
	va_list ap;
dvander@186
    74
	va_start(ap, types);
dvander@186
    75
	
dvander@186
    76
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    77
dvander@186
    78
	va_end(ap);
dvander@186
    79
dvander@211
    80
	if (fwd)
dvander@211
    81
	{
ds@611
    82
		g_PluginSys.AddFunctionsToForward(name, fwd);
ds@611
    83
dvander@211
    84
		m_managed.push_back(fwd);
dvander@211
    85
	}
dvander@211
    86
dvander@186
    87
	return fwd;
dvander@186
    88
}
dvander@186
    89
ds@559
    90
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
dvander@186
    91
{
dvander@186
    92
	CForward *fwd;
dvander@186
    93
	va_list ap;
dvander@186
    94
	va_start(ap, types);
dvander@186
    95
dvander@186
    96
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    97
dvander@186
    98
	va_end(ap);
dvander@186
    99
dvander@211
   100
	if (fwd)
dvander@211
   101
	{
dvander@211
   102
		m_unmanaged.push_back(fwd);
dvander@211
   103
	}
dvander@211
   104
dvander@186
   105
	return fwd;
dvander@186
   106
}
dvander@186
   107
dvander@211
   108
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
dvander@211
   109
{
dvander@211
   110
	/* Attach any globally managed forwards */
dvander@211
   111
	List<CForward *>::iterator iter;
dvander@211
   112
	CForward *fwd;
dvander@211
   113
dvander@211
   114
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@211
   115
	{
dvander@211
   116
		fwd = (*iter);
dvander@327
   117
		IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
dvander@211
   118
		if (pFunc)
dvander@211
   119
		{
dvander@211
   120
			fwd->AddFunction(pFunc);
dvander@211
   121
		}
dvander@211
   122
	}
dvander@211
   123
}
dvander@211
   124
dvander@211
   125
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
dvander@211
   126
{
dvander@211
   127
	List<CForward *>::iterator iter;
dvander@211
   128
	CForward *fwd;
dvander@211
   129
dvander@211
   130
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@211
   131
	{
dvander@211
   132
		fwd = (*iter);
dvander@211
   133
		fwd->RemoveFunctionsOfPlugin(plugin);
dvander@211
   134
	}
dvander@232
   135
dvander@232
   136
	for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
dvander@232
   137
	{
dvander@232
   138
		fwd = (*iter);
dvander@232
   139
		fwd->RemoveFunctionsOfPlugin(plugin);
dvander@232
   140
	}
dvander@211
   141
}
dvander@211
   142
dvander@186
   143
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
dvander@186
   144
{
dvander@186
   145
	List<CForward *>::iterator iter;
dvander@186
   146
	CForward *fwd;
dvander@186
   147
dvander@186
   148
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@186
   149
	{
dvander@186
   150
		fwd = (*iter);
dvander@186
   151
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
   152
		{
dvander@186
   153
			if (ifchng)
dvander@186
   154
			{
dvander@186
   155
				*ifchng = NULL;
dvander@186
   156
			}
dvander@186
   157
			return fwd;
dvander@186
   158
		}
dvander@186
   159
	}
dvander@186
   160
dvander@186
   161
	for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
dvander@186
   162
	{
dvander@186
   163
		fwd = (*iter);
dvander@186
   164
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
   165
		{
dvander@186
   166
			if (ifchng)
dvander@186
   167
			{
dvander@186
   168
				*ifchng = fwd;
dvander@186
   169
			}
dvander@186
   170
			return fwd;
dvander@186
   171
		}
dvander@186
   172
	}
dvander@186
   173
dvander@186
   174
	if (ifchng)
dvander@186
   175
	{
dvander@186
   176
		*ifchng = NULL;
dvander@186
   177
	}
dvander@186
   178
dvander@186
   179
	return NULL;
dvander@186
   180
}
dvander@186
   181
dvander@186
   182
void CForwardManager::ReleaseForward(IForward *forward)
dvander@186
   183
{
dvander@186
   184
	ForwardFree(static_cast<CForward *>(forward));
dvander@186
   185
}
dvander@186
   186
dvander@186
   187
void CForwardManager::ForwardFree(CForward *fwd)
dvander@186
   188
{
dvander@186
   189
	m_FreeForwards.push(fwd);
faluco@291
   190
	m_managed.remove(fwd);
dvander@186
   191
}
dvander@186
   192
dvander@186
   193
CForward *CForwardManager::ForwardMake()
dvander@186
   194
{
dvander@186
   195
	CForward *fwd;
dvander@186
   196
	if (m_FreeForwards.empty())
dvander@186
   197
	{
dvander@186
   198
		fwd = new CForward;
dvander@186
   199
	} else {
dvander@186
   200
		fwd = m_FreeForwards.front();
dvander@186
   201
		m_FreeForwards.pop();
dvander@186
   202
	}
dvander@186
   203
	return fwd;
dvander@186
   204
}
dvander@186
   205
faluco@430
   206
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
faluco@430
   207
{
dvander@526
   208
	/* No longer used */
faluco@430
   209
}
faluco@430
   210
dvander@186
   211
/*************************************
dvander@186
   212
 * ACTUAL FORWARD API IMPLEMENTATION *
dvander@186
   213
 *************************************/
dvander@186
   214
ds@559
   215
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
dvander@180
   216
{
dvander@180
   217
	ParamType _types[SP_MAX_EXEC_PARAMS];
dvander@180
   218
dvander@180
   219
	if (num_params > SP_MAX_EXEC_PARAMS)
dvander@180
   220
	{
dvander@180
   221
		return NULL;
dvander@180
   222
	}
dvander@180
   223
	
dvander@180
   224
	if (types == NULL && num_params)
dvander@180
   225
	{
dvander@180
   226
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   227
		{
dvander@351
   228
			_types[i] = (ParamType)va_arg(ap, int);
dvander@180
   229
			if (_types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   230
			{
dvander@180
   231
				return NULL;
dvander@180
   232
			}
dvander@180
   233
		}
dvander@180
   234
		types = _types;
dvander@180
   235
	} else {
dvander@180
   236
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   237
		{
dvander@529
   238
			_types[i] = types[i];
dvander@180
   239
			if (types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   240
			{
dvander@180
   241
				return NULL;
dvander@180
   242
			}
dvander@180
   243
		}
dvander@180
   244
	}
dvander@180
   245
dvander@180
   246
	/* First parameter can never be varargs */
dvander@529
   247
	if (num_params && _types[0] == Param_VarArgs)
dvander@180
   248
	{
dvander@180
   249
		return NULL;
dvander@180
   250
	}
dvander@180
   251
dvander@186
   252
	CForward *pForward = g_Forwards.ForwardMake();
dvander@180
   253
	pForward->m_curparam = 0;
dvander@180
   254
	pForward->m_ExecType = et;
dvander@180
   255
	snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
dvander@180
   256
	
dvander@180
   257
	for (unsigned int i=0; i<num_params; i++)
dvander@180
   258
	{
dvander@529
   259
		pForward->m_types[i] = _types[i];
dvander@180
   260
	}
dvander@180
   261
dvander@529
   262
	if (num_params && _types[num_params-1] == Param_VarArgs)
dvander@180
   263
	{
dvander@183
   264
		pForward->m_varargs = num_params--;
dvander@180
   265
	} else {
dvander@180
   266
		pForward->m_varargs = false;
dvander@180
   267
	}
dvander@180
   268
dvander@180
   269
	pForward->m_numparams = num_params;
dvander@180
   270
	pForward->m_errstate = SP_ERROR_NONE;
dvander@180
   271
dvander@961
   272
	pForward->m_functions.clear();
dvander@961
   273
dvander@180
   274
	return pForward;
dvander@180
   275
}
dvander@180
   276
dvander@180
   277
int CForward::Execute(cell_t *result, IForwardFilter *filter)
dvander@180
   278
{
dvander@180
   279
	if (m_errstate)
dvander@180
   280
	{
dvander@180
   281
		int err = m_errstate;
dvander@180
   282
		Cancel();
dvander@180
   283
		return err;
dvander@180
   284
	}
dvander@180
   285
dvander@180
   286
	if (filter)
dvander@180
   287
	{
dvander@180
   288
		filter->OnExecuteBegin();
dvander@180
   289
	}
dvander@180
   290
dvander@180
   291
	FuncIter iter = m_functions.begin();
dvander@180
   292
	IPluginFunction *func;
dvander@180
   293
	cell_t cur_result = 0;
dvander@180
   294
	cell_t high_result = 0;
dvander@180
   295
	int err;
dvander@180
   296
	unsigned int failed=0, success=0;
dvander@183
   297
	unsigned int num_params = m_curparam;
dvander@183
   298
	FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
dvander@183
   299
	FwdParamInfo *param;
dvander@183
   300
	ParamType type;
dvander@180
   301
dvander@183
   302
	/* Save local, reset */
dvander@183
   303
	memcpy(temp_info, m_params, sizeof(m_params));
dvander@183
   304
	m_curparam = 0;
dvander@183
   305
dvander@180
   306
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   307
	{
dvander@180
   308
		func = (*iter);
dvander@183
   309
dvander@183
   310
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   311
		{
dvander@1339
   312
			int err = SP_ERROR_PARAM;
dvander@183
   313
			param = &temp_info[i];
dvander@183
   314
			if (i >= m_numparams || m_types[i] == Param_Any)
dvander@183
   315
			{
dvander@183
   316
				type = param->pushedas;
dvander@183
   317
			} else {
dvander@183
   318
				type = m_types[i];
dvander@183
   319
			}
dvander@183
   320
			if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
dvander@180
   321
			{
dvander@183
   322
				/* If we're byref or we're vararg, we always push everything by ref.
dvander@183
   323
				 * Even if they're byval, we must push them byref.
dvander@183
   324
				 */
faluco@192
   325
				if (type == Param_String)
dvander@180
   326
				{
dvander@1339
   327
					err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
dvander@183
   328
				} else if (type == Param_Float || type == Param_Cell) {
dvander@1339
   329
					err = func->PushCellByRef(&param->val); 
dvander@183
   330
				} else {
dvander@1339
   331
					err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
dvander@183
   332
					assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
dvander@180
   333
				}
dvander@183
   334
			} else {
dvander@183
   335
				/* If we're not byref or not vararg, our job is a bit easier. */
dvander@183
   336
				assert(type == Param_Cell || type == Param_Float);
dvander@1339
   337
				err = func->PushCell(param->val);
dvander@1339
   338
			}
dvander@1339
   339
			if (err != SP_ERROR_NONE)
dvander@1339
   340
			{
dvander@1339
   341
				if (!filter || !filter->OnErrorReport(this, func, err))
dvander@1339
   342
				{
dvander@1339
   343
					g_DbgReporter.GenerateError(func->GetParentContext(), 
dvander@1339
   344
						func->GetFunctionID(), 
dvander@1339
   345
						err, 
dvander@1339
   346
						"Failed to push parameter while executing forward");
dvander@1339
   347
				}
dvander@1339
   348
				continue;
dvander@180
   349
			}
dvander@180
   350
		}
dvander@183
   351
		
dvander@211
   352
		/* Call the function and deal with the return value. */
dvander@183
   353
		if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
dvander@180
   354
		{
dvander@180
   355
			if (filter)
dvander@180
   356
			{
dvander@1339
   357
				filter->OnErrorReport(this, func, err);
dvander@180
   358
			}
dvander@180
   359
			failed++;
dvander@180
   360
		} else {
dvander@180
   361
			success++;
dvander@180
   362
			switch (m_ExecType)
dvander@180
   363
			{
dvander@180
   364
			case ET_Event:
dvander@180
   365
				{
dvander@180
   366
					if (cur_result > high_result)
dvander@180
   367
					{
dvander@180
   368
						high_result = cur_result;
dvander@180
   369
					}
dvander@180
   370
					break;
dvander@180
   371
				}
dvander@180
   372
			case ET_Hook:
dvander@180
   373
				{
dvander@180
   374
					if (cur_result > high_result)
dvander@180
   375
					{
dvander@180
   376
						high_result = cur_result;
dvander@180
   377
						if ((ResultType)high_result == Pl_Stop)
dvander@180
   378
						{
ds@1140
   379
							goto done;
dvander@180
   380
						}
dvander@180
   381
					}
dvander@180
   382
					break;
dvander@180
   383
				}
dvander@180
   384
			case ET_Custom:
dvander@180
   385
				{
dvander@180
   386
					if (filter)
dvander@180
   387
					{
dvander@180
   388
						if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
dvander@180
   389
						{
ds@1140
   390
							goto done;
dvander@180
   391
						}
dvander@180
   392
					}
dvander@180
   393
					break;
dvander@180
   394
				}
dvander@351
   395
			default:
dvander@351
   396
				{
dvander@351
   397
					break;
dvander@351
   398
				}
dvander@180
   399
			}
dvander@180
   400
		}
dvander@180
   401
	}
dvander@180
   402
ds@1140
   403
done:
dvander@447
   404
	if (success)
dvander@180
   405
	{
dvander@447
   406
		if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
dvander@447
   407
		{
dvander@447
   408
			cur_result = high_result;
dvander@447
   409
		} else if (m_ExecType == ET_Ignore) {
dvander@447
   410
			cur_result = 0;
dvander@447
   411
		}
dvander@447
   412
		if (result)
dvander@447
   413
		{
dvander@447
   414
			*result = cur_result;
dvander@447
   415
		}
dvander@180
   416
	}
dvander@180
   417
dvander@180
   418
	if (filter)
dvander@180
   419
	{
dvander@180
   420
		filter->OnExecuteEnd(&cur_result, success, failed);
dvander@180
   421
	}
dvander@180
   422
dvander@180
   423
	return SP_ERROR_NONE;
dvander@180
   424
}
dvander@180
   425
dvander@180
   426
int CForward::PushCell(cell_t cell)
dvander@180
   427
{
dvander@180
   428
	if (m_curparam < m_numparams)
dvander@180
   429
	{
dvander@183
   430
		if (m_types[m_curparam] == Param_Any)
dvander@180
   431
		{
dvander@183
   432
			m_params[m_curparam].pushedas = Param_Cell;
dvander@183
   433
		} else if (m_types[m_curparam] != Param_Cell) {
dvander@180
   434
			return SetError(SP_ERROR_PARAM);
dvander@180
   435
		}
dvander@180
   436
	} else {
dvander@180
   437
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   438
		{
dvander@180
   439
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   440
		}
dvander@183
   441
		m_params[m_curparam].pushedas = Param_Cell;
dvander@180
   442
	}
dvander@180
   443
dvander@183
   444
	m_params[m_curparam++].val = cell;
dvander@180
   445
dvander@180
   446
	return SP_ERROR_NONE;
dvander@180
   447
}
dvander@180
   448
dvander@180
   449
int CForward::PushFloat(float number)
dvander@180
   450
{
dvander@180
   451
	if (m_curparam < m_numparams)
dvander@180
   452
	{
dvander@183
   453
		if (m_types[m_curparam] == Param_Any)
dvander@180
   454
		{
dvander@183
   455
			m_params[m_curparam].pushedas = Param_Float;
dvander@183
   456
		} else if (m_types[m_curparam] != Param_Float) {
dvander@180
   457
			return SetError(SP_ERROR_PARAM);
dvander@180
   458
		}
dvander@180
   459
	} else {
dvander@180
   460
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   461
		{
dvander@180
   462
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   463
		}
dvander@183
   464
		m_params[m_curparam].pushedas = Param_Float;
dvander@180
   465
	}
dvander@180
   466
dvander@183
   467
	m_params[m_curparam++].val = *(cell_t *)&number;
dvander@180
   468
dvander@180
   469
	return SP_ERROR_NONE;
dvander@180
   470
}
dvander@180
   471
ds@585
   472
int CForward::PushCellByRef(cell_t *cell, int flags)
dvander@180
   473
{
dvander@180
   474
	if (m_curparam < m_numparams)
dvander@180
   475
	{
faluco@192
   476
		if (m_types[m_curparam] == Param_Any)
dvander@180
   477
		{
faluco@192
   478
			m_params[m_curparam].pushedas = Param_CellByRef;
faluco@192
   479
		} else if (m_types[m_curparam] != Param_CellByRef) {
dvander@180
   480
			return SetError(SP_ERROR_PARAM);
dvander@180
   481
		}
dvander@180
   482
	} else {
dvander@180
   483
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   484
		{
dvander@180
   485
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   486
		}
faluco@192
   487
		m_params[m_curparam].pushedas = Param_CellByRef;
dvander@180
   488
	}
dvander@180
   489
ds@585
   490
	_Int_PushArray(cell, 1, flags);
dvander@180
   491
	m_curparam++;
dvander@180
   492
dvander@180
   493
	return SP_ERROR_NONE;
dvander@180
   494
}
dvander@180
   495
ds@585
   496
int CForward::PushFloatByRef(float *num, int flags)
dvander@180
   497
{
dvander@180
   498
	if (m_curparam < m_numparams)
dvander@180
   499
	{
faluco@192
   500
		if (m_types[m_curparam] == Param_Any)
dvander@180
   501
		{
faluco@192
   502
			m_params[m_curparam].pushedas = Param_FloatByRef;
faluco@192
   503
		} else if (m_types[m_curparam] != Param_FloatByRef) {
dvander@180
   504
			return SetError(SP_ERROR_PARAM);
dvander@180
   505
		}
dvander@180
   506
	} else {
dvander@180
   507
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   508
		{
dvander@180
   509
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   510
		}
faluco@192
   511
		m_params[m_curparam].pushedas = Param_FloatByRef;
dvander@180
   512
	}
dvander@180
   513
ds@585
   514
	_Int_PushArray((cell_t *)num, 1, flags);
dvander@180
   515
	m_curparam++;
dvander@180
   516
dvander@180
   517
	return SP_ERROR_NONE;
dvander@180
   518
}
dvander@180
   519
dvander@180
   520
void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   521
{
dvander@183
   522
	m_params[m_curparam].byref.cells = cells;
dvander@183
   523
	m_params[m_curparam].byref.flags = flags;
dvander@183
   524
	m_params[m_curparam].byref.orig_addr = inarray;
dvander@180
   525
}
dvander@180
   526
dvander@589
   527
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   528
{
dvander@180
   529
	/* We don't allow this here */
dvander@180
   530
	if (!inarray)
dvander@180
   531
	{
dvander@180
   532
		return SetError(SP_ERROR_PARAM);
dvander@180
   533
	}
dvander@180
   534
dvander@180
   535
	if (m_curparam < m_numparams)
dvander@180
   536
	{
dvander@183
   537
		if (m_types[m_curparam] == Param_Any)
dvander@180
   538
		{
dvander@183
   539
			m_params[m_curparam].pushedas = Param_Array;
dvander@183
   540
		} else if (m_types[m_curparam] != Param_Array) {
dvander@180
   541
			return SetError(SP_ERROR_PARAM);
dvander@180
   542
		}
dvander@180
   543
	} else {
dvander@180
   544
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   545
		{
dvander@180
   546
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   547
		}
dvander@183
   548
		m_params[m_curparam].pushedas = Param_Array;
dvander@180
   549
	}
dvander@180
   550
dvander@180
   551
	_Int_PushArray(inarray, cells, flags);
dvander@180
   552
dvander@180
   553
	m_curparam++;
dvander@180
   554
dvander@180
   555
	return SP_ERROR_NONE;
dvander@180
   556
}
dvander@180
   557
faluco@192
   558
void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
faluco@192
   559
{
faluco@192
   560
	m_params[m_curparam].byref.cells = cells;	/* Notice this contains the char count not cell count */
faluco@192
   561
	m_params[m_curparam].byref.flags = cp_flags;
faluco@192
   562
	m_params[m_curparam].byref.orig_addr = inarray;
faluco@192
   563
	m_params[m_curparam].byref.sz_flags = sz_flags;
faluco@192
   564
}
faluco@192
   565
dvander@180
   566
int CForward::PushString(const char *string)
dvander@180
   567
{
dvander@180
   568
	if (m_curparam < m_numparams)
dvander@180
   569
	{
dvander@183
   570
		if (m_types[m_curparam] == Param_Any)
dvander@180
   571
		{
dvander@183
   572
			m_params[m_curparam].pushedas = Param_String;
faluco@188
   573
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   574
			return SetError(SP_ERROR_PARAM);
dvander@180
   575
		}
dvander@180
   576
	} else {
dvander@180
   577
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   578
		{
dvander@180
   579
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   580
		}
dvander@183
   581
		m_params[m_curparam].pushedas = Param_String;
dvander@180
   582
	}
dvander@180
   583
dvander@211
   584
	_Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
dvander@180
   585
	m_curparam++;
dvander@180
   586
dvander@180
   587
	return SP_ERROR_NONE;
dvander@180
   588
}
dvander@180
   589
faluco@192
   590
int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
dvander@180
   591
{
dvander@180
   592
	if (m_curparam < m_numparams)
dvander@180
   593
	{
dvander@183
   594
		if (m_types[m_curparam] == Param_Any)
dvander@180
   595
		{
dvander@183
   596
			m_params[m_curparam].pushedas = Param_String;
faluco@188
   597
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   598
			return SetError(SP_ERROR_PARAM);
dvander@180
   599
		}
dvander@180
   600
	} else {
dvander@180
   601
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   602
		{
dvander@180
   603
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   604
		}
dvander@183
   605
		m_params[m_curparam].pushedas = Param_String;
dvander@180
   606
	}
dvander@180
   607
faluco@192
   608
	_Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
dvander@180
   609
	m_curparam++;
dvander@180
   610
dvander@180
   611
	return SP_ERROR_NONE;
dvander@180
   612
}
dvander@180
   613
dvander@180
   614
void CForward::Cancel()
dvander@180
   615
{
dvander@180
   616
	if (!m_curparam)
dvander@180
   617
	{
dvander@180
   618
		return;
dvander@180
   619
	}
dvander@180
   620
dvander@183
   621
	m_curparam = 0;
dvander@180
   622
	m_errstate = SP_ERROR_NONE;
dvander@180
   623
}
dvander@180
   624
dvander@327
   625
bool CForward::AddFunction(IPluginContext *pContext, funcid_t index)
dvander@180
   626
{
dvander@327
   627
	IPluginFunction *pFunc = pContext->GetFunctionById(index);
dvander@180
   628
dvander@180
   629
	if (!pFunc)
dvander@180
   630
	{
dvander@180
   631
		return false;
dvander@180
   632
	}
dvander@180
   633
dvander@180
   634
	return AddFunction(pFunc);
dvander@180
   635
}
dvander@180
   636
ds@621
   637
bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
ds@621
   638
{
ds@621
   639
	IPluginFunction *pFunc = pContext->GetFunctionById(index);
ds@621
   640
ds@621
   641
	if (!pFunc)
ds@621
   642
	{
ds@621
   643
		return false;
ds@621
   644
	}
ds@621
   645
ds@621
   646
	return RemoveFunction(pFunc);
ds@621
   647
}
ds@621
   648
dvander@180
   649
bool CForward::RemoveFunction(IPluginFunction *func)
dvander@180
   650
{
dvander@180
   651
	bool found = false;
dvander@180
   652
	FuncIter iter;
dvander@527
   653
	List<IPluginFunction *> *lst;
dvander@527
   654
dvander@527
   655
	if (func->IsRunnable())
dvander@527
   656
	{
dvander@527
   657
		lst = &m_functions;
dvander@527
   658
	} else {
dvander@527
   659
		lst = &m_paused;
dvander@527
   660
	}
dvander@180
   661
dvander@525
   662
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   663
	{
dvander@180
   664
		if ((*iter) == func)
dvander@180
   665
		{
dvander@180
   666
			found = true;
dvander@527
   667
			lst->erase(iter);
faluco@430
   668
			break;
dvander@180
   669
		}
dvander@180
   670
	}
dvander@180
   671
dvander@180
   672
	/* Cancel a call, if any */
dvander@183
   673
	if (found || m_curparam)
dvander@180
   674
	{
dvander@180
   675
		func->Cancel();
dvander@180
   676
	}
dvander@180
   677
dvander@180
   678
	return found;
dvander@180
   679
}
dvander@180
   680
dvander@180
   681
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
dvander@180
   682
{
dvander@180
   683
	FuncIter iter;
dvander@180
   684
	IPluginFunction *func;
dvander@180
   685
	unsigned int removed = 0;
dvander@327
   686
	IPluginContext *pContext = plugin->GetBaseContext();
dvander@180
   687
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   688
	{
dvander@180
   689
		func = (*iter);
dvander@327
   690
		if (func->GetParentContext() == pContext)
dvander@180
   691
		{
dvander@180
   692
			iter = m_functions.erase(iter);
dvander@180
   693
			removed++;
dvander@180
   694
		} else {
dvander@180
   695
			iter++;
dvander@180
   696
		}
dvander@180
   697
	}
dvander@180
   698
dvander@180
   699
	return removed;
dvander@180
   700
}
dvander@180
   701
dvander@180
   702
bool CForward::AddFunction(IPluginFunction *func)
dvander@180
   703
{
dvander@180
   704
	if (m_curparam)
dvander@180
   705
	{
dvander@180
   706
		return false;
dvander@180
   707
	}
dvander@180
   708
dvander@527
   709
	if (func->IsRunnable())
dvander@527
   710
	{
dvander@527
   711
		m_functions.push_back(func);
dvander@527
   712
	} else {
dvander@527
   713
		m_paused.push_back(func);
dvander@527
   714
	}
dvander@180
   715
dvander@180
   716
	return true;
dvander@180
   717
}
dvander@180
   718
dvander@615
   719
const char *CForward::GetForwardName()
dvander@180
   720
{
dvander@180
   721
	return m_name;
dvander@180
   722
}
dvander@180
   723
dvander@615
   724
unsigned int CForward::GetFunctionCount()
dvander@180
   725
{
dvander@180
   726
	return m_functions.size();
dvander@180
   727
}
dvander@180
   728
dvander@615
   729
ExecType CForward::GetExecType()
dvander@180
   730
{
dvander@180
   731
	return m_ExecType;
dvander@180
   732
}