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