refactored plugin api; refactored callback library; added signals library
[xonotic/netradiant.git] / contrib / bobtoolz / ScriptParser.cpp
1 /*
2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include "ScriptParser.h"
21
22 CScriptParser::CScriptParser(void): 
23         m_pScript(NULL),
24         m_pScriptSection(NULL),
25         m_pLastScriptSection(NULL),
26         m_pToken(NULL) {
27         ClearBuffer();
28 }
29
30 CScriptParser::~CScriptParser(void) {
31         ClearBuffer();
32 }
33
34 void CScriptParser::ClearBuffer(void) {
35         if(m_pScript) {
36                 delete[] m_pScript;
37                 m_pScript = NULL;
38         }
39         if(m_pToken) {
40                 delete[] m_pToken;
41                 m_pToken = NULL;
42         }
43         m_pScriptSection = NULL;
44         m_pLastScriptSection = NULL;
45         memset(m_breakChars, 0, sizeof(m_breakChars));
46 }
47
48 const char* CScriptParser::MakeToken(const char* pToken) {
49         if(m_pToken) {
50                 delete[] m_pToken;
51                 m_pToken = NULL;
52         }
53
54         if(!pToken) {
55                 pToken = "";
56         }
57
58         int len = static_cast<int>(strlen(pToken));
59
60         m_pToken = new char[len + 1];
61         m_pToken[len] = '\0';
62         strcpy(m_pToken, pToken);
63
64         return m_pToken;
65 }
66
67 #define MAX_TOKEN_STRING 1024
68 // Should NEVER return NULL
69 const char* CScriptParser::GetToken(bool bAllowLinebreaks) {
70         int c = 0, len;
71         char token[MAX_TOKEN_STRING];
72         bool bNewLines = false;
73
74         m_pLastScriptSection = m_pScriptSection;
75
76         len = 0;
77         *token = '\0';
78
79         if(!m_pScript || !m_pScriptSection) {
80                 return MakeToken(token);
81         }
82
83         while ( true ) {
84                 SkipWhitespace( &bNewLines );
85                 if ( !*m_pScriptSection ) {
86                         return MakeToken(token);
87                 }
88                 if ( bNewLines && !bAllowLinebreaks ) {
89                         return MakeToken(token);
90                 }
91
92                 c = *m_pScriptSection;
93                 
94                 if ( c == '/' && m_pScriptSection[1] == '/' ) { // C style comments
95                         m_pScriptSection += 2;
96                         while (*m_pScriptSection && *m_pScriptSection != '\n') {
97                                 m_pScriptSection++;
98                         }
99                 } else if ( c=='/' && m_pScriptSection[1] == '*' ) { // C++ style comments
100                         m_pScriptSection += 2;
101                         while ( *m_pScriptSection && ( *m_pScriptSection != '*' || m_pScriptSection[1] != '/' ) ) {
102                                 m_pScriptSection++;
103                         }
104                         if ( *m_pScriptSection ) {
105                                 m_pScriptSection += 2;
106                         }
107                 } else {
108                         break;
109                 }
110         }
111
112         if (c == '\"') {
113                 m_pScriptSection++;
114                 while ( true ) {
115                         c = *m_pScriptSection++;
116                         if (c=='\"' || !c) {
117                                 token[len] = 0;
118                                 return MakeToken(token);
119                         }
120                         if (len < MAX_TOKEN_STRING) {
121                                 token[len] = c;
122                                 len++;
123                         }
124                 }
125         }
126
127         do {
128                 if(len > 0 && IsBreakChar(*m_pScriptSection)) {
129                         break;
130                 }
131
132                 if (len < MAX_TOKEN_STRING) {
133                         token[len] = c;
134                         len++;
135                 }
136                 m_pScriptSection++;
137
138                 if(IsBreakChar(c)) {
139                         break;
140                 }
141
142                 c = *m_pScriptSection;
143         } while (c > 32);
144
145         if (len == MAX_TOKEN_STRING) {
146                 len = 0;
147         }
148         token[len] = 0;
149
150         return MakeToken(token);
151 }
152
153 void CScriptParser::SkipWhitespace(bool* pbNewLines) {
154         int c;
155
156         if(!m_pScript || !m_pScriptSection) {
157                 return;
158         }
159
160         while( (c = *m_pScriptSection) <= ' ') {
161                 if( !c ) {
162                         return;
163                 }
164                 if( c == '\n' ) {
165                         *pbNewLines = true;
166                 }
167                 m_pScriptSection++;
168         }
169 }
170
171 void CScriptParser::SkipBracedSection(void) {
172         const char              *token;
173         int                             depth;
174
175         depth = 0;
176         do {
177                 token = GetToken( true );
178                 if( token[1] == 0 ) {
179                         if( *token == '{' ) {
180                                 depth++;
181                         } else if( *token == '}' ) {
182                                 depth--;
183                         }
184                 }
185         } while( depth && *m_pScriptSection );
186 }
187
188 void CScriptParser::SkipRestOfLine(void) {
189         char    *p;
190         int             c;
191
192         p = m_pScriptSection;
193         while ( (c = *p++) != 0 ) {
194                 if ( c == '\n' ) {
195                         break;
196                 }
197         }
198         m_pScriptSection = p;
199 }
200
201 void CScriptParser::UndoGetToken(void) {
202         if(!m_pLastScriptSection) {
203                 return;
204         }
205         m_pScriptSection = m_pLastScriptSection;
206         m_pLastScriptSection = NULL;
207 }
208
209 void CScriptParser::ResetParseSession(void) {
210         if(!m_pScript) {
211                 return;
212         }
213
214         m_pScriptSection = m_pScript;
215         m_pLastScriptSection = NULL;
216 }
217
218 char* CScriptParser::GetBufferCopy(void) {
219         if(!m_pScript) {
220                 return NULL;
221         }
222
223         int len = static_cast<int>(strlen(m_pScript));
224         char* pBuffer = new char[len + 1];
225         strcpy(pBuffer, m_pScript);
226         return pBuffer;
227 }
228
229 int CScriptParser::GetTokenOffset(void) {
230         if(!m_pScript || !m_pScriptSection) {
231                 return 0;
232         }
233
234         return static_cast<int>(m_pScriptSection - m_pScript);
235 }
236
237 void CScriptParser::LoadScript(const char* pScript) {
238         ClearBuffer();
239
240         int len = static_cast<int>(strlen(pScript));
241         if(len <= 0) {
242                 return;
243         }
244
245         m_pScript = new char[len + 1];
246         m_pScript[len] = '\0';
247
248         strcpy(m_pScript, pScript);
249         m_pScriptSection = m_pScript;
250 }
251
252 void CScriptParser::AddBreakChar(char c) {
253         for(int i = 0; i < SP_MAX_BREAKCHARS; i++) {
254                 if(!m_breakChars[i]) {
255                         m_breakChars[i] = c;
256                         return;
257                 }
258         }
259
260         // TODO: Error: max break chars hit
261 }
262
263 bool CScriptParser::IsBreakChar(char c) {
264         for(int i = 0; i < SP_MAX_BREAKCHARS; i++) {
265                 if(!m_breakChars[i]) {
266                         return false;
267                 }
268                 if(m_breakChars[i] == c) {
269                         return true;
270                 }
271         }
272         return false;
273 }
274
275 void CScriptParser::SetScript(char* pScript) {
276         ClearBuffer();
277
278         int len = static_cast<int>(strlen(pScript));
279         if(len <= 0) {
280                 return;
281         }
282
283         m_pScript = pScript;
284         m_pScriptSection = m_pScript;
285 }