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