Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_struct.c (12367B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 /*****************************************************************************
     24  * name:		l_struct.c
     25  *
     26  * desc:		structure reading / writing
     27  *
     28  * $Archive: /MissionPack/CODE/botlib/l_struct.c $
     29  *
     30  *****************************************************************************/
     31 
     32 #ifdef BOTLIB
     33 #include "../game/q_shared.h"
     34 #include "../game/botlib.h"				//for the include of be_interface.h
     35 #include "l_script.h"
     36 #include "l_precomp.h"
     37 #include "l_struct.h"
     38 #include "l_utils.h"
     39 #include "be_interface.h"
     40 #endif //BOTLIB
     41 
     42 #ifdef BSPC
     43 //include files for usage in the BSP Converter
     44 #include "../bspc/qbsp.h"
     45 #include "../bspc/l_log.h"
     46 #include "../bspc/l_mem.h"
     47 #include "l_precomp.h"
     48 #include "l_struct.h"
     49 
     50 #define qtrue	true
     51 #define qfalse	false
     52 #endif //BSPC
     53 
     54 //===========================================================================
     55 //
     56 // Parameter:				-
     57 // Returns:					-
     58 // Changes Globals:		-
     59 //===========================================================================
     60 fielddef_t *FindField(fielddef_t *defs, char *name)
     61 {
     62 	int i;
     63 
     64 	for (i = 0; defs[i].name; i++)
     65 	{
     66 		if (!strcmp(defs[i].name, name)) return &defs[i];
     67 	} //end for
     68 	return NULL;
     69 } //end of the function FindField
     70 //===========================================================================
     71 //
     72 // Parameter:				-
     73 // Returns:					-
     74 // Changes Globals:		-
     75 //===========================================================================
     76 qboolean ReadNumber(source_t *source, fielddef_t *fd, void *p)
     77 {
     78 	token_t token;
     79 	int negative = qfalse;
     80 	long int intval, intmin = 0, intmax = 0;
     81 	double floatval;
     82 
     83 	if (!PC_ExpectAnyToken(source, &token)) return 0;
     84 
     85 	//check for minus sign
     86 	if (token.type == TT_PUNCTUATION)
     87 	{
     88 		if (fd->type & FT_UNSIGNED)
     89 		{
     90 			SourceError(source, "expected unsigned value, found %s", token.string);
     91 			return 0;
     92 		} //end if
     93 		//if not a minus sign
     94 		if (strcmp(token.string, "-"))
     95 		{
     96 			SourceError(source, "unexpected punctuation %s", token.string);
     97 			return 0;
     98 		} //end if
     99 		negative = qtrue;
    100 		//read the number
    101 		if (!PC_ExpectAnyToken(source, &token)) return 0;
    102 	} //end if
    103 	//check if it is a number
    104 	if (token.type != TT_NUMBER)
    105 	{
    106 		SourceError(source, "expected number, found %s", token.string);
    107 		return 0;
    108 	} //end if
    109 	//check for a float value
    110 	if (token.subtype & TT_FLOAT)
    111 	{
    112 		if ((fd->type & FT_TYPE) != FT_FLOAT)
    113 		{
    114 			SourceError(source, "unexpected float");
    115 			return 0;
    116 		} //end if
    117 		floatval = token.floatvalue;
    118 		if (negative) floatval = -floatval;
    119 		if (fd->type & FT_BOUNDED)
    120 		{
    121 			if (floatval < fd->floatmin || floatval > fd->floatmax)
    122 			{
    123 				SourceError(source, "float out of range [%f, %f]", fd->floatmin, fd->floatmax);
    124 				return 0;
    125 			} //end if
    126 		} //end if
    127 		*(float *) p = (float) floatval;
    128 		return 1;
    129 	} //end if
    130 	//
    131 	intval = token.intvalue;
    132 	if (negative) intval = -intval;
    133 	//check bounds
    134 	if ((fd->type & FT_TYPE) == FT_CHAR)
    135 	{
    136 		if (fd->type & FT_UNSIGNED) {intmin = 0; intmax = 255;}
    137 		else {intmin = -128; intmax = 127;}
    138 	} //end if
    139 	if ((fd->type & FT_TYPE) == FT_INT)
    140 	{
    141 		if (fd->type & FT_UNSIGNED) {intmin = 0; intmax = 65535;}
    142 		else {intmin = -32768; intmax = 32767;}
    143 	} //end else if
    144 	if ((fd->type & FT_TYPE) == FT_CHAR || (fd->type & FT_TYPE) == FT_INT)
    145 	{
    146 		if (fd->type & FT_BOUNDED)
    147 		{
    148 			intmin = Maximum(intmin, fd->floatmin);
    149 			intmax = Minimum(intmax, fd->floatmax);
    150 		} //end if
    151 		if (intval < intmin || intval > intmax)
    152 		{
    153 			SourceError(source, "value %d out of range [%d, %d]", intval, intmin, intmax);
    154 			return 0;
    155 		} //end if
    156 	} //end if
    157 	else if ((fd->type & FT_TYPE) == FT_FLOAT)
    158 	{
    159 		if (fd->type & FT_BOUNDED)
    160 		{
    161 			if (intval < fd->floatmin || intval > fd->floatmax)
    162 			{
    163 				SourceError(source, "value %d out of range [%f, %f]", intval, fd->floatmin, fd->floatmax);
    164 				return 0;
    165 			} //end if
    166 		} //end if
    167 	} //end else if
    168 	//store the value
    169 	if ((fd->type & FT_TYPE) == FT_CHAR)
    170 	{
    171 		if (fd->type & FT_UNSIGNED) *(unsigned char *) p = (unsigned char) intval;
    172 		else *(char *) p = (char) intval;
    173 	} //end if
    174 	else if ((fd->type & FT_TYPE) == FT_INT)
    175 	{
    176 		if (fd->type & FT_UNSIGNED) *(unsigned int *) p = (unsigned int) intval;
    177 		else *(int *) p = (int) intval;
    178 	} //end else
    179 	else if ((fd->type & FT_TYPE) == FT_FLOAT)
    180 	{
    181 		*(float *) p = (float) intval;
    182 	} //end else
    183 	return 1;
    184 } //end of the function ReadNumber
    185 //===========================================================================
    186 //
    187 // Parameter:				-
    188 // Returns:					-
    189 // Changes Globals:		-
    190 //===========================================================================
    191 qboolean ReadChar(source_t *source, fielddef_t *fd, void *p)
    192 {
    193 	token_t token;
    194 
    195 	if (!PC_ExpectAnyToken(source, &token)) return 0;
    196 
    197 	//take literals into account
    198 	if (token.type == TT_LITERAL)
    199 	{
    200 		StripSingleQuotes(token.string);
    201 		*(char *) p = token.string[0];
    202 	} //end if
    203 	else
    204 	{
    205 		PC_UnreadLastToken(source);
    206 		if (!ReadNumber(source, fd, p)) return 0;
    207 	} //end if
    208 	return 1;
    209 } //end of the function ReadChar
    210 //===========================================================================
    211 //
    212 // Parameter:				-
    213 // Returns:					-
    214 // Changes Globals:		-
    215 //===========================================================================
    216 int ReadString(source_t *source, fielddef_t *fd, void *p)
    217 {
    218 	token_t token;
    219 
    220 	if (!PC_ExpectTokenType(source, TT_STRING, 0, &token)) return 0;
    221 	//remove the double quotes
    222 	StripDoubleQuotes(token.string);
    223 	//copy the string
    224 	strncpy((char *) p, token.string, MAX_STRINGFIELD);
    225 	//make sure the string is closed with a zero
    226 	((char *)p)[MAX_STRINGFIELD-1] = '\0';
    227 	//
    228 	return 1;
    229 } //end of the function ReadString
    230 //===========================================================================
    231 //
    232 // Parameter:				-
    233 // Returns:					-
    234 // Changes Globals:		-
    235 //===========================================================================
    236 int ReadStructure(source_t *source, structdef_t *def, char *structure)
    237 {
    238 	token_t token;
    239 	fielddef_t *fd;
    240 	void *p;
    241 	int num;
    242 
    243 	if (!PC_ExpectTokenString(source, "{")) return 0;
    244 	while(1)
    245 	{
    246 		if (!PC_ExpectAnyToken(source, &token)) return qfalse;
    247 		//if end of structure
    248 		if (!strcmp(token.string, "}")) break;
    249 		//find the field with the name
    250 		fd = FindField(def->fields, token.string);
    251 		if (!fd)
    252 		{
    253 			SourceError(source, "unknown structure field %s", token.string);
    254 			return qfalse;
    255 		} //end if
    256 		if (fd->type & FT_ARRAY)
    257 		{
    258 			num = fd->maxarray;
    259 			if (!PC_ExpectTokenString(source, "{")) return qfalse;
    260 		} //end if
    261 		else
    262 		{
    263 			num = 1;
    264 		} //end else
    265 		p = (void *)(structure + fd->offset);
    266 		while (num-- > 0)
    267 		{
    268 			if (fd->type & FT_ARRAY)
    269 			{
    270 				if (PC_CheckTokenString(source, "}")) break;
    271 			} //end if
    272 			switch(fd->type & FT_TYPE)
    273 			{
    274 				case FT_CHAR:
    275 				{
    276 					if (!ReadChar(source, fd, p)) return qfalse;
    277 					p = (char *) p + sizeof(char);
    278 					break;
    279 				} //end case
    280 				case FT_INT:
    281 				{
    282 					if (!ReadNumber(source, fd, p)) return qfalse;
    283 					p = (char *) p + sizeof(int);
    284 					break;
    285 				} //end case
    286 				case FT_FLOAT:
    287 				{
    288 					if (!ReadNumber(source, fd, p)) return qfalse;
    289 					p = (char *) p + sizeof(float);
    290 					break;
    291 				} //end case
    292 				case FT_STRING:
    293 				{
    294 					if (!ReadString(source, fd, p)) return qfalse;
    295 					p = (char *) p + MAX_STRINGFIELD;
    296 					break;
    297 				} //end case
    298 				case FT_STRUCT:
    299 				{
    300 					if (!fd->substruct)
    301 					{
    302 						SourceError(source, "BUG: no sub structure defined");
    303 						return qfalse;
    304 					} //end if
    305 					ReadStructure(source, fd->substruct, (char *) p);
    306 					p = (char *) p + fd->substruct->size;
    307 					break;
    308 				} //end case
    309 			} //end switch
    310 			if (fd->type & FT_ARRAY)
    311 			{
    312 				if (!PC_ExpectAnyToken(source, &token)) return qfalse;
    313 				if (!strcmp(token.string, "}")) break;
    314 				if (strcmp(token.string, ","))
    315 				{
    316 					SourceError(source, "expected a comma, found %s", token.string);
    317 					return qfalse;
    318 				} //end if
    319 			} //end if
    320 		} //end while
    321 	} //end while
    322 	return qtrue;
    323 } //end of the function ReadStructure
    324 //===========================================================================
    325 //
    326 // Parameter:				-
    327 // Returns:					-
    328 // Changes Globals:		-
    329 //===========================================================================
    330 int WriteIndent(FILE *fp, int indent)
    331 {
    332 	while(indent-- > 0)
    333 	{
    334 		if (fprintf(fp, "\t") < 0) return qfalse;
    335 	} //end while
    336 	return qtrue;
    337 } //end of the function WriteIndent
    338 //===========================================================================
    339 //
    340 // Parameter:				-
    341 // Returns:					-
    342 // Changes Globals:		-
    343 //===========================================================================
    344 int WriteFloat(FILE *fp, float value)
    345 {
    346 	char buf[128];
    347 	int l;
    348 
    349 	sprintf(buf, "%f", value);
    350 	l = strlen(buf);
    351 	//strip any trailing zeros
    352 	while(l-- > 1)
    353 	{
    354 		if (buf[l] != '0' && buf[l] != '.') break;
    355 		if (buf[l] == '.')
    356 		{
    357 			buf[l] = 0;
    358 			break;
    359 		} //end if
    360 		buf[l] = 0;
    361 	} //end while
    362 	//write the float to file
    363 	if (fprintf(fp, "%s", buf) < 0) return 0;
    364 	return 1;
    365 } //end of the function WriteFloat
    366 //===========================================================================
    367 //
    368 // Parameter:				-
    369 // Returns:					-
    370 // Changes Globals:		-
    371 //===========================================================================
    372 int WriteStructWithIndent(FILE *fp, structdef_t *def, char *structure, int indent)
    373 {
    374 	int i, num;
    375 	void *p;
    376 	fielddef_t *fd;
    377 
    378 	if (!WriteIndent(fp, indent)) return qfalse;
    379 	if (fprintf(fp, "{\r\n") < 0) return qfalse;
    380 
    381 	indent++;
    382 	for (i = 0; def->fields[i].name; i++)
    383 	{
    384 		fd = &def->fields[i];
    385 		if (!WriteIndent(fp, indent)) return qfalse;
    386 		if (fprintf(fp, "%s\t", fd->name) < 0) return qfalse;
    387 		p = (void *)(structure + fd->offset);
    388 		if (fd->type & FT_ARRAY)
    389 		{
    390 			num = fd->maxarray;
    391 			if (fprintf(fp, "{") < 0) return qfalse;
    392 		} //end if
    393 		else
    394 		{
    395 			num = 1;
    396 		} //end else
    397 		while(num-- > 0)
    398 		{
    399 			switch(fd->type & FT_TYPE)
    400 			{
    401 				case FT_CHAR:
    402 				{
    403 					if (fprintf(fp, "%d", *(char *) p) < 0) return qfalse;
    404 					p = (char *) p + sizeof(char);
    405 					break;
    406 				} //end case
    407 				case FT_INT:
    408 				{
    409 					if (fprintf(fp, "%d", *(int *) p) < 0) return qfalse;
    410 					p = (char *) p + sizeof(int);
    411 					break;
    412 				} //end case
    413 				case FT_FLOAT:
    414 				{
    415 					if (!WriteFloat(fp, *(float *)p)) return qfalse;
    416 					p = (char *) p + sizeof(float);
    417 					break;
    418 				} //end case
    419 				case FT_STRING:
    420 				{
    421 					if (fprintf(fp, "\"%s\"", (char *) p) < 0) return qfalse;
    422 					p = (char *) p + MAX_STRINGFIELD;
    423 					break;
    424 				} //end case
    425 				case FT_STRUCT:
    426 				{
    427 					if (!WriteStructWithIndent(fp, fd->substruct, structure, indent)) return qfalse;
    428 					p = (char *) p + fd->substruct->size;
    429 					break;
    430 				} //end case
    431 			} //end switch
    432 			if (fd->type & FT_ARRAY)
    433 			{
    434 				if (num > 0)
    435 				{
    436 					if (fprintf(fp, ",") < 0) return qfalse;
    437 				} //end if
    438 				else
    439 				{
    440 					if (fprintf(fp, "}") < 0) return qfalse;
    441 				} //end else
    442 			} //end if
    443 		} //end while
    444 		if (fprintf(fp, "\r\n") < 0) return qfalse;
    445 	} //end for
    446 	indent--;
    447 
    448 	if (!WriteIndent(fp, indent)) return qfalse;
    449 	if (fprintf(fp, "}\r\n") < 0) return qfalse;
    450 	return qtrue;
    451 } //end of the function WriteStructWithIndent
    452 //===========================================================================
    453 //
    454 // Parameter:				-
    455 // Returns:					-
    456 // Changes Globals:		-
    457 //===========================================================================
    458 int WriteStructure(FILE *fp, structdef_t *def, char *structure)
    459 {
    460 	return WriteStructWithIndent(fp, def, structure, 0);
    461 } //end of the function WriteStructure
    462