]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/ScriptParser.cpp
reformat code! now the code is only ugly on the *inside*
[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 #include <string.h>
22
23 CScriptParser::CScriptParser(void) :
24         m_pScript(NULL),
25         m_pScriptSection(NULL),
26         m_pLastScriptSection(NULL),
27         m_pToken(NULL)
28 {
29     ClearBuffer();
30 }
31
32 CScriptParser::~CScriptParser(void)
33 {
34     ClearBuffer();
35 }
36
37 void CScriptParser::ClearBuffer(void)
38 {
39     if (m_pScript) {
40         delete[] m_pScript;
41         m_pScript = NULL;
42     }
43     if (m_pToken) {
44         delete[] m_pToken;
45         m_pToken = NULL;
46     }
47     m_pScriptSection = NULL;
48     m_pLastScriptSection = NULL;
49     memset(m_breakChars, 0, sizeof(m_breakChars));
50 }
51
52 const char *CScriptParser::MakeToken(const char *pToken)
53 {
54     if (m_pToken) {
55         delete[] m_pToken;
56         m_pToken = NULL;
57     }
58
59     if (!pToken) {
60         pToken = "";
61     }
62
63     int len = static_cast<int>( strlen(pToken));
64
65     m_pToken = new char[len + 1];
66     m_pToken[len] = '\0';
67     strcpy(m_pToken, pToken);
68
69     return m_pToken;
70 }
71
72 const int MAX_TOKEN_STRING = 1024;
73
74 // Should NEVER return NULL
75 const char *CScriptParser::GetToken(bool bAllowLinebreaks)
76 {
77     int c = 0, len;
78     char token[MAX_TOKEN_STRING];
79     bool bNewLines = false;
80
81     m_pLastScriptSection = m_pScriptSection;
82
83     len = 0;
84     *token = '\0';
85
86     if (!m_pScript || !m_pScriptSection) {
87         return MakeToken(token);
88     }
89
90     while (true) {
91         SkipWhitespace(&bNewLines);
92         if (!*m_pScriptSection) {
93             return MakeToken(token);
94         }
95         if (bNewLines && !bAllowLinebreaks) {
96             return MakeToken(token);
97         }
98
99         c = *m_pScriptSection;
100
101         if (c == '/' && m_pScriptSection[1] == '/') { // C style comments
102             m_pScriptSection += 2;
103             while (*m_pScriptSection && *m_pScriptSection != '\n') {
104                 m_pScriptSection++;
105             }
106         } else if (c == '/' && m_pScriptSection[1] == '*') { // C++ style comments
107             m_pScriptSection += 2;
108             while (*m_pScriptSection && (*m_pScriptSection != '*' || m_pScriptSection[1] != '/')) {
109                 m_pScriptSection++;
110             }
111             if (*m_pScriptSection) {
112                 m_pScriptSection += 2;
113             }
114         } else {
115             break;
116         }
117     }
118
119     if (c == '\"') {
120         m_pScriptSection++;
121         while (true) {
122             c = *m_pScriptSection++;
123             if (c == '\"' || !c) {
124                 token[len] = 0;
125                 return MakeToken(token);
126             }
127             if (len < MAX_TOKEN_STRING) {
128                 token[len] = c;
129                 len++;
130             }
131         }
132     }
133
134     do {
135         if (len > 0 && IsBreakChar(*m_pScriptSection)) {
136             break;
137         }
138
139         if (len < MAX_TOKEN_STRING) {
140             token[len] = c;
141             len++;
142         }
143         m_pScriptSection++;
144
145         if (IsBreakChar(c)) {
146             break;
147         }
148
149         c = *m_pScriptSection;
150     } while (c > 32);
151
152     if (len == MAX_TOKEN_STRING) {
153         len = 0;
154     }
155     token[len] = 0;
156
157     return MakeToken(token);
158 }
159
160 void CScriptParser::SkipWhitespace(bool *pbNewLines)
161 {
162     int c;
163
164     if (!m_pScript || !m_pScriptSection) {
165         return;
166     }
167
168     while ((c = *m_pScriptSection) <= ' ') {
169         if (!c) {
170             return;
171         }
172         if (c == '\n') {
173             *pbNewLines = true;
174         }
175         m_pScriptSection++;
176     }
177 }
178
179 void CScriptParser::SkipBracedSection(void)
180 {
181     const char *token;
182     int depth;
183
184     depth = 0;
185     do {
186         token = GetToken(true);
187         if (token[1] == 0) {
188             if (*token == '{') {
189                 depth++;
190             } else if (*token == '}') {
191                 depth--;
192             }
193         }
194     } while (depth && *m_pScriptSection);
195 }
196
197 void CScriptParser::SkipRestOfLine(void)
198 {
199     char *p;
200     int c;
201
202     p = m_pScriptSection;
203     while ((c = *p++) != 0) {
204         if (c == '\n') {
205             break;
206         }
207     }
208     m_pScriptSection = p;
209 }
210
211 void CScriptParser::UndoGetToken(void)
212 {
213     if (!m_pLastScriptSection) {
214         return;
215     }
216     m_pScriptSection = m_pLastScriptSection;
217     m_pLastScriptSection = NULL;
218 }
219
220 void CScriptParser::ResetParseSession(void)
221 {
222     if (!m_pScript) {
223         return;
224     }
225
226     m_pScriptSection = m_pScript;
227     m_pLastScriptSection = NULL;
228 }
229
230 char *CScriptParser::GetBufferCopy(void)
231 {
232     if (!m_pScript) {
233         return NULL;
234     }
235
236     int len = static_cast<int>( strlen(m_pScript));
237     char *pBuffer = new char[len + 1];
238     strcpy(pBuffer, m_pScript);
239     return pBuffer;
240 }
241
242 int CScriptParser::GetTokenOffset(void)
243 {
244     if (!m_pScript || !m_pScriptSection) {
245         return 0;
246     }
247
248     return static_cast<int>( m_pScriptSection - m_pScript );
249 }
250
251 void CScriptParser::LoadScript(const char *pScript)
252 {
253     ClearBuffer();
254
255     int len = static_cast<int>( strlen(pScript));
256     if (len <= 0) {
257         return;
258     }
259
260     m_pScript = new char[len + 1];
261     m_pScript[len] = '\0';
262
263     strcpy(m_pScript, pScript);
264     m_pScriptSection = m_pScript;
265 }
266
267 void CScriptParser::AddBreakChar(char c)
268 {
269     for (int i = 0; i < SP_MAX_BREAKCHARS; i++) {
270         if (!m_breakChars[i]) {
271             m_breakChars[i] = c;
272             return;
273         }
274     }
275
276     // TODO: Error: max break chars hit
277 }
278
279 bool CScriptParser::IsBreakChar(char c)
280 {
281     for (int i = 0; i < SP_MAX_BREAKCHARS; i++) {
282         if (!m_breakChars[i]) {
283             return false;
284         }
285         if (m_breakChars[i] == c) {
286             return true;
287         }
288     }
289     return false;
290 }
291
292 void CScriptParser::SetScript(char *pScript)
293 {
294     ClearBuffer();
295
296     int len = static_cast<int>( strlen(pScript));
297     if (len <= 0) {
298         return;
299     }
300
301     m_pScript = pScript;
302     m_pScriptSection = m_pScript;
303 }