Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2527 lines
74 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
tpdiff.c
Abstract:
This is the main component of the NDIS 3.0 MAC Tester log file program.
Author:
Sanjeev Katariya (sanjeevk) 3-May-1993
Revision History:
created
--*/
//
// Includes
//
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
#include <ctype.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include "tpdiff.h"
//
// Global Variables
//
CHAR *Keywords[] = {
"-SECTION_START-",
"-SECTION_END-" ,
"-OPTIONALS-" ,
"-TOKEN_MATCH-" ,
"-SECTION_DESC-"
};
PCHAR SummaryBuffer;
/*
********************************************************************************
* *
* General Program Considerations: *
* *
* This program has been designed for generic section matching. However, since *
* the second file for its current use is marked GOLDEN, certain changes have *
* been introduced in line comparison and result printing to account for *
* special type of file. *
* *
* *
********************************************************************************
*/
/********************************** main():start ***********************************************/
VOID _cdecl
main(
INT argc,
CHAR *argv[]
)
{
FILE *IoFile;
FILE *DiffTxtFile;
PCHAR *FileList = &argv[1];
PCHAR Difference_FileName = ( argc == 4 ) ? argv[3] : "DIFF.TXT" ;
PCHAR TmpSummaryBuffer;
MFILE FirstFile, SecondFile;
UINT NumberOfComparisons = 0 ;
UINT NumberOfFilesCompared = 0;
UINT i,j;
ULONG TotalDifferenceCount = 0;
BOOL InputFromFile = FALSE;
ULONG FileOpenErrors = 0;
//
// 1. CHECK INCOMING ARGUMENT SYNTAX
//
if ( ( argc < 3 ) || ( argc > 4 ) ) {
Usage();
exit( -1 );
} else {
printf( "\nMAC NDIS 3.0 Tester - Comparator Tool Version 1.0.2\n\n" );
}
//
// 2. CHECK IF THE FILE LIST TO BE GENERATED IS TO BE EXTRACTED FROM THE COMMAND
// LINE OR FROM A FILE
//
if ( !strncmp( argv[1], "-f", 2 ) ||
!strncmp( argv[1], "-F", 2 ) ) {
CHAR Buffer[2*MAX_LINE_SIZE];
//
// 2.A INDICATE THE LIST IS TO BE GENERATED FROM A FILE
//
InputFromFile = TRUE;
//
// 2.B OPEN THE FILE
//
if ( (IoFile = fopen( argv[2], "r" )) == NULL ) {
printf( "Could not open the primary log list file: %s\n", argv[2] );
Usage();
exit( -1 );
}
//
// 2.C GENERATE THE FILE PAIRS TO BE ANALYZED
//
//
// 2.C.1 DETERMINE THE NUMBER OF VALID FILE PAIRS
//
while( !feof( IoFile ) ) {
memset( Buffer, 0, sizeof(Buffer) );
if ( ( fgets( Buffer, sizeof( Buffer ), IoFile ) != NULL ) &&
( strlen( Buffer ) > 2 ) ) {
NumberOfComparisons++;
}
}
//
// 2.C.2 ALLOCATE THE APPROPRIATE SIZED BLOCK
//
FileList = (PCHAR *)malloc( (NumberOfComparisons*2)*sizeof( PCHAR ) );
if ( FileList == (PCHAR *)NULL ) {
printf("The system has run out of memory resources. Unable to run this program.\n");
exit( -1 );
} else {
memset( FileList, 0, (NumberOfComparisons*2)*sizeof( PCHAR ) );
}
//
// 2.C.2 AND BUILD THE FILE ARRAY LIST
//
i = j = 0;
fseek( IoFile, 0, SEEK_SET );
while ( !feof( IoFile ) ) {
//
// Get the next line out of the file list file
//
memset( Buffer, 0, sizeof(Buffer) );
if ( ( fgets( Buffer, sizeof( Buffer ), IoFile ) != NULL ) &&
( strlen( Buffer ) > 2 ) ) {
//
// Replace the newline Character with a NULL Character
//
*(strchr( Buffer, '\n')) = '\0';
//
// Extract the log file name pairs
//
if ( !GetFilePair( &FileList[j*2], &FileList[(j*2)+1], Buffer ) ) {
printf("An error occurred determining the file pair at line %d in the file list: %s\n",
(i+1), argv[2] );
exit( -1 );
} else {
//
// Increment the file list array counter
//
j++;
}
}
//
// Increment the file line counter
//
i++;
}
//
// 2.C.3 CLOSE THE FILE
//
fclose( IoFile );
} else {
NumberOfComparisons = 1;
//
// The FileList is pre-initialized to the command line arguments and thus we
// simply need to set the file pair comparison count
//
}
//
// 3. INITIALIZE THE SUMMARY BUFFER
//
SummaryBuffer = calloc( NumberOfComparisons, MAX_LINE_SIZE );
if ( SummaryBuffer == (PCHAR)NULL ) {
printf("The system has run out of memory resources for this program\n");
exit( -1 );
} else {
TmpSummaryBuffer = SummaryBuffer ;
}
//
// 4. OBTAIN THE DIFFERENCE FILE NAME INTO WHICH THE RESULTS WILL BE LOGGED
// OR USE THE DEFAULT DIFF.TXT.
//
DiffTxtFile = fopen( Difference_FileName, "w+" );
if ( DiffTxtFile == (FILE *)NULL ) {
printf( "Unable to open the difference text file %s for logging the results.\n", Difference_FileName );
exit( -1 );
} else {
fprintf( DiffTxtFile, "\n\n" );
}
//
// 5. COMPARE THE FILE PAIRS
//
fprintf( DiffTxtFile, "__________DETAILS_LOG__________\n\n" );
fprintf( stdout, "__________DETAILS_LOG__________\n\n" );
for( i = 0; i < NumberOfComparisons; i++ ) {
memset( &FirstFile , 0, sizeof( MFILE ) );
memset( &SecondFile, 0, sizeof( MFILE ) );
FirstFile.FileName = FileList[2*i];
SecondFile.FileName = FileList[(2*i)+1];
fprintf( stdout, "Comparing files %s and %s\n", FirstFile.FileName, SecondFile.FileName );
//
// 5.A OPEN THE FILE PAIR
//
if ( OpenFiles( &FirstFile, FileList[2*i], &SecondFile, FileList[(2*i)+1] ) ) {
ULONG OldDifferenceCount = TotalDifferenceCount;
fprintf( DiffTxtFile, "\n\n**Comparing %s and %s\n\n", FirstFile.FileName, SecondFile.FileName );
NumberOfFilesCompared++;
//
// 5.B COMPARE THEM
//
CompareFiles( &FirstFile, &SecondFile, DiffTxtFile, &TotalDifferenceCount );
//
// 5.C LOG THE RESULTS OF THE COMPARISON INTO THE DIFFERENCE FILE
//
fprintf( DiffTxtFile, "\n\n--TPDIFF %s, %s ERROR(S): %u\n",
FirstFile.FileName, SecondFile.FileName, (TotalDifferenceCount-OldDifferenceCount) );
sprintf( TmpSummaryBuffer, "TPDIFF %s, %s ERROR(S): %u\n",
FirstFile.FileName, SecondFile.FileName, (TotalDifferenceCount-OldDifferenceCount) );
TmpSummaryBuffer += strlen( TmpSummaryBuffer );
} else {
fprintf( DiffTxtFile, "\n\n--TPDIFF %s, %s", FirstFile.FileName, SecondFile.FileName );
if ( FirstFile.FileP == (FILE *)NULL ) {
fprintf( DiffTxtFile, "\tUnable to open file %s\n", FirstFile.FileName );
}
if ( SecondFile.FileP == (FILE *)NULL ) {
fprintf( DiffTxtFile, "\tUnable to open file %s\n", SecondFile.FileName );
}
sprintf( TmpSummaryBuffer, "TPDIFF %s, %s resulted in a file open error\n",
FirstFile.FileName, SecondFile.FileName );
FileOpenErrors++;
TmpSummaryBuffer += strlen( TmpSummaryBuffer );
}
//
// 5.D CLOSE THE FILE PAIR
//
CloseFiles( FirstFile, SecondFile );
FirstFile.FileName = (PCHAR)NULL;
SecondFile.FileName = (PCHAR)NULL;
FirstFile.FileP = (FILE *)NULL;
SecondFile.FileP = (FILE *)NULL;
//
// 5.E FREE THE FILE PAIR FROM THE LIST
//
free( FileList[2*i] );
free( FileList[(2*i)+1] );
}
fprintf( DiffTxtFile, "\n__________END_DETAILS_LOG__________\n\n" );
fprintf( stdout, "\n__________END_DETAILS_LOG__________\n\n" );
//
// 6. LOG THE CUMMULATIVE RESULTS AND SUMMARY INTO THE DIFFERENCE FILE AND STDOUT
//
fprintf( DiffTxtFile, "\n\n__________SUMMARY_LOG__________\n\n" );
fprintf( DiffTxtFile, SummaryBuffer );
fprintf( DiffTxtFile, "\n__________END_SUMMARY_LOG__________\n\n" );
fprintf( DiffTxtFile, "\n\n__________CUMMALATIVE_RESULTS_LOG__________\n\n" );
fprintf( DiffTxtFile, "COMPARED %d FILE PAIR(S)\n" , NumberOfFilesCompared );
fprintf( DiffTxtFile, "TOTAL NUMBER OF DIFFERENCES ENCOUNTERED: %u\n", TotalDifferenceCount );
fprintf( DiffTxtFile, "TOTAL NUMBER OF FILE OPEN ERRORS : %u\n", FileOpenErrors );
fprintf( DiffTxtFile, "\n__________END_CUMMALATIVE_RESULTS_LOG__________\n\n" );
fprintf( stdout, "\n\n__________SUMMARY_LOG__________\n\n" );
fprintf( stdout, SummaryBuffer );
fprintf( stdout, "\n__________END_SUMMARY_LOG__________\n\n" );
fprintf( stdout, "\n\n__________CUMMALATIVE_RESULTS_LOG__________\n\n" );
fprintf( stdout, "COMPARED %d FILE PAIR(S)\n" , NumberOfFilesCompared );
fprintf( stdout, "TOTAL NUMBER OF DIFFERENCES ENCOUNTERED: %u\n", TotalDifferenceCount );
fprintf( stdout, "TOTAL NUMBER OF FILE OPEN ERRORS : %u\n", FileOpenErrors );
fprintf( stdout, "\n__________END_CUMMALATIVE_RESULTS_LOG__________\n\n" );
//
// 7. CLOSE THE DIFFERENCE FILE AND PERFORM ANY REMAINING CLEANUP
//
fclose( DiffTxtFile );
free( SummaryBuffer );
if ( InputFromFile ) {
free( FileList );
}
}
/********************************** main():end *************************************************/
VOID
Usage()
{
printf( "\n\tUsage: TPDIFF LOG_FILE GOLDEN_LOG_FILE [DIFFS_FILE]\n\n" );
printf( "\tWhere:\n\n");
printf( "\tLOG_FILE - is the log file that is to be verified\n" );
printf( "\t for correctness.\n" );
printf( "\tKNOWN_LOG_FILE - is the known good log file that will be\n" );
printf( "\t used to verify the log file.\n" );
printf( "\tDIFFS_FILE - is the file the differences, if any exist,\n" );
printf( "\t between the log files and the known good log\n" );
printf( "\t files will be written to. If no file name is\n" );
printf( "\t given the differences will be printed to the\n" );
printf( "\t default file DIFF.TXT and the console.\n" );
printf( "\t\t- OR -\n\n" );
printf( "\tTPDIFF -F LOG_FILE_LIST [DIFFS_FILE]\n\n" );
printf( "\tWhere:\n\n" );
printf( "\tLOG_FILE_LIST - is a file containing pairs of log file\n" );
printf( "\t names and known good log file names. The\n" );
printf( "\t pairs of file names must be on the same line\n" );
printf( "\t in the file\n" );
printf( "\tDIFFS_FILE - is the file the differences, if any exist,\n" );
printf( "\t between the log files and the known good log\n" );
printf( "\t files will be written to. If no file name is\n" );
printf( "\t given the differences will be printed to the\n" );
printf( "\t default file DIFF.TXT and the console.\n" );
}
BOOLEAN
GetFilePair(
PCHAR *FirstFile,
PCHAR *SecondFile,
PCHAR Buffer
)
{
PCHAR Token[2] ;
PCHAR Seperators = " ,\t" ;
UINT TokenLength[2] ;
//
// Extract the log file names from the string buffer
//
Token[0] = strtok( Buffer, Seperators );
if ( Token[0] != (PCHAR)NULL ) {
Token[1] = strtok( NULL, Seperators );
if ( Token[1] == (PCHAR)NULL ) {
printf("The first log file name is:\t%s\nHowever the program was unable to determine the second log file name.\n",
Token[0]);
return FALSE;
} else {
TokenLength[0] = strlen( Token[0] );
TokenLength[1] = strlen( Token[1] );
}
} else {
printf("Unable to determine the first log file name.\n");
return FALSE;
}
//
// Create storage on the file list for the file names
//
*FirstFile = malloc( (TokenLength[0]+1)*sizeof(CHAR) );
*SecondFile = malloc( (TokenLength[1]+1)*sizeof(CHAR) );
if ( *FirstFile == (PCHAR)NULL || *SecondFile == (PCHAR)NULL ) {
printf("The system has run out of memory resources for this program\n");
free( *FirstFile );
free( *SecondFile );
exit( -1 );
}
//
// Copy the file names into the allocated storage
//
memset( *FirstFile, 0, TokenLength[0]+1 );
memset( *SecondFile, 0, TokenLength[1]+1 );
strncpy( *FirstFile, Token[0], TokenLength[0] );
strncpy( *SecondFile, Token[1], TokenLength[1] );
//
// And return success
//
return TRUE;
}
BOOLEAN
OpenFiles(
PMFILE FirstFile,
PCHAR FirstFileName,
PMFILE SecondFile,
PCHAR SecondFileName
)
{
//
// Open the two files
//
FirstFile->FileP = fopen( FirstFileName, "r" );
SecondFile->FileP = fopen( SecondFileName, "r" );
//
// If there was an error while opening functionally report it
//
if ( ( FirstFile->FileP == (FILE *)NULL ) ||
( SecondFile->FileP == (FILE *)NULL ) ) {
return FALSE;
}
return TRUE;
}
BOOLEAN
CompareFiles(
PMFILE FirstFile,
PMFILE SecondFile,
FILE *DifferenceFile,
PULONG TotalDifferenceCounter
)
{
PSECTION SectionZero_FirstFile;
PSECTION SectionZero_SecondFile;
ULONG FileComparisonDifferences = 0 ;
//
// Create the two special sections.
// These sections indicate the beggining of the two files being compared
//
SectionZero_FirstFile = CreateSection();
SectionZero_SecondFile = CreateSection();
if ( SectionZero_FirstFile == (PSECTION)NULL) {
printf("The system has run out of memory resources for this program\n");
if ( SectionZero_SecondFile != (PSECTION)NULL) {
DestroySection( SectionZero_SecondFile );
}
exit( -1 );
} else if ( SectionZero_SecondFile == (PSECTION)NULL) {
printf("The system has run out of memory resources for this program\n");
DestroySection( SectionZero_FirstFile );
exit( -1 );
}
//
// Initialize the two sections
//
SectionZero_FirstFile->File = FirstFile ;
SectionZero_SecondFile->File = SecondFile;
strcpy( SectionZero_FirstFile->SectionDescription, FirstFile->FileName );
strcpy( SectionZero_SecondFile->SectionDescription, SecondFile->FileName );
//
// Now since the second file is also the GOLDEN file, set that as the
// base control section. Lines, sections will be compared AGAINST this control
// section. In the generic case however, this would not be true since either
// one can be marked as the base section. That requires this line to be remarked
// and changes made to the -TOKEN_MATCH-() keyword syntax to accept the variable
// BASE.
//
SectionZero_SecondFile->Control.BaseControlSection = TRUE;
//
// Proceed with the comparisons
//
CompareSections( SectionZero_FirstFile, SectionZero_SecondFile,
DifferenceFile, &FileComparisonDifferences );
//
// And indicate the completion of a successful comparison
//
*TotalDifferenceCounter += FileComparisonDifferences;
return TRUE;
}
BOOLEAN
CompareSections(
PSECTION FirstSection,
PSECTION SecondSection,
FILE *DifferenceFile,
PULONG FileDifferenceCounter
)
{
PFUNCTION_ELEMENTS FunctionElements;
//
// Initialize the lines used to store information extracted from the files
//
FunctionElements = CreateFunctionElements();
if ( FunctionElements == (PFUNCTION_ELEMENTS)NULL ) {
printf("The system has run out of memory resources for this program\n");
exit( -1 );
} else {
FunctionElements->SectionEndsNotSynchronized = TRUE;
}
//
// Indicate a sectional compare IF the section is not the base section 0.0
//
// fprintf( DifferenceFile, "\n\n__PERFORMING SECTIONAL ANALYSIS ON SECTION ID: %f__\n",
// SecondSection->Control.SectionIdentifier );
//
// Repeat until the section ends from the two files match
// and the section comparison completes
//
while ( FunctionElements->SectionEndsNotSynchronized ) {
//
// Get the next line from first section IFF sectional synchronization is not
// required
//
if ( FunctionElements->FirstSectionSynchronize == FALSE ) {
//
// Keep attempting to access the next line till we do not have to skip lines
//
FunctionElements->SkipLine = TRUE;
while ( FunctionElements->SkipLine ) {
ClearAndSetLine( FirstSection , &FunctionElements->FirstSectionCurrentLine );
if ( GetNextLine( FirstSection ) ) {
if ( DoNotSkipThisLine( FirstSection ) ) {
ExtractResults( FirstSection );
FunctionElements->SkipLine = FALSE;
}
FirstSection->Control.SectionLineCount++;
FirstSection->File->CurrentFileLine++;
} else {
//
// Mark this line as type SECTION_END. This is actually the EOF which
// is also the end of section 0.0(the file)
//
FirstSection->CurrentLine->LineType = LINE_TYPE_SECTION_END;
FunctionElements->SkipLine = FALSE ;
}
}
}
//
// Get the next line from second section IFF sectional synchronization is not
// required
//
if ( FunctionElements->SecondSectionSynchronize == FALSE ) {
//
// Keep attempting to access the next line till we do not have to skip lines
//
FunctionElements->SkipLine = TRUE;
while ( FunctionElements->SkipLine ) {
ClearAndSetLine( SecondSection, &FunctionElements->SecondSectionCurrentLine );
if ( GetNextLine( SecondSection ) ) {
if ( DoNotSkipThisLine( SecondSection ) ) {
//
// Since the second file section is the golden section
// we do not need to extract results from the line.
// However, if the program is changed for generic control
// the line should be included
//
// ExtractResults( FirstSection );
//
ExtractBetweenValues( SecondSection );
FunctionElements->SkipLine = FALSE;
}
SecondSection->Control.SectionLineCount++;
SecondSection->File->CurrentFileLine++;
} else {
//
// Mark this line as type SECTION_END. This is actually the EOF which
// is also the end of section 0.0(the file)
//
SecondSection->CurrentLine->LineType = LINE_TYPE_SECTION_END;
FunctionElements->SkipLine = FALSE ;
}
}
}
//
// Determine the line types of both sections.
// The line type indicate the beggining of a section, ending of a section,
// or a regular line
//
LineType( FirstSection );
LineType( SecondSection );
//
// Determine the variation to be examined. The variation is simply a combination
// of the two line types to indicate common behavior. e.g. if the first line was
// a section ending and the second line was a regular line, the behaviour of
// the program would be the same if the line types were reversed
//
CombinedVariation( FirstSection, SecondSection, &FunctionElements->CombinedLineVariation );
//
// And now operate on the deduced variation
//
switch( FunctionElements->CombinedLineVariation ) {
//
// If both lines are the beginning of new sections
//
case SECTIONHDR_SECTIONHDR:
//
// Examine both section ID's specified in the current lines match the
// following conditions
// 1. The two ID's are the same
// 2. The two ID do NOT match the current section ID's
//
if ( CheckSectionIDFromCurrentLines( FirstSection, SecondSection ) ) {
//
// Sections have been synchronized
//
FunctionElements->FirstSectionSynchronize = FALSE;
FunctionElements->SecondSectionSynchronize = FALSE;
//
// Create two new sections
//
FunctionElements->NewFirstSection = CreateSection();
FunctionElements->NewSecondSection = CreateSection();
if ( FunctionElements->NewFirstSection == (PSECTION)NULL ) {
printf("The system has run out of memory resources for this program\n");
if ( FunctionElements->NewSecondSection != (PSECTION)NULL ) {
DestroySection( FunctionElements->NewSecondSection );
}
exit( -1 );
} else if ( FunctionElements->NewSecondSection == (PSECTION)NULL ) {
printf("The system has run out of memory resources for this program\n");
DestroySection( FunctionElements->NewFirstSection );
exit( -1 );
}
//
// Initialize section control
//
if ( !InitializeSectionControl( FunctionElements->NewFirstSection, FirstSection ) ||
!InitializeSectionControl( FunctionElements->NewSecondSection, SecondSection ) ) {
//
// Once again this should not occur
//
fprintf( DifferenceFile, "\nA BAD SECTIONAL CONTROL SEGMENT HAS BEEN DETECTED\n");
fprintf( DifferenceFile, "\nCHECK FOR A SYNTAX ERROR\n" );
PrintSectionInformation( FirstSection, DifferenceFile );
PrintSectionInformation( SecondSection, DifferenceFile );
//
// Free up the resources allocates
//
DestroySection( FunctionElements->NewFirstSection );
DestroySection( FunctionElements->NewSecondSection );
//
// Reset and compare as regular lines
//
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
} else {
//
// Compare the two new sections
//
CompareSections( FunctionElements->NewFirstSection,
FunctionElements->NewSecondSection,
DifferenceFile,
FileDifferenceCounter );
//
// Readjust the current line counters for the First and Second
// Sections
//
FirstSection->Control.SectionLineCount +=
FunctionElements->NewFirstSection->Control.SectionLineCount;
SecondSection->Control.SectionLineCount +=
FunctionElements->NewSecondSection->Control.SectionLineCount;
//
// Free up the resources allocates
//
DestroySection( FunctionElements->NewFirstSection );
DestroySection( FunctionElements->NewSecondSection );
}
} else {
//
// Force synchronize the sections
//
FunctionElements->FirstSectionSynchronize = FALSE;
FunctionElements->SecondSectionSynchronize = FALSE;
//
// switch them to regular lines.
// This condition should never be reached and if so treat these
// lines as regular lines
//
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
}
break;
//
// If both lines are ends of sections
//
case SECTIONEND_SECTIONEND:
FunctionElements->FirstSectionID = ExtractSectionIDFromLine( FirstSection );
FunctionElements->SecondSectionID = ExtractSectionIDFromLine( SecondSection );
//
// Global section control. Ends section comparisons.
//
if ( FunctionElements->FirstSectionID > FunctionElements->SecondSectionID ) {
FunctionElements->FirstSectionSynchronize = FALSE;
FunctionElements->SecondSectionSynchronize = TRUE;
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
} else if ( FunctionElements->FirstSectionID < FunctionElements->SecondSectionID ) {
FunctionElements->FirstSectionSynchronize = TRUE;
FunctionElements->SecondSectionSynchronize = FALSE;
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
} else {
//
// Sections are synchronized
//
FunctionElements->FirstSectionSynchronize = FALSE;
FunctionElements->SecondSectionSynchronize = FALSE;
//
// Now make sure that the extracted section IDs match the
// current section ID
//
if ( FunctionElements->FirstSectionID == FirstSection->Control.SectionIdentifier ) {
//
// ALL TOKEN MATCHING IS DONE AT THE ENDS OF SECTIONS
//
if ( SecondSection->Control.TokenMatching == TRUE ) {
CompareTokensAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
}
FunctionElements->SectionEndsNotSynchronized = FALSE;
} else {
//
// Switch them to regular lines
//
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
}
}
break;
//
// If one line is the beggining of a section
// and the other is the end of a section
//
case SECTIONHDR_SECTIONEND:
//
// We have come across the case where another section has been detected
// while another was ending.
//
if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) {
FunctionElements->FirstSectionSynchronize = TRUE;
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
} else {
FunctionElements->SecondSectionSynchronize = TRUE;
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
}
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
break;
//
// If one line is the beggining of a section and the other
// is a regular line
//
case SECTIONHDR_REGLINE :
//
// We have come to a point where a section header has been detected
// in one section and a regular line in another
// This forces us to now attempt to re-synchronize the sections
//
if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) {
if ( ExtractSectionIDFromLine( FirstSection ) != (DOUBLE)0 ) {
FunctionElements->FirstSectionSynchronize = TRUE;
} else {
//
// Simply RESET this line as a regular line and compare
//
FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
}
} else {
if ( ExtractSectionIDFromLine( SecondSection ) != (DOUBLE)0 ) {
FunctionElements->SecondSectionSynchronize = TRUE;
} else {
//
// Simply RESET this line as a regular line and compare
//
SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR;
}
}
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
break;
//
// If one line is the end of a section and
// the other is a regular line
//
case SECTIONEND_REGLINE :
//
// We have come to a point where a section end has been detected
// in one section and a regular line in another
// This forces us to now attempt to re-synchronize the sections
//
if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) {
FunctionElements->FirstSectionSynchronize = TRUE;
} else {
FunctionElements->SecondSectionSynchronize = TRUE;
}
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
break;
//
// If both lines are regular lines
//
case REGLINE_REGLINE :
CompareLinesAndPrintResults( FirstSection,
SecondSection,
&FunctionElements->ErrorCount,
DifferenceFile );
break;
} // !switch{}
} // !while( FunctionElements->SectionEndsNotSynchronized )
//
// Print out the section comparison results
//
if ( FunctionElements->ErrorCount ) {
fprintf( DifferenceFile, "\n\n__SECTIONAL RESULTS FOR SECTION ID : %f ERROR(S): %u\n",
SecondSection->Control.SectionIdentifier,
FunctionElements->ErrorCount );
}
//
// Cleanup
//
*FileDifferenceCounter += FunctionElements->ErrorCount;
DestroyFunctionElements( FunctionElements );
return TRUE;
}
BOOLEAN
GetNextLine(
PSECTION Section
)
{
UINT i,j;
PCHAR Tmp;
//
// Get the normal line. Read in until MAX_LINE_SIZE-1. This is done to ensure that
// should the line be longer, only the first MAX_LINE_SIZE-1 bytes are read in and
// the last byte is 0.
//
if ( fgets( Section->CurrentLine->NormalLine,
(sizeof( Section->CurrentLine->NormalLine )-1),
Section->File->FileP
) != NULL ) {
//
// Replace the first occurence of a new line with a null
//
Tmp = strchr( Section->CurrentLine->NormalLine, '\n');
if ( Tmp != (PCHAR)NULL ) {
*Tmp = '\0';
}
Section->CurrentLine->NormalLineSize = strlen( Section->CurrentLine->NormalLine );
//
// Obtain a compressed uppercase version of the line
//
for( i = 0, j = 0 ; i < strlen( Section->CurrentLine->NormalLine ); i++ ) {
if ( isspace( Section->CurrentLine->NormalLine[i] ) == 0 ) {
Section->CurrentLine->CompressedLine[j] = toupper( Section->CurrentLine->NormalLine[i] );
Section->CurrentLine->CompressedLineSize++;
j++;
}
}
//
// And return
//
return TRUE;
}
//
// This indicates an EOF has been reached
//
return FALSE;
}
VOID
LineType(
PSECTION Section
)
{
//
// If while entering the line type was marked as SECTION_END
// it indicates the EOF has been encountered. Since EOF is also
// the end of section ID 0.0, the line is premarked
// is read. This is the only special type which is premarked
//
if ( Section->CurrentLine->LineType == LINE_TYPE_SECTION_END ) {
return;
}
//
// If the line contains a MAY_DIFFER, irrespective of what the control
// is it is turned into a regular line
//
if ( strstr( Section->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) {
Section->CurrentLine->LineType = LINE_TYPE_REGULAR;
return;
}
//
// Search for the special keyword -SECTION_START-
//
if ( strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_START] ) != NULL ) {
Section->CurrentLine->LineType = LINE_TYPE_SECTION_START;
return;
}
//
// Search for the special keyword -SECTION_END-
//
if ( strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_END] ) != NULL ) {
Section->CurrentLine->LineType = LINE_TYPE_SECTION_END;
return;
}
Section->CurrentLine->LineType = LINE_TYPE_REGULAR;
return;
}
BOOLEAN
ExtractResults(
PSECTION Section
)
{
PCHAR TmpBuf;
PCHAR Token ;
BOOLEAN ExtractMoreResults = TRUE;
CHAR Seperators[] = " ,\t";
ULONG i;
CHAR TmpLine[MAX_LINE_SIZE];
//
// First move the Current results into the Last results and clear the current results
// one at a time
//
for( i = 0; i < Section->NumberOfCurrentResults;i++ ) {
Section->LastResults[i] = Section->CurrentResults[i];
Section->CurrentResults[i] = 0 ;
}
Section->NumberOfLastResults = Section->NumberOfCurrentResults;
Section->NumberOfCurrentResults = 0;
//
// Clear the tmp variable and copy the Normal Line contents into it
// This is done to preserve the contents of the normal line since strtok
// changes the contents.
//
memset( TmpLine, 0, MAX_LINE_SIZE );
strcpy( TmpLine, Section->CurrentLine->NormalLine );
//
// Search for the right hand value of the expression. This is extracted
// by searching for the = or the : operator.
//
// NOTE
//
// We use strrchr to get to the last occurence of = or :
//
//
// Locate the = operator
//
TmpBuf = strrchr( TmpLine, '=' );
if ( TmpBuf == NULL ) {
//
// Locate the : operator
//
TmpBuf = strrchr( TmpLine, ':' );
if ( TmpBuf == NULL ) {
return FALSE;
}
}
//
// The fact that we are here indicates that one of the operator
// types was located
//
TmpBuf++;
Token = strtok( TmpBuf, Seperators );
while ( ( Section->NumberOfCurrentResults < MAX_RESULTS_COUNT ) &&
( Token != NULL ) &&
( ExtractMoreResults ) ) {
if ( (*Token >= '0') && (*Token <= '9') ) {
Section->CurrentResults[Section->NumberOfCurrentResults] = atol( Token );
Section->NumberOfCurrentResults++;
Token = strtok( NULL, Seperators );
} else {
ExtractMoreResults = FALSE;
}
}
if ( Section->NumberOfCurrentResults ) {
return TRUE;
}
return FALSE;
}
BOOLEAN
ExtractBetweenValues(
PSECTION Section
)
{
PCHAR Tmp, Tmp1;
ULONG SwapValue;
//
// Search for the AT_LEAST Keyword
//
Tmp = strstr( Section->CurrentLine->CompressedLine, "BETWEEN_VALUES" );
if ( Tmp != NULL ) {
Tmp += strlen( "BETWEEN_VALUES" );
//
// Extract the minimum-first value
//
Section->MinimumValue = atol( Tmp );
//
// Proceed to look for the maximum-second value
//
Tmp1 = strstr( Tmp, "," );
if ( Tmp1 != NULL ) {
Tmp1 += strlen( "," );
//
// Extract the minimum-first value
//
Section->MaximumValue = atol( Tmp1 );
} else {
Section->MaximumValue = 0xffffffff;
}
if ( Section->MinimumValue > Section->MaximumValue ) {
SwapValue = Section->MinimumValue;
Section->MinimumValue = Section->MaximumValue;
Section->MaximumValue = SwapValue ;
}
return TRUE;
}
//
// Could not locate AT_LEAST or no associated value was recovered
//
Section->MinimumValue = 0;
Section->MaximumValue = 0xffffffff;
return FALSE;
}
BOOLEAN
CombinedVariation(
PSECTION FirstSection,
PSECTION SecondSection,
PUCHAR CombinedLineVariation
)
{
//
// THERE ARE THE FOLLOWING POSSIBLE 6 COMBINATIONS
//
// START-START, START-REGLINE, START-END
// END-REGLINE, END-END
// REGLINE-REGLINE
//
if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) {
*CombinedLineVariation = SECTIONHDR_SECTIONHDR;
return TRUE;
}
if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) {
*CombinedLineVariation = SECTIONEND_SECTIONEND;
return TRUE;
}
if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) ) {
*CombinedLineVariation = REGLINE_REGLINE;
return TRUE;
}
if ( (
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END )
) ||
(
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START )
) ) {
*CombinedLineVariation = SECTIONHDR_SECTIONEND;
return TRUE;
}
if ( (
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR )
) ||
(
( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START )
) ) {
*CombinedLineVariation = SECTIONHDR_REGLINE;
return TRUE;
}
if ( (
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR )
) ||
(
( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END )
) ) {
*CombinedLineVariation = SECTIONEND_REGLINE;
return TRUE;
}
return FALSE;
}
RESULT
CompareLines(
PSECTION FirstSection,
PSECTION SecondSection
)
{
BOOLEAN ResultErrorsDiscovered = FALSE;
ULONG i;
//
// THIS IS ANOTHER VERY CRITICAL PIECE OF THE CODE SINCE BASED ON THE LINE TYPES
// COMPARISONS ARE MADE
//
// ON ENTERING THIS FUNCTION THERE ARE ONLY THREE COMBINATIONS A LINE COULD
// BE IN THE FOLLOWING STATES
//
// REGLINE-REGLINE
// REGLINE-SECTIONHDR
// REGLINE-SECTIONEND
//
// FURTHER SINCE THE SECTIONS ARE SYNCHRONIZED WE CAN USE THE CONTROL SETTINGS
// OF EITHER ONE
//
//
// COMMON COMPARISONS BETWEEN ALL LINE TYPES
//
//
// Possible MAY_DIFFER.
//
if ( MayDifferExistsInOneOrMoreLines( FirstSection, SecondSection ) ) {
return COMPARE_SUCCESS;
}
//
// Possible EQUAL_LAST
//
if ( strstr( FirstSection->CurrentLine->CompressedLine, "EQUAL_LAST" ) != NULL ) {
if ( SecondSection->Control.OptionalMatching == FALSE ) {
for( i = 1; i <= FirstSection->NumberOfCurrentResults; i++ ) {
if ( i > FirstSection->NumberOfLastResults ) {
FirstSection->ResultsError[i-1] = RESULTS_NOT_PRESENT;
ResultErrorsDiscovered = TRUE;
} else {
if ( FirstSection->CurrentResults[i-1] != FirstSection->LastResults[i-1] ) {
FirstSection->ResultsError[i-1] = RESULTS_UNEQUAL;
ResultErrorsDiscovered = TRUE;
} else {
FirstSection->ResultsError[i-1] = RESULTS_EQUAL;
}
}
}
if ( ResultErrorsDiscovered ) {
return COMPARE_EQUAL_LAST;
}
}
return COMPARE_SUCCESS;
}
//
// Possible BETWEEN_VALUES from the Golden log file
//
if ( strstr( SecondSection->CurrentLine->CompressedLine, "BETWEEN_VALUES" ) != NULL ) {
if ( SecondSection->Control.OptionalMatching == FALSE ) {
for( i = 1; i <= FirstSection->NumberOfCurrentResults; i++ ) {
if ( ( FirstSection->CurrentResults[i-1] < SecondSection->MinimumValue ) ||
( FirstSection->CurrentResults[i-1] > SecondSection->MaximumValue ) ) {
FirstSection->ResultsError[i-1] = RESULTS_MINMAX;
ResultErrorsDiscovered = TRUE;
} else {
FirstSection->ResultsError[i-1] = RESULTS_EQUAL;
}
}
if ( ResultErrorsDiscovered ) {
return COMPARE_BETWEEN_VALUES;
}
}
return COMPARE_SUCCESS;
}
//
// REGLINE-SECTIONHDR
//
if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) {
if ( SecondSection->Control.OptionalMatching == TRUE ) {
return COMPARE_SUCCESS;
}
if ( SecondSection->Control.TokenMatching == TRUE ) {
TokenInsertInSection( FirstSection );
return COMPARE_SUCCESS;
}
return COMPARE_START;
}
if( ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) {
if ( SecondSection->Control.OptionalMatching == TRUE ) {
return COMPARE_SUCCESS;
}
if ( SecondSection->Control.TokenMatching == TRUE ) {
TokenInsertInSection( SecondSection );
return COMPARE_SUCCESS;
}
return COMPARE_START;
}
//
// REGLINE-SECTIONEND
//
if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) {
if ( SecondSection->Control.OptionalMatching == TRUE ) {
return COMPARE_SUCCESS;
}
if ( SecondSection->Control.TokenMatching == TRUE ) {
TokenInsertInSection( FirstSection );
return COMPARE_SUCCESS;
}
return COMPARE_END;
}
if ( ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) &&
( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) {
if ( SecondSection->Control.OptionalMatching == TRUE ) {
return COMPARE_SUCCESS;
}
if ( SecondSection->Control.TokenMatching == TRUE ) {
TokenInsertInSection( SecondSection );
return COMPARE_SUCCESS;
}
return COMPARE_END;
}
//
// REGLINE-REGLINE
//
if ( memcmp( FirstSection->CurrentLine->CompressedLine,
SecondSection->CurrentLine->CompressedLine,
max( FirstSection->CurrentLine->CompressedLineSize, SecondSection->CurrentLine->CompressedLineSize )
)
!= 0 ) {
//
// Since we can only be at this point if the two section headers match,
// either control sections can be used
//
if ( SecondSection->Control.OptionalMatching == TRUE ) {
return COMPARE_SUCCESS;
}
if ( SecondSection->Control.TokenMatching == TRUE ) {
TokenInsertInSection( FirstSection );
TokenInsertInSection( SecondSection );
return COMPARE_SUCCESS;
}
return COMPARE_LINE;
}
return COMPARE_SUCCESS;
}
BOOLEAN
InitializeSectionControl(
PSECTION NewSection,
PSECTION OldSection
)
{
PCHAR TmpBuffer;
INT Length ;
CHAR EnvironmentVar[MAX_LINE_SIZE];
CHAR TmpLine[MAX_LINE_SIZE] ;
//
// Initialize the file pointers
//
// NOTE
//
// If you do not specify any control for the section and the section is nested
// it will inherit the options of the parent node
//
NewSection->File = OldSection->File;
NewSection->CurrentLine = (PLINE)NULL;
NewSection->Control.BaseControlSection = OldSection->Control.BaseControlSection;
NewSection->Control.OptionalMatching = OldSection->Control.OptionalMatching ;
NewSection->Control.TokenMatching = OldSection->Control.TokenMatching ;
NewSection->Control.TokenMatchStartLine = OldSection->Control.TokenMatchStartLine;
NewSection->Control.TokenMatchStopLine = OldSection->Control.TokenMatchStopLine ;
//
// Since we are going to use strtok to preserve the Normal and Compressed Lines
// we copy them into two local variables when required
//
memset( TmpLine, 0, MAX_LINE_SIZE );
//
// Initialize the section ID
//
// KEYWORD : -SECTION_START-
// USAGE : -SECTION_START-( SectionId )
//
//
NewSection->Control.SectionIdentifier = ExtractSectionIDFromLine( OldSection );
if ( NewSection->Control.SectionIdentifier == (DOUBLE)0 ) {
//
// A section without a section ID has ben defined. This is not acceptable
//
return FALSE;
}
//
// Initialize the section description
//
// KEYWORD : -SECTION_DESC-
// USAGE : -SECTION_DESC-( "Section for MACFRAME testing only" )
//
//
TmpBuffer = strstr( OldSection->CurrentLine->NormalLine, Keywords[SECTION_DESC] );
if ( TmpBuffer != NULL ) {
TmpBuffer = strchr( TmpBuffer, '"' )+1;
Length = strrchr( TmpBuffer, '"' ) - TmpBuffer;
if ( Length < 0 ) {
Length = 0;
}
strncpy( NewSection->SectionDescription, TmpBuffer, Length );
}
//
// Initialize any Optional control sectioning. This if detected without any
// parameters suggests that the section is under optional comparison. Else
// certain environment variables are checked and is found enabled, this
// section is matched
//
// KEYWORD : -OPTIONALS-
// USAGE : -OPTIONALS-( EnvironmentVar1, EnvironmentVar2...EnvironmentVarN )
//
//
strcpy( TmpLine, OldSection->CurrentLine->CompressedLine );
TmpBuffer = strstr( TmpLine, Keywords[OPTIONALS] );
if ( TmpBuffer != NULL ) {
UINT EnvCounter1 = 0 , EnvCounter2 = 0 ;
PCHAR Token ;
PCHAR Seperators = ",)" ;
//
// Weve detected an optional section
//
NewSection->Control.OptionalMatching = TRUE;
TmpBuffer += (strlen( Keywords[OPTIONALS] )+1);
//
// Now detect which Environment variables are enabled.
// If ALL are not enabled, the section remains an
// optional section
//
Token = strtok( TmpBuffer, Seperators );
while ( Token != NULL ) {
EnvCounter1++;
memset( EnvironmentVar, 0, sizeof( EnvironmentVar ) );
strncpy( EnvironmentVar, Token, strlen( Token ) );
if ( getenv( EnvironmentVar ) != NULL ) {
EnvCounter2++;
}
Token = strtok( NULL, Seperators );
}
//
// If all the environment variables have been enabled, this is
// no longer an optional section
//
if ( (EnvCounter1 == EnvCounter2) && (EnvCounter1 != 0) ) {
NewSection->Control.OptionalMatching = FALSE;
}
}
//
// Initialize any Token matching control within the sections.
//
// KEYWORD : -TOKEN_MATCH-
// USAGE : -TOKEN_MATCH-( StartLine, StopLine )
//
// NOTE: The StopLine is expressed as a relative offset from the start line
//
NewSection->Control.HeadUnmatchedTokens = NULL;
TmpBuffer = strstr( OldSection->CurrentLine->CompressedLine, Keywords[TOKEN_MATCH] );
if ( TmpBuffer != NULL ) {
//
// Weve detected an Token matching section
//
NewSection->Control.TokenMatching = TRUE;
TmpBuffer += (strlen( Keywords[TOKEN_MATCH] )+1);
NewSection->Control.TokenMatchStartLine = atol( TmpBuffer );
NewSection->Control.TokenMatchStopLine = atol( (strchr(TmpBuffer, ',')+1) );
if ( NewSection->Control.TokenMatchStopLine == 0 ) {
NewSection->Control.TokenMatchStopLine = TOKEN_MATCHING_ALL;
}
}
return TRUE;
}
VOID
PrintComparisonResults(
PSECTION FirstSection,
PSECTION SecondSection,
RESULT ReturnResult,
ULONG ErrorCount,
FILE *DifferenceFile
)
{
ULONG i;
switch ( ReturnResult ) {
case COMPARE_LINE :
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
fprintf( DifferenceFile, "\nFOUND (COMP.FILE LINE CONTENTS) : %s\n",
FirstSection->CurrentLine->NormalLine );
fprintf( DifferenceFile, "EXPECTED (GOLDEN FILE LINE CONTENTS) : %s\n",
SecondSection->CurrentLine->NormalLine );
//
// Since this program is for the second file being the GOLDEN file
// It prints out information with reference to the GOLDEN file
//
fprintf( DifferenceFile, "\n\tERROR TYPE : LINE COMPARISON FAILURE\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
SecondSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n",
FirstSection->File->FileName );
fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n",
FirstSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n",
FirstSection->File->CurrentFileLine );
fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n",
SecondSection->File->FileName );
fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n",
SecondSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n",
SecondSection->File->CurrentFileLine );
break;
case COMPARE_EQUAL_LAST:
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
fprintf( DifferenceFile, "\nINDEX FOUND(CURRENT EXTRACTED RESULTS) EXPECTED(LAST EXTRACTED RESULTS)\n" );
for( i = 0; i < FirstSection->NumberOfCurrentResults; i++ ) {
if ( FirstSection->ResultsError[i] != RESULTS_EQUAL ) {
fprintf( DifferenceFile, "%5u %32u %32u\n",
(i+1),
FirstSection->CurrentResults[i],
FirstSection->LastResults[i]
);
}
}
fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT VALUE(S) FAILED TO EQUAL LAST\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
FirstSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", FirstSection->File->FileName );
fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n",
FirstSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n",
FirstSection->File->CurrentFileLine );
break;
case COMPARE_BETWEEN_VALUES:
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
fprintf( DifferenceFile, "\nEXPECTED VALUES BETWEEN (EXTRACTED FROM GOLDEN) : %u, %u\n",
SecondSection->MinimumValue, SecondSection->MaximumValue );
fprintf( DifferenceFile, "\nFOUND RESULTS IN ERROR(EXTRACTED RESULTS)\n" );
fprintf( DifferenceFile, "INDEX RESULT\n" );
for( i = 0; i < FirstSection->NumberOfCurrentResults; i++ ) {
if ( FirstSection->ResultsError[i] != RESULTS_EQUAL ) {
fprintf( DifferenceFile, "%5u %23u\n",
(i+1),
FirstSection->CurrentResults[i]
);
}
}
fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT VALUE(S) IS(ARE) NOT BETWEEN THE EXPECTED VALUES\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
FirstSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", FirstSection->File->FileName );
fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n",
FirstSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n",
FirstSection->File->CurrentFileLine );
break;
case COMPARE_TOKEN :
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
fprintf( DifferenceFile, "\nUNABLE TO LOCATE LINE IN THE COMP. FILE : %s\n",
SecondSection->Control.HeadUnmatchedTokens->NormalToken );
fprintf( DifferenceFile, "\n\tERROR TYPE : UNABLE TO LOCATE TOKEN\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
SecondSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n",
FirstSection->File->FileName );
fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n",
SecondSection->File->FileName );
fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n",
SecondSection->Control.HeadUnmatchedTokens->LinePosition );
fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n",
SecondSection->Control.HeadUnmatchedTokens->FileLinePosition );
break;
case COMPARE_START :
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
if ( FirstSection->CurrentLine->LineType != LINE_TYPE_SECTION_START ) {
fprintf( DifferenceFile, "\nEXTRA LINE DETECTED (COMP. FILE LINE CONTENTS) : %s\n",
FirstSection->CurrentLine->NormalLine );
fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): %s\n",
SecondSection->CurrentLine->NormalLine );
} else {
fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : %s\n",
FirstSection->CurrentLine->NormalLine );
fprintf( DifferenceFile, "LINE ABSENT IN COMP. FILE (GOLDEN FILE LINE CONTENTS) : %s\n",
SecondSection->CurrentLine->NormalLine );
}
fprintf( DifferenceFile, "\n\tERROR TYPE : NEW SECTION START SYNCHRONIZATION FAILURE\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
SecondSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n",
FirstSection->File->FileName );
fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n",
FirstSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n",
FirstSection->File->CurrentFileLine );
fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n",
SecondSection->File->FileName );
fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n",
SecondSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n",
SecondSection->File->CurrentFileLine );
break;
case COMPARE_END :
//
// Report the difference in the difference file
//
fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount );
if ( FirstSection->CurrentLine->LineType != LINE_TYPE_SECTION_END ) {
fprintf( DifferenceFile, "\nEXTRA LINE DETECTED (COMP. FILE LINE CONTENTS) : %s\n",
FirstSection->CurrentLine->NormalLine );
if ( ( SecondSection->Control.SectionIdentifier == (DOUBLE)0 ) &&
( strlen( SecondSection->CurrentLine->CompressedLine ) == 0 ) ) {
fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): END_OF_FILE\n" );
} else {
fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): %s\n",
SecondSection->CurrentLine->NormalLine );
}
} else {
if ( ( FirstSection->Control.SectionIdentifier == (DOUBLE)0 ) &&
( strlen( FirstSection->CurrentLine->CompressedLine ) == 0 ) ) {
fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : END_OF_FILE\n" );
} else {
fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : %s\n",
FirstSection->CurrentLine->NormalLine );
}
fprintf( DifferenceFile, "LINE ABSENT IN COMP. FILE (GOLDEN FILE LINE CONTENTS) : %s\n",
SecondSection->CurrentLine->NormalLine );
}
fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT SECTION END SYNCH. FAILURE\n" );
fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n",
SecondSection->Control.SectionIdentifier );
fprintf( DifferenceFile, "\tCOMP. FILE : %s\n",
FirstSection->File->FileName );
fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n",
FirstSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n",
FirstSection->File->CurrentFileLine );
fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n",
SecondSection->File->FileName );
fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n",
SecondSection->Control.SectionLineCount );
fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n",
SecondSection->File->CurrentFileLine );
break;
default :
fprintf( DifferenceFile, "\n\nUNKNOWN COMPARISON RESULT: %u\n", ReturnResult );
break;
}
}
VOID
PrintSectionInformation(
PSECTION Section,
FILE *DifferenceFile
)
{
fprintf( DifferenceFile, "FILE NAME : %s\n" , Section->File->FileName );
fprintf( DifferenceFile, "SECTION ID : %f\n" , Section->Control.SectionIdentifier );
fprintf( DifferenceFile, "SECTION OFFSET LINE# : %u\n", Section->Control.SectionLineCount );
fprintf( DifferenceFile, "SECTION LINE CONTENTS: %s\n" , Section->CurrentLine->NormalLine );
}
DOUBLE
ExtractSectionIDFromLine(
PSECTION Section
)
{
PCHAR TmpBuffer;
//
// Examine for -SECTION_START-
//
TmpBuffer = strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_START] );
if ( TmpBuffer != (PCHAR)NULL ) {
TmpBuffer += (strlen( Keywords[SECTION_START] )+1);
return (DOUBLE)(atof( TmpBuffer ));
}
//
// Examine for -SECTION_END-
//
TmpBuffer = strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_END] );
if ( TmpBuffer != (PCHAR)NULL ) {
TmpBuffer += (strlen( Keywords[SECTION_END] )+1);
return (DOUBLE)(atof( TmpBuffer ));
}
return (DOUBLE)0;
}
BOOLEAN
CheckSectionIDFromCurrentLines(
PSECTION FirstSection,
PSECTION SecondSection )
{
DOUBLE SectionID_1, SectionID_2;
SectionID_1 = ExtractSectionIDFromLine( FirstSection );
SectionID_2 = ExtractSectionIDFromLine( SecondSection );
if ( ( SectionID_1 != SectionID_2 ) ||
( SectionID_1 == (DOUBLE)0 ) ||
( SectionID_2 == (DOUBLE)0 ) ) {
return FALSE;
}
return TRUE;
}
BOOLEAN
CompareLinesAndPrintResults(
PSECTION FirstSection,
PSECTION SecondSection,
PULONG ErrorCount,
FILE *DifferenceFile
)
{
RESULT ComparisonResult;
ComparisonResult = CompareLines( FirstSection, SecondSection );
if ( ComparisonResult != COMPARE_SUCCESS ) {
//
// Increment the section error count
//
(*ErrorCount)++ ;
PrintComparisonResults( FirstSection,
SecondSection,
ComparisonResult,
*ErrorCount,
DifferenceFile );
}
return TRUE;
}
VOID
TokenInsertInSection(
PSECTION Section
)
{
PTOKEN_LIST Token;
ULONG MaxLineCount;
ULONG MinLineCount;
//
// A safe way of determining if the maximum line which will generate a valid token
// is <= 0xfffffff
//
if( Section->Control.TokenMatchStartLine > (TOKEN_MATCHING_ALL - Section->Control.TokenMatchStopLine ) ) {
MaxLineCount = TOKEN_MATCHING_ALL;
} else {
MaxLineCount = Section->Control.TokenMatchStartLine +
Section->Control.TokenMatchStopLine ;
}
MinLineCount = Section->Control.TokenMatchStartLine;
//
// First examine if the current line has not exceeded the Maximum StopLine AND is also greater
// than the minimum line count. Because of this condition, it becomes a valid token
//
if( ( Section->Control.SectionLineCount <= MaxLineCount ) &&
( Section->Control.SectionLineCount >= MinLineCount ) ) {
//
// Create a TOKEN and link it into the section control
//
Token = (PTOKEN_LIST)calloc( 1, sizeof( TOKEN_LIST ) );
if ( Token == (PTOKEN_LIST)NULL ) {
printf( "The system has run out of memory resources\n" );
exit( -1 );
}
//
// Initialize this token and insert it into the unmatched list
//
strncpy( Token->NormalToken,
Section->CurrentLine->NormalLine,
Section->CurrentLine->NormalLineSize );
strncpy( Token->CompressedToken,
Section->CurrentLine->CompressedLine,
Section->CurrentLine->CompressedLineSize );
Token->LinePosition = Section->Control.SectionLineCount;
Token->FileLinePosition = Section->File->CurrentFileLine ;
Token->TokenState = TOKEN_UNMATCHED;
Token->NextToken = NULL;
InsertToken( Token, Section->Control.HeadUnmatchedTokens );
}
}
RESULT
MatchTopToken(
PTOKEN_LIST BaseList,
PTOKEN_LIST ComparisonList
)
{
PTOKEN_LIST CurrentToken ;
INT Length ;
CurrentToken = ComparisonList;
//
// Check if the Base Token under comparison is a possible MAY_DIFFER
//
if ( strstr( BaseList->CompressedToken, "MAY_DIFFER" ) != NULL ) {
return COMPARE_SUCCESS;
}
//
// Walk down the token chain list looking for a match. Note if the token has been
// matched before, it is marked so and hence cannot be reused
//
Length = strlen( BaseList->CompressedToken );
while ( CurrentToken != (PTOKEN_LIST )NULL ) {
if ( ( CurrentToken->TokenState == TOKEN_UNMATCHED ) &&
( strncmp( BaseList->CompressedToken, CurrentToken->CompressedToken, Length ) == 0 )
) {
//
// Found a match
//
CurrentToken->TokenState = TOKEN_MATCHED;
return COMPARE_SUCCESS;
}
CurrentToken = CurrentToken->NextToken;
}
return COMPARE_TOKEN;
}
VOID
CompareTokensAndPrintResults(
PSECTION FirstSection,
PSECTION SecondSection,
PULONG ErrorCount,
FILE *DifferenceFile
)
{
RESULT ComparisonResult;
PTOKEN_LIST Tmp;
//
// The base set for comparison will always come from the second file(golden file)
//
//
// And now search for matches for the individual tokens from the base set
//
while ( SecondSection->Control.HeadUnmatchedTokens != (PTOKEN_LIST)NULL ) {
ComparisonResult = MatchTopToken( SecondSection->Control.HeadUnmatchedTokens,
FirstSection->Control.HeadUnmatchedTokens );
if ( ComparisonResult != COMPARE_SUCCESS ) {
(*ErrorCount)++ ;
PrintComparisonResults( FirstSection,
SecondSection,
ComparisonResult,
*ErrorCount,
DifferenceFile );
}
//
// And now destroy this token from the base list
//
Tmp =
SecondSection->Control.HeadUnmatchedTokens;
SecondSection->Control.HeadUnmatchedTokens =
SecondSection->Control.HeadUnmatchedTokens->NextToken;
DestroyToken( Tmp );
}
//
// Finally cleanup the tokens on the compared section
//
while ( FirstSection->Control.HeadUnmatchedTokens != (PTOKEN_LIST)NULL ) {
Tmp =
FirstSection->Control.HeadUnmatchedTokens;
FirstSection->Control.HeadUnmatchedTokens =
FirstSection->Control.HeadUnmatchedTokens->NextToken;
DestroyToken( Tmp );
}
}
BOOLEAN
MayDifferExistsInOneOrMoreLines(
PSECTION FirstSection,
PSECTION SecondSection
)
{
if ( ( strstr( FirstSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) ||
( strstr( SecondSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) ) {
//
// Token matching is a special case. Since we care only about the second
// section since that is the golden section, we make another exception
// and not check for the first section
//
if ( SecondSection->Control.TokenMatching == TRUE ) {
if ( strstr( SecondSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) == NULL ) {
//
// This implies that the firstsection line had a MAY_DIFFER in it and the second
// section did not
//
// Now check the line type
//
TokenInsertInSection( FirstSection );
if ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) {
TokenInsertInSection( SecondSection );
}
} else {
//
// The secondsection had a MAY_DIFFER in it
//
TokenInsertInSection( SecondSection );
if ( strstr( FirstSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) == NULL ) {
//
// The FirstSection did not have a MAY_DIFFER in it
//
if ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) {
TokenInsertInSection( FirstSection );
}
} else {
//
// At this point we have determined that both lines contained MAY_DIFFER
// in them
//
TokenInsertInSection( FirstSection );
}
}
}
return TRUE;
}
return FALSE;
}
BOOLEAN
DoNotSkipThisLine(
PSECTION Section
)
{
CHAR *SpecialLine = "[TPCTL:]";
//
// This function is responsible for informing the calling function to skip lines
// should it detect the presence of the keyword SKIP_LINE or match the compressed
// line with the special line. This can be later extented to cover special lines
//
if ( ( strstr( Section->CurrentLine->CompressedLine, "SKIP_LINE" ) == NULL ) &&
( strcmp( Section->CurrentLine->CompressedLine, SpecialLine ) != 0 ) &&
( strlen( Section->CurrentLine->CompressedLine ) != 0 ) ) {
return TRUE;
}
return FALSE;
}