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