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