mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
|
|
}
|