3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_globals.h"
33 #include <ITextParsers.h>
34 #include "HandleSys.h"
36 HandleType_t g_TypeSMC = 0;
38 class ParseInfo : public ITextListener_SMC
52 void ReadSMC_ParseStart()
57 parse_start->PushCell(handle);
58 parse_start->Execute(&result);
62 void ReadSMC_ParseEnd(bool halted, bool failed)
67 parse_end->PushCell(handle);
68 parse_end->PushCell(halted ? 1 : 0);
69 parse_end->PushCell(failed ? 1 : 0);
70 parse_end->Execute(&result);
74 SMCParseResult ReadSMC_NewSection(const char *name, bool opt_quotes)
76 cell_t result = SMCParse_Continue;
80 new_section->PushCell(handle);
81 new_section->PushString(name);
82 new_section->PushCell(opt_quotes ? 1 : 0);
83 new_section->Execute(&result);
86 return (SMCParseResult)result;
89 SMCParseResult ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
91 cell_t result = SMCParse_Continue;
95 key_value->PushCell(handle);
96 key_value->PushString(key);
97 key_value->PushString(value);
98 key_value->PushCell(key_quotes ? 1 : 0);
99 key_value->PushCell(value_quotes ? 1 : 0);
100 key_value->Execute(&result);
103 return (SMCParseResult)result;
106 SMCParseResult ReadSMC_LeavingSection()
108 cell_t result = SMCParse_Continue;
112 end_section->PushCell(handle);
113 end_section->Execute(&result);
116 return (SMCParseResult)result;
119 SMCParseResult ReadSMC_RawLine(const char *line, unsigned int curline)
121 cell_t result = SMCParse_Continue;
125 raw_line->PushCell(handle);
126 raw_line->PushString(line);
127 raw_line->PushCell(curline);
128 raw_line->Execute(&result);
131 return (SMCParseResult)result;
134 IPluginFunction *parse_start;
135 IPluginFunction *parse_end;
136 IPluginFunction *new_section;
137 IPluginFunction *key_value;
138 IPluginFunction *end_section;
139 IPluginFunction *raw_line;
143 class TextParseGlobals :
144 public SMGlobalClass,
145 public IHandleTypeDispatch
148 void OnSourceModAllInitialized()
152 /* These cannot be cloned, because they are locked to a specific plugin.
153 * However, we let anyone read them because we don't care.
155 g_HandleSys.InitAccessDefaults(NULL, &sec);
156 sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
157 sec.access[HandleAccess_Read] = 0;
159 g_TypeSMC = g_HandleSys.CreateType("SMCParser", this, 0, NULL, &sec, g_pCoreIdent, NULL);
162 void OnSourceModShutdown()
164 g_HandleSys.RemoveType(g_TypeSMC, g_pCoreIdent);
167 void OnHandleDestroy(HandleType_t type, void *object)
169 ParseInfo *parse = (ParseInfo *)object;
174 TextParseGlobals g_TextParseGlobals;
176 static cell_t SMC_CreateParser(IPluginContext *pContext, const cell_t *params)
178 ParseInfo *pInfo = new ParseInfo();
180 Handle_t hndl = g_HandleSys.CreateHandle(g_TypeSMC, pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL);
182 /* Should never happen */
189 pInfo->handle = hndl;
194 static cell_t SMC_SetParseStart(IPluginContext *pContext, const cell_t *params)
196 Handle_t hndl = (Handle_t)params[1];
200 if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
203 return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
206 parse->parse_start = pContext->GetFunctionById((funcid_t)params[2]);
211 static cell_t SMC_SetParseEnd(IPluginContext *pContext, const cell_t *params)
213 Handle_t hndl = (Handle_t)params[1];
217 if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
220 return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
223 parse->parse_end = pContext->GetFunctionById((funcid_t)params[2]);
228 static cell_t SMC_SetReaders(IPluginContext *pContext, const cell_t *params)
230 Handle_t hndl = (Handle_t)params[1];
234 if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
237 return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
240 parse->new_section = pContext->GetFunctionById((funcid_t)params[2]);
241 parse->key_value = pContext->GetFunctionById((funcid_t)params[3]);
242 parse->end_section = pContext->GetFunctionById((funcid_t)params[4]);
247 static cell_t SMC_SetRawLine(IPluginContext *pContext, const cell_t *params)
249 Handle_t hndl = (Handle_t)params[1];
253 if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
256 return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
259 parse->raw_line = pContext->GetFunctionById((funcid_t)params[2]);
264 static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
266 Handle_t hndl = (Handle_t)params[1];
270 if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
273 return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
277 pContext->LocalToString(params[2], &file);
279 char path[PLATFORM_MAX_PATH];
280 g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
282 unsigned int line = 0, col = 0;
283 SMCParseError p_err = textparsers->ParseFile_SMC(path, parse, &line, &col);
285 cell_t *c_line, *c_col;
286 pContext->LocalToPhysAddr(params[3], &c_line);
287 pContext->LocalToPhysAddr(params[4], &c_col);
292 return (cell_t)p_err;
295 static cell_t SMC_GetErrorString(IPluginContext *pContext, const cell_t *params)
297 const char *str = textparsers->GetSMCErrorString((SMCParseError)params[1]);
304 pContext->StringToLocal(params[2], params[3], str);
309 REGISTER_NATIVES(textNatives)
311 {"SMC_CreateParser", SMC_CreateParser},
312 {"SMC_ParseFile", SMC_ParseFile},
313 {"SMC_GetErrorString", SMC_GetErrorString},
314 {"SMC_SetParseStart", SMC_SetParseStart},
315 {"SMC_SetParseEnd", SMC_SetParseEnd},
316 {"SMC_SetReaders", SMC_SetReaders},
317 {"SMC_SetRawLine", SMC_SetRawLine},