transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / radiant / parse.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "stdafx.h"\r
23 \r
24 char      token[MAXTOKEN];\r
25 qboolean  unget;\r
26 char*     script_p;\r
27 int       scriptline;\r
28 \r
29 // Hydra: added support for GetTokenExtra()\r
30 char *currentdelimiters;\r
31 qboolean  script_keepdelimiter;\r
32 \r
33 void StartTokenParsing (char *data)\r
34 {\r
35   scriptline = 1;\r
36   script_p = data;\r
37   unget = false;\r
38 \r
39   // Hydra: added support for GetTokenExtra()\r
40   currentdelimiters = NULL;\r
41   script_keepdelimiter = true;\r
42 }\r
43 \r
44 \r
45 qboolean GetToken (qboolean crossline)\r
46 {\r
47   char    *token_p;\r
48   \r
49   if (unget)                         // is a token already waiting?\r
50   {\r
51     unget = false;\r
52     return true;\r
53   }\r
54   \r
55   //\r
56   // skip space\r
57   //\r
58 skipspace:\r
59   while (*script_p <= 32)\r
60   {\r
61     if (!*script_p)\r
62     {\r
63       if (!crossline)\r
64         Sys_Printf("Warning: Line %i is incomplete [01]\n",scriptline);\r
65       return false;\r
66     }\r
67     \r
68     if (*script_p++ == '\n')\r
69     {\r
70       if (!crossline)\r
71         Sys_Printf("Warning: Line %i is incomplete [02]\n",scriptline);\r
72       scriptline++;\r
73     }\r
74   }\r
75   \r
76   if (script_p[0] == '/' && script_p[1] == '/') // comment field\r
77   {\r
78     if (!crossline)\r
79       Sys_Printf("Warning: Line %i is incomplete [03]\n",scriptline);\r
80     while (*script_p++ != '\n')\r
81       if (!*script_p)\r
82       {\r
83         if (!crossline)\r
84           Sys_Printf("Warning: Line %i is incomplete [04]\n",scriptline);\r
85         return false;\r
86       }\r
87       scriptline++; // Hydra: fixed bad line numbers problem\r
88       goto skipspace;\r
89   }\r
90   \r
91   //\r
92   // copy token\r
93   //\r
94   token_p = token;\r
95   \r
96   if (*script_p == '"')\r
97   {\r
98     script_p++;\r
99     while ( *script_p != '"' )\r
100     {\r
101       if (!*script_p)\r
102         Error ("EOF inside quoted token");\r
103       *token_p++ = *script_p++;\r
104       if (token_p == &token[MAXTOKEN])\r
105         Error ("Token too large on line %i",scriptline);\r
106     }\r
107     script_p++;\r
108   }\r
109   else \r
110   while ( *script_p > 32 )\r
111   {\r
112     // Hydra: added support for GetTokenExtra(), care was taken to maintain speed\r
113     if((currentdelimiters) && (!script_keepdelimiter) && (strchr(currentdelimiters,*(script_p))))\r
114       break;\r
115 \r
116     *token_p++ = *script_p++;\r
117     if (token_p == &token[MAXTOKEN])\r
118       Error ("Token too large on line %i",scriptline);\r
119 \r
120     // Hydra: added support for GetTokenExtra()\r
121     if((currentdelimiters) && (strchr(currentdelimiters,*(script_p-1))))\r
122       break;\r
123 \r
124   }\r
125   \r
126   *token_p = 0;\r
127   \r
128   return true;\r
129 }\r
130 \r
131 void UngetToken (void)\r
132 {\r
133   unget = true;\r
134 }\r
135 \r
136 /*\r
137 ==============\r
138 GetTokenExtra\r
139 \r
140 This function expands the use of GetToken() so it can be used to parse\r
141 more complex file formats.\r
142 \r
143 Hydra - Notes:\r
144 You can use this function to split a string like this\r
145 \r
146 string1:("string2")\r
147 \r
148 into two strings, like this:\r
149 string1\r
150 string2\r
151 \r
152 whilst still checking for the brackets and colons, like this:\r
153 \r
154 GetTokenExtra(false,":",false);// contains "string1"\r
155 GetTokenExtra(false,":",true); // contains ":"\r
156 GetTokenExtra(false,"(",true); // contains "("\r
157 GetToken(false);               // contains "string2"\r
158 GetTokenExtra(false,")",true); // contains ")"\r
159 \r
160 here's what you get, given the same string, with this code:\r
161 \r
162 GetToken(false); // contains "string1:("string2")"\r
163 \r
164 Parsing will end if any character in the script matches any one of the\r
165 characters in the "delimiters" string.\r
166 \r
167 it's also possible to do things like this:\r
168 \r
169 source strings:\r
170 1,2\r
171 1:2\r
172 1-2\r
173 1*2\r
174 \r
175 code:\r
176 GetTokenExtra(false,",:-*",false); // token contains "1"\r
177 GetTokenExtra(false,",:-*",false); // token contains the delimiter that was used\r
178 GetToken(false);                   // contains "2"\r
179 ==============\r
180 */\r
181 qboolean GetTokenExtra (qboolean crossline,char *delimiters, qboolean keepdelimiter)\r
182 {\r
183   qboolean result;\r
184   char *olddelimiters = currentdelimiters; // store it\r
185 \r
186   currentdelimiters = delimiters; // change the delimiters\r
187   script_keepdelimiter = keepdelimiter; // change the global flag\r
188 \r
189   result = GetToken(crossline);\r
190   currentdelimiters = olddelimiters; // restore it\r
191   return(result);\r
192 }\r
193 \r
194 /*\r
195 ==============\r
196 TokenAvailable\r
197 \r
198 Returns true if there is another token on the line\r
199 ==============\r
200 */\r
201 qboolean TokenAvailable (void)\r
202 {\r
203   char *search_p;\r
204 \r
205   search_p = script_p;\r
206 \r
207   while ( *search_p <= 32)\r
208   {\r
209     if (*search_p == '\n')\r
210       return false;\r
211     if (*search_p == 0)\r
212       return false;\r
213     search_p++;\r
214   }\r
215 \r
216   if (*search_p == ';')\r
217     return false;\r
218 \r
219   return true;\r
220 }\r