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