Ejemplo n.º 1
0
//============================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadNumber( script_t *script, token_t *token ) {
	int len = 0, i;
	int octal, dot;
	char c;
//	unsigned long int intvalue = 0;
//	long double floatvalue = 0;

	token->type = TT_NUMBER;
	//check for a hexadecimal number
	if ( *script->script_p == '0' &&
		 ( *( script->script_p + 1 ) == 'x' ||
		   *( script->script_p + 1 ) == 'X' ) ) {
		token->string[len++] = *script->script_p++;
		token->string[len++] = *script->script_p++;
		c = *script->script_p;
		//hexadecimal
		while ( ( c >= '0' && c <= '9' ) ||
				( c >= 'a' && c <= 'f' ) ||
				( c >= 'A' && c <= 'A' ) )
		{
			token->string[len++] = *script->script_p++;
			if ( len >= MAX_TOKEN ) {
				ScriptError( script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return 0;
			} //end if
			c = *script->script_p;
		} //end while
		token->subtype |= TT_HEX;
	} //end if
#ifdef BINARYNUMBERS
	//check for a binary number
	else if ( *script->script_p == '0' &&
			  ( *( script->script_p + 1 ) == 'b' ||
				*( script->script_p + 1 ) == 'B' ) ) {
		token->string[len++] = *script->script_p++;
		token->string[len++] = *script->script_p++;
		c = *script->script_p;
		//hexadecimal
		while ( c == '0' || c == '1' )
		{
			token->string[len++] = *script->script_p++;
			if ( len >= MAX_TOKEN ) {
				ScriptError( script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return 0;
			} //end if
			c = *script->script_p;
		} //end while
		token->subtype |= TT_BINARY;
	} //end if
#endif //BINARYNUMBERS
	else //decimal or octal integer or floating point number
	{
		octal = qfalse;
		dot = qfalse;
		if ( *script->script_p == '0' ) {
			octal = qtrue;
		}
		while ( 1 )
		{
			token->string[len++] = *script->script_p++;
			if ( len >= MAX_TOKEN ) {
				ScriptError( script, "number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return 0;
			} //end if
			c = *script->script_p;
			if ( c == '.' ) {
				dot = qtrue;
			} else if ( c == '8' || c == '9' ) {
				octal = qfalse;
			} else if ( c < '0' || c > '9' )                                              {
				break;
			}
		} //end while
		if ( octal ) {
			token->subtype |= TT_OCTAL;
		} else { token->subtype |= TT_DECIMAL;}
		if ( dot ) {
			token->subtype |= TT_FLOAT;
		}
	} //end else
	for ( i = 0; i < 2; i++ )
	{
		c = *script->script_p;
		//check for a LONG number
		if ( c == 'l' || c == 'L' &&
			 !( token->subtype & TT_LONG ) ) {
			script->script_p++;
			token->subtype |= TT_LONG;
		} //end if
		  //check for an UNSIGNED number
		else if ( c == 'u' || c == 'U' &&
				  !( token->subtype & ( TT_UNSIGNED | TT_FLOAT ) ) ) {
			script->script_p++;
			token->subtype |= TT_UNSIGNED;
		} //end if
	} //end for
	token->string[len] = '\0';
#ifdef NUMBERVALUE
	NumberValue( token->string, token->subtype, &token->intvalue, &token->floatvalue );
#endif //NUMBERVALUE
	if ( !( token->subtype & TT_FLOAT ) ) {
		token->subtype |= TT_INTEGER;
	}
	return 1;
} //end of the function PS_ReadNumber
Ejemplo n.º 2
0
//============================================================================
// Reads an escape character.
//
// Parameter:				script		: script to read from
//								ch				: place to store the read escape character
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadEscapeCharacter( script_t *script, char *ch ) {
	int c, val, i;

	//step over the leading '\\'
	script->script_p++;
	//determine the escape character
	switch ( *script->script_p )
	{
	case '\\': c = '\\'; break;
	case 'n': c = '\n'; break;
	case 'r': c = '\r'; break;
	case 't': c = '\t'; break;
	case 'v': c = '\v'; break;
	case 'b': c = '\b'; break;
	case 'f': c = '\f'; break;
	case 'a': c = '\a'; break;
	case '\'': c = '\''; break;
	case '\"': c = '\"'; break;
	case '\?': c = '\?'; break;
	case 'x':
	{
		script->script_p++;
		for ( i = 0, val = 0; ; i++, script->script_p++ )
		{
			c = *script->script_p;
			if ( c >= '0' && c <= '9' ) {
				c = c - '0';
			} else if ( c >= 'A' && c <= 'Z' ) {
				c = c - 'A' + 10;
			} else if ( c >= 'a' && c <= 'z' )                                            {
				c = c - 'a' + 10;
			} else { break;}
			val = ( val << 4 ) + c;
		}     //end for
		script->script_p--;
		if ( val > 0xFF ) {
			ScriptWarning( script, "too large value in escape character" );
			val = 0xFF;
		}     //end if
		c = val;
		break;
	}     //end case
	default:     //NOTE: decimal ASCII code, NOT octal
	{
		if ( *script->script_p < '0' || *script->script_p > '9' ) {
			ScriptError( script, "unknown escape char" );
		}
		for ( i = 0, val = 0; ; i++, script->script_p++ )
		{
			c = *script->script_p;
			if ( c >= '0' && c <= '9' ) {
				c = c - '0';
			} else { break;}
			val = val * 10 + c;
		}     //end for
		script->script_p--;
		if ( val > 0xFF ) {
			ScriptWarning( script, "too large value in escape character" );
			val = 0xFF;
		}     //end if
		c = val;
		break;
	}     //end default
	} //end switch
	  //step over the escape character or the last digit of the number
	script->script_p++;
	//store the escape character
	*ch = c;
	//succesfully read escape character
	return 1;
} //end of the function PS_ReadEscapeCharacter
Ejemplo n.º 3
0
//============================================================================
// Reads C-like string. Escape characters are interpretted.
// Quotes are included with the string.
// Reads two strings with a white space between them as one string.
//
// Parameter:				script		: script to read from
//								token			: buffer to store the string
// Returns:					qtrue when a string was read succesfully
// Changes Globals:		-
//============================================================================
int PS_ReadString( script_t *script, token_t *token, int quote ) {
	int len, tmpline;
	char *tmpscript_p;

	if ( quote == '\"' ) {
		token->type = TT_STRING;
	} else { token->type = TT_LITERAL;}

	len = 0;
	//leading quote
	token->string[len++] = *script->script_p++;
	//
	while ( 1 )
	{
		//minus 2 because trailing double quote and zero have to be appended
		if ( len >= MAX_TOKEN - 2 ) {
			ScriptError( script, "string longer than MAX_TOKEN = %d", MAX_TOKEN );
			return 0;
		} //end if
		  //if there is an escape character and
		  //if escape characters inside a string are allowed
		if ( *script->script_p == '\\' && !( script->flags & SCFL_NOSTRINGESCAPECHARS ) ) {
			if ( !PS_ReadEscapeCharacter( script, &token->string[len] ) ) {
				token->string[len] = 0;
				return 0;
			} //end if
			len++;
		} //end if
		  //if a trailing quote
		else if ( *script->script_p == quote ) {
			//step over the double quote
			script->script_p++;
			//if white spaces in a string are not allowed
			if ( script->flags & SCFL_NOSTRINGWHITESPACES ) {
				break;
			}
			//
			tmpscript_p = script->script_p;
			tmpline = script->line;
			//read unusefull stuff between possible two following strings
			if ( !PS_ReadWhiteSpace( script ) ) {
				script->script_p = tmpscript_p;
				script->line = tmpline;
				break;
			} //end if
			  //if there's no leading double qoute
			if ( *script->script_p != quote ) {
				script->script_p = tmpscript_p;
				script->line = tmpline;
				break;
			} //end if
			  //step over the new leading double quote
			script->script_p++;
		} //end if
		else
		{
			if ( *script->script_p == '\0' ) {
				token->string[len] = 0;
				ScriptError( script, "missing trailing quote" );
				return 0;
			} //end if
			if ( *script->script_p == '\n' ) {
				token->string[len] = 0;
				ScriptError( script, "newline inside string %s", token->string );
				return 0;
			} //end if
			token->string[len++] = *script->script_p++;
		} //end else
	} //end while
	  //trailing quote
	token->string[len++] = quote;
	//end string with a zero
	token->string[len] = '\0';
	//the sub type is the length of the string
	token->subtype = len;
	return 1;
} //end of the function PS_ReadString
Ejemplo n.º 4
0
//============================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadPunctuation(script_t *script, token_t *token)
{
	int len;
	char *p;
	punctuation_t *punc;

#ifdef PUNCTABLE
	for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next)
	{
#else
	int i;

	for (i = 0; script->punctuations[i].p; i++)
	{
		punc = &script->punctuations[i];
#endif //PUNCTABLE
		p = punc->p;
		len = strlen(p);
		//if the script contains at least as much characters as the punctuation
		if (script->script_p + len <= script->end_p)
		{
			//if the script contains the punctuation
			if (!strncmp(script->script_p, p, len))
			{
				strncpy(token->string, p, MAX_TOKEN);
				script->script_p += len;
				token->type = TT_PUNCTUATION;
				//sub type is the number of the punctuation
				token->subtype = punc->n;
				return 1;
			} //end if
		} //end if
	} //end for
	return 0;
} //end of the function PS_ReadPunctuation
//============================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadPrimitive(script_t *script, token_t *token)
{
	int len;

	len = 0;
	while(*script->script_p > ' ' && *script->script_p != ';')
	{
		if (len >= MAX_TOKEN)
		{
			ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN);
			return 0;
		} //end if
		token->string[len++] = *script->script_p++;
	} //end while
	token->string[len] = 0;
	//copy the token into the script structure
	Com_Memcpy(&script->token, token, sizeof(token_t));
	//primitive reading successfull
	return 1;
} //end of the function PS_ReadPrimitive
Ejemplo n.º 5
0
//============================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ReadToken(script_t *script, token_t *token)
{
	//if there is a token available (from UnreadToken)
	if (script->tokenavailable)
	{
		script->tokenavailable = 0;
		Com_Memcpy(token, &script->token, sizeof(token_t));
		return 1;
	} //end if
	//save script pointer
	script->lastscript_p = script->script_p;
	//save line counter
	script->lastline = script->line;
	//clear the token stuff
	Com_Memset(token, 0, sizeof(token_t));
	//start of the white space
	script->whitespace_p = script->script_p;
	token->whitespace_p = script->script_p;
	//read unusefull stuff
	if (!PS_ReadWhiteSpace(script)) return 0;
	//end of the white space
	script->endwhitespace_p = script->script_p;
	token->endwhitespace_p = script->script_p;
	//line the token is on
	token->line = script->line;
	//number of lines crossed before token
	token->linescrossed = script->line - script->lastline;
	//if there is a leading double quote
	if (*script->script_p == '\"')
	{
		if (!PS_ReadString(script, token, '\"')) return 0;
	} //end if
	//if an literal
	else if (*script->script_p == '\'')
	{
		//if (!PS_ReadLiteral(script, token)) return 0;
		if (!PS_ReadString(script, token, '\'')) return 0;
	} //end if
	//if there is a number
	else if ((*script->script_p >= '0' && *script->script_p <= '9') ||
				(*script->script_p == '.' &&
				(*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9')))
	{
		if (!PS_ReadNumber(script, token)) return 0;
	} //end if
	//if this is a primitive script
	else if (script->flags & SCFL_PRIMITIVE)
	{
		return PS_ReadPrimitive(script, token);
	} //end else if
	//if there is a name
	else if ((*script->script_p >= 'a' && *script->script_p <= 'z') ||
		(*script->script_p >= 'A' && *script->script_p <= 'Z') ||
		*script->script_p == '_')
	{
		if (!PS_ReadName(script, token)) return 0;
	} //end if
	//check for punctuations
	else if (!PS_ReadPunctuation(script, token))
	{
		ScriptError(script, "can't read token");
		return 0;
	} //end if
	//copy the token into the script structure
	Com_Memcpy(&script->token, token, sizeof(token_t));
	//succesfully read a token
	return 1;
} //end of the function PS_ReadToken
Ejemplo n.º 6
0
void Interpreter::execute(const DirectoryName & root,
    ScriptType type, const ScriptName & name)
{
    std::string scriptDir = root + "/scripts/";
    std::string scriptDir2 = root + "/";
    switch (type)
    {
    case rule:
        scriptDir += "rules/";
        scriptDir2 += "rules/";
        break;
    case transformation:
        scriptDir += "transformations/";
        scriptDir2 += "transformations/";
        break;
    }

    // first look at tcl rules
    std::string tclName = name;
    if (boost::algorithm::ends_with(tclName, ".tcl") == false)
    {
      tclName += ".tcl";
    }
    if (boost::filesystem::exists(scriptDir + tclName))
    {
        TclInterpreter::execute(root, type, scriptDir + tclName);
        return;
    }
    else if (boost::filesystem::exists(scriptDir2 + tclName))
    {
        TclInterpreter::execute(root, type, scriptDir2 + tclName);
        return;
    }
#ifdef VERA_PYTHON
    // then python
    std::string pyName = name;
    if (boost::algorithm::ends_with(pyName, ".py") == false)
    {
      pyName += ".py";
    }
    if (boost::filesystem::exists(scriptDir + pyName))
    {
        PythonInterpreter::execute(root, type, scriptDir + pyName);
        return;
    }
    else if (boost::filesystem::exists(scriptDir2 + pyName))
    {
        PythonInterpreter::execute(root, type, scriptDir2 + pyName);
        return;
    }
#endif
#ifdef VERA_LUA
    // then lua
    std::string luaName = name;
    if (boost::algorithm::ends_with(luaName, ".lua") == false)
    {
      luaName += ".lua";
    }
    if (boost::filesystem::exists(scriptDir + luaName))
    {
        LuaInterpreter::execute(root, type, scriptDir + luaName);
        return;
    }
    else if (boost::filesystem::exists(scriptDir2 + luaName))
    {
        LuaInterpreter::execute(root, type, scriptDir2 + luaName);
        return;
    }
#endif
    std::ostringstream ss;
    ss << "cannot open script " << name;
    throw ScriptError(ss.str());
}
Ejemplo n.º 7
0
//============================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//============================================================================
int PS_ExpectTokenType( script_t *script, int type, int subtype, token_t *token ) {
	char str[MAX_TOKEN];

	if ( !PS_ReadToken( script, token ) ) {
		ScriptError( script, "couldn't read expected token" );
		return 0;
	} //end if

	if ( token->type != type ) {
		strcpy(str, "");
		if ( type == TT_STRING ) {
			strcpy( str, "string" );
		}
		if ( type == TT_LITERAL ) {
			strcpy( str, "literal" );
		}
		if ( type == TT_NUMBER ) {
			strcpy( str, "number" );
		}
		if ( type == TT_NAME ) {
			strcpy( str, "name" );
		}
		if ( type == TT_PUNCTUATION ) {
			strcpy( str, "punctuation" );
		}
		ScriptError( script, "expected a %s, found %s", str, token->string );
		return 0;
	} //end if
	if ( token->type == TT_NUMBER ) {
		if ( ( token->subtype & subtype ) != subtype ) {
			strcpy(str, "");
			if ( subtype & TT_DECIMAL ) {
				strcpy( str, "decimal" );
			}
			if ( subtype & TT_HEX ) {
				strcpy( str, "hex" );
			}
			if ( subtype & TT_OCTAL ) {
				strcpy( str, "octal" );
			}
			if ( subtype & TT_BINARY ) {
				strcpy( str, "binary" );
			}
			if ( subtype & TT_LONG ) {
				strcat( str, " long" );
			}
			if ( subtype & TT_UNSIGNED ) {
				strcat( str, " unsigned" );
			}
			if ( subtype & TT_FLOAT ) {
				strcat( str, " float" );
			}
			if ( subtype & TT_INTEGER ) {
				strcat( str, " integer" );
			}
			ScriptError( script, "expected %s, found %s", str, token->string );
			return 0;
		} //end if
	} //end if
	else if ( token->type == TT_PUNCTUATION ) {
		if ( subtype < 0 ) {
			ScriptError( script, "BUG: wrong punctuation subtype" );
			return 0;
		} //end if
		if ( token->subtype != subtype ) {
			ScriptError( script, "expected %s, found %s",
					script->punctuations[subtype].p, token->string);
			return 0;
		} //end if
	} //end else if
	return 1;
} //end of the function PS_ExpectTokenType
Ejemplo n.º 8
0
void FScanner::MustGetValue(bool allowfloat)
{
	if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
}
Ejemplo n.º 9
0
void FScanner::MustGetBoolToken()
{
	if (!CheckBoolToken())
		ScriptError("Expected true or false");
}
Ejemplo n.º 10
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
void AAS_ParseBSPEntities(void)
{
	script_t *script;
	token_t token;
	bsp_entity_t *ent;
	bsp_epair_t *epair;

	script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
	SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE);

	bspworld.numentities = 1;

	while(PS_ReadToken(script, &token))
	{
		if (strcmp(token.string, "{"))
		{
			ScriptError(script, "invalid %s\n", token.string);
			AAS_FreeBSPEntities();
			FreeScript(script);
			return;
		} //end if
		if (bspworld.numentities >= MAX_BSPENTITIES)
		{
			botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n");
			break;
		} //end if
		ent = &bspworld.entities[bspworld.numentities];
		bspworld.numentities++;
		ent->epairs = NULL;
		while(PS_ReadToken(script, &token))
		{
			if (!strcmp(token.string, "}")) break;
			epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t));
			epair->next = ent->epairs;
			ent->epairs = epair;
			if (token.type != TT_STRING)
			{
				ScriptError(script, "invalid %s\n", token.string);
				AAS_FreeBSPEntities();
				FreeScript(script);
				return;
			} //end if
			StripDoubleQuotes(token.string);
			epair->key = (char *) GetHunkMemory(strlen(token.string) + 1);
			strcpy(epair->key, token.string);
			if (!PS_ExpectTokenType(script, TT_STRING, 0, &token))
			{
				AAS_FreeBSPEntities();
				FreeScript(script);
				return;
			} //end if
			StripDoubleQuotes(token.string);
			epair->value = (char *) GetHunkMemory(strlen(token.string) + 1);
			strcpy(epair->value, token.string);
		} //end while
		if (strcmp(token.string, "}"))
		{
			ScriptError(script, "missing }\n");
			AAS_FreeBSPEntities();
			FreeScript(script);
			return;
		} //end if
	} //end while
	FreeScript(script);
} //end of the function AAS_ParseBSPEntities
Ejemplo n.º 11
0
static bool PS_ReadNumber( script_t* script, token_t* token ) {
	int len = 0;

	token->type = TT_NUMBER;
	//check for a hexadecimal number
	if ( *script->script_p == '0' &&
		 ( *( script->script_p + 1 ) == 'x' ||
		   *( script->script_p + 1 ) == 'X' ) ) {
		token->string[ len++ ] = *script->script_p++;
		token->string[ len++ ] = *script->script_p++;
		char c = *script->script_p;
		//hexadecimal
		while ( ( c >= '0' && c <= '9' ) ||
				( c >= 'a' && c <= 'f' ) ||
				( c >= 'A' && c <= 'A' ) ) {
			token->string[ len++ ] = *script->script_p++;
			if ( len >= MAX_TOKEN ) {
				ScriptError( script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return false;
			}
			c = *script->script_p;
		}
		token->subtype |= TT_HEX;
	}
	//check for a binary number
	else if ( *script->script_p == '0' &&
			  ( *( script->script_p + 1 ) == 'b' ||
				*( script->script_p + 1 ) == 'B' ) ) {
		token->string[ len++ ] = *script->script_p++;
		token->string[ len++ ] = *script->script_p++;
		char c = *script->script_p;
		//binary
		while ( c == '0' || c == '1' ) {
			token->string[ len++ ] = *script->script_p++;
			if ( len >= MAX_TOKEN ) {
				ScriptError( script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return 0;
			}
			c = *script->script_p;
		}
		token->subtype |= TT_BINARY;
	} else {	//decimal or octal integer or floating point number
		bool octal = false;
		int dot = false;
		if ( *script->script_p == '0' ) {
			octal = true;
		}
		while ( 1 ) {
			char c = *script->script_p;
			if ( c == '.' ) {
				dot = true;
			} else if ( c == '8' || c == '9' ) {
				octal = false;
			} else if ( c < '0' || c > '9' ) {
				break;
			}
			token->string[ len++ ] = *script->script_p++;
			if ( len >= MAX_TOKEN - 1 ) {
				ScriptError( script, "number longer than MAX_TOKEN = %d", MAX_TOKEN );
				return false;
			}
		}
		if ( octal ) {
			token->subtype |= TT_OCTAL;
		} else {
			token->subtype |= TT_DECIMAL;
		}
		if ( dot ) {
			token->subtype |= TT_FLOAT;
		}
	}
	for ( int i = 0; i < 2; i++ ) {
		char c = *script->script_p;
		//check for a LONG number
		if ( ( c == 'l' || c == 'L' ) &&
			 !( token->subtype & TT_LONG ) ) {
			script->script_p++;
			token->subtype |= TT_LONG;
		}
		//check for an UNSIGNED number
		else if ( ( c == 'u' || c == 'U' ) &&
				  !( token->subtype & ( TT_UNSIGNED | TT_FLOAT ) ) ) {
			script->script_p++;
			token->subtype |= TT_UNSIGNED;
		}
	}
	token->string[ len ] = '\0';
	NumberValue( token->string, token->subtype, &token->intvalue, &token->floatvalue );
	if ( !( token->subtype & TT_FLOAT ) ) {
		token->subtype |= TT_INTEGER;
	}
	return true;
}
Ejemplo n.º 12
0
/*
=======================================================================================================================================
AAS_ParseBSPEntities
=======================================================================================================================================
*/
void AAS_ParseBSPEntities(void) {
	script_t *script;
	token_t token;
	bsp_entity_t *ent;
	bsp_epair_t *epair;
	byte *buffer, *buftrav;
	int bufsize;

	// modified this, so that it first gathers up memory requirements, then allocates a single chunk, and places the strings all in there
	bspworld.ebuffer = NULL;

	script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");

	SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS); // SCFL_PRIMITIVE

	bufsize = 0;

	while (PS_ReadToken(script, &token)) {
		if (strcmp(token.string, "{")) {
			ScriptError(script, "invalid %s", token.string);
			AAS_FreeBSPEntities();
			FreeScript(script);
			return;
		}

		if (bspworld.numentities >= MAX_BSPENTITIES) {
			botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n");
			break;
		}

		while (PS_ReadToken(script, &token)) {
			if (!strcmp(token.string, "}")) {
				break;
			}

			bufsize += sizeof(bsp_epair_t);

			if (token.type != TT_STRING) {
				ScriptError(script, "invalid %s", token.string);
				AAS_FreeBSPEntities();
				FreeScript(script);
				return;
			}

			StripDoubleQuotes(token.string);
			bufsize += strlen(token.string) + 1;

			if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) {
				AAS_FreeBSPEntities();
				FreeScript(script);
				return;
			}

			StripDoubleQuotes(token.string);
			bufsize += strlen(token.string) + 1;
		}

		if (strcmp(token.string, "}")) {
			ScriptError(script, "missing}");
			AAS_FreeBSPEntities();
			FreeScript(script);
			return;
		}
	}

	FreeScript(script);

	buffer = (byte *)GetClearedHunkMemory(bufsize);
	buftrav = buffer;
	bspworld.ebuffer = buffer;
	// now parse the entities into memory
	// NOTE: removed error checks for speed, no need to do them twice
	script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
	SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS); // SCFL_PRIMITIVE

	bspworld.numentities = 1;

	while (PS_ReadToken(script, &token)) {
		ent = &bspworld.entities[bspworld.numentities];
		bspworld.numentities++;
		ent->epairs = NULL;

		while (PS_ReadToken(script, &token)) {
			if (!strcmp(token.string, "}")) {
				break;
			}

			epair = (bsp_epair_t *)buftrav; buftrav += sizeof(bsp_epair_t);
			epair->next = ent->epairs;
			ent->epairs = epair;
			StripDoubleQuotes(token.string);
			epair->key = (char *)buftrav; buftrav += (strlen(token.string) + 1);
			strcpy(epair->key, token.string);

			if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) {
				AAS_FreeBSPEntities();
				FreeScript(script);
				return;
			}

			StripDoubleQuotes(token.string);
			epair->value = (char *)buftrav; buftrav += (strlen(token.string) + 1);
			strcpy(epair->value, token.string);
		}
	}

	FreeScript(script);
}