core/systems/ForwardSys.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1231 17badaf66ce4
child 1339 02e8f2c0f8af
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

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