1 /*
2 * entmap.c
3 * a program for remapping entity key/value pairs
4 *
5 * $Id: entmap.c,v 1.7 2007-12-14 16:41:23 sezero Exp $
6 *
7 * Copyright (C) 1996-1997 Id Software, Inc.
8 * Copyright (C) 1997-1998 Raven Software Corp.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include "q_stdinc.h"
27 #include "compiler.h"
28 #include "arch_def.h"
29 #include "cmdlib.h"
30 #include "util_io.h"
31 #include "pathutil.h"
32 #include "mathlib.h"
33 #include "bspfile.h"
34 #include "bsp5.h"
35
36
37 #define MAXTOKEN 128
38
39 static char token[MAXTOKEN];
40 static qboolean unget;
41 static char *script_p;
42 static int scriptline;
43 static FILE *f;
44
StartTokenParsing(char * data)45 static void StartTokenParsing (char *data)
46 {
47 scriptline = 1;
48 script_p = data;
49 unget = false;
50 }
51
GetToken(qboolean crossline)52 static qboolean GetToken (qboolean crossline)
53 {
54 char *token_p;
55
56 if (unget) // is a token already waiting?
57 {
58 unget = false;
59 return true;
60 }
61
62 //
63 // skip space
64 //
65 skipspace:
66 while (*script_p <= 32)
67 {
68 if (!*script_p)
69 {
70 if (!crossline)
71 COM_Error ("Line %i is incomplete",scriptline);
72 return false;
73 }
74 if (*script_p++ == '\n')
75 {
76 if (!crossline)
77 COM_Error ("Line %i is incomplete",scriptline);
78 scriptline++;
79 }
80 }
81
82 if (script_p[0] == '/' && script_p[1] == '/') // comment field
83 {
84 if (!crossline)
85 COM_Error ("Line %i is incomplete\n",scriptline);
86 while (*script_p++ != '\n')
87 if (!*script_p)
88 {
89 if (!crossline)
90 COM_Error ("Line %i is incomplete",scriptline);
91 return false;
92 }
93 goto skipspace;
94 }
95
96 //
97 // copy token
98 //
99 token_p = token;
100
101 if (*script_p == '"')
102 {
103 script_p++;
104 while ( *script_p != '"' )
105 {
106 if (!*script_p)
107 COM_Error ("EOF inside quoted token");
108 *token_p++ = *script_p++;
109 if (token_p == &token[MAXTOKEN])
110 COM_Error ("Token too large on line %i",scriptline);
111 }
112 script_p++;
113 }
114 else while ( *script_p > 32 )
115 {
116 *token_p++ = *script_p++;
117 if (token_p == &token[MAXTOKEN])
118 COM_Error ("Token too large on line %i",scriptline);
119 }
120
121 *token_p = 0;
122
123 return true;
124 }
125
UngetToken(void)126 static void UngetToken (void)
127 {
128 unget = true;
129 }
130
131
132 //============================================================================
133
134 static int num_entities;
135 static entity_t entity;
136 static entity_t *ent = &entity;
137
138 #if 0
139 static char *ValueForKey (entity_t *ent, char *key)
140 {
141 epair_t *ep;
142
143 for (ep = ent->epairs ; ep ; ep = ep->next)
144 if (!strcmp (ep->key, key) )
145 return ep->value;
146 return "";
147 }
148 #endif
149
150 /*
151 =================
152 MapEntity
153 =================
154 */
MapEntity(void)155 static void MapEntity (void)
156 {
157 #if 0
158 char *class;
159
160 class = ValueForKey (ent, "classname");
161
162 if (!strcmp(class, "path_runcorner")
163 || !strcmp(class, "path_stand")
164 || !strcmp(class, "path_walkcorner")
165 || !strcmp(class, "path_bow") )
166 {
167 printf ("remapped %s\n", class);
168 strcpy (class, "path_corner");
169 return;
170 }
171 #endif
172 }
173
174 /*
175 =================
176 ParseEpair
177 =================
178 */
ParseEpair(void)179 static void ParseEpair (void)
180 {
181 epair_t *e;
182
183 e = (epair_t *) SafeMalloc (sizeof(epair_t));
184 e->next = ent->epairs;
185 ent->epairs = e;
186
187 strcpy (e->key, token);
188 GetToken (false);
189 strcpy (e->value, token);
190 }
191
192 /*
193 =================
194 CopyBrush
195
196 Just copy the brush to the output file
197 =================
198 */
CopyBrush(void)199 static qboolean CopyBrush (void)
200 {
201 int i, j;
202 int pts[3][3];
203 char texname[32];
204 int sofs, tofs, flags;
205 int scale[2], shift[2], rotate;
206
207 fprintf (f,"{\n");
208 while (1)
209 {
210 //
211 // read it in the old way
212 //
213 GetToken (true);
214 if (token[0] == '}')
215 break;
216 UngetToken ();
217
218 for (i = 0 ; i < 3 ; i++)
219 {
220 GetToken (false);
221 if (token[0] != '(')
222 return false; //COM_Error ("%s: couldn't parse", __thisfunc__);
223 for (j = 0 ; j < 3 ; j++)
224 {
225 GetToken (false);
226 pts[i][j] = atoi(token);
227 }
228 GetToken (false);
229 if (token[0] != ')')
230 return false; //COM_Error ("%s: couldn't parse", __thisfunc__);
231 }
232
233 GetToken (false);
234 strcpy (texname, token);
235 GetToken (false);
236 sofs = atoi(token);
237 GetToken (false);
238 tofs = atoi(token);
239 GetToken (false);
240 flags = atoi(token);
241
242 //
243 // convert to new definitions
244 //
245 flags &= 7;
246
247 shift[0] = sofs;
248 shift[1] = tofs;
249
250 rotate = 0;
251 scale[0] = 1;
252 scale[1] = 1;
253
254 #define TEX_FLIPAXIS 1
255 #define TEX_FLIPS 2
256 #define TEX_FLIPT 4
257
258 if (flags & TEX_FLIPAXIS)
259 {
260 rotate = 90;
261 if ( !(flags & TEX_FLIPT) )
262 scale[0] = -1;
263 if (flags & TEX_FLIPS)
264 scale[1] = -1;
265 }
266 else
267 {
268 if (flags & TEX_FLIPS)
269 scale[0] = -1;
270 if (flags & TEX_FLIPT)
271 scale[1] = -1;
272 }
273
274 //
275 // write it out the new way
276 //
277 for (i = 0 ; i < 3 ; i++)
278 fprintf (f, "( %d %d %d ) ", pts[i][0], pts[i][1], pts[i][2]);
279 fprintf (f, "%s %d %d %d %d %d\n", texname, shift[0], shift[1], rotate, scale[0], scale[1]);
280 }
281
282 fprintf (f,"}\n");
283
284 return true;
285 }
286
287 /*
288 ================
289 ParseEntity
290 ================
291 */
ParseEntity(void)292 static int ParseEntity (void)
293 {
294 epair_t *ep;
295
296 if (!GetToken (true))
297 return false;
298
299 if (strcmp (token, "{") )
300 COM_Error ("%s: { not found", __thisfunc__);
301
302 fprintf (f,"{\n");
303
304 ent->epairs = NULL;
305
306 do
307 {
308 if (!GetToken (true))
309 COM_Error ("%s: EOF without closing brace", __thisfunc__);
310 if (!strcmp (token, "}") )
311 break;
312 if (!strcmp (token, "{") )
313 {
314 if (!CopyBrush ())
315 return -1;
316 }
317 else
318 ParseEpair ();
319 } while (1);
320
321 // map the epairs
322 MapEntity ();
323
324 // write the epairs
325 for (ep = ent->epairs ; ep ; ep = ep->next)
326 fprintf (f,"\"%s\" \"%s\"\n", ep->key, ep->value);
327
328 fprintf (f,"}\n");
329
330 return true;
331 }
332
333 /*
334 ================
335 Remap
336 ================
337 */
Remap(char * filename)338 static void Remap (char *filename)
339 {
340 char *buf;
341 char backname[1024];
342 char workname[1024];
343 int r;
344
345 printf ("--------------\n%s\n", filename);
346
347 LoadFile (filename, (void **)&buf);
348 strcpy (backname, filename);
349 StripExtension (backname);
350 strcpy (workname, backname);
351 strcat (backname, ".old");
352 strcat (workname, ".tmp");
353
354 Q_unlink (workname);
355
356 f = fopen (workname, "w");
357 if (!f)
358 COM_Error ("Couldn't write to %s", backname);
359
360 StartTokenParsing (buf);
361
362 num_entities = 0;
363
364 while (1)
365 {
366 r = ParseEntity ();
367 if (r != 1)
368 break;
369 num_entities++;
370 }
371
372 free (buf);
373
374 fclose (f);
375
376 if (r == -1)
377 {
378 printf ("Error parsing %s\n", filename);
379 return;
380 }
381
382 printf ("%5i entities\n", num_entities);
383 Q_unlink (backname);
384 Q_rename (filename, backname);
385 Q_rename (workname, filename);
386 }
387
388
main(int argc,char ** argv)389 int main (int argc, char **argv)
390 {
391 int i;
392
393 if (argc < 2)
394 COM_Error ("USAGE: entmap [mapfile]\nRenames the map to .old, then remaps entity values");
395
396 for (i = 1 ; i < argc ; i++)
397 Remap (argv[i]);
398
399 exit (0);
400 }
401
402