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