/*------------------------------------------------------------------------------ FILE : Parser.c CREATED : 98/05/17 AUTHOR : Mircea Petrescu CONTENTS: parsing structures, variables & functions ------------------------------------------------------------------------------*/ #include #include "StdInc.h" #include "File.h" #include "DynArray.h" #include "Parser.h" #include "Register.h" #include "Link.h" #ifdef LDT_MULTITHREADED CRITICAL_SECTION GReadExclusion; #endif #define FALSE 0 #define TRUE 1 /* Valid characters in a word */ char tbl[256]; /* variables used for in place break into words */ char g_lastChar=0; int g_lastIndex=-1; int parseLen[256], parseCount; unsigned char* parsePos[256]; /* for in-place word break */ unsigned char* g_ulPos=0; unsigned long g_ulBeginLineMark; /* last begin of line found */ /* variables for building a complete section name (in case of subsections) */ char g_szType[512]=""; char g_szName[512]=""; char g_szParent[512]=""; char g_szId[512]=""; LDT_tdst_FileDesc TheFileDesc, *g_FileDesc=NULL; LDT_tdst_Link *g_CrtSection=NULL; /*------------------------------------------------------------------------------ DESC. : initializes character classes for parsing CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void InitParser( void ) { char sztmp[]=":^!%&*+-<=>?_|~\\QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890"; int i; for( i=0; i<128; i++ ) tbl[i]= (char)(( strchr( sztmp, (char)i )!=NULL )?1:0 ); for( i=128; i<255; i++ ) tbl[i]= 1; tbl[255]=0; tbl[(unsigned char )'\"']=2; tbl[(unsigned char )'[']=3; tbl[(unsigned char )']']=4; tbl[(unsigned char )'$']=5; tbl[(unsigned char )'{']=6; tbl[(unsigned char )'}']=7; tbl[(unsigned char )';']=8; tbl[(unsigned char )'\n']=9; } /*------------------------------------------------------------------------------ DESC. : access function for word #i in current line CREATED : 98/05/17 AUTHOR : Mircea Petrescu MODIFIED: Catalin Cocos ------------------------------------------------------------------------------*/ char *LDT_szGetParam( int i ) { if( (i<0) || (i>parseCount) ) return NULL; if( g_FileDesc->iLastIndex!=-1 ) *g_ulPos=g_FileDesc->chLastChar; g_ulPos = parsePos[i]+parseLen[i]; g_FileDesc->chLastChar = *g_ulPos; *g_ulPos = 0; g_FileDesc->iLastIndex = i; return (char *) parsePos[i]; } /*------------------------------------------------------------------------------ DESC. : actualize section name and level in file @ begin section CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void BeginSection( void ) { char *szName=LDT_szGetParam( 0 ); char *szId; if( g_szParent[0]!=0 ) strcat( g_szParent, "^" ); strcat( g_szParent, g_szName ); strcpy( g_szName, szName ); szId=strchr( g_szName, ':' ); if( szId ) { strcpy( g_szId, szId+1 ); *szId=0; strcpy( g_szType, g_szName ); *szId=':'; } else { g_szId[0]=0; strcpy( g_szType, szName ); } if( !(g_FileDesc->uwLoadType) ) /* construct file contents in case not loading all file */ { DSAr_Add( &g_FileDesc->arContents, (void *) LDT_Create_Position( g_szId, g_szParent, GetType( g_szType, LDT_REG_SECTION ), g_FileDesc->uwFlags, g_ulBeginLineMark, g_FileDesc->iLineNumber, g_FileDesc->iLevel ) ); } g_FileDesc->iLevel++; } /*------------------------------------------------------------------------------ DESC. : actualize section name and level in file @ end section CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void EndSection( void ) { char *szTmp, *szTmp1; int erase=0; g_FileDesc->iLevel--; szTmp=strrchr( g_szParent, '^' ); /* get last child in parent xxx:xx^xxx:xx^XXX:XX */ if( szTmp ) /* if we have a child ( parent is not xxx:xx )*/ { *szTmp=0; /* cut it from parent */ szTmp++; } else { szTmp=g_szParent; /* only one section name */ erase=1; /* so erase it after we extract child */ } strcpy( g_szName, szTmp ); /* CC - moved this line here !!! the copy is always needed /// paste it to current section name */ szTmp1=strchr( szTmp, ':' ); /* current name in szTmp */ if( szTmp1 ) { strcpy( g_szId, szTmp1+1 ); /* split it in Type:Id */ *szTmp1=0; } else g_szId[0]=0; strcpy( g_szType, szTmp ); if( erase ) g_szParent[0]=0; if( g_FileDesc->iLevel==0 ) /* adjust for file level */ { g_szName[0]=0; g_szParent[0]=0; g_CrtSection=NULL; } } /*------------------------------------------------------------------------------ DESC. : split a line in the component words CREATED : 98/06/29 AUTHOR : Catalin Cocos ------------------------------------------------------------------------------*/ int bConvertToLowerCase=0; void GetWords( LDT_tdst_MemFile* pMemFile, unsigned char* buffer, int bSeek ) { int i = 0; if( bSeek ) { while( buffer[i] != '\n' ) i++; pMemFile->Pos = buffer +i +1 - (unsigned char *)pMemFile->pBuffer; return; } for(;;) { while( tbl[buffer[i]] == 0 ) i++; switch( tbl[buffer[i]] ) { case 2: /* a string */ i++; parsePos[parseCount]= buffer + i; while( buffer[i] != '\"') i++; parseLen[parseCount] = buffer +i -parsePos[parseCount]; parseCount++; i++; break; case 3: /* a format specifier -- ignore */ while( buffer[i] != ']' && buffer[i] != '\n' ) i++; if(buffer[i] == ']') i++; break; case 8: /* comment - skip the rest of the line */ while( buffer[i] != '\n') i++; case 9: /* end of line */ pMemFile->Pos = buffer +i +1 - (unsigned char *)pMemFile->pBuffer; return; default: /* an usual word */ parsePos[parseCount]= buffer + i; if( bConvertToLowerCase ) while( tbl[buffer[i]] == 1 ) { if( buffer[i]>='A' && buffer[i]<='Z' ) buffer[i] += 'a'-'A'; i++; } else while( tbl[buffer[i]] == 1 ) i++; parseLen[parseCount] = buffer +i -parsePos[parseCount]; parseCount++; break; } } } LDT_tdeParseResult fn_e_ParseLine( int bSeek ) { LDT_tdst_MemFile* pMemFile = g_FileDesc->_pInfoMemFile; unsigned char *buffer; parseCount=0; /* no words */ bConvertToLowerCase = 0; /* no lowercase conversion*/ if( g_FileDesc->iLastIndex!=-1 ) { /* sentinel - restores the previously requested word */ *g_ulPos = g_FileDesc->chLastChar; g_FileDesc->iLastIndex=-1; } for( ;; ) { int i = 0; if(pMemFile->Pos >= pMemFile->Size) /* the end of file was reached*/ return (g_FileDesc->iLevel? ParseResult_EOF: ParseResult_EndSection); buffer=(unsigned char *)pMemFile->pBuffer+pMemFile->Pos; /* the line buffer */ g_FileDesc->iLineNumber++; /* incrementing the line number */ while( tbl[buffer[i]] == 0 ) i++; /* skipping the blank spaces */ g_ulBeginLineMark=pMemFile->Pos + i; /* the beginning of the line */ switch( tbl[buffer[i]] ) { case 1: /* an entry */ GetWords(pMemFile, buffer +i, bSeek); return ParseResult_Entry; case 5: /* directive */ bConvertToLowerCase = 1; /* to lowercase */ GetWords(pMemFile, buffer +i +1, bSeek); bConvertToLowerCase = 0; if(!parseCount) break; switch(*((long*)LDT_szGetParam( 0 ))) { case 'crof': g_FileDesc->uwFlags|=LDT_uw_Anl_ForceAnalyse; break; /* "ForceAnalyse" */ case 'fdne': g_FileDesc->uwFlags&=~LDT_uw_Anl_ForceAnalyse; break; /* "EndForceAnalyse" */ case 'ston': g_FileDesc->uwFlags|=LDT_uw_Anl_NotSaveSection; break; /* "NotSaveSection" */ case 'ndne': g_FileDesc->uwFlags&=~LDT_uw_Anl_NotSaveSection; break;/* "EndNotSaveSection"*/ case 'ctes': /* "SetCurrentFileLong" || "SetCurrentFileDouble" */ if( parseCount != 3 ) break; // TODO : Signal ERROR i = atoi( LDT_szGetParam( 1 ) ); if( i<0 || i>7 ) break; if( strcmp( LDT_szGetParam( 0 ), "setcurrentfiledouble" ) ) g_FileDesc->ulValues[i]=(unsigned long)atol( LDT_szGetParam( 2 ) ); else g_FileDesc->dValues[i]=(double)atof( LDT_szGetParam( 2 ) ); break; case 'mmoc': /* "Comments" */ for(g_FileDesc->uwFlags|=LDT_uw_Anl_Comments;;) /* parse the file until the "EndComments" directive is found or EOF is reached */ { i = 0; if(pMemFile->Pos >= pMemFile->Size) /* the end of file was reached*/ return (g_FileDesc->iLevel? ParseResult_EOF: ParseResult_EndSection); buffer=(unsigned char *)pMemFile->pBuffer+pMemFile->Pos; /* the line buffer */ g_FileDesc->iLineNumber++; /* incrementing the line number */ while( tbl[buffer[i]] == 0 ) i++; /* skipping the blank spaces */ g_ulBeginLineMark=pMemFile->Pos + i; /* the beginning of the line */ if(tbl[buffer[i]] == 5) { bConvertToLowerCase = 1; GetWords(pMemFile, buffer +i +1, bSeek); bConvertToLowerCase = 0; if(parseCount && (!strcmp( LDT_szGetParam( 0 ), "endcomments" ))) g_FileDesc->uwFlags&=~LDT_uw_Anl_Comments; break; } else { while( tbl[buffer[i]] != 9 ) i++; /* skip the line */ pMemFile->Pos = buffer +i +1 - (unsigned char*)pMemFile->pBuffer; } } } break; case 6: /* begin of section */ bConvertToLowerCase = 1; /* to lowercase */ GetWords(pMemFile, buffer +i +1, 0); BeginSection(); return ParseResult_BeginSection; case 7: /* end of section */ GetWords( pMemFile, buffer +i +1, bSeek); EndSection(); return ParseResult_EndSection; case 8: /* a comment */ while( tbl[buffer[i]] != 9 ) i++; /* skip the line */ case 9: /* an empty line */ pMemFile->Pos = buffer +i +1 - (unsigned char*)pMemFile->pBuffer; break; } } } /*------------------------------------------------------------------------------ DESC. : get next entry in section ( or begin/end section ) CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ LDT_tdeParseResult LDT_GetNextEntry( void ) { return fn_e_ParseLine(0); } /*------------------------------------------------------------------------------ DESC. : various access functions for callbacks CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ char *LDT_szGetSectionName() { return g_szId; } char *LDT_szGetSectionType() { return g_szType; } char *LDT_szGetEntryName() { return LDT_szGetParam(0); } int LDT_iGetNbParams() { return parseCount; } /*------------------------------------------------------------------------------ DESC. : various access functions for file values CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ unsigned long LDT_GetFileLong( int i ) { if( !g_FileDesc ) return 0; return g_FileDesc->ulValues[i]; } double LDT_GetFileDouble( int i ) { if( !g_FileDesc ) return (double)0.0; return g_FileDesc->dValues[i]; } void LDT_SetFileLong( int i, unsigned long ul ) { if( !g_FileDesc ) return; g_FileDesc->ulValues[i]=ul; } void LDT_SetFileDouble( int i, double d ) { if( !g_FileDesc ) return; g_FileDesc->dValues[i]=d; } /*------------------------------------------------------------------------------ DESC. : opens a file and fills in the FileDesc CREATED : 98/05/17 AUTHOR : Mircea Petrescu MODIFIED: Catalin Cocos ------------------------------------------------------------------------------*/ int OpenFileDesc( char* szFile, LDT_tdst_MemFile* pFile ) { int i; if( !pFile ) return -1; TheFileDesc.szFile=szFile; TheFileDesc._pInfoMemFile = pFile; /* CC : contents initialization -> start */ DSAr_Init( &TheFileDesc.arContents ); DSAr_SetSortMethod( &TheFileDesc.arContents, LDT_Compare_Positions ); DSAr_SetGranularity( &TheFileDesc.arContents, 50 ); /* CC : contents initialization -> end */ TheFileDesc.iLevel=0; TheFileDesc.iLineNumber=0; TheFileDesc.iLastIndex=-1; TheFileDesc.chLastChar=0; TheFileDesc.uwFlags=0; TheFileDesc.uwLoadType=0; /* CC : Loading Type */ for( i=0; i<256; i++ ) TheFileDesc.ulValues[i]=0; for( i=0; i<8; i++ ) TheFileDesc.dValues[i]=0.0; g_FileDesc=&TheFileDesc; g_szName[0]=0; g_szParent[0]=0; return 0; } /*------------------------------------------------------------------------------ DESC. : closes a file and fills in the FileDesc CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void CloseFileDesc( void ) { int idx; LDT_M_File_Close( TheFileDesc._pInfoMemFile ); #ifdef LDT_MULTITHREADED ReleaseSemaphore( GReadLimit, 1, NULL); /* signal that the file was closed */ #endif /* CC : contents clean-up -> start */ for(idx = DSAr_GetUpperBound( &TheFileDesc.arContents); idx>=0; idx--) free( TheFileDesc.arContents.pData[idx] ); DSAr_RemoveAll( &TheFileDesc.arContents ); /* CC : contents clean-up -> end */ g_FileDesc=NULL; } /*------------------------------------------------------------------------------ DESC. : positions a file and fills in the FileDesc CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void PositionFile( LDT_tdst_Position *pos ) { LDT_M_File_Seek( TheFileDesc._pInfoMemFile, pos->dwPos, SEEK_SET ); g_ulBeginLineMark=pos->dwPos; TheFileDesc.iLineNumber=pos->nLine; TheFileDesc.iLevel=pos->iLevel; TheFileDesc.uwFlags=pos->uwFlags; TheFileDesc.iLastIndex=-1; TheFileDesc.chLastChar=0; fn_e_ParseLine( 0 ); /* read the begin section line */ } LDT_tdst_Link *pParent[100]; /*------------------------------------------------------------------------------ DESC. : default create - does nothing CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ int LDT_Default_NULL_Create(LDT_tdst_Link *link) { link->pObject = NULL; return 0; } /*------------------------------------------------------------------------------ DESC. : skipping a section CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void SkipSection( ) { LDT_tdeParseResult result; int iLevel=g_FileDesc->iLevel; do{ result=fn_e_ParseLine( 0 ); }while ((g_FileDesc->iLevel>=iLevel)&&(result !=ParseResult_EOF) ); } /*------------------------------------------------------------------------------ DESC. : default loading CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ int LDT_Default_Load( LDT_tdst_Link *_Link ) { LDT_tdeParseResult result; _Link=_Link; do{ result=LDT_GetNextEntry(); if( result== ParseResult_BeginSection ) LDT_LoadSection( NULL ); }while ( result!=ParseResult_EndSection ); return 0; } /*------------------------------------------------------------------------------ DESC. : load the whole file CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ int LoadAllFile( LDT_tdst_Link *link ) { int ERRoR = 0; TheFileDesc.uwLoadType=1; /* CC : load-all-file flag */ g_CrtSection=pParent[0]= link; if(( link->dwFlags&LDT_LF_LOADED ) == 0) { /* CC ...allowing file closure ->start*/ if(( link->dwFlags&LDT_LF_ALLOCATED ) == 0) { ERRoR=link->Type->Create( link ); /* the Type is always !NULL */ link->dwFlags |= LDT_LF_ALLOCATED; /* the link was allocated */ } if(!ERRoR) { ERRoR = link->Type->Load( link ); link->dwFlags |= LDT_LF_LOADED; /* the link was loaded */ } /* CC ...allowing file closure ->end*/ } return ERRoR; } /*------------------------------------------------------------------------------ DESC. : loads a list of delayed references ( corresponding to a file ) CREATED : 98/05/17 AUTHOR : Mircea Petrescu MODIFIED: Catalin Cocos ------------------------------------------------------------------------------*/ int Solve( LDT_tdst_Refs *refs ) { LDT_tdst_MemFile* pFile; char bAllFile=0; LDT_tdst_Link *link = NULL, *link1, TmpLink; LDT_tdeParseResult result; LDT_tdst_CallbackEntry *Type; int ERRoR = 0; if( DSAr_GetSize( &refs->Links )==1 ) { link=(LDT_tdst_Link*)DSAr_GetAt( &refs->Links, 0 ); if( link->dwFlags& LDT_LF_FILE ) bAllFile=1; } pParent[0]=NULL; #ifdef LDT_MULTITHREADED pFile = refs->pFile; #else LDT_M_File_OpenRead(pFile, refs->szFile); #endif if( OpenFileDesc( refs->szFile, pFile )) /* open the file */ return -1; if( bAllFile ) ERRoR = LoadAllFile( link ); /* load all file */ else /* load a list of sections */ { do{ result=fn_e_ParseLine( 1 ); switch( result ) { case ParseResult_BeginSection: { int index; Type = GetType( g_szType, LDT_REG_SECTION ); TmpLink.szFile = refs->szFile; TmpLink.szParent = g_szParent; TmpLink.szName = g_szId; TmpLink.Type = Type; index=DSAr_Index( &refs->Links, &TmpLink, NULL ); if( index!=-1 ) { link1=(LDT_tdst_Link *)DSAr_GetAt( &refs->Links, index ); DSAr_RemoveAt( &refs->Links, index ); pParent[ g_FileDesc->iLevel ]=link1; g_CrtSection=link1; ERRoR=Type->Load( link1 ); if(!ERRoR) link1->dwFlags |= LDT_LF_LOADED; /* the link was loaded */ else return -1; } } default: break; } }while ( (result !=ParseResult_EOF)&&(DSAr_GetSize(&refs->Links)>0) ); if(DSAr_GetSize(&refs->Links)>0) DSAr_QSort( &g_FileDesc->arContents ); while( DSAr_GetSize(&refs->Links)>0 ) { LDT_tdst_Position pos, *p; int index=DSAr_GetUpperBound( &refs->Links ); link1=(LDT_tdst_Link *)DSAr_GetAt( &refs->Links, index ); if( link1->dwFlags&LDT_LF_FILE ) /* all file requested */ { int i; /* reset the file */ if( g_FileDesc->iLastIndex!=-1 ) { /* sentinel - restores the previously requested word */ *g_ulPos = g_FileDesc->chLastChar; g_FileDesc->iLastIndex=-1; } LDT_M_File_Seek( TheFileDesc._pInfoMemFile, 0, SEEK_SET ); TheFileDesc.iLevel=0; TheFileDesc.iLineNumber=0; TheFileDesc.iLastIndex=-1; TheFileDesc.chLastChar=0; TheFileDesc.uwFlags=0; for( i=0; i<8; i++ ) { TheFileDesc.ulValues[i]=0; TheFileDesc.dValues[i]=0.0; } ERRoR = LoadAllFile( link1 ); /* load all file */ CloseFileDesc(); /* close the file */ return ERRoR; } DSAr_RemoveAt( &refs->Links, index ); pos.szName=link1->szName; pos.szParent=link1->szParent; pos.Type=link1->Type; index=DSAr_Index( &g_FileDesc->arContents, (void *)&pos, NULL ); if( index<0 ) { ERRoR = -1; break; } p=(LDT_tdst_Position *)DSAr_GetAt( &g_FileDesc->arContents, index ); PositionFile( p ); g_CrtSection=link1; pParent[g_FileDesc->iLevel]=link1; if( (index=link1->Type->Load( link1 )) <0 ) return index; } } CloseFileDesc(); /* close the file */ return ERRoR; } /*------------------------------------------------------------------------------ DESC. : loads a subsection CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ int GetSubSection( LDT_tdst_Link *link ) { g_CrtSection=link; pParent[g_FileDesc->iLevel]=link; return link->Type->Load( link ); } /*------------------------------------------------------------------------------ DESC. : breaks a reference name in file, parent, type, id CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ void LDT_SplitSectionName( char *szSection, char *szFile, char *szParent, char *szType, char *szId ) { char *szP, *szI, *szT; strcpy( szFile, szSection ); szT=strrchr( szFile, '^' ); *szT=0; szT++; szI=strrchr( szT, ':' ); if( szI ) { *szI=0; szI++; strcpy( szId, szI ); } else szId[0]=0; strcpy( szType, szT ); szP=strchr( szFile, '^' ); if( szP ) { *szP=0; szP++; strcpy( szParent, szP ); } else szParent[0]=0; } /*------------------------------------------------------------------------------ DESC. : computes name of current section and returns length of file name CREATED : 98/05/17 AUTHOR : Mircea Petrescu ------------------------------------------------------------------------------*/ int LDT_ComputeSectionName( char *buffer ) { LDT_tdst_Link* link=g_CrtSection; int i=strlen( link->szFile ); strcpy( buffer, link->szFile); if( link->szParent[0] ) { strcat( buffer, "^" ); strcat( buffer, link->szParent ); } strcat( buffer, "^" ); strcat( buffer, link->Type->szType ); if( link->szName[0] ) { strcat( buffer, ":" ); strcat( buffer, link->szName ); } return i; }