예제 #1
0
// ParseIncludeDirective
//------------------------------------------------------------------------------
bool BFFParser::ParseIncludeDirective( BFFIterator & iter )
{
	// Sanity check include depth to detect cyclic includes
	if ( s_Depth >= 128 )
	{
		Error::Error_1035_ExcessiveDepthComplexity( iter );
		return false;
	}

	// we expect a " quoted string
	if ( *iter != '"' )
	{
		Error::Error_1031_UnexpectedCharFollowingDirectiveName( iter, AStackString<>( "include" ), '"' ); 
		return false;
	}

	BFFIterator stringStart( iter );
	stringStart++; // first actual character

	// find end of string
	if ( iter.ParseToNext( '"' ) == false )
	{
		Error::Error_1012_UnexpectedEndOfFile( iter );
		return false;
	}

	// unescape and substitute variables
	AStackString<> include;
	if ( PerformVariableSubstitutions( stringStart, iter, include ) == false )
	{
		return false;
	}

	iter++; // skip closing quote before returning

	FLOG_INFO( "Including: %s\n", include.Get() );

	// open include

	// 1) Try current directory
	AStackString<> includeToUse;
	if (PathUtils::IsFullPath(include) == false)
	{
		const char * lastSlash = iter.GetFileName().FindLast( NATIVE_SLASH );
		lastSlash = lastSlash ? lastSlash : iter.GetFileName().FindLast( OTHER_SLASH );
		lastSlash = lastSlash ? ( lastSlash + 1 ): iter.GetFileName().Get(); // file only, truncate to empty
		includeToUse.Assign( iter.GetFileName().Get(), lastSlash );
	}
	includeToUse += include;
	AStackString<> includeToUseClean;
	NodeGraph::CleanPath( includeToUse, includeToUseClean );
	FileStream f;
	if ( f.Open( includeToUseClean.Get(), FileStream::READ_ONLY ) == false )
	{
		Error::Error_1032_UnableToOpenInclude( stringStart, includeToUseClean );
		return false;
	}

	// check if include uses "once" pragma
	if ( FBuild::Get().GetDependencyGraph().IsOneUseFile( includeToUseClean ) )
	{
		// already seen, and uses #once : don't include again
		return true;
	}

	uint64_t includeTimeStamp = FileIO::GetFileLastWriteTime( includeToUseClean );

	// read content of include
	const uint32_t fileSize = (uint32_t)f.GetFileSize();
	AutoPtr< char > mem( (char *)ALLOC( fileSize + 1 ) );
	if ( f.Read( mem.Get(), fileSize ) != fileSize )
	{
		Error::Error_1033_ErrorReadingInclude( stringStart, include, Env::GetLastErr() );
		return false;
	}
	mem.Get()[ fileSize ] = '\000'; // sentinel
	BFFParser parser;
	const bool pushStackFrame = false; // include is treated as if injected at this point
	return parser.Parse( mem.Get(), fileSize, includeToUseClean.Get(), includeTimeStamp, pushStackFrame ); 
}
예제 #2
0
// ParseVariableDeclaration
//------------------------------------------------------------------------------
bool BFFParser::ParseVariableDeclaration( BFFIterator & iter, const AString & varName, BFFStackFrame * frame )
{
	m_SeenAVariable = true;

	// look for an appropriate operator
	BFFIterator operatorIter( iter );
	bool modification = false;
	if ( *iter == BFF_VARIABLE_ASSIGNMENT )
	{
		// assignment
	}
	else if ( ( *iter == BFF_VARIABLE_CONCATENATION ) ||
			  ( *iter == BFF_VARIABLE_SUBTRACTION ) )
	{
		// concatenation
		modification = true;
	}
	else
	{
		Error::Error_1016_UnexepectedCharFollowingVariableName( iter );
		return false;
	}

	// skip the assignment symbol and whitespace
	iter++;
	iter.SkipWhiteSpaceAndComments();
	if ( iter.IsAtEnd() )
	{
		Error::Error_1012_UnexpectedEndOfFile( iter );
		return false;
	}

	char openToken = *iter;
	char closeToken = 0;
	bool ok = false;
	if ( ( openToken == '"' ) || ( openToken == '\'' ) )
	{
		closeToken = openToken;
		ok = true;
	}
	else if ( openToken == BFF_SCOPE_OPEN )
	{
		closeToken = BFF_SCOPE_CLOSE;
		ok = true;
	}
	else if ( openToken == BFF_STRUCT_OPEN )
	{
		closeToken = BFF_STRUCT_CLOSE;
		ok = true;
	}
	else if ( ( openToken >= '0' ) && ( openToken <= '9' ) )
	{
		if ( modification )
		{
			Error::Error_1027_CannotModify( operatorIter, varName, BFFVariable::VAR_ANY, BFFVariable::VAR_INT );
			return false;
		}

		// integer value?
		BFFIterator startIntValue( iter );
		while ( iter.IsAtEnd() == false )
		{
			iter++;
			if ( ( *iter < '0' ) || ( *iter > '9' ) )
			{
				break; // end of integer
			}
		}
		if ( startIntValue.GetDistTo( iter ) > 10 )
		{
			Error::Error_1018_IntegerValueCouldNotBeParsed( startIntValue );
			return false;
		}
		AStackString<> intAsString( startIntValue.GetCurrent(), iter.GetCurrent() );
		int i = 0;
		if ( sscanf( intAsString.Get(), "%i", &i ) != 1 )
		{
			Error::Error_1018_IntegerValueCouldNotBeParsed( startIntValue );
			return false;
		}
		return StoreVariableInt( varName, i, frame );
	}
	else if ( ( *iter == 't' ) || ( *iter == 'f' ) )
	{
		// might be 'true' or 'false'
		BFFIterator startBoolValue( iter );
		if ( iter.ParseToNext( 'e' ) == true )
		{
			iter++;
			if ( ( startBoolValue.GetDistTo( iter ) <= 5 ) )
			{
				AStackString<8> value( startBoolValue.GetCurrent(), iter.GetCurrent() );
				if ( value == "true" )
				{
					if ( modification )
					{
						Error::Error_1027_CannotModify( operatorIter, varName, BFFVariable::VAR_ANY, BFFVariable::VAR_BOOL );
						return false;
					}
					return StoreVariableBool( varName, true, frame );
				}
				else if ( value == "false" )
				{
					if ( modification )
					{
						Error::Error_1027_CannotModify( operatorIter, varName, BFFVariable::VAR_ANY, BFFVariable::VAR_BOOL );
						return false;
					}
					return StoreVariableBool( varName, false, frame );
				}
			}
		}

		// not a valid bool value
	}
	else if ( *iter == BFF_DECLARE_VAR_INTERNAL ||
			  *iter == BFF_DECLARE_VAR_PARENT )
	{
		return StoreVariableToVariable( varName, iter, operatorIter, frame );
	}

	if ( !ok )
	{
		Error::Error_1017_UnexepectedCharInVariableValue( iter );
		return false;
	}

	bool result = false;

	// find closing token
	BFFIterator openTokenPos( iter );
	BFFIterator openTokenForError( iter ); // take note of opening token pos for possible error
	openTokenPos++; // more start iter to first char of value
	if ( openToken == BFF_SCOPE_OPEN )
	{
		if ( iter.ParseToMatchingBrace( openToken, closeToken ) )
		{
			result = StoreVariableArray( varName, openTokenPos, iter, operatorIter, frame );
		}
		else
		{
			Error::Error_1002_MatchingClosingTokenNotFound( openTokenForError, nullptr, closeToken );
		}
	}
	else if ( openToken == BFF_STRUCT_OPEN )
	{
		if ( iter.ParseToMatchingBrace( openToken, closeToken ) )
		{
			result = StoreVariableStruct( varName, openTokenPos, iter, operatorIter, frame );
		}
		else
		{
			Error::Error_1002_MatchingClosingTokenNotFound( openTokenForError, nullptr, closeToken );
		}
	}
	else
	{
		ASSERT( ( openToken == '\'' ) || ( openToken == '"' ) );
		iter.SkipString( closeToken );
		if ( *iter == closeToken )
		{
			result = StoreVariableString( varName, openTokenPos, iter, operatorIter, frame );
		}
		else		
		{
			Error::Error_1002_MatchingClosingTokenNotFound( openTokenForError, nullptr, closeToken );
		}
	}

	if ( result )
	{
		iter++; // skip over the end token
	}

	// StoreVariable will have emitted an error if there was one
	return result;
}