🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Wierd compiler errors that can be fixed by removing spaces before code

Started by
7 comments, last by howie_007 9 years, 6 months ago

On my script, I started having the compiler error when I added the last 3 functions. The error info suggests lines beyond the actual code.

Below is the code in question (menu.ang).


void Menu_TransIn( CSpriteScript2d @script )
{
    script.SetAlpha( 0 );
    FadeTo( 250, script.GetDefaultAlpha(), script );
}

void Menu_TransOut( CSpriteScript2d @script )
{
    FadeTo( 250, 0, script );
}

void Control_TransIn( CSpriteScript2d @script )
{
    g_allowEvent = true;

    script.SetAlpha( 0 );
    FadeTo( 250, script.GetDefaultAlpha(), script );

    if( g_allowEvent )
    {
        g_allowEvent = false;
        DispatchEvent( EGE_MENU_TRANS_IN, ETC_END );
    }
}

void Control_TransOut( CSpriteScript2d @script )
{
    g_allowEvent = true;

    FadeTo( 250, 0, script );

    if( g_allowEvent )
    {
        g_allowEvent = false;
        DispatchEvent( EGE_MENU_TRANS_OUT, ETC_END );
    }
}

void Control_Inactive( CSpriteScript2d @script )
{
    script.SetDefaultColor();
}

void Control_Hidden( CSpriteScript2d @script )
{
    script.SetVisible( false );
}

void Control_Active( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.3 );

    CColor lowColor = script.GetDefaultColor();
    lowColor.TransformHSV( 0, 1, .5 );

    while(true)
    {
        ColorTo( 500, hiColor, script );
        ColorTo( 500, lowColor, script );
    }
}

void Control_Solid_Active( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.1 );

    CColor lowColor = script.GetDefaultColor();
    lowColor.TransformHSV( 0, 1, .5 );

    while(true)
    {
        ColorTo( 500, hiColor, script );
        ColorTo( 500, lowColor, script );
    }
}

void Control_Face_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.7 );

    CColor lowColor = script.GetDefaultColor();
    lowColor.TransformHSV( 0, 1, .6 );

    script.SetColor( hiColor );

    ColorTo( 120, lowColor, script );
    ColorTo( 120, hiColor, script );

    script.SetColor( script.GetDefaultColor() );

    DispatchEvent( EGE_MENU_SELECT_EXECUTE );
}

void Control_Frame_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.7 );

    CColor lowColor = script.GetDefaultColor();
    lowColor.TransformHSV( 0, 1, .6 );

    script.SetColor( hiColor );

    ColorTo( 120, lowColor, script );
    ColorTo( 120, hiColor, script );

    script.SetVisible( false );
}

void Control_Solid_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.5 );

    CColor lowColor = script.GetDefaultColor();
    lowColor.TransformHSV( 0, 1, .6 );

    script.SetColor( hiColor );

    ColorTo( 120, lowColor, script );
    ColorTo( 100, hiColor, script );

    script.SetVisible( false );
}

void Control_Fast_Face_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.7 );

    script.SetColor( hiColor );

    Hold( 50 );

    script.SetDefaultColor();
}

void Control_Fast_Frame_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.7 );

    script.SetColor( hiColor );

    Hold( 50 );

    script.SetVisible( false );
}

void Control_Fast_Solid_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.5 );

    script.SetColor( hiColor );

    Hold( 50 );

    script.SetVisible( false );
}

Below is the error info. The "}" of the very last function is line 188. There's no code after this point.


data/objects/2d/scripts/menu.ang (189, 2) : ERROR : Expected identifier
data/objects/2d/scripts/menu.ang (189, 2) : ERROR : Instead found '('
data/objects/2d/scripts/menu.ang (192, 12) : ERROR : Expected identifier
data/objects/2d/scripts/menu.ang (192, 12) : ERROR : Instead found '.'
data/objects/2d/scripts/menu.ang (194, 11) : ERROR : Expected identifier
data/objects/2d/scripts/menu.ang (194, 11) : ERROR : Instead found '.'
data/objects/2d/scripts/menu.ang (196, 9) : ERROR : Expected identifier
data/objects/2d/scripts/menu.ang (196, 9) : ERROR : Instead found '('

Now if I do the below to the last two functions, the code will compile and run as expected. All I did was remove the spaces before the lines of code. As you can see, most of the functions are similar.


void Control_Fast_Frame_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

CColor hiColor = script.GetDefaultColor();
hiColor.TransformHSV( 0, 1, 1.7 );

script.SetColor( hiColor );

Hold( 50 );

script.SetVisible( false );
}

void Control_Fast_Solid_Selected( CSpriteScript2d @script )
{
script.SetVisible( true );
script.SetDefaultColor();

CColor hiColor = script.GetDefaultColor();
hiColor.TransformHSV( 0, 1, 1.5 );

script.SetColor( hiColor );

Hold( 50 );

script.SetVisible( false );
}

The only thing I can think of is there's a limit to how big the code file is? Any ideas? I'm using version 2.29.2

Advertisement

Once I had problems with debugging code in visual studio - debugger was stepping the wrong lines. Reason - I copied some code from .pdf file and newlines were wrong. Maybe you can try reopen that file in notepad++, enable all symbols and see what have you got there. :) just an idea.

The parser is apparently reading beyond the script, thus encountering garbage which is does not expect.

Are you using the CScriptBuilder add-on to load the script file? Or have you implemented your own loading routine?

Make sure the buffer holding the script is properly terminated with a null character when calling asIScriptModule::AddScriptSection (if you inform 0 as the codeLength), or inform the correct size of the buffer.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks for your help! I found the problem. I use my own loader but the problem is the below line of code. The file size in bytes is 4,146 but std::strlen only seems to report a number as high as 4,096. Putting zero in that same spot appears to be subject to the same problem.


if( pScriptModule->AddScriptSection(filePath.c_str(), spChar.get(), std::strlen( spChar.get() )) < 0 )

I spoke too soon. Further tests show std::strlen will return a number greater then 4,096. I can also solve the problem by copying that last function, pasting it at the bottom and append a number to the function name.

I don't think this is an AngelScript issue. Not sure what the problem is.

I think your problem is that the buffer that you loaded the script into is not null terminated. Without the null character at the end, strlen will not know when to stop counting the characters in the buffer (and will continue reading into the memory that comes after the buffer). That is the only explanation why the parser is reading beyond the script code.

Double check the code you use for loading the script file into spChar, and make sure that it appends a '\0' after the source code.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Update: I found the problem. I need to open the file as "rb" and not "r".

Below is my function for loading the code file into a buffer. Something odd is going on here. I added some test code to save out the buffer.


boost::shared_array<char> FileToBuf( const std::string & file, size_t & sizeInBytes )
{
    const size_t TERMINATOR_SIZE(10);

    // Open file for reading
    NSmart::scoped_filehandle_ptr<FILE> scpFile( fopen(file.c_str(), "r") );
    if( scpFile.isNull() )
        throw NExcept::CCriticalException("File Load Error!",
            boost::str( boost::format("Error Loading file (%s).\n\n%s\nLine: %s") % file % __FUNCTION__ % __LINE__ ));

    // Seek to the end of the file to find out
    // how many bytes into the file we are and add one for temination
    fseek( scpFile.get(), 0, SEEK_END );
    sizeInBytes = ftell( scpFile.get() ) + TERMINATOR_SIZE;

    // Allocate a buffer for the entire length
    // of the file and a null termination
    boost::shared_array<char> spChar( new char[sizeInBytes] );

    // zero out the whole buffer
    std::memset(spChar.get(), 0, sizeInBytes);

    // Go back to the beginning of the file and 
    // read the contents of the file in to the buffer
    fseek( scpFile.get(), 0, SEEK_SET );
    fread( spChar.get(), sizeInBytes-TERMINATOR_SIZE, 1, scpFile.get() );

    return spChar;

}	// FileToBuf

This is the bottom of the file. It's definately not a null termination problem.


void Control_Fast_Solid_Selected( CSpriteScript2d @script )
{
    script.SetVisible( true );
    script.SetDefaultColor();

    CColor hiColor = script.GetDefaultColor();
    hiColor.TransformHSV( 0, 1, 1.3 );

    script.SetColor( hiColor );

    Hold( 100 );

    script.SetVisible( false );
}
();



    CColor hiColor = script.GetDefaultColor();

    hiColor.TransformHSV( 0, 1, 1.3 );



    script.SetColor( hiColor );



    Hold

When reading textfiles on Windows, a line ends with both the \r and \n characters. file.read() compacts them and returns a single character (\n), but file.seekg() reads the bytes.
This makes the byte size of the file greater than the read size of the file, and makes your buffer too large (and filled with garbage past the end of the string), so you need to truncate it to the actual amount of *characters* (not bytes) read before you return it.

I'm not sure how you'd do it with classes you are using, but this is how I do it with the standard library classes:


//Loads the entire file, newlines and all, and returns its contents as a string.
//Returns an empty string if the file doesn't exist.
std::string LoadFileAsString(const std::string &filename, bool *successful)
{
	return LoadFileAsString(filename, std::string::npos, successful);
}

std::string LoadFileAsString(const std::string &filename, size_t bytesToRead, bool *successful)
{
	if(successful) *successful = false;

	//Open the file for reading.
	std::ifstream file(filename.c_str(), std::ios_base::in);

	if(!file)
	{
		Log::Message(MSG_SOURCE("FileFunctions", Log::Severity::Error)) << "Failed to load '" << Log_HighlightCyan(GetFilenameFromPath(filename)) << "' at " << Log_DisplayPath(filename)
																		<< "\nDo I have sufficient privileges? Does the file even exist?" << Log::FlushStream;

		return "";
	}

	/*
	//This is my old method:

		//Read the file into the stringStream.
		std::ostringstream stringStream;
		stringStream << file.rdbuf();

		//Convert the stringStream into a regular string.
		return stringStream.str();

	//The method below is supposed to be faster, but I haven't benchmarked it.
	*/

	std::string fileContents;

	//Find the size of the file, by seeking to the end.
	file.seekg(0, std::ios::end);

	//Resize our buffer to match the size of the file, or the maximum amount to read.
	size_t endPos = file.tellg();
	bytesToRead = std::min(bytesToRead, endPos);
	fileContents.resize(bytesToRead);

	//Seek back to the beginning of the file.
	file.seekg(0, std::ios::beg);

	//Read the file into the string.
	file.read(&fileContents[0], bytesToRead);

	//Truncate it to the actual amount of characters read.
	if(!file && (file.rdstate() & std::ifstream::eofbit))
	{
		fileContents.resize(file.gcount());
	}

	if(successful) *successful = true;
	return fileContents;
}

Thanks for the info!

This topic is closed to new replies.

Advertisement