/*
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *  SCR_Anl.c
 *  To analyse a section.
 *
 *  Scripts, Beaudet Christophe
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 */
 
/*
 *=================================================================================================
 *  Includes.
 *=================================================================================================
 */
 
#include <memory.h>
#include "SCR.h"
 
/*
 *=================================================================================================
 *  Global variables.
 *=================================================================================================
 */
 
/*
 *  Array of all callbacks.
 */
SCR_tdst_DyAr_Description   SCR_g_st_Anl_ArrayCallbacks;
 
/*
 *	For parser. To treat return values of callbacks.
 */
int							g_iExitBeforeLevel = -1;
 
/*
 *=================================================================================================
 *  Functions.
 *=================================================================================================
 */
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Init.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_InitModule(void)
{
    fn_v_DyAr_InitArray(&SCR_g_st_Anl_ArrayCallbacks);
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Close.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_CloseModule(void)
{
    SCR_M_DyAr_DeleteAllElements(SCR_tdst_Anl_Callback, &SCR_g_st_Anl_ArrayCallbacks, ;);
}
 
/*===============================================================================================*/
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To add a callback for a file or a section.
 *  _p_szSectionName    :   Name of section or file.
 *  _pfn_eCallback      :   Address of function callback.
 *  _cForSection        :   0 - It's a file callback.
 *                          1 - It's a section callback.
 *  Returns address of allocated structure.
 *-------------------------------------------------------------------------------------------------
 */
SCR_tdst_Anl_Callback *fnp_st_Anl_AddCallback
(
    char                    *_p_szSectionName, 
    SCR_tdpfn_Anl_Callback  _pfn_eCallback,
    char                    _cForSection
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned int            uiPos;
    SCR_tdst_Anl_Callback   *p_stCallback;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_Assert_P(_p_szSectionName != NULL);
    SCR_M_Dbg_Assert_P(_pfn_eCallback != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Add element.
     */
    SCR_M_DyAr_AddElement(SCR_tdst_Anl_Callback, uiPos, p_stCallback, SCR_g_st_Anl_ArrayCallbacks);
 
    /*
     *  Initialize structure.
     */
    strcpy(p_stCallback->a_szSectionName, _p_szSectionName);
    p_stCallback->pfn_eCallback = _pfn_eCallback;
    p_stCallback->cForSection = _cForSection;
 
    /* Return structure */
    return p_stCallback;
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To delete a callback.
 *  _p_szCallback   :   Callback to delete.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_DeleteCallback(SCR_tdst_Anl_Callback *_p_stCallback)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Anl_Callback, _p_stCallback);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_DyAr_DeleteElement
    (
        SCR_tdst_Anl_Callback,
        _p_stCallback->stHeader.uiIndexInArray, 
        &SCR_g_st_Anl_ArrayCallbacks, 
        ;
    );
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To search a callback.
 *  _p_szSectionName    :   Name of section.
 *  _cForSection        :   0 - It's a file callback.
 *                          1 - It's a section callback.
 *  Returns address of allocated structure.
 *-------------------------------------------------------------------------------------------------
 */
SCR_tdst_Anl_Callback *fnp_st_Anl_SearchCallback
(
    char *_p_szSectionName, 
    char _cForSection
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned int            uiPos;
    SCR_tdst_Anl_Callback   *p_stPointer = NULL;
    char                    *p_szTemp;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_Assert_P(_p_szSectionName != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    SCR_M_DyAr_SearchElement
    (
        SCR_tdst_Anl_Callback,
        uiPos,
        p_stPointer,
        SCR_g_st_Anl_ArrayCallbacks,
        (
            (!strcmpi(p_stPointer->a_szSectionName, _p_szSectionName))
        &&  (p_stPointer->cForSection == _cForSection)
        )
    );
 
    /*
     *  If we have not found the callback, and if it's for a file, we search a
     *  callback associated to the file extension (if one).
     */
    if((p_stPointer == NULL) && (_cForSection == 0))
    {
        p_szTemp = strrchr(_p_szSectionName, '.');
        if(p_szTemp)
        {
            SCR_M_DyAr_SearchElement
            (
                SCR_tdst_Anl_Callback,
                uiPos,
                p_stPointer,
                SCR_g_st_Anl_ArrayCallbacks,
                (
                    (!strcmpi(p_stPointer->a_szSectionName, p_szTemp))
                &&  (p_stPointer->cForSection == _cForSection)
                )
            );
        }
    }
 
    return p_stPointer;
}
 
/*===============================================================================================*/
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To add a new section in list. Section description must be in current context.
 *  _p_stContext        :   Current context.        
 *  _p_stParentSection  :   Address of parent section description (can be NULL).
 *  Returns address of allocated structure.
 *-------------------------------------------------------------------------------------------------
 */
SCR_tdst_Anl_SectionDes *fnp_st_Anl_AddSectionDes
(
    SCR_tdst_Cxt_Description    *_p_stContext,
    SCR_tdst_Anl_SectionDes     *_p_stParentSection
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned int                uiPos;
    SCR_tdst_Anl_SectionDes     *p_stSection;
    SCR_tdx_Hash_Key            xHashKey;
    unsigned int                uiIndexOfHashValue;
	unsigned char				ucMemoLevel;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	/*
	 * Force memory level to be equal to file one.
	 */
	ucMemoLevel = g_uc_Mem_CurrentMemLevel;
	g_uc_Mem_CurrentMemLevel = _p_stContext->p_stOpenFile->stHeader.ucMemLevel;
 
    /*
     *  Add element in dynamic array.
     */
    SCR_M_DyAr_AddElement
    (
        SCR_tdst_Anl_SectionDes, 
        uiPos, 
        p_stSection,
        _p_stContext->p_stOpenFile->stSectionsDes
    );
 
    /*
     *  Compute hash key of section complete name.
     *  Add the section description in the hash table.
     */
    SCR_M_Sect_ComputeHashKey
    (
        xHashKey, 
        _p_stContext->stBuffers.a_szBufferCompleteName
    );
 
    fnp_st_Hash_AddValue
    (
        xHashKey, 
        _p_stContext->p_stOpenFile->a_stHashSectionsDes,
        (unsigned long) p_stSection,
        &uiIndexOfHashValue
    );
 
    /*
     *  Initialize structure.
     */
	fn_v_Mem_SetMode(p_stSection->stHeader.ucMemLevel);
    SCR_M_Cxt_CopyBuffersToDyn(&p_stSection->stBuffers, &_p_stContext->stBuffers);
    memcpy(&p_stSection->stBeginPosition, &_p_stContext->stPosition, sizeof(SCR_tdst_Cxt_Position));
	memset(&p_stSection->stEndPosition, 0, sizeof(SCR_tdst_Cxt_Position));
    p_stSection->uwDynamicFlags = _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags;
    p_stSection->p_stParentSection = _p_stParentSection;
    p_stSection->uiIndexOfHashValue = uiIndexOfHashValue;
	p_stSection->p_stOpenSection = NULL;
 
	/*
	 * Restore memory level.
	 */
	g_uc_Mem_CurrentMemLevel = ucMemoLevel;
 
    return p_stSection;
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To search a section description in list.
 *  _p_stOpenFile       :   File to search the section description.
 *  _p_szSectionName    :   Name of section to add.
 *  _Line               :   Line to search (0 to ignore)
 *  Returns address of allocated structure.
 *-------------------------------------------------------------------------------------------------
 */
SCR_tdst_Anl_SectionDes *fnp_st_Anl_SearchSectionDes
(
    SCR_tdst_File_Open  *_p_stOpenFile,
    char                *_p_szSectionName,
    unsigned int        _uiLineInFile,
	unsigned int		_uiNum
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned int            uiPos;
    SCR_tdst_Hash_Value     *p_stPointer = NULL;
    SCR_tdx_Hash_Key        xHashKey;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stOpenFile);
    SCR_M_Dbg_Assert_P(_p_szSectionName != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Compute hash key of section complete name.
     */
    SCR_M_Sect_ComputeHashKey
    (
        xHashKey, 
        _p_szSectionName
    );
 
    /*
     *  We search the section in a_stHashSectionDes.
     */
    SCR_M_DyAr_SearchElement
    (
        SCR_tdst_Hash_Value,
        uiPos,
        p_stPointer,
        _p_stOpenFile->a_stHashSectionsDes[xHashKey],
        (
			(!strcmpi(((SCR_tdst_Anl_SectionDes *) (p_stPointer->ulValue))->stBuffers.p_szBufferCompleteName, _p_szSectionName))
        &&	(
				(_uiLineInFile == 0)
			||	(((SCR_tdst_Anl_SectionDes *) (p_stPointer->ulValue))->stBeginPosition.uiLineInFile == _uiLineInFile)
			)
		&&	(!_uiNum || !_uiNum--)
        )
    );
 
    /*
     *  Return address of structure.
     */
    if(p_stPointer)
        return (SCR_tdst_Anl_SectionDes *) p_stPointer->ulValue;
    else
        return NULL;
}
 
/*===============================================================================================*/
 
/*
 *-------------------------------------------------------------------------------------------------
 *  We analyse a dynamic directive.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_AnalyseDynamicDirective(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    char    *p_szDirective;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    p_szDirective = _p_stContext->stBuffers.a_szBufferName;
 
	/*
	 *	SCR_CD_sz_Cfg_BreakPoint. Only in debug mode.
	 */
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_BreakPoint))
	{
#if defined(_DEBUG) && !defined(SCR_DM_ProtectedVersion)
		/*
		 *	USER BREAKPOINT.
		 *	A directive has been found in file.
		 */
		SCR_M_Dbg_BreakForDebug();
#else if defined(SCR_DM_ProtectedVersion)
		printf("User breakpoint detected\n");
#endif /* _DEBUG */
	}
 
	/*
	 *	SCR_CD_sz_Cfg_UpdateLog
	 */
	else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_UpdateLog))
	{
		sprintf
		(
			g_st_Err_GlobalError.a_szBufferTmp1,
			"User update log in file \"%s\" at line \"%d\".\n",
			_p_stContext->p_stOpenFile->stFile.a_szFileName,
			_p_stContext->stPosition.uiLineInFile
		);
        sprintf
		(
			g_st_Err_GlobalError.a_szBufferTmp2,
			"Section is \"%s\".", 
			_p_stContext->stBuffersCopy.a_szBufferCompleteName
		);
		strcpy(g_st_Err_GlobalError.a_szBufferOut, g_st_Err_GlobalError.a_szBufferTmp1);
		strcat(g_st_Err_GlobalError.a_szBufferOut, g_st_Err_GlobalError.a_szBufferTmp2);
		fn_v_Err_UpdateLogFile();
	}
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Parser has found a directive in file.
 *  We analyse it and we update the stDirectives structure of current parsing infos in file.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_AnalyseDirective(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    char    *p_szDirective;
    char    *ap_szParameters[SCR_CV_ui_Cfg_MaxNumPars];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    p_szDirective = _p_stContext->stBuffers.a_szBufferName;
 
    /*
     *  Test all directives.
     */
 
	/*
	 *	Dynamic directives that must be ignored.
	 */
    if
	(
		(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_BreakPoint))
	||	(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_UpdateLog))
	)
	{
	}
 
    /* 
     *  SCR_CD_sz_Cfg_Comments.
     *  All next sections will never not be treated.
     */
	else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_Comments))
    {
        if(_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_Comments)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags |= SCR_CDF_uw_Anl_Comments;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_EndComments.
     *  End of previous mode.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_EndComments))
    {
        if((_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_Comments) == 0)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags &= ~SCR_CDF_uw_Anl_Comments;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_ForceAnalyse.
     *  All next sections will be analyse even if it was already done.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_ForceAnalyse))
    {
        if(_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_ForceAnalyse)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags |= SCR_CDF_uw_Anl_ForceAnalyse;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_EndForceAnalyse.
     *  End of previous mode.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_EndForceAnalyse))
    {
        if((_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_ForceAnalyse) == 0)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags &= ~SCR_CDF_uw_Anl_ForceAnalyse;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_NotSaveSection.
     *  All next sections will not be saved.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_NotSaveSection))
    {
        if(_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_NotSaveSection)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags |= SCR_CDF_uw_Anl_NotSaveSection;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_EndNotSaveSection.
     *  End of previous mode.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_EndNotSaveSection))
    {
        if((_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_NotSaveSection) == 0)
        {
            SCR_M_Err_UpdateSyntaxError();
            sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Directive is \"%s\".", p_szDirective);
            SCR_M_Err_RaiseWarning(SCR_EI_Err_UnnecessaryDirective);
        }
        else
            _p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags &= ~SCR_CDF_uw_Anl_NotSaveSection;
    }
 
    /* 
     *  SCR_CD_sz_Cfg_SetFileLong.
     *  To initialize a long file value of a relative context.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_SetCurrentFileLong))
    {
        fn_v_Pars_ConvertNormalParameters(_p_stContext->stBuffers.a_szBufferParams, ap_szParameters);
        SCR_M_Dbg_Assert_D(SCR_fn_uc_RdL0_GetNumberOfParameters(ap_szParameters) == 2);
        SCR_M_RdL0_SetFileLong(0, atol(ap_szParameters[0]), atol(ap_szParameters[1]));
        SCR_M_Pars_FreeParameters(ap_szParameters);
    }
 
    /* 
     *  SCR_CD_sz_Cfg_SetFileDouble.
     *  To initialize a double file value of a relative context.
     */
    else
    if(!strcmpi(p_szDirective, SCR_CD_sz_Cfg_SetCurrentFileDouble))
    {
        fn_v_Pars_ConvertNormalParameters(_p_stContext->stBuffers.a_szBufferParams, ap_szParameters);
        SCR_M_Dbg_Assert_D(SCR_fn_uc_RdL0_GetNumberOfParameters(ap_szParameters) == 2);
        SCR_M_RdL0_SetFileDouble(0, atol(ap_szParameters[0]), atof(ap_szParameters[1]));
        SCR_M_Pars_FreeParameters(ap_szParameters);
    }
 
    /* 
     *  Else unknown directive : Error.
     */
    else
    {
        SCR_M_Err_UpdateSyntaxError();
        sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Unknown directive is \"%s\".", p_szDirective);
        SCR_M_Err_RaiseError(SCR_EI_Err_UnknownDirective);
    }
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Update the a_szBufferCompleteName of current context.
 *  _p_stContext        :   Current context.
 *  Returns address of parent section (NULL if not).
 *-------------------------------------------------------------------------------------------------
 */
SCR_tdst_Anl_SectionDes *fnp_st_Anl_ComputeCompleteName
(
    SCR_tdst_Cxt_Description    *_p_stContext,
    char                        _cUpdateParser
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Anl_SectionDes     *p_stSection = NULL;
    unsigned int                uiSectionPos;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /* 
     *  If current level is 1, it's a main section without parent.
     *  Parent section returns is NULL.
     *  We add the file name before the section one.
     *  We add the id section name after it.
     */
    if(_p_stContext->stPosition.uiLevel == 1)
    {
        strcpy(_p_stContext->stBuffers.a_szBufferCompleteName, _p_stContext->p_stOpenFile->stFile.a_szFileName);
        p_stSection = NULL;
    }
    else
    {
        /*
         *  Else current section has a parent. We must found it and compute the complete section
         *  name of the current one.
         *
         *  If we have not yet parsed this section :
         *  We began with the last section in array of sections.
         *
         *  If we have already parsed this section :
         *  We are analysed it, so stBuffersCopy of current context contains the parent
         *  section name.
         */
        if(_cUpdateParser)
        {
            uiSectionPos = _p_stContext->p_stOpenFile->stSectionsDes.uiNumValues;
            do
            {
                uiSectionPos--;
                SCR_M_DyAr_GetElement
                (
                    SCR_tdst_Anl_SectionDes, 
                    uiSectionPos,
                    p_stSection,
                    _p_stContext->p_stOpenFile->stSectionsDes
                );
            } while
            (
                (uiSectionPos) 
            &&  (p_stSection->stBeginPosition.uiLevel >= _p_stContext->stPosition.uiLevel)
            );
            SCR_M_Dbg_Assert_P(p_stSection->stBeginPosition.uiLevel < _p_stContext->stPosition.uiLevel);
 
            /* Parent complete section name is in section description found */
            strcpy(_p_stContext->stBuffers.a_szBufferCompleteName, p_stSection->stBuffers.p_szBufferCompleteName);
        }
        else
        {
            /* Parent complete section name is in buffer copy of actual context */
            strcpy(_p_stContext->stBuffers.a_szBufferCompleteName, _p_stContext->stBuffersCopy.a_szBufferCompleteName);
        }
    }
 
    /*
     *  We add the separator, the actual section action name and the actual section id name.
     */
    strcat(_p_stContext->stBuffers.a_szBufferCompleteName, SCR_CC_sz_Cfg_NameSeparator);
    strcat(_p_stContext->stBuffers.a_szBufferCompleteName, _p_stContext->stBuffers.a_szBufferName);
    if(*_p_stContext->stBuffers.a_szBufferNameExt)
    {
        strcat(_p_stContext->stBuffers.a_szBufferCompleteName, SCR_CC_sz_Cfg_SectionIdMark);
        strcat(_p_stContext->stBuffers.a_szBufferCompleteName, _p_stContext->stBuffers.a_szBufferNameExt);
    }
 
    return p_stSection;
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To compute the seek just after a EndSection marker.
 *  Update p_stSectionDes in current context.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_ComputeSeekEnd(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Anl_SectionDes     *p_stSection;
    unsigned int                uiSectionPos;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Anl_SectionDes, _p_stContext->p_stSectionDes);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Search the first section with the same level than the current one.
     */
	/*MP: BINARY*/
	if( _p_stContext->p_stSectionDes == NULL )
		return;
 
    uiSectionPos = _p_stContext->p_stSectionDes->stHeader.uiIndexInArray + 1;
    do
    {
        uiSectionPos--;
        SCR_M_DyAr_GetElement
        (
            SCR_tdst_Anl_SectionDes,
            uiSectionPos,
            p_stSection,
            _p_stContext->p_stOpenFile->stSectionsDes
        );
    } while
    (
        (uiSectionPos) 
    &&  (p_stSection->stBeginPosition.uiLevel != _p_stContext->stPosition.uiLevel)
    );
    SCR_M_Dbg_Assert_P(p_stSection->stBeginPosition.uiLevel == _p_stContext->stPosition.uiLevel);
 
    /*
     *  Update lSeekEndSection of current section.
     *  Update uiCurrentSectionDescription of current context.
     */
    memcpy(&p_stSection->stEndPosition, &_p_stContext->stPosition, sizeof(SCR_tdst_Cxt_Position));
    _p_stContext->p_stSectionDes = p_stSection;
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Update parsing infos of current file.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_UpdateInfos(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Anl_SectionDes     *p_stParentSection;
    char                        cUpdateParser = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	if( _p_stContext->eParseType== SCR_EPT_Cxt_Directive )
	{
		 /*
	     *  It's a directive.
		 *  We analyse it and update stParsingInfos.stDirectives.
		 */
        if( _p_stContext->p_stOpenFile->stFile.bBinaryMode )
			_p_stContext->stPosition.lAfterSeekInFile+=fn_l_Bin_AnalyseDirective(_p_stContext);
		else
			fn_v_Anl_AnalyseDirective(_p_stContext);
	}
 
    /*
     *  cUpdateParser is set to 0 if it's the first time we parsed that line.
     *  Else cUpdateParser is set to 0.
     */
    if(_p_stContext->stPosition.uiLineInFile > _p_stContext->p_stOpenFile->stParsingInfos.stPosition.uiLineInFile)
	{
        cUpdateParser = 1;
		if
        (
            (_p_stContext->p_stOpenFile->stSectionsDes.uiNumValues)
        &&  (_p_stContext->cForSection&~2)
        )
		{
			SCR_M_DyAr_GetElement
			(
				SCR_tdst_Anl_SectionDes,
				_p_stContext->p_stOpenFile->stSectionsDes.uiNumValues - 1,
				_p_stContext->p_stSectionDes,
				_p_stContext->p_stOpenFile->stSectionsDes
			);
		}
	}
 
    /* 
     *  Position of parser is the one of context.
     */
    if(cUpdateParser)
    {
        memcpy
        (
            &_p_stContext->p_stOpenFile->stParsingInfos.stPosition, 
            &_p_stContext->stPosition, 
            sizeof(SCR_tdst_Cxt_Position)
        );
    }
 
    switch(_p_stContext->eParseType)
    {
    /*
     *  Is this an entry or a blank line ?
     */
    case SCR_EPT_Cxt_Entry:
    case SCR_EPT_Cxt_None:
        break;
 
    /*
     *  Is this a section name ?
     *  We update the current level.
     *  We compute its complete section name.
     *  We add this section to the array for file.
     */
    case SCR_EPT_Cxt_BeginSection:
 
        /* We update level of current context and of infos */
        if(cUpdateParser)
            _p_stContext->p_stOpenFile->stParsingInfos.stPosition.uiLevel++;
        _p_stContext->stPosition.uiLevel++;
 
        /* We compute complete section name */
        p_stParentSection = fnp_st_Anl_ComputeCompleteName(_p_stContext, cUpdateParser);
 
        /* We add the section to the array for the file and we update p_stSectionDes */
        if(cUpdateParser)
        {
            _p_stContext->p_stSectionDes = fnp_st_Anl_AddSectionDes
            (
                _p_stContext,
                p_stParentSection
            );
        }
 
        /* We simply update p_stSectionDes */
        else
        {
            _p_stContext->p_stSectionDes = fnp_st_Anl_SearchSectionDes
            (
                _p_stContext->p_stOpenFile,
                _p_stContext->stBuffers.a_szBufferCompleteName,
                _p_stContext->stPosition.uiLineInFile,
				0
            );
        }
        break;
 
    /*
     *  Is this a end of section ?
     *  Update lSeekEndSection of corresponding section.
     *  Update current parsing level.
     */
    case SCR_EPT_Cxt_EndSection:
 
        /* End section without begin one */
        if(_p_stContext->stPosition.uiLevel == 0)
        {
            SCR_M_Err_UpdateSyntaxError();
            SCR_M_Err_RaiseError(SCR_EI_Err_EndSectionAlone);
        }
 
        if(cUpdateParser)
        {
            /* Compute seek end */
            fn_v_Anl_ComputeSeekEnd(_p_stContext);
            /* Update current level of parser */
            _p_stContext->p_stOpenFile->stParsingInfos.stPosition.uiLevel--;
        }
        _p_stContext->stPosition.uiLevel--;
        break;
    }
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To parse a line to current context.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
int fn_i_Anl_LineToContext(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    int				iRead;
    unsigned int    uiNbRead;
	int				iCpt;
	char			a_szTempBuffer[SCR_CV_ui_Cfg_MaxLenLine + 1];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Parse one line of file.
     */
    _p_stContext->stBuffers.a_szBufferCompleteName[0] = 0;
    _p_stContext->stPosition.uiLineInFile++;
 
	/* MP - BINARY mode START */	
	if( _p_stContext->p_stOpenFile->stFile.bBinaryMode )
	{
		short sLineLength;
 
		fn_v_Bin_Line(
			&_p_stContext->p_stOpenFile->stFile,
			_p_stContext->stBuffers.a_szBufferName,
			_p_stContext->stBuffers.a_szBufferNameExt,
			_p_stContext->stBuffers.a_szBufferFormat,
			_p_stContext->stBuffers.a_szBufferParams,
			&_p_stContext->eParseType,
			&uiNbRead
		);
 
		
		iRead='a'; /* for convenience...*/
		
		if( _p_stContext->eParseType==SCR_EPT_Cxt_None )
		{
			char tmp[100];
			
			sLineLength=SCR_fn_s_Bin_GetSHORT( &_p_stContext->p_stOpenFile->stFile ); /* get line length */
			if( sLineLength==0 )
  				iRead=EOF;
			else
				iRead='0';
			/* temp */
			fn_v_Bin_Read( &_p_stContext->p_stOpenFile->stFile, sLineLength, (void *)tmp );
			uiNbRead+=sLineLength+2;
		}
		
	}
	else
	/* MP - BINARY mode END */
    /*
     *  If current parsing directive is ignore, we swap the line like a comment
     *  (except if it is the $EndComments directive).
     */
    if(_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags & SCR_CDF_uw_Anl_Comments)
    {
		/* 
		 *	Get the current line.
		 */
		iCpt = 0;
		SCR_g_ui_Pars_NbRead = 0;
		SCR_M_Pars_GetNextNonSpaceChar(&_p_stContext->p_stOpenFile->stFile, iRead);
		while((iRead != '\n') && (iRead != EOF))
		{
			if(!SCR_M_Pars_IsSpace(iRead))
				a_szTempBuffer[iCpt++] = (char) iRead;
			SCR_M_Pars_ReadChar(&_p_stContext->p_stOpenFile->stFile, iRead);
		}
		a_szTempBuffer[iCpt] = '\0';
		uiNbRead = SCR_g_ui_Pars_NbRead;
 
		/*
		 *	Test for end of comment directive.
		 */
        if
		(
			(*a_szTempBuffer != SCR_CC_c_Cfg_DirectiveMark)
		||	(strcmpi(a_szTempBuffer + 1, SCR_CD_sz_Cfg_EndComments))
		)
        {
            _p_stContext->eParseType = SCR_EPT_Cxt_None;
            _p_stContext->stBuffers.a_szBufferName[0] = '\0';
        }
		else
			_p_stContext->p_stOpenFile->stParsingInfos.uwDynamicFlags &= ~SCR_CDF_uw_Anl_Comments;
    }
	else
	{
		iRead = (char) fn_i_Pars_Line
		(
			&_p_stContext->p_stOpenFile->stFile,
			_p_stContext->stBuffers.a_szBufferName,
			_p_stContext->stBuffers.a_szBufferNameExt,
			_p_stContext->stBuffers.a_szBufferFormat,
			_p_stContext->stBuffers.a_szBufferParams,
			&_p_stContext->eParseType,
			&uiNbRead
		);
	}
 
    /*
     *  Update seek after reading.
     */
    _p_stContext->stPosition.lAfterSeekInFile += uiNbRead;
 
    /* 
     *  Update parsing infos.
     */
    fn_v_Anl_UpdateInfos(_p_stContext);
 
    /* Return last character read */
    return iRead;
}
 
/*===============================================================================================*/
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Initialize the current context with the section title of _p_szSectionName.
 *  _p_stContext        :   Current context.
 *  _p_szSectionName    :   Name of section.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_ContextToSection(SCR_tdst_Cxt_Description *_p_stContext, char *_p_szSectionName)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Anl_SectionDes     *p_stSection;
    char                        iRead;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
    SCR_M_Dbg_Assert_P(_p_szSectionName != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  We search the section in the array. The first section with the good name
     *  is took !
     */
    _p_stContext->cForSection = 1;
	if( _p_stContext->p_stOpenFile->stFile.bBinaryMode ) /* MP: BINARY */
		_p_stContext->cForSection = 3;
    p_stSection = fnp_st_Anl_SearchSectionDes(_p_stContext->p_stOpenFile, _p_szSectionName, 0, 0);
    if(p_stSection)
    {
        /* Update position of context and file */
        SCR_M_Anl_CxtFileToPos
        (
            _p_stContext, 
            p_stSection->stBeginPosition
        );
        /* Update buffers */
        SCR_M_Cxt_CopyDynToBuffers(&_p_stContext->stBuffers, &p_stSection->stBuffers);
        /* Update other fields */
        _p_stContext->p_stSectionDes = p_stSection;
        return;
    }
 
    /*
     *  Parser has not yet reached the section. We must parse to it.
     *  => Current context position is parsing infos of current file.
     *  => Parse file
     */
    SCR_M_Anl_CxtFileToPos
    (
        _p_stContext, 
        _p_stContext->p_stOpenFile->stParsingInfos.stPosition
    );
    do
    {
        /* Read one line of file */
        iRead = (char) fn_i_Anl_LineToContext(_p_stContext);
        if(iRead == (char) EOF)
            break;
 
        /* If current line is a section, we test its complete name */
        if(_p_stContext->eParseType == SCR_EPT_Cxt_BeginSection)
        {
            p_stSection = _p_stContext->p_stSectionDes;
            if(!strcmpi(p_stSection->stBuffers.p_szBufferCompleteName, _p_szSectionName))
                return;
			else if( _p_stContext->p_stOpenFile->stFile.bBinaryMode ) /* MP: BINARY */
			{
				long l=fn_l_Bin_ToEndSection( _p_stContext );
				_p_stContext->stPosition.lAfterSeekInFile+=l;
				_p_stContext->p_stOpenFile->stFile.lToEndSection=0;
			}
        }
    } while(iRead != (char) EOF);
    
    /*
     *  We have reached the end of file : Unknown section.
     */
    SCR_M_Err_UpdateSyntaxError();
    sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Unknown section is \"%s\".", _p_szSectionName);
    SCR_M_Err_RaiseError(SCR_EI_Err_UnknownSection);
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  Place the current context to the end of the current section.
 *  _p_stContext    :   Current context.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_ContextToEndSection(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    unsigned int    uiFirstLevel;
    int             iRead;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	if(_p_stContext->cForSection==2) /*MP: BINARY */
		return;
 
 
	if(_p_stContext->cForSection==3) /*MP: BINARY */
	{
		long l=fn_l_Bin_ToEndSection( _p_stContext );
		_p_stContext->stPosition.lAfterSeekInFile+=l;
		
		/*fn_i_Anl_LineToContext(_p_stContext);*/
		
		/*return;*/
	}
 
    /*
     *  No section description, it's a file, we zap to the end (we parse).
     */
    if(_p_stContext->p_stSectionDes == NULL)
    {
		do
		{
			iRead = fn_i_Anl_LineToContext(_p_stContext);
		} while(iRead != EOF);
        return;
    }
 
    /*
     *  The end of section seek has not been parsed : We must parse to it.
     *  We go to the last parsing position and we parse.
     */
    if((_p_stContext->p_stSectionDes->stEndPosition.uiLineInFile == 0)||
		( _p_stContext->p_stOpenFile->stFile.bBinaryMode )) /*MP: BINARY*/
    {
        uiFirstLevel = _p_stContext->stPosition.uiLevel;
        
		if( !_p_stContext->p_stOpenFile->stFile.bBinaryMode ) /*MP: BINARY*/
			SCR_M_Anl_CxtFileToPos
			(
				_p_stContext, 
				_p_stContext->p_stOpenFile->stParsingInfos.stPosition
			);
        do
        {
            /* Get one line of file */
            iRead = fn_i_Anl_LineToContext(_p_stContext);
 
			/* MP: BINARY */
			if(_p_stContext->eParseType == SCR_EPT_Cxt_BeginSection)
			{
				if( _p_stContext->p_stOpenFile->stFile.bBinaryMode )
				{
					long l=fn_l_Bin_ToEndSection( _p_stContext );
					_p_stContext->stPosition.lAfterSeekInFile+=l;
					_p_stContext->p_stOpenFile->stFile.lToEndSection=0;
				}
			}
 
            /* Until endsection */
            if
            (
                (_p_stContext->eParseType == SCR_EPT_Cxt_EndSection)
            &&  (_p_stContext->stPosition.uiLevel == uiFirstLevel - 1)
            )
            {
                return;
            }
        } while(iRead != EOF);
 
        SCR_M_Err_UpdateSyntaxError();
        SCR_M_Err_RaiseError(SCR_EI_Err_MissingEndSection);
    }
 
    /*
     *  Else we go to the end of section.
     */
    else
    {
        SCR_M_Anl_CxtFileToPos
        (
            _p_stContext, 
            _p_stContext->p_stSectionDes->stEndPosition
        );
        _p_stContext->stPosition.uiLevel--;
    }
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To init the parser for a file.
 *  p_stOpenFile must be correct in current context.
 *  _p_stContext    :   Current context
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_ContextToFile(SCR_tdst_Cxt_Description *_p_stContext)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Cxt_Position   stPosition;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_Cxt_Description, _p_stContext);
    SCR_M_Dbg_AssertStruct_P(SCR_tdst_File_Open, _p_stContext->p_stOpenFile);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Initialize position to 0.
     */
    memset(&stPosition, 0, sizeof(SCR_tdst_Cxt_Position));
 
	/* MP: BINARY */
	if( _p_stContext->p_stOpenFile->stFile.bBinaryMode )
		stPosition.lAfterSeekInFile=SCR_M_ftell(&_p_stContext->p_stOpenFile->stFile);
	/*
	 *  Position the file to its beginning.
	 */
	/* End BINARY */
 
    /*
     *  a_szBufferCompleteName, a_szBufferName and a_szBufferNameExt are name of file 
     *  (with path).
     *  No format and no parameters.
     *  Parse type is a file begin (that will be replace by a section begin later).
     *  No section description.
     */
    strcpy
    (
        _p_stContext->stBuffers.a_szBufferCompleteName,
        _p_stContext->p_stOpenFile->stFile.a_szFileName
    );
    strcpy
    (
        _p_stContext->stBuffers.a_szBufferName,
        _p_stContext->p_stOpenFile->stFile.a_szFileName
    );
    strcpy
    (
        _p_stContext->stBuffers.a_szBufferNameExt,
        _p_stContext->p_stOpenFile->stFile.a_szFileName
    );
    *_p_stContext->stBuffers.a_szBufferFormat = '\0';
    *_p_stContext->stBuffers.a_szBufferParams = '\0';
    _p_stContext->cForSection = 0;
	/* MP: BINARY */
	if( _p_stContext->p_stOpenFile->stFile.bBinaryMode )
		    _p_stContext->cForSection = 2;
    _p_stContext->eParseType = SCR_EPT_Cxt_BeginSection;
    _p_stContext->p_stSectionDes = NULL;
 
    /*
     *  Position the file to its beginning.
     */
    SCR_M_Anl_CxtFileToPos
    (
        _p_stContext, 
        stPosition
    );
}
 
/*===============================================================================================*/
 
/*
 *-------------------------------------------------------------------------------------------------
 *  A call to a callback.
 *  _p_stP                  :   Parser values.
 *  _eAction                :   Action for callback.
 *  _p_iExitBeforeLevel     :   To treat call-back return values.
 *  Returns return value of callback.
 *-------------------------------------------------------------------------------------------------
 */
char fn_c_Anl_CallToCallback
(
    SCR_tdst_Anl_ParserValues   *_p_stP,
    SCR_tde_Anl_Action          _eAction,
    int                         *_p_iExitBeforeLevel
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    char                        cReturn;
    char                        *ap_szParameters[SCR_CV_ui_Cfg_MaxNumPars];
    SCR_tdst_Cxt_Description    *p_stNextContext;
    SCR_tdst_Cxt_Buffers        *p_stBuffers;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_M_Dbg_Assert_P(_p_stP != NULL);
    SCR_M_Dbg_Assert_P(_p_iExitBeforeLevel != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	/*
	 *	Call the callback
	 *----------------------
	 */
	p_stNextContext = _p_stP->p_stContext;
    p_stBuffers = &_p_stP->p_stContext->stBuffers;
    ap_szParameters[0] = NULL;
 
    switch(_eAction)
    {
    /*
     *  A begin of section, a end of section or an entry.
     */
    case SCR_EA_Anl_BeginSection:
    case SCR_EA_Anl_EndSection:
    case SCR_EA_Anl_Entry:
    
        /* Convert parameters */
        fn_v_Pars_ConvertParameters
        (
            p_stBuffers->a_szBufferFormat, 
            p_stBuffers->a_szBufferParams, 
            ap_szParameters
        );
 
        /* Call the callback */
        SCR_M_Dbg_Assert_P(_p_stP->p_stCallback != NULL);
        SCR_M_Dbg_Assert_P(_p_stP->p_stCallback->pfn_eCallback != NULL);
        _p_stP->eReturnValue = _p_stP->p_stCallback->pfn_eCallback
        (
            &_p_stP->p_stContext->p_stOpenFile->stFile,
            p_stBuffers->a_szBufferNameExt,
            ap_szParameters,
            _eAction
        );
 
        /* Free parameters */
        SCR_M_Pars_FreeParameters(ap_szParameters);
        break;
 
    /* 
     *  A begin of a subsection.
     *  Current context contains in stBuffers all info about subsection.
     *  A end of a subsection.
     *  The next context contains infos (in stBuffersCopy) about subsection.
     *
     *  stBuffersCopy of current context contains infos about current section.
     */
    case SCR_EA_Anl_EndSubSection:
        p_stNextContext = fnp_st_Cxt_Compute(1);
        p_stBuffers = &p_stNextContext->stBuffersCopy;
        
    case SCR_EA_Anl_BeginSubSection:
 
        /* Prepare parameters with infos about subsection (the one in context) */
        ap_szParameters[0] = p_stBuffers->a_szBufferName;
        ap_szParameters[1] = p_stBuffers->a_szBufferNameExt;
        ap_szParameters[2] = p_stBuffers->a_szBufferCompleteName;
        ap_szParameters[3] = (char *) (&p_stNextContext->stSectionValues);
        ap_szParameters[4] = NULL;
 
        /* Call the callback */
        _p_stP->eReturnValue = _p_stP->p_stCallback->pfn_eCallback
        (
            &_p_stP->p_stContext->p_stOpenFile->stFile,
            _p_stP->p_stContext->stBuffersCopy.a_szBufferNameExt,
            ap_szParameters,
            _eAction
        );
 
 
        /* Erase array of parameters */
        ap_szParameters[0] = NULL;
        break;
 
    /* 
     *  Section already analysed.
     *  No parameters.
     */
    case SCR_EA_Anl_AlreadyAnalysed:
 
        ap_szParameters[0] = NULL;
        _p_stP->eReturnValue = _p_stP->p_stCallback->pfn_eCallback
        (
            &_p_stP->p_stContext->p_stOpenFile->stFile,
            p_stBuffers->a_szBufferNameExt,
            ap_szParameters,
            SCR_EA_Anl_AlreadyAnalysed
        );
        break;
    }
 
    /* 
     *
     *  Treat return value.
     *
     */
	cReturn = 0;
    switch(_p_stP->eReturnValue)
    {
    /* Normal return : Continue */
    case SCR_ERV_Anl_NormalReturn:
        cReturn = 0;
        break;
 
    /* End of current section */
    case SCR_ERV_Anl_TerminateCurrentSection:
        *_p_iExitBeforeLevel = _p_stP->p_stContext->stPosition.uiLevel;
        cReturn = 1;
        break;
 
    /* End of parent section */
    case SCR_ERV_Anl_TerminateParentSection:
        *_p_iExitBeforeLevel = _p_stP->p_stContext->stPosition.uiLevel - 1;
        cReturn = 1;
        break;
 
    /* End of main section */
    case SCR_ERV_Anl_TerminateMainSection:
        *_p_iExitBeforeLevel = 1;
        cReturn = 1;
        break;
 
    /* End of file */
    case SCR_ERV_Anl_TerminateFile:
        *_p_iExitBeforeLevel = 0;
        cReturn = 1;
        break;
 
    /* Default : Error */
    default:
        SCR_M_Dbg_Assert_P(0);
    }
 
    /* 
     *  Treat uiExitBeforeLevel.
     *  It is the level we want to pass below without parsing (and going to the end
     *  of sections while passing).
     */
    if(*_p_iExitBeforeLevel >= 0)
    {
        /* We have reached the level */
        if((int) (_p_stP->p_stContext->stPosition.uiLevel + 1) == *_p_iExitBeforeLevel)
        {
            *_p_iExitBeforeLevel = -1;
            cReturn = 0;
        }
 
        /* We are above the level : We zap the current section */
        else 
        {
            fn_v_Anl_ContextToEndSection(_p_stP->p_stContext);
            cReturn = 1;
        }
    }
    return cReturn;
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To parse the current section of file.
 *  Context must be placed at the beginning of the section (title has been parsed).
 *  _uwDynamicFlags :   Dynamic flags to modify parsing.
 *-------------------------------------------------------------------------------------------------
 */
 
 
void fn_v_Anl_ParseCurrentSection(unsigned short _uwDynamicFlags)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    SCR_tdst_Anl_ParserValues   stP;
    SCR_tdst_Cxt_Description    *p_stNewContext;
    SCR_tdx_Hash_Key            xHashKey;
    int                         iRead = 0;
    char                        cEndSection, cForceEnd, cFirst;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
    /*
     *  Update stBuffersCopy.
     *  It will always contain the first state of stBuffers structure (so the name
     *  of the section itself).
     */
    stP.p_stContext = fnp_st_Cxt_Compute(0);
    SCR_M_Cxt_CopyBuffers(&stP.p_stContext->stBuffersCopy, &stP.p_stContext->stBuffers);
    stP.p_stContext->uwDynamicFlags = _uwDynamicFlags;
 
    /* 
     *  Current user callback return value is normal.
     */
    stP.eReturnValue = SCR_ERV_Anl_NormalReturn;
 
	if( stP.p_stContext->p_stOpenFile->stFile.bBinaryMode ) /* MP: BINARY */
		stP.p_stContext->cForSection|=2;
 
 
    /* 
     *  Get callback.
     */
    stP.p_stCallback = fnp_st_Anl_SearchCallback
    (
        stP.p_stContext->stBuffers.a_szBufferName,
        stP.p_stContext->cForSection
    );
 
    /*
     *  If there's no section for that callback, we raise a warning except if we analyse
     *  a file.
     *  We exit for a real section (we never analyse subsections if a section has no
     *  callback).
     */
    if((stP.p_stCallback == NULL) && (stP.p_stContext->cForSection&~2))
    {
        *g_st_Err_GlobalError.a_szBufferTmp1 = '\0';
        sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Section is \"%s\".", stP.p_stContext->stBuffers.a_szBufferName);
        SCR_M_Err_RaiseWarning(SCR_EI_Err_SectionWithoutCallback);
        fn_v_Anl_ContextToEndSection(stP.p_stContext);
		return;
    }
 
    /*
     *  Compute hash key code of this section.
     *  Is section has already been parsed ?
     *  If it's the case (and if there's a callback), we initialize static results
     */
    SCR_M_Sect_ComputeHashKey
    (
        xHashKey,
        stP.p_stContext->stBuffers.a_szBufferCompleteName
    );
	if(stP.p_stContext->p_stSectionDes)
		stP.p_stContext->p_stOpenSection = stP.p_stContext->p_stSectionDes->p_stOpenSection;
	else
	{
		stP.p_stContext->p_stOpenSection = fnp_st_Sect_SearchOpen
		(
			stP.p_stContext->stBuffers.a_szBufferCompleteName,
			stP.p_stContext->stPosition.uiLineInFile,
			xHashKey
		);
	}
    
    /*
     *  Here, we are sure that we want to analyse the section.
     *  If section has not already been analysed once (p_stOpenSection not NULL), we add
     *  it to the array of open sections if we can (_uwDynamicFlags &= SCR_CDF_uw_Anl_NotSave false
     *  and section flag false too).
     */
    cFirst = 0;
    if
    (
        (stP.p_stContext->p_stOpenSection == NULL)
    &&  
        (
            (stP.p_stContext->p_stSectionDes == NULL)
        ||  ((stP.p_stContext->p_stSectionDes->uwDynamicFlags & SCR_CDF_uw_Anl_NotSaveSection) == 0)
        )
    )
    {
        stP.p_stContext->p_stOpenSection = fnp_st_Sect_AddOpen(stP.p_stContext, xHashKey);
		if(stP.p_stContext->p_stSectionDes)
			stP.p_stContext->p_stSectionDes->p_stOpenSection = stP.p_stContext->p_stOpenSection;
        cFirst = 1;
    }
 
    /*
     *  Update values.
     */
    if(stP.p_stContext->cSectionValuesValid)
    {
        memcpy
        (
            &stP.p_stContext->p_stOpenSection->stSectionValues,
            &stP.p_stContext->stSectionValues,
            sizeof(SCR_tdst_Cxt_Values)
        );
        stP.p_stContext->cSectionValuesValid = 0;
    }
    else
    {
        memcpy
        (
            &stP.p_stContext->stSectionValues,
            &stP.p_stContext->p_stOpenSection->stSectionValues,
            sizeof(SCR_tdst_Cxt_Values)
        );
    }
 
    /*
     *  Test open section.
     *  If section is not forced to be analyse (_uwDynamicFlags &= SCR_CDF_uw_Anl_ForceAnalyse or
     *  flag set by a directive), and if section has already been analysed (p_stOpenSection not NULL), 
     *  we call the callback (if one) with SCR_EA_Anl_AlreadyAnalysed, and we exit after being to the 
     *  end of section.
     */
    if
    (
        (!cFirst)
    &&  (stP.p_stContext->p_stOpenSection)
    &&  ((_uwDynamicFlags & SCR_CDF_uw_Anl_ForceAnalyse) == 0)
    &&  
        (
            (stP.p_stContext->p_stSectionDes == NULL)
        ||  ((stP.p_stContext->p_stSectionDes->uwDynamicFlags & SCR_CDF_uw_Anl_ForceAnalyse) == 0)
        )
    )
    {
        if(stP.p_stCallback)
            fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_AlreadyAnalysed, &g_iExitBeforeLevel);
        fn_v_Anl_ContextToEndSection(stP.p_stContext);
		/*
		 *  Force end of special return if we are at level 0.
		 */
		if(stP.p_stContext->stPosition.uiLevel == 0)
			g_iExitBeforeLevel = -1;
        return;
    }
 
    /*
     *  We call the callback with SCR_EA_Anl_BeginSection.
     *  cForceEnd can be set to 1 to force the end of parsing for that section (cause of
     *  a callback return value).
     *  cEndSection is set to 1 if a endsection has been parsed. We must end parser too.
     */
    cForceEnd = 0;
    cEndSection = 0;
    if(stP.p_stCallback)
        cForceEnd = fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_BeginSection, &g_iExitBeforeLevel);
 
    /*
     *  Parsing.
     */
    while((!cEndSection) && (!cForceEnd))
    {
        /* 
         *  Get one line of text.
         *  If last character read is EOF, we raise a warning for a real section (cause we
         *  have not found the endsection).
         *  We exit the parser (cause it's like a end section).
         */
        iRead = fn_i_Anl_LineToContext(stP.p_stContext);
        if(iRead == EOF)
        {
            cEndSection = 1;
            if((stP.p_stContext->p_stSectionDes) && (stP.p_stContext->eParseType != SCR_EPT_Cxt_EndSection))
            {
                *g_st_Err_GlobalError.a_szBufferTmp1 = '\0';
                sprintf(g_st_Err_GlobalError.a_szBufferTmp2, "Section is \"%s\".", stP.p_stContext->stBuffersCopy.a_szBufferCompleteName);
                SCR_M_Err_RaiseWarning(SCR_EI_Err_MissingEndSection);
            }
            break;
        }
 
        switch(stP.p_stContext->eParseType)
        {
        /* 
         *  Dummy values.
         *  We don't care about directives that has already been treat when reading the line.
         */
        case SCR_EPT_Cxt_None:
			break;
 
        case SCR_EPT_Cxt_Directive:
            fn_v_Anl_AnalyseDynamicDirective(stP.p_stContext);
            break;
 
        /* 
         *  An entry.
         *  We call the callback (if one).
         */
        case SCR_EPT_Cxt_Entry:
 
            if(stP.p_stCallback)
                cForceEnd = fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_Entry, &g_iExitBeforeLevel);
            break;
 
        /* 
         *  A Sub Section.
         */
        case SCR_EPT_Cxt_BeginSection:
 
            /* Callback SCR_EA_Anl_BeginSubSection */
            if(stP.p_stCallback)
            {
                cForceEnd = fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_BeginSubSection, &g_iExitBeforeLevel);
                if(cForceEnd) 
                    break;
            }
 
            /* Add one context */
            p_stNewContext = fnp_st_Cxt_Add();
 
            /* Copy old context to new one */
            SCR_M_Cxt_CopyBuffers(&p_stNewContext->stBuffers, &stP.p_stContext->stBuffers);
            memcpy(&p_stNewContext->stPosition, &stP.p_stContext->stPosition, sizeof(SCR_tdst_Cxt_Position));
            p_stNewContext->p_stOpenFile = stP.p_stContext->p_stOpenFile;
            p_stNewContext->p_stSectionDes = stP.p_stContext->p_stSectionDes;
            p_stNewContext->cForSection = 1;
			if( p_stNewContext->p_stOpenFile->stFile.bBinaryMode ) /* MP: BINARY */
				p_stNewContext->cForSection=3;
            /* Parse section */
            fn_v_Anl_ParseCurrentSection(_uwDynamicFlags);
 
            /* Copy new position to current context */
            memcpy(&stP.p_stContext->stPosition, &p_stNewContext->stPosition, sizeof(SCR_tdst_Cxt_Position));
            stP.p_stContext->p_stSectionDes = stP.p_stContext->p_stSectionDes->p_stParentSection;
 
            /* Delete last context */
            fn_v_Cxt_DeleteLast();
 
            /* To treat eventual return of section analyse */
            stP.eReturnValue = SCR_ERV_Anl_NormalReturn;
            cForceEnd = fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_Invalid, &g_iExitBeforeLevel);
 
            /* Callback SCR_EA_Anl_EndSubSection */
            if((stP.p_stCallback) && (cForceEnd == 0))
                cForceEnd = fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_EndSubSection, &g_iExitBeforeLevel);
            break;
 
        /* 
         *  End of section or file.
         */
        case SCR_EPT_Cxt_EndSection:
            cEndSection = 1;
            break;
        }
    }
 
    /*
     *  Test if an end section is missing.
     *  We raise an error in that case.
     */
    if((cEndSection == 0) && (iRead == EOF) && (stP.p_stContext->p_stSectionDes))
    {
        SCR_M_Err_UpdateSyntaxError();
        SCR_M_Err_RaiseError(SCR_EI_Err_MissingEndSection);
    }
 
    /*
     *  Call the callback with SCR_EA_Anl_EndSection only if the end of this section has not 
     *  been forced.
     */
    if((cEndSection) && (stP.p_stCallback))
    {
        /* To have the really good name of section (id part passed to the callback) */
        strcpy(stP.p_stContext->stBuffers.a_szBufferNameExt, stP.p_stContext->stBuffersCopy.a_szBufferNameExt);
        /* Call the callback */
        fn_c_Anl_CallToCallback(&stP, SCR_EA_Anl_EndSection, &g_iExitBeforeLevel);
    }
 
    /*
     *  Force end of special return if we are at level 0.
     */
    if(stP.p_stContext->stPosition.uiLevel == 0)
        g_iExitBeforeLevel = -1;
}
 
/*
 **************************************************************************************************
 **************************************************************************************************
 **************************************************************************************************
 **************************************************************************************************
 */
 
/*
 *-------------------------------------------------------------------------------------------------
 *  To reduce memory size.
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_ReduceMemory(void)
{
	/* Pack array of callbacks */
	SCR_M_DyAr_PackArray(SCR_tdst_Anl_Callback, SCR_g_st_Anl_ArrayCallbacks, ;);
}
 
/*
 *-------------------------------------------------------------------------------------------------
 *-------------------------------------------------------------------------------------------------
 */
void fn_v_Anl_DeleteWithMemLevel(unsigned char _ucMin, unsigned char _ucMax)
{
	SCR_M_DyAr_DeleteElementWithMemLevel
	(
		SCR_tdst_Anl_Callback, 
		SCR_g_st_Anl_ArrayCallbacks,
		;,
		_ucMin,
		_ucMax
	);
}
