core/ForwardSys.cpp
author David Anderson <dvander@alliedmods.net>
Fri Aug 30 10:16:28 2013 -0700 (2013-08-30)
changeset 4109 10eb68d668af
parent 4086 63763f2a5c6c
permissions -rw-r--r--
Use Refcounted to manage to NativeEntry (bug 5852 part 4, r=ds).
ds@730
     1
/**
dvander@2883
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 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@3792
    36
#include "logic_bridge.h"
dvander@180
    37
dvander@186
    38
CForwardManager g_Forwards;
dvander@186
    39
dvander@183
    40
/**
ds@729
    41
 * Genesis turns to its source, reduction occurs stepwise although the essence is all one.
dvander@183
    42
 * End of line.  FTL system check.
dvander@183
    43
 *
dvander@282
    44
 * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
dvander@183
    45
 * VARARG FUNCTIONS:
dvander@183
    46
 * - Pushing no varargs
dvander@183
    47
 */
dvander@183
    48
faluco@226
    49
// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
faluco@226
    50
// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
faluco@226
    51
faluco@641
    52
CForwardManager::~CForwardManager()
faluco@641
    53
{
faluco@641
    54
	CStack<CForward *>::iterator iter;
faluco@641
    55
	for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
faluco@641
    56
	{
faluco@641
    57
		delete (*iter);
faluco@641
    58
	}
faluco@641
    59
	m_FreeForwards.popall();
faluco@641
    60
}
faluco@641
    61
dvander@211
    62
void CForwardManager::OnSourceModAllInitialized()
dvander@211
    63
{
dvander@3872
    64
	scripts->AddPluginsListener(this);
dvander@3872
    65
	sharesys->AddInterface(NULL, this);
dvander@211
    66
}
dvander@211
    67
ds@559
    68
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
dvander@186
    69
{
dvander@186
    70
	CForward *fwd;
dvander@186
    71
	va_list ap;
dvander@186
    72
	va_start(ap, types);
dvander@186
    73
	
dvander@186
    74
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    75
dvander@186
    76
	va_end(ap);
dvander@186
    77
dvander@211
    78
	if (fwd)
dvander@211
    79
	{
dvander@3872
    80
		scripts->AddFunctionsToForward(name, fwd);
ds@611
    81
dvander@211
    82
		m_managed.push_back(fwd);
dvander@211
    83
	}
dvander@211
    84
dvander@186
    85
	return fwd;
dvander@186
    86
}
dvander@186
    87
ds@559
    88
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
dvander@186
    89
{
dvander@186
    90
	CForward *fwd;
dvander@186
    91
	va_list ap;
dvander@186
    92
	va_start(ap, types);
dvander@186
    93
dvander@186
    94
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    95
dvander@186
    96
	va_end(ap);
dvander@186
    97
dvander@211
    98
	if (fwd)
dvander@211
    99
	{
dvander@211
   100
		m_unmanaged.push_back(fwd);
dvander@211
   101
	}
dvander@211
   102
dvander@186
   103
	return fwd;
dvander@186
   104
}
dvander@186
   105
dvander@211
   106
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
dvander@211
   107
{
dvander@211
   108
	/* Attach any globally managed forwards */
dvander@211
   109
	List<CForward *>::iterator iter;
dvander@211
   110
	CForward *fwd;
dvander@211
   111
dvander@211
   112
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@211
   113
	{
dvander@211
   114
		fwd = (*iter);
dvander@327
   115
		IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
dvander@211
   116
		if (pFunc)
dvander@211
   117
		{
dvander@211
   118
			fwd->AddFunction(pFunc);
dvander@211
   119
		}
dvander@211
   120
	}
dvander@211
   121
}
dvander@211
   122
dvander@211
   123
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
dvander@211
   124
{
dvander@211
   125
	List<CForward *>::iterator iter;
dvander@211
   126
	CForward *fwd;
dvander@211
   127
dvander@211
   128
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@211
   129
	{
dvander@211
   130
		fwd = (*iter);
dvander@211
   131
		fwd->RemoveFunctionsOfPlugin(plugin);
dvander@211
   132
	}
dvander@232
   133
dvander@232
   134
	for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
dvander@232
   135
	{
dvander@232
   136
		fwd = (*iter);
dvander@232
   137
		fwd->RemoveFunctionsOfPlugin(plugin);
dvander@232
   138
	}
dvander@211
   139
}
dvander@211
   140
dvander@186
   141
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
dvander@186
   142
{
dvander@186
   143
	List<CForward *>::iterator iter;
dvander@186
   144
	CForward *fwd;
dvander@186
   145
dvander@186
   146
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@186
   147
	{
dvander@186
   148
		fwd = (*iter);
dvander@186
   149
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
   150
		{
dvander@186
   151
			if (ifchng)
dvander@186
   152
			{
dvander@186
   153
				*ifchng = NULL;
dvander@186
   154
			}
dvander@186
   155
			return fwd;
dvander@186
   156
		}
dvander@186
   157
	}
dvander@186
   158
dvander@186
   159
	for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
dvander@186
   160
	{
dvander@186
   161
		fwd = (*iter);
dvander@186
   162
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
   163
		{
dvander@186
   164
			if (ifchng)
dvander@186
   165
			{
dvander@186
   166
				*ifchng = fwd;
dvander@186
   167
			}
dvander@186
   168
			return fwd;
dvander@186
   169
		}
dvander@186
   170
	}
dvander@186
   171
dvander@186
   172
	if (ifchng)
dvander@186
   173
	{
dvander@186
   174
		*ifchng = NULL;
dvander@186
   175
	}
dvander@186
   176
dvander@186
   177
	return NULL;
dvander@186
   178
}
dvander@186
   179
dvander@186
   180
void CForwardManager::ReleaseForward(IForward *forward)
dvander@186
   181
{
dvander@186
   182
	ForwardFree(static_cast<CForward *>(forward));
dvander@186
   183
}
dvander@186
   184
dvander@186
   185
void CForwardManager::ForwardFree(CForward *fwd)
dvander@186
   186
{
dvander@2234
   187
    if (fwd == NULL)
dvander@2234
   188
    {
dvander@2234
   189
        return;
dvander@2234
   190
    }
dvander@2234
   191
dvander@186
   192
	m_FreeForwards.push(fwd);
faluco@291
   193
	m_managed.remove(fwd);
dvander@186
   194
}
dvander@186
   195
dvander@186
   196
CForward *CForwardManager::ForwardMake()
dvander@186
   197
{
dvander@186
   198
	CForward *fwd;
dvander@186
   199
	if (m_FreeForwards.empty())
dvander@186
   200
	{
dvander@186
   201
		fwd = new CForward;
dvander@186
   202
	} else {
dvander@186
   203
		fwd = m_FreeForwards.front();
dvander@186
   204
		m_FreeForwards.pop();
dvander@186
   205
	}
dvander@186
   206
	return fwd;
dvander@186
   207
}
dvander@186
   208
faluco@430
   209
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
faluco@430
   210
{
januk@4086
   211
	if(paused)
januk@4086
   212
		return;
januk@4086
   213
januk@4086
   214
	/* Attach any globally managed forwards */
januk@4086
   215
	List<CForward *>::iterator iter;
januk@4086
   216
	CForward *fwd;
januk@4086
   217
januk@4086
   218
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
januk@4086
   219
	{
januk@4086
   220
		fwd = (*iter);
januk@4086
   221
		IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
januk@4086
   222
		// Only add functions, if they aren't registered yet!
januk@4086
   223
		if (pFunc && !fwd->IsFunctionRegistered(pFunc))
januk@4086
   224
		{
januk@4086
   225
			fwd->AddFunction(pFunc);
januk@4086
   226
		}
januk@4086
   227
	}
faluco@430
   228
}
faluco@430
   229
dvander@186
   230
/*************************************
dvander@186
   231
 * ACTUAL FORWARD API IMPLEMENTATION *
dvander@186
   232
 *************************************/
dvander@186
   233
ds@559
   234
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
dvander@180
   235
{
dvander@180
   236
	ParamType _types[SP_MAX_EXEC_PARAMS];
dvander@180
   237
dvander@180
   238
	if (num_params > SP_MAX_EXEC_PARAMS)
dvander@180
   239
	{
dvander@180
   240
		return NULL;
dvander@180
   241
	}
dvander@180
   242
	
dvander@180
   243
	if (types == NULL && num_params)
dvander@180
   244
	{
dvander@180
   245
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   246
		{
dvander@351
   247
			_types[i] = (ParamType)va_arg(ap, int);
dvander@180
   248
			if (_types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   249
			{
dvander@180
   250
				return NULL;
dvander@180
   251
			}
dvander@180
   252
		}
dvander@180
   253
		types = _types;
dvander@180
   254
	} else {
dvander@180
   255
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   256
		{
dvander@529
   257
			_types[i] = types[i];
dvander@180
   258
			if (types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   259
			{
dvander@180
   260
				return NULL;
dvander@180
   261
			}
dvander@180
   262
		}
dvander@180
   263
	}
dvander@180
   264
dvander@180
   265
	/* First parameter can never be varargs */
dvander@529
   266
	if (num_params && _types[0] == Param_VarArgs)
dvander@180
   267
	{
dvander@180
   268
		return NULL;
dvander@180
   269
	}
dvander@180
   270
dvander@186
   271
	CForward *pForward = g_Forwards.ForwardMake();
dvander@2890
   272
	pForward->m_IterGuard = NULL;
dvander@180
   273
	pForward->m_curparam = 0;
dvander@180
   274
	pForward->m_ExecType = et;
dvander@180
   275
	snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
dvander@180
   276
	
dvander@180
   277
	for (unsigned int i=0; i<num_params; i++)
dvander@180
   278
	{
dvander@529
   279
		pForward->m_types[i] = _types[i];
dvander@180
   280
	}
dvander@180
   281
dvander@529
   282
	if (num_params && _types[num_params-1] == Param_VarArgs)
dvander@180
   283
	{
dvander@183
   284
		pForward->m_varargs = num_params--;
dvander@180
   285
	} else {
dvander@180
   286
		pForward->m_varargs = false;
dvander@180
   287
	}
dvander@180
   288
dvander@180
   289
	pForward->m_numparams = num_params;
dvander@180
   290
	pForward->m_errstate = SP_ERROR_NONE;
dvander@180
   291
dvander@961
   292
	pForward->m_functions.clear();
dvander@961
   293
dvander@180
   294
	return pForward;
dvander@180
   295
}
dvander@180
   296
dvander@180
   297
int CForward::Execute(cell_t *result, IForwardFilter *filter)
dvander@180
   298
{
dvander@180
   299
	if (m_errstate)
dvander@180
   300
	{
dvander@180
   301
		int err = m_errstate;
dvander@180
   302
		Cancel();
dvander@180
   303
		return err;
dvander@180
   304
	}
dvander@180
   305
dvander@180
   306
	FuncIter iter = m_functions.begin();
dvander@180
   307
	IPluginFunction *func;
dvander@180
   308
	cell_t cur_result = 0;
dvander@180
   309
	cell_t high_result = 0;
ds@2181
   310
	cell_t low_result = 0;
dvander@180
   311
	int err;
dvander@2890
   312
	unsigned int success=0;
dvander@183
   313
	unsigned int num_params = m_curparam;
dvander@183
   314
	FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
dvander@183
   315
	FwdParamInfo *param;
dvander@183
   316
	ParamType type;
dvander@180
   317
dvander@183
   318
	/* Save local, reset */
dvander@183
   319
	memcpy(temp_info, m_params, sizeof(m_params));
dvander@183
   320
	m_curparam = 0;
dvander@183
   321
dvander@2890
   322
	FuncIteratorGuard guard(&m_IterGuard, &iter);
dvander@2890
   323
dvander@2890
   324
	while (iter != m_functions.end())
dvander@180
   325
	{
dvander@180
   326
		func = (*iter);
dvander@183
   327
dvander@2883
   328
		if (filter)
dvander@2883
   329
			filter->Preprocess(func, temp_info);
dvander@2883
   330
dvander@183
   331
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   332
		{
dvander@1339
   333
			int err = SP_ERROR_PARAM;
dvander@183
   334
			param = &temp_info[i];
ds@2181
   335
dvander@183
   336
			if (i >= m_numparams || m_types[i] == Param_Any)
dvander@183
   337
			{
dvander@183
   338
				type = param->pushedas;
ds@2181
   339
			}
ds@2181
   340
			else
ds@2181
   341
			{
dvander@183
   342
				type = m_types[i];
dvander@183
   343
			}
ds@2181
   344
dvander@183
   345
			if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
dvander@180
   346
			{
dvander@183
   347
				/* If we're byref or we're vararg, we always push everything by ref.
dvander@183
   348
				 * Even if they're byval, we must push them byref.
dvander@183
   349
				 */
faluco@192
   350
				if (type == Param_String)
dvander@180
   351
				{
dvander@1339
   352
					err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
ds@2181
   353
				}
ds@2181
   354
				else if (type == Param_Float || type == Param_Cell)
ds@2181
   355
				{
dvander@1339
   356
					err = func->PushCellByRef(&param->val); 
ds@2181
   357
				}
ds@2181
   358
				else
ds@2181
   359
				{
dvander@1339
   360
					err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
dvander@183
   361
					assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
dvander@180
   362
				}
ds@2181
   363
			}
ds@2181
   364
			else
ds@2181
   365
			{
dvander@183
   366
				/* If we're not byref or not vararg, our job is a bit easier. */
dvander@183
   367
				assert(type == Param_Cell || type == Param_Float);
dvander@1339
   368
				err = func->PushCell(param->val);
dvander@1339
   369
			}
ds@2181
   370
dvander@1339
   371
			if (err != SP_ERROR_NONE)
dvander@1339
   372
			{
dvander@3792
   373
				logicore.GenerateError(func->GetParentContext(), 
ds@2181
   374
					func->GetFunctionID(), 
ds@2181
   375
					err, 
ds@2181
   376
					"Failed to push parameter while executing forward");
dvander@1339
   377
				continue;
dvander@180
   378
			}
dvander@180
   379
		}
dvander@183
   380
		
dvander@211
   381
		/* Call the function and deal with the return value. */
dvander@2890
   382
		if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
ds@2181
   383
		{
dvander@180
   384
			success++;
dvander@180
   385
			switch (m_ExecType)
dvander@180
   386
			{
dvander@180
   387
			case ET_Event:
dvander@180
   388
				{
dvander@180
   389
					if (cur_result > high_result)
dvander@180
   390
					{
dvander@180
   391
						high_result = cur_result;
dvander@180
   392
					}
dvander@180
   393
					break;
dvander@180
   394
				}
dvander@180
   395
			case ET_Hook:
dvander@180
   396
				{
dvander@180
   397
					if (cur_result > high_result)
dvander@180
   398
					{
dvander@180
   399
						high_result = cur_result;
dvander@180
   400
						if ((ResultType)high_result == Pl_Stop)
dvander@180
   401
						{
ds@1140
   402
							goto done;
dvander@180
   403
						}
dvander@180
   404
					}
dvander@180
   405
					break;
dvander@180
   406
				}
ds@2181
   407
			case ET_LowEvent:
dvander@180
   408
				{
pred@2183
   409
					/* Check if the current result is the lowest so far (or if it's the first result) */
pred@2183
   410
					if (cur_result < low_result || success == 1)
dvander@180
   411
					{
ds@2181
   412
						low_result = cur_result;
dvander@180
   413
					}
dvander@180
   414
					break;
dvander@180
   415
				}
dvander@351
   416
			default:
dvander@351
   417
				{
dvander@351
   418
					break;
dvander@351
   419
				}
dvander@180
   420
			}
dvander@180
   421
		}
dvander@2890
   422
dvander@2890
   423
		if (!guard.Triggered())
dvander@2890
   424
			iter++;
dvander@180
   425
	}
dvander@180
   426
ds@1140
   427
done:
ds@2181
   428
dvander@447
   429
	if (success)
dvander@180
   430
	{
ds@2181
   431
		switch (m_ExecType)
dvander@447
   432
		{
ds@2181
   433
		case ET_Ignore:
ds@2181
   434
			{
ds@2181
   435
				cur_result = 0;
ds@2181
   436
				break;
ds@2181
   437
			}
ds@2181
   438
		case ET_Event:
ds@2181
   439
		case ET_Hook:
ds@2181
   440
			{
ds@2181
   441
				cur_result = high_result;
ds@2181
   442
				break;
ds@2181
   443
			}
ds@2181
   444
		case ET_LowEvent:
ds@2181
   445
			{
ds@2181
   446
				cur_result = low_result;
ds@2181
   447
				break;
ds@2181
   448
			}
ds@2181
   449
		default:
ds@2181
   450
			{
ds@2181
   451
				break;
ds@2181
   452
			}
dvander@447
   453
		}
ds@2181
   454
dvander@447
   455
		if (result)
dvander@447
   456
		{
dvander@447
   457
			*result = cur_result;
dvander@447
   458
		}
dvander@180
   459
	}
dvander@180
   460
dvander@180
   461
	return SP_ERROR_NONE;
dvander@180
   462
}
dvander@180
   463
dvander@180
   464
int CForward::PushCell(cell_t cell)
dvander@180
   465
{
dvander@180
   466
	if (m_curparam < m_numparams)
dvander@180
   467
	{
dvander@183
   468
		if (m_types[m_curparam] == Param_Any)
dvander@180
   469
		{
dvander@183
   470
			m_params[m_curparam].pushedas = Param_Cell;
dvander@183
   471
		} else if (m_types[m_curparam] != Param_Cell) {
dvander@180
   472
			return SetError(SP_ERROR_PARAM);
dvander@180
   473
		}
dvander@180
   474
	} else {
dvander@180
   475
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   476
		{
dvander@180
   477
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   478
		}
dvander@183
   479
		m_params[m_curparam].pushedas = Param_Cell;
dvander@180
   480
	}
dvander@180
   481
dvander@183
   482
	m_params[m_curparam++].val = cell;
dvander@180
   483
dvander@180
   484
	return SP_ERROR_NONE;
dvander@180
   485
}
dvander@180
   486
dvander@180
   487
int CForward::PushFloat(float number)
dvander@180
   488
{
dvander@180
   489
	if (m_curparam < m_numparams)
dvander@180
   490
	{
dvander@183
   491
		if (m_types[m_curparam] == Param_Any)
dvander@180
   492
		{
dvander@183
   493
			m_params[m_curparam].pushedas = Param_Float;
dvander@183
   494
		} else if (m_types[m_curparam] != Param_Float) {
dvander@180
   495
			return SetError(SP_ERROR_PARAM);
dvander@180
   496
		}
dvander@180
   497
	} else {
dvander@180
   498
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   499
		{
dvander@180
   500
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   501
		}
dvander@183
   502
		m_params[m_curparam].pushedas = Param_Float;
dvander@180
   503
	}
dvander@180
   504
dvander@183
   505
	m_params[m_curparam++].val = *(cell_t *)&number;
dvander@180
   506
dvander@180
   507
	return SP_ERROR_NONE;
dvander@180
   508
}
dvander@180
   509
ds@585
   510
int CForward::PushCellByRef(cell_t *cell, int flags)
dvander@180
   511
{
dvander@180
   512
	if (m_curparam < m_numparams)
dvander@180
   513
	{
faluco@192
   514
		if (m_types[m_curparam] == Param_Any)
dvander@180
   515
		{
faluco@192
   516
			m_params[m_curparam].pushedas = Param_CellByRef;
faluco@192
   517
		} else if (m_types[m_curparam] != Param_CellByRef) {
dvander@180
   518
			return SetError(SP_ERROR_PARAM);
dvander@180
   519
		}
dvander@180
   520
	} else {
dvander@180
   521
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   522
		{
dvander@180
   523
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   524
		}
faluco@192
   525
		m_params[m_curparam].pushedas = Param_CellByRef;
dvander@180
   526
	}
dvander@180
   527
ds@585
   528
	_Int_PushArray(cell, 1, flags);
dvander@180
   529
	m_curparam++;
dvander@180
   530
dvander@180
   531
	return SP_ERROR_NONE;
dvander@180
   532
}
dvander@180
   533
ds@585
   534
int CForward::PushFloatByRef(float *num, int flags)
dvander@180
   535
{
dvander@180
   536
	if (m_curparam < m_numparams)
dvander@180
   537
	{
faluco@192
   538
		if (m_types[m_curparam] == Param_Any)
dvander@180
   539
		{
faluco@192
   540
			m_params[m_curparam].pushedas = Param_FloatByRef;
faluco@192
   541
		} else if (m_types[m_curparam] != Param_FloatByRef) {
dvander@180
   542
			return SetError(SP_ERROR_PARAM);
dvander@180
   543
		}
dvander@180
   544
	} else {
dvander@180
   545
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   546
		{
dvander@180
   547
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   548
		}
faluco@192
   549
		m_params[m_curparam].pushedas = Param_FloatByRef;
dvander@180
   550
	}
dvander@180
   551
ds@585
   552
	_Int_PushArray((cell_t *)num, 1, flags);
dvander@180
   553
	m_curparam++;
dvander@180
   554
dvander@180
   555
	return SP_ERROR_NONE;
dvander@180
   556
}
dvander@180
   557
dvander@180
   558
void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   559
{
dvander@183
   560
	m_params[m_curparam].byref.cells = cells;
dvander@183
   561
	m_params[m_curparam].byref.flags = flags;
dvander@183
   562
	m_params[m_curparam].byref.orig_addr = inarray;
dvander@180
   563
}
dvander@180
   564
dvander@589
   565
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   566
{
dvander@180
   567
	/* We don't allow this here */
dvander@180
   568
	if (!inarray)
dvander@180
   569
	{
dvander@180
   570
		return SetError(SP_ERROR_PARAM);
dvander@180
   571
	}
dvander@180
   572
dvander@180
   573
	if (m_curparam < m_numparams)
dvander@180
   574
	{
dvander@183
   575
		if (m_types[m_curparam] == Param_Any)
dvander@180
   576
		{
dvander@183
   577
			m_params[m_curparam].pushedas = Param_Array;
dvander@183
   578
		} else if (m_types[m_curparam] != Param_Array) {
dvander@180
   579
			return SetError(SP_ERROR_PARAM);
dvander@180
   580
		}
dvander@180
   581
	} else {
dvander@180
   582
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   583
		{
dvander@180
   584
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   585
		}
dvander@183
   586
		m_params[m_curparam].pushedas = Param_Array;
dvander@180
   587
	}
dvander@180
   588
dvander@180
   589
	_Int_PushArray(inarray, cells, flags);
dvander@180
   590
dvander@180
   591
	m_curparam++;
dvander@180
   592
dvander@180
   593
	return SP_ERROR_NONE;
dvander@180
   594
}
dvander@180
   595
faluco@192
   596
void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
faluco@192
   597
{
faluco@192
   598
	m_params[m_curparam].byref.cells = cells;	/* Notice this contains the char count not cell count */
faluco@192
   599
	m_params[m_curparam].byref.flags = cp_flags;
faluco@192
   600
	m_params[m_curparam].byref.orig_addr = inarray;
faluco@192
   601
	m_params[m_curparam].byref.sz_flags = sz_flags;
faluco@192
   602
}
faluco@192
   603
dvander@180
   604
int CForward::PushString(const char *string)
dvander@180
   605
{
dvander@180
   606
	if (m_curparam < m_numparams)
dvander@180
   607
	{
dvander@183
   608
		if (m_types[m_curparam] == Param_Any)
dvander@180
   609
		{
dvander@183
   610
			m_params[m_curparam].pushedas = Param_String;
faluco@188
   611
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   612
			return SetError(SP_ERROR_PARAM);
dvander@180
   613
		}
dvander@180
   614
	} else {
dvander@180
   615
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   616
		{
dvander@180
   617
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   618
		}
dvander@183
   619
		m_params[m_curparam].pushedas = Param_String;
dvander@180
   620
	}
dvander@180
   621
dvander@211
   622
	_Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
dvander@180
   623
	m_curparam++;
dvander@180
   624
dvander@180
   625
	return SP_ERROR_NONE;
dvander@180
   626
}
dvander@180
   627
faluco@192
   628
int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
dvander@180
   629
{
dvander@180
   630
	if (m_curparam < m_numparams)
dvander@180
   631
	{
dvander@183
   632
		if (m_types[m_curparam] == Param_Any)
dvander@180
   633
		{
dvander@183
   634
			m_params[m_curparam].pushedas = Param_String;
faluco@188
   635
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   636
			return SetError(SP_ERROR_PARAM);
dvander@180
   637
		}
dvander@180
   638
	} else {
dvander@180
   639
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   640
		{
dvander@180
   641
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   642
		}
dvander@183
   643
		m_params[m_curparam].pushedas = Param_String;
dvander@180
   644
	}
dvander@180
   645
faluco@192
   646
	_Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
dvander@180
   647
	m_curparam++;
dvander@180
   648
dvander@180
   649
	return SP_ERROR_NONE;
dvander@180
   650
}
dvander@180
   651
dvander@180
   652
void CForward::Cancel()
dvander@180
   653
{
dvander@180
   654
	if (!m_curparam)
dvander@180
   655
	{
dvander@180
   656
		return;
dvander@180
   657
	}
dvander@180
   658
dvander@183
   659
	m_curparam = 0;
dvander@180
   660
	m_errstate = SP_ERROR_NONE;
dvander@180
   661
}
dvander@180
   662
dvander@327
   663
bool CForward::AddFunction(IPluginContext *pContext, funcid_t index)
dvander@180
   664
{
dvander@327
   665
	IPluginFunction *pFunc = pContext->GetFunctionById(index);
dvander@180
   666
dvander@180
   667
	if (!pFunc)
dvander@180
   668
	{
dvander@180
   669
		return false;
dvander@180
   670
	}
dvander@180
   671
dvander@180
   672
	return AddFunction(pFunc);
dvander@180
   673
}
dvander@180
   674
ds@621
   675
bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
ds@621
   676
{
ds@621
   677
	IPluginFunction *pFunc = pContext->GetFunctionById(index);
ds@621
   678
ds@621
   679
	if (!pFunc)
ds@621
   680
	{
ds@621
   681
		return false;
ds@621
   682
	}
ds@621
   683
ds@621
   684
	return RemoveFunction(pFunc);
ds@621
   685
}
ds@621
   686
dvander@180
   687
bool CForward::RemoveFunction(IPluginFunction *func)
dvander@180
   688
{
dvander@180
   689
	bool found = false;
dvander@180
   690
	FuncIter iter;
dvander@527
   691
	List<IPluginFunction *> *lst;
dvander@527
   692
dvander@527
   693
	if (func->IsRunnable())
dvander@527
   694
	{
dvander@527
   695
		lst = &m_functions;
dvander@527
   696
	} else {
dvander@527
   697
		lst = &m_paused;
dvander@527
   698
	}
dvander@180
   699
kyle@3995
   700
	for (iter=lst->begin(); iter!=lst->end(); iter++)
dvander@180
   701
	{
dvander@180
   702
		if ((*iter) == func)
dvander@180
   703
		{
dvander@2890
   704
			m_IterGuard->FixIteratorChain(iter);
dvander@180
   705
			found = true;
dvander@527
   706
			lst->erase(iter);
faluco@430
   707
			break;
dvander@180
   708
		}
dvander@180
   709
	}
dvander@180
   710
dvander@180
   711
	/* Cancel a call, if any */
dvander@183
   712
	if (found || m_curparam)
dvander@180
   713
	{
dvander@180
   714
		func->Cancel();
dvander@180
   715
	}
dvander@180
   716
dvander@180
   717
	return found;
dvander@180
   718
}
dvander@180
   719
dvander@180
   720
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
dvander@180
   721
{
dvander@180
   722
	FuncIter iter;
dvander@180
   723
	IPluginFunction *func;
dvander@180
   724
	unsigned int removed = 0;
dvander@327
   725
	IPluginContext *pContext = plugin->GetBaseContext();
dvander@180
   726
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   727
	{
dvander@180
   728
		func = (*iter);
dvander@327
   729
		if (func->GetParentContext() == pContext)
dvander@180
   730
		{
dvander@180
   731
			iter = m_functions.erase(iter);
dvander@180
   732
			removed++;
dvander@180
   733
		} else {
dvander@180
   734
			iter++;
dvander@180
   735
		}
dvander@180
   736
	}
dvander@180
   737
dvander@180
   738
	return removed;
dvander@180
   739
}
dvander@180
   740
dvander@180
   741
bool CForward::AddFunction(IPluginFunction *func)
dvander@180
   742
{
dvander@180
   743
	if (m_curparam)
dvander@180
   744
	{
dvander@180
   745
		return false;
dvander@180
   746
	}
dvander@180
   747
dvander@527
   748
	if (func->IsRunnable())
dvander@527
   749
	{
dvander@527
   750
		m_functions.push_back(func);
dvander@527
   751
	} else {
dvander@527
   752
		m_paused.push_back(func);
dvander@527
   753
	}
dvander@180
   754
dvander@180
   755
	return true;
dvander@180
   756
}
dvander@180
   757
januk@4086
   758
bool CForward::IsFunctionRegistered(IPluginFunction *func)
januk@4086
   759
{
januk@4086
   760
	FuncIter iter;
januk@4086
   761
	List<IPluginFunction *> *lst;
januk@4086
   762
januk@4086
   763
	if (func->IsRunnable())
januk@4086
   764
	{
januk@4086
   765
		lst = &m_functions;
januk@4086
   766
	} else {
januk@4086
   767
		lst = &m_paused;
januk@4086
   768
	}
januk@4086
   769
januk@4086
   770
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
januk@4086
   771
	{
januk@4086
   772
		if ((*iter) == func)
januk@4086
   773
		{
januk@4086
   774
			return true;
januk@4086
   775
		}
januk@4086
   776
	}
januk@4086
   777
	return false;
januk@4086
   778
}
januk@4086
   779
dvander@615
   780
const char *CForward::GetForwardName()
dvander@180
   781
{
dvander@180
   782
	return m_name;
dvander@180
   783
}
dvander@180
   784
dvander@615
   785
unsigned int CForward::GetFunctionCount()
dvander@180
   786
{
dvander@180
   787
	return m_functions.size();
dvander@180
   788
}
dvander@180
   789
dvander@615
   790
ExecType CForward::GetExecType()
dvander@180
   791
{
dvander@180
   792
	return m_ExecType;
dvander@180
   793
}