core/systems/ForwardSys.cpp
author Borja Ferrer <faluco@alliedmods.net>
Wed Dec 06 14:52:11 2006 +0000 (2006-12-06)
changeset 192 dee91851dcd4
parent 188 8951baf7cb3c
child 211 4c77142eaf36
permissions -rw-r--r--
rewritten PushStringEx in Forward and Function systems
fixed PushCellByRef and PushFloatByRef in the varargs case where it wouldn't set the pushed type
fixed the BindNatives functions not setting the BOUND flag thus making the JIT not exec the natives
done the rest of tests with forwards, only left to do string varargs
dvander@180
     1
#include <assert.h>
dvander@180
     2
#include "ForwardSys.h"
dvander@180
     3
#include "PluginSys.h"
dvander@180
     4
dvander@186
     5
CForwardManager g_Forwards;
dvander@186
     6
dvander@183
     7
/**
dvander@183
     8
 * Gensis turns to its source, reduction occurs stepwise although the essence is all one.
dvander@183
     9
 * End of line.  FTL system check.
dvander@183
    10
 *
dvander@183
    11
 * :TODO: Implement the manager.  ho ho ho
dvander@183
    12
 *
dvander@183
    13
 * :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST (X=done, -=TODO)
dvander@183
    14
 * NORMAL FUNCTIONS:
dvander@183
    15
 * X Push cells
dvander@183
    16
 * X Push cells byref (copyback tested = yes)
faluco@187
    17
 * X Push floats
faluco@187
    18
 * X Push floats byref (copyback tested = yes)
faluco@187
    19
 * X Push arrays  (copyback tested = yes)
faluco@188
    20
 * X Push strings (copyback tested = yes)
dvander@183
    21
 * VARARG FUNCTIONS:
dvander@183
    22
 * - Pushing no varargs
faluco@192
    23
 * X Push vararg cells (copyback should be verified to not happen = didnt happen)
faluco@192
    24
 * X Push vararg cells byref (copyback tested = yes)
faluco@192
    25
 * X Push vararg floats (copyback should be verified to not happen = didnt happen)
faluco@192
    26
 * X Push vararg floats byref (copyback tested = yes)
faluco@192
    27
 * X Push vararg arrays  (copyback tested = yes)
faluco@192
    28
 * X Push vararg strings (copyback tested = :TODO:)
dvander@183
    29
 */
dvander@183
    30
dvander@186
    31
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, ...)
dvander@186
    32
{
dvander@186
    33
	CForward *fwd;
dvander@186
    34
	va_list ap;
dvander@186
    35
	va_start(ap, types);
dvander@186
    36
	
dvander@186
    37
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    38
dvander@186
    39
	va_end(ap);
dvander@186
    40
dvander@186
    41
	return fwd;
dvander@186
    42
}
dvander@186
    43
dvander@186
    44
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, ParamType *types, ...)
dvander@186
    45
{
dvander@186
    46
	CForward *fwd;
dvander@186
    47
	va_list ap;
dvander@186
    48
	va_start(ap, types);
dvander@186
    49
dvander@186
    50
	fwd = CForward::CreateForward(name, et, num_params, types, ap);
dvander@186
    51
dvander@186
    52
	va_end(ap);
dvander@186
    53
dvander@186
    54
	return fwd;
dvander@186
    55
}
dvander@186
    56
dvander@186
    57
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
dvander@186
    58
{
dvander@186
    59
	List<CForward *>::iterator iter;
dvander@186
    60
	CForward *fwd;
dvander@186
    61
dvander@186
    62
	for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
dvander@186
    63
	{
dvander@186
    64
		fwd = (*iter);
dvander@186
    65
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
    66
		{
dvander@186
    67
			if (ifchng)
dvander@186
    68
			{
dvander@186
    69
				*ifchng = NULL;
dvander@186
    70
			}
dvander@186
    71
			return fwd;
dvander@186
    72
		}
dvander@186
    73
	}
dvander@186
    74
dvander@186
    75
	for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
dvander@186
    76
	{
dvander@186
    77
		fwd = (*iter);
dvander@186
    78
		if (strcmp(fwd->GetForwardName(), name) == 0)
dvander@186
    79
		{
dvander@186
    80
			if (ifchng)
dvander@186
    81
			{
dvander@186
    82
				*ifchng = fwd;
dvander@186
    83
			}
dvander@186
    84
			return fwd;
dvander@186
    85
		}
dvander@186
    86
	}
dvander@186
    87
dvander@186
    88
	if (ifchng)
dvander@186
    89
	{
dvander@186
    90
		*ifchng = NULL;
dvander@186
    91
	}
dvander@186
    92
dvander@186
    93
	return NULL;
dvander@186
    94
}
dvander@186
    95
dvander@186
    96
void CForwardManager::ReleaseForward(IForward *forward)
dvander@186
    97
{
dvander@186
    98
	ForwardFree(static_cast<CForward *>(forward));
dvander@186
    99
}
dvander@186
   100
dvander@186
   101
void CForwardManager::ForwardFree(CForward *fwd)
dvander@186
   102
{
dvander@186
   103
	m_FreeForwards.push(fwd);
dvander@186
   104
}
dvander@186
   105
dvander@186
   106
CForward *CForwardManager::ForwardMake()
dvander@186
   107
{
dvander@186
   108
	CForward *fwd;
dvander@186
   109
	if (m_FreeForwards.empty())
dvander@186
   110
	{
dvander@186
   111
		fwd = new CForward;
dvander@186
   112
	} else {
dvander@186
   113
		fwd = m_FreeForwards.front();
dvander@186
   114
		m_FreeForwards.pop();
dvander@186
   115
	}
dvander@186
   116
	return fwd;
dvander@186
   117
}
dvander@186
   118
dvander@186
   119
/*************************************
dvander@186
   120
 * ACTUAL FORWARD API IMPLEMENTATION *
dvander@186
   121
 *************************************/
dvander@186
   122
dvander@180
   123
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, ParamType *types, va_list ap)
dvander@180
   124
{
dvander@180
   125
	ParamType _types[SP_MAX_EXEC_PARAMS];
dvander@180
   126
dvander@180
   127
	if (num_params > SP_MAX_EXEC_PARAMS)
dvander@180
   128
	{
dvander@180
   129
		return NULL;
dvander@180
   130
	}
dvander@180
   131
	
dvander@180
   132
	if (types == NULL && num_params)
dvander@180
   133
	{
dvander@180
   134
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   135
		{
dvander@180
   136
			_types[i] = va_arg(ap, ParamType);
dvander@180
   137
			if (_types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   138
			{
dvander@180
   139
				return NULL;
dvander@180
   140
			}
dvander@180
   141
		}
dvander@180
   142
		types = _types;
dvander@180
   143
	} else {
dvander@180
   144
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   145
		{
dvander@180
   146
			if (types[i] == Param_VarArgs && (i != num_params - 1))
dvander@180
   147
			{
dvander@180
   148
				return NULL;
dvander@180
   149
			}
dvander@180
   150
		}
dvander@180
   151
	}
dvander@180
   152
dvander@180
   153
	/* First parameter can never be varargs */
dvander@180
   154
	if (types[0] == Param_VarArgs)
dvander@180
   155
	{
dvander@180
   156
		return NULL;
dvander@180
   157
	}
dvander@180
   158
dvander@186
   159
	CForward *pForward = g_Forwards.ForwardMake();
dvander@180
   160
	pForward->m_curparam = 0;
dvander@180
   161
	pForward->m_ExecType = et;
dvander@180
   162
	snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
dvander@180
   163
	
dvander@180
   164
	for (unsigned int i=0; i<num_params; i++)
dvander@180
   165
	{
dvander@180
   166
		pForward->m_types[i] = types[i];
dvander@180
   167
	}
dvander@180
   168
dvander@180
   169
	if (num_params && types[num_params-1] == Param_VarArgs)
dvander@180
   170
	{
dvander@183
   171
		pForward->m_varargs = num_params--;
dvander@180
   172
	} else {
dvander@180
   173
		pForward->m_varargs = false;
dvander@180
   174
	}
dvander@180
   175
dvander@180
   176
	pForward->m_numparams = num_params;
dvander@180
   177
	pForward->m_errstate = SP_ERROR_NONE;
dvander@180
   178
dvander@180
   179
	return pForward;
dvander@180
   180
}
dvander@180
   181
dvander@180
   182
int CForward::Execute(cell_t *result, IForwardFilter *filter)
dvander@180
   183
{
dvander@180
   184
	if (m_errstate)
dvander@180
   185
	{
dvander@180
   186
		int err = m_errstate;
dvander@180
   187
		Cancel();
dvander@180
   188
		return err;
dvander@180
   189
	}
dvander@180
   190
dvander@180
   191
	if (filter)
dvander@180
   192
	{
dvander@180
   193
		filter->OnExecuteBegin();
dvander@180
   194
	}
dvander@180
   195
dvander@180
   196
	FuncIter iter = m_functions.begin();
dvander@180
   197
	IPluginFunction *func;
dvander@180
   198
	cell_t cur_result = 0;
dvander@180
   199
	cell_t high_result = 0;
dvander@180
   200
	int err;
dvander@180
   201
	unsigned int failed=0, success=0;
dvander@180
   202
	unsigned int save_numcopy = 0;
dvander@183
   203
	unsigned int num_params = m_curparam;
dvander@183
   204
	FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
dvander@183
   205
	FwdParamInfo *param;
dvander@183
   206
	ParamType type;
dvander@180
   207
dvander@183
   208
	/* Save local, reset */
dvander@183
   209
	memcpy(temp_info, m_params, sizeof(m_params));
dvander@183
   210
	m_curparam = 0;
dvander@183
   211
dvander@180
   212
	for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
dvander@180
   213
	{
dvander@180
   214
		func = (*iter);
dvander@183
   215
dvander@183
   216
		for (unsigned int i=0; i<num_params; i++)
dvander@180
   217
		{
dvander@183
   218
			param = &temp_info[i];
dvander@183
   219
			if (i >= m_numparams || m_types[i] == Param_Any)
dvander@183
   220
			{
dvander@183
   221
				type = param->pushedas;
dvander@183
   222
			} else {
dvander@183
   223
				type = m_types[i];
dvander@183
   224
			}
dvander@183
   225
			if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
dvander@180
   226
			{
dvander@183
   227
				/* If we're byref or we're vararg, we always push everything by ref.
dvander@183
   228
				 * Even if they're byval, we must push them byref.
dvander@183
   229
				 */
faluco@192
   230
				if (type == Param_String)
dvander@180
   231
				{
faluco@192
   232
					func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
dvander@183
   233
				} else if (type == Param_Float || type == Param_Cell) {
dvander@183
   234
					func->PushCellByRef(&param->val, 0); 
dvander@183
   235
				} else {
dvander@183
   236
					func->PushArray(param->byref.orig_addr, param->byref.cells, NULL, param->byref.flags);
dvander@183
   237
					assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
dvander@180
   238
				}
dvander@183
   239
			} else {
dvander@183
   240
				/* If we're not byref or not vararg, our job is a bit easier. */
dvander@183
   241
				assert(type == Param_Cell || type == Param_Float);
dvander@183
   242
				func->PushCell(param->val);
dvander@180
   243
			}
dvander@180
   244
		}
dvander@183
   245
		
dvander@180
   246
		/* Call the function and deal with the return value.
dvander@180
   247
		 * :TODO: only pass reader if we know we have an array in the list
dvander@180
   248
		 */
dvander@183
   249
		if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
dvander@180
   250
		{
dvander@180
   251
			bool handled = false;
dvander@180
   252
			if (filter)
dvander@180
   253
			{
dvander@180
   254
				handled = filter->OnErrorReport(this, func, err);
dvander@180
   255
			}
dvander@180
   256
			if (!handled)
dvander@180
   257
			{
dvander@180
   258
				/* :TODO: invoke global error reporting here */
dvander@180
   259
			}
dvander@180
   260
			failed++;
dvander@180
   261
		} else {
dvander@180
   262
			success++;
dvander@180
   263
			switch (m_ExecType)
dvander@180
   264
			{
dvander@180
   265
			case ET_Event:
dvander@180
   266
				{
dvander@180
   267
					if (cur_result > high_result)
dvander@180
   268
					{
dvander@180
   269
						high_result = cur_result;
dvander@180
   270
					}
dvander@180
   271
					break;
dvander@180
   272
				}
dvander@180
   273
			case ET_Hook:
dvander@180
   274
				{
dvander@180
   275
					if (cur_result > high_result)
dvander@180
   276
					{
dvander@180
   277
						high_result = cur_result;
dvander@180
   278
						if ((ResultType)high_result == Pl_Stop)
dvander@180
   279
						{
dvander@180
   280
							iter = m_functions.end();
dvander@180
   281
							break;
dvander@180
   282
						}
dvander@180
   283
					}
dvander@180
   284
					break;
dvander@180
   285
				}
dvander@180
   286
			case ET_Custom:
dvander@180
   287
				{
dvander@180
   288
					if (filter)
dvander@180
   289
					{
dvander@180
   290
						if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
dvander@180
   291
						{
dvander@180
   292
							iter = m_functions.end();
dvander@180
   293
						}
dvander@180
   294
					}
dvander@180
   295
					break;
dvander@180
   296
				}
dvander@180
   297
			}
dvander@180
   298
		}
dvander@180
   299
	}
dvander@180
   300
dvander@180
   301
	if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
dvander@180
   302
	{
dvander@180
   303
		cur_result = high_result;
dvander@180
   304
	} else if (m_ExecType == ET_Ignore) {
dvander@180
   305
		cur_result = 0;
dvander@180
   306
	}
dvander@180
   307
dvander@180
   308
	*result = cur_result;
dvander@180
   309
dvander@180
   310
	if (filter)
dvander@180
   311
	{
dvander@180
   312
		filter->OnExecuteEnd(&cur_result, success, failed);
dvander@180
   313
	}
dvander@180
   314
dvander@180
   315
	return SP_ERROR_NONE;
dvander@180
   316
}
dvander@180
   317
dvander@180
   318
int CForward::PushCell(cell_t cell)
dvander@180
   319
{
dvander@180
   320
	if (m_curparam < m_numparams)
dvander@180
   321
	{
dvander@183
   322
		if (m_types[m_curparam] == Param_Any)
dvander@180
   323
		{
dvander@183
   324
			m_params[m_curparam].pushedas = Param_Cell;
dvander@183
   325
		} else if (m_types[m_curparam] != Param_Cell) {
dvander@180
   326
			return SetError(SP_ERROR_PARAM);
dvander@180
   327
		}
dvander@180
   328
	} else {
dvander@180
   329
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   330
		{
dvander@180
   331
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   332
		}
dvander@183
   333
		m_params[m_curparam].pushedas = Param_Cell;
dvander@180
   334
	}
dvander@180
   335
dvander@183
   336
	m_params[m_curparam++].val = cell;
dvander@180
   337
dvander@180
   338
	return SP_ERROR_NONE;
dvander@180
   339
}
dvander@180
   340
dvander@180
   341
int CForward::PushFloat(float number)
dvander@180
   342
{
dvander@180
   343
	if (m_curparam < m_numparams)
dvander@180
   344
	{
dvander@183
   345
		if (m_types[m_curparam] == Param_Any)
dvander@180
   346
		{
dvander@183
   347
			m_params[m_curparam].pushedas = Param_Float;
dvander@183
   348
		} else if (m_types[m_curparam] != Param_Float) {
dvander@180
   349
			return SetError(SP_ERROR_PARAM);
dvander@180
   350
		}
dvander@180
   351
	} else {
dvander@180
   352
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   353
		{
dvander@180
   354
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   355
		}
dvander@183
   356
		m_params[m_curparam].pushedas = Param_Float;
dvander@180
   357
	}
dvander@180
   358
dvander@183
   359
	m_params[m_curparam++].val = *(cell_t *)&number;
dvander@180
   360
dvander@180
   361
	return SP_ERROR_NONE;
dvander@180
   362
}
dvander@180
   363
dvander@180
   364
int CForward::PushCellByRef(cell_t *cell, int flags)
dvander@180
   365
{
dvander@180
   366
	if (m_curparam < m_numparams)
dvander@180
   367
	{
faluco@192
   368
		if (m_types[m_curparam] == Param_Any)
dvander@180
   369
		{
faluco@192
   370
			m_params[m_curparam].pushedas = Param_CellByRef;
faluco@192
   371
		} else if (m_types[m_curparam] != Param_CellByRef) {
dvander@180
   372
			return SetError(SP_ERROR_PARAM);
dvander@180
   373
		}
dvander@180
   374
	} else {
dvander@180
   375
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   376
		{
dvander@180
   377
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   378
		}
faluco@192
   379
		m_params[m_curparam].pushedas = Param_CellByRef;
dvander@180
   380
	}
dvander@180
   381
dvander@183
   382
	_Int_PushArray(cell, 1, flags);
dvander@180
   383
	m_curparam++;
dvander@180
   384
dvander@180
   385
	return SP_ERROR_NONE;
dvander@180
   386
}
dvander@180
   387
dvander@180
   388
int CForward::PushFloatByRef(float *num, int flags)
dvander@180
   389
{
dvander@180
   390
	if (m_curparam < m_numparams)
dvander@180
   391
	{
faluco@192
   392
		if (m_types[m_curparam] == Param_Any)
dvander@180
   393
		{
faluco@192
   394
			m_params[m_curparam].pushedas = Param_FloatByRef;
faluco@192
   395
		} else if (m_types[m_curparam] != Param_FloatByRef) {
dvander@180
   396
			return SetError(SP_ERROR_PARAM);
dvander@180
   397
		}
dvander@180
   398
	} else {
dvander@180
   399
		if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
dvander@180
   400
		{
dvander@180
   401
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   402
		}
faluco@192
   403
		m_params[m_curparam].pushedas = Param_FloatByRef;
dvander@180
   404
	}
dvander@180
   405
dvander@183
   406
	_Int_PushArray((cell_t *)num, 1, flags);
dvander@180
   407
	m_curparam++;
dvander@180
   408
dvander@180
   409
	return SP_ERROR_NONE;
dvander@180
   410
}
dvander@180
   411
dvander@180
   412
void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
dvander@180
   413
{
dvander@183
   414
	m_params[m_curparam].byref.cells = cells;
dvander@183
   415
	m_params[m_curparam].byref.flags = flags;
dvander@183
   416
	m_params[m_curparam].byref.orig_addr = inarray;
dvander@180
   417
}
dvander@180
   418
dvander@180
   419
int CForward::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int flags)
dvander@180
   420
{
dvander@180
   421
	/* We don't allow this here */
dvander@180
   422
	if (!inarray)
dvander@180
   423
	{
dvander@180
   424
		return SetError(SP_ERROR_PARAM);
dvander@180
   425
	}
dvander@180
   426
dvander@180
   427
	if (m_curparam < m_numparams)
dvander@180
   428
	{
dvander@183
   429
		if (m_types[m_curparam] == Param_Any)
dvander@180
   430
		{
dvander@183
   431
			m_params[m_curparam].pushedas = Param_Array;
dvander@183
   432
		} else if (m_types[m_curparam] != Param_Array) {
dvander@180
   433
			return SetError(SP_ERROR_PARAM);
dvander@180
   434
		}
dvander@180
   435
	} else {
dvander@180
   436
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   437
		{
dvander@180
   438
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   439
		}
dvander@183
   440
		m_params[m_curparam].pushedas = Param_Array;
dvander@180
   441
	}
dvander@180
   442
dvander@180
   443
	if (phys_addr)
dvander@180
   444
	{
dvander@180
   445
		*phys_addr = NULL;
dvander@180
   446
	}
dvander@180
   447
dvander@180
   448
	_Int_PushArray(inarray, cells, flags);
dvander@180
   449
dvander@180
   450
	m_curparam++;
dvander@180
   451
dvander@180
   452
	return SP_ERROR_NONE;
dvander@180
   453
}
dvander@180
   454
faluco@192
   455
void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
faluco@192
   456
{
faluco@192
   457
	m_params[m_curparam].byref.cells = cells;	/* Notice this contains the char count not cell count */
faluco@192
   458
	m_params[m_curparam].byref.flags = cp_flags;
faluco@192
   459
	m_params[m_curparam].byref.orig_addr = inarray;
faluco@192
   460
	m_params[m_curparam].byref.sz_flags = sz_flags;
faluco@192
   461
}
faluco@192
   462
dvander@180
   463
int CForward::PushString(const char *string)
dvander@180
   464
{
dvander@180
   465
	if (m_curparam < m_numparams)
dvander@180
   466
	{
dvander@183
   467
		if (m_types[m_curparam] == Param_Any)
dvander@180
   468
		{
dvander@183
   469
			m_params[m_curparam].pushedas = Param_String;
faluco@188
   470
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   471
			return SetError(SP_ERROR_PARAM);
dvander@180
   472
		}
dvander@180
   473
	} else {
dvander@180
   474
		if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
dvander@180
   475
		{
dvander@180
   476
			return SetError(SP_ERROR_PARAMS_MAX);
dvander@180
   477
		}
dvander@183
   478
		m_params[m_curparam].pushedas = Param_String;
dvander@180
   479
	}
dvander@180
   480
faluco@192
   481
	_Int_PushString((cell_t *)string, strlen(string)+1, SP_STRING_COPY, 0);
dvander@180
   482
	m_curparam++;
dvander@180
   483
dvander@180
   484
	return SP_ERROR_NONE;
dvander@180
   485
}
dvander@180
   486
faluco@192
   487
int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
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_String;
faluco@188
   494
		} else if (m_types[m_curparam] != Param_String) {
dvander@180
   495
			return SetError(SP_ERROR_PARAM);
dvander@180
   496
		}
dvander@180
   497
	} else {
dvander@180
   498
		if (!m_varargs || m_curparam > 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_String;
dvander@180
   503
	}
dvander@180
   504
faluco@192
   505
	_Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
dvander@180
   506
	m_curparam++;
dvander@180
   507
dvander@180
   508
	return SP_ERROR_NONE;
dvander@180
   509
}
dvander@180
   510
dvander@180
   511
void CForward::Cancel()
dvander@180
   512
{
dvander@180
   513
	if (!m_curparam)
dvander@180
   514
	{
dvander@180
   515
		return;
dvander@180
   516
	}
dvander@180
   517
dvander@183
   518
	m_curparam = 0;
dvander@180
   519
	m_errstate = SP_ERROR_NONE;
dvander@180
   520
}
dvander@180
   521
dvander@180
   522
bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
dvander@180
   523
{
dvander@180
   524
	IPlugin *pPlugin = g_PluginMngr.FindPluginByContext(ctx);
dvander@180
   525
	if (!pPlugin)
dvander@180
   526
	{
dvander@180
   527
		return false;
dvander@180
   528
	}
dvander@180
   529
dvander@180
   530
	IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
dvander@180
   531
	if (!pFunc)
dvander@180
   532
	{
dvander@180
   533
		return false;
dvander@180
   534
	}
dvander@180
   535
dvander@180
   536
	return AddFunction(pFunc);
dvander@180
   537
}
dvander@180
   538
dvander@180
   539
bool CForward::RemoveFunction(IPluginFunction *func)
dvander@180
   540
{
dvander@180
   541
	bool found = false;
dvander@180
   542
	FuncIter iter;
dvander@180
   543
	IPluginFunction *pNext = NULL;
dvander@180
   544
dvander@180
   545
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   546
	{
dvander@180
   547
		if ((*iter) == func)
dvander@180
   548
		{
dvander@180
   549
			found = true;
dvander@180
   550
			/* If this iterator is being used, swap in a new one !*/
dvander@180
   551
			iter = m_functions.erase(iter);
dvander@180
   552
		} else {
dvander@180
   553
			iter++;
dvander@180
   554
		}
dvander@180
   555
	}
dvander@180
   556
dvander@180
   557
	/* Cancel a call, if any */
dvander@183
   558
	if (found || m_curparam)
dvander@180
   559
	{
dvander@180
   560
		func->Cancel();
dvander@180
   561
	}
dvander@180
   562
dvander@180
   563
	return found;
dvander@180
   564
}
dvander@180
   565
dvander@180
   566
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
dvander@180
   567
{
dvander@180
   568
	FuncIter iter;
dvander@180
   569
	IPluginFunction *func;
dvander@180
   570
	unsigned int removed = 0;
dvander@180
   571
	for (iter=m_functions.begin(); iter!=m_functions.end();)
dvander@180
   572
	{
dvander@180
   573
		func = (*iter);
dvander@180
   574
		if (func->GetParentPlugin() == plugin)
dvander@180
   575
		{
dvander@180
   576
			iter = m_functions.erase(iter);
dvander@180
   577
			removed++;
dvander@180
   578
		} else {
dvander@180
   579
			iter++;
dvander@180
   580
		}
dvander@180
   581
	}
dvander@180
   582
dvander@180
   583
	return removed;
dvander@180
   584
}
dvander@180
   585
dvander@180
   586
bool CForward::AddFunction(IPluginFunction *func)
dvander@180
   587
{
dvander@180
   588
	if (m_curparam)
dvander@180
   589
	{
dvander@180
   590
		return false;
dvander@180
   591
	}
dvander@180
   592
dvander@183
   593
	//:TODO: eventually we will tell the plugin we're using it
dvander@183
   594
	m_functions.push_back(func);
dvander@180
   595
dvander@180
   596
	return true;
dvander@180
   597
}
dvander@180
   598
dvander@180
   599
const char *CForward::GetForwardName()
dvander@180
   600
{
dvander@180
   601
	return m_name;
dvander@180
   602
}
dvander@180
   603
dvander@180
   604
unsigned int CForward::GetFunctionCount()
dvander@180
   605
{
dvander@180
   606
	return m_functions.size();
dvander@180
   607
}
dvander@180
   608
dvander@180
   609
ExecType CForward::GetExecType()
dvander@180
   610
{
dvander@180
   611
	return m_ExecType;
dvander@180
   612
}