1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/logic/smn_textparse.cpp Wed May 13 21:55:50 2009 -0400
1.3 @@ -0,0 +1,325 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "common_logic.h"
1.36 +#include <ITextParsers.h>
1.37 +#include <ISourceMod.h>
1.38 +
1.39 +HandleType_t g_TypeSMC = 0;
1.40 +
1.41 +class ParseInfo : public ITextListener_SMC
1.42 +{
1.43 +public:
1.44 + ParseInfo()
1.45 + {
1.46 + parse_start = NULL;
1.47 + parse_end = NULL;
1.48 + new_section = NULL;
1.49 + key_value = NULL;
1.50 + end_section = NULL;
1.51 + raw_line = NULL;
1.52 + handle = 0;
1.53 + }
1.54 +public:
1.55 + void ReadSMC_ParseStart()
1.56 + {
1.57 + if (parse_start)
1.58 + {
1.59 + cell_t result;
1.60 + parse_start->PushCell(handle);
1.61 + parse_start->Execute(&result);
1.62 + }
1.63 + }
1.64 +
1.65 + void ReadSMC_ParseEnd(bool halted, bool failed)
1.66 + {
1.67 + if (parse_end)
1.68 + {
1.69 + cell_t result;
1.70 + parse_end->PushCell(handle);
1.71 + parse_end->PushCell(halted ? 1 : 0);
1.72 + parse_end->PushCell(failed ? 1 : 0);
1.73 + parse_end->Execute(&result);
1.74 + }
1.75 + }
1.76 +
1.77 + SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
1.78 + {
1.79 + cell_t result = SMCResult_Continue;
1.80 +
1.81 + if (new_section)
1.82 + {
1.83 + new_section->PushCell(handle);
1.84 + new_section->PushString(name);
1.85 + new_section->PushCell(1);
1.86 + new_section->Execute(&result);
1.87 + }
1.88 +
1.89 + return (SMCResult)result;
1.90 + }
1.91 +
1.92 + SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
1.93 + {
1.94 + cell_t result = SMCResult_Continue;
1.95 +
1.96 + if (key_value)
1.97 + {
1.98 + key_value->PushCell(handle);
1.99 + key_value->PushString(key);
1.100 + key_value->PushString(value);
1.101 + key_value->PushCell(1);
1.102 + key_value->PushCell(1);
1.103 + key_value->Execute(&result);
1.104 + }
1.105 +
1.106 + return (SMCResult)result;
1.107 + }
1.108 +
1.109 + SMCResult ReadSMC_LeavingSection(const SMCStates *states)
1.110 + {
1.111 + cell_t result = SMCResult_Continue;
1.112 +
1.113 + if (end_section)
1.114 + {
1.115 + end_section->PushCell(handle);
1.116 + end_section->Execute(&result);
1.117 + }
1.118 +
1.119 + return (SMCResult)result;
1.120 + }
1.121 +
1.122 + SMCResult ReadSMC_RawLine(const SMCStates *states, const char *line)
1.123 + {
1.124 + cell_t result = SMCResult_Continue;
1.125 +
1.126 + if (raw_line)
1.127 + {
1.128 + raw_line->PushCell(handle);
1.129 + raw_line->PushString(line);
1.130 + raw_line->PushCell(states->line);
1.131 + raw_line->Execute(&result);
1.132 + }
1.133 +
1.134 + return (SMCResult)result;
1.135 + }
1.136 +public:
1.137 + IPluginFunction *parse_start;
1.138 + IPluginFunction *parse_end;
1.139 + IPluginFunction *new_section;
1.140 + IPluginFunction *key_value;
1.141 + IPluginFunction *end_section;
1.142 + IPluginFunction *raw_line;
1.143 + Handle_t handle;
1.144 +};
1.145 +
1.146 +class TextParseGlobals :
1.147 + public SMGlobalClass,
1.148 + public IHandleTypeDispatch
1.149 +{
1.150 +public:
1.151 + void OnSourceModAllInitialized()
1.152 + {
1.153 + HandleAccess sec;
1.154 +
1.155 + /* These cannot be cloned, because they are locked to a specific plugin.
1.156 + * However, we let anyone read them because we don't care.
1.157 + */
1.158 + handlesys->InitAccessDefaults(NULL, &sec);
1.159 + sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
1.160 + sec.access[HandleAccess_Read] = 0;
1.161 +
1.162 + g_TypeSMC = handlesys->CreateType("SMCParser", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.163 + }
1.164 +
1.165 + void OnSourceModShutdown()
1.166 + {
1.167 + handlesys->RemoveType(g_TypeSMC, g_pCoreIdent);
1.168 + }
1.169 +
1.170 + void OnHandleDestroy(HandleType_t type, void *object)
1.171 + {
1.172 + ParseInfo *parse = (ParseInfo *)object;
1.173 + delete parse;
1.174 + }
1.175 +
1.176 + bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.177 + {
1.178 + *pSize = sizeof(ParseInfo);
1.179 + return true;
1.180 + }
1.181 +};
1.182 +
1.183 +TextParseGlobals g_TextParseGlobals;
1.184 +
1.185 +static cell_t SMC_CreateParser(IPluginContext *pContext, const cell_t *params)
1.186 +{
1.187 + ParseInfo *pInfo = new ParseInfo();
1.188 +
1.189 + Handle_t hndl = handlesys->CreateHandle(g_TypeSMC, pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.190 +
1.191 + /* Should never happen */
1.192 + if (!hndl)
1.193 + {
1.194 + delete pInfo;
1.195 + return 0;
1.196 + }
1.197 +
1.198 + pInfo->handle = hndl;
1.199 +
1.200 + return hndl;
1.201 +}
1.202 +
1.203 +static cell_t SMC_SetParseStart(IPluginContext *pContext, const cell_t *params)
1.204 +{
1.205 + Handle_t hndl = (Handle_t)params[1];
1.206 + HandleError err;
1.207 + ParseInfo *parse;
1.208 +
1.209 + if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
1.210 + != HandleError_None)
1.211 + {
1.212 + return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
1.213 + }
1.214 +
1.215 + parse->parse_start = pContext->GetFunctionById((funcid_t)params[2]);
1.216 +
1.217 + return 1;
1.218 +}
1.219 +
1.220 +static cell_t SMC_SetParseEnd(IPluginContext *pContext, const cell_t *params)
1.221 +{
1.222 + Handle_t hndl = (Handle_t)params[1];
1.223 + HandleError err;
1.224 + ParseInfo *parse;
1.225 +
1.226 + if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
1.227 + != HandleError_None)
1.228 + {
1.229 + return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
1.230 + }
1.231 +
1.232 + parse->parse_end = pContext->GetFunctionById((funcid_t)params[2]);
1.233 +
1.234 + return 1;
1.235 +}
1.236 +
1.237 +static cell_t SMC_SetReaders(IPluginContext *pContext, const cell_t *params)
1.238 +{
1.239 + Handle_t hndl = (Handle_t)params[1];
1.240 + HandleError err;
1.241 + ParseInfo *parse;
1.242 +
1.243 + if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
1.244 + != HandleError_None)
1.245 + {
1.246 + return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
1.247 + }
1.248 +
1.249 + parse->new_section = pContext->GetFunctionById((funcid_t)params[2]);
1.250 + parse->key_value = pContext->GetFunctionById((funcid_t)params[3]);
1.251 + parse->end_section = pContext->GetFunctionById((funcid_t)params[4]);
1.252 +
1.253 + return 1;
1.254 +}
1.255 +
1.256 +static cell_t SMC_SetRawLine(IPluginContext *pContext, const cell_t *params)
1.257 +{
1.258 + Handle_t hndl = (Handle_t)params[1];
1.259 + HandleError err;
1.260 + ParseInfo *parse;
1.261 +
1.262 + if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
1.263 + != HandleError_None)
1.264 + {
1.265 + return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
1.266 + }
1.267 +
1.268 + parse->raw_line = pContext->GetFunctionById((funcid_t)params[2]);
1.269 +
1.270 + return 1;
1.271 +}
1.272 +
1.273 +static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
1.274 +{
1.275 + Handle_t hndl = (Handle_t)params[1];
1.276 + HandleError err;
1.277 + ParseInfo *parse;
1.278 +
1.279 + if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
1.280 + != HandleError_None)
1.281 + {
1.282 + return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
1.283 + }
1.284 +
1.285 + char *file;
1.286 + pContext->LocalToString(params[2], &file);
1.287 +
1.288 + char path[PLATFORM_MAX_PATH];
1.289 + g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
1.290 +
1.291 + SMCStates states;
1.292 + SMCError p_err = textparsers->ParseFile_SMC(path, parse, &states);
1.293 +
1.294 + cell_t *c_line, *c_col;
1.295 + pContext->LocalToPhysAddr(params[3], &c_line);
1.296 + pContext->LocalToPhysAddr(params[4], &c_col);
1.297 +
1.298 + *c_line = states.line;
1.299 + *c_col = states.col;
1.300 +
1.301 + return (cell_t)p_err;
1.302 +}
1.303 +
1.304 +static cell_t SMC_GetErrorString(IPluginContext *pContext, const cell_t *params)
1.305 +{
1.306 + const char *str = textparsers->GetSMCErrorString((SMCError)params[1]);
1.307 +
1.308 + if (!str)
1.309 + {
1.310 + return 0;
1.311 + }
1.312 +
1.313 + pContext->StringToLocal(params[2], params[3], str);
1.314 +
1.315 + return 1;
1.316 +}
1.317 +
1.318 +REGISTER_NATIVES(textNatives)
1.319 +{
1.320 + {"SMC_CreateParser", SMC_CreateParser},
1.321 + {"SMC_ParseFile", SMC_ParseFile},
1.322 + {"SMC_GetErrorString", SMC_GetErrorString},
1.323 + {"SMC_SetParseStart", SMC_SetParseStart},
1.324 + {"SMC_SetParseEnd", SMC_SetParseEnd},
1.325 + {"SMC_SetReaders", SMC_SetReaders},
1.326 + {"SMC_SetRawLine", SMC_SetRawLine},
1.327 + {NULL, NULL},
1.328 +};