summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/testprot/tpdiff
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/testprot/tpdiff
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/makefile11
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/sources63
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/tpdiff.c2527
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/tpdiff.h213
-rw-r--r--private/ntos/ndis/testprot/tpdiff/makefile6
-rw-r--r--private/ntos/ndis/testprot/tpdiff/sources48
-rw-r--r--private/ntos/ndis/testprot/tpdiff/tpdiff.c1749
7 files changed, 4617 insertions, 0 deletions
diff --git a/private/ntos/ndis/testprot/tpdiff.new/makefile b/private/ntos/ndis/testprot/tpdiff.new/makefile
new file mode 100644
index 000000000..99bdba8ee
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff.new/makefile
@@ -0,0 +1,11 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+
+cleanup:
+ if exist *.bak del *.bak
+ if exist build.* del build.*
diff --git a/private/ntos/ndis/testprot/tpdiff.new/sources b/private/ntos/ndis/testprot/tpdiff.new/sources
new file mode 100644
index 000000000..7667196a8
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff.new/sources
@@ -0,0 +1,63 @@
+!IF 0
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+!ENDIF
+
+
+# COMMENT: The build "SOURCE" file follows the same syntax as a regular
+# makefile. BUILD includes the SOURCES file into the makefile.def
+# which is to be found in $(BASEDIR)\public\oak\bin. After that
+# has been completed, it passes it on to nmake
+
+
+MAJORCOMP=TESTPROT
+MINORCOMP=TPDIFF
+
+TARGETNAME=tpdiff
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+C_DEFINES=-DWIN32
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\libc.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+
+
+SOURCES=tpdiff.c
+
+
+#
+# 386
+#
+386_WARNING_LEVEL=-W3
+386_STDCALL=1
+386_OPTIMIZATION=/Fc
+MAX_ID_LENGTH=/H128
+
+#
+# MIPS
+#
+MIPS_FLAGS=-D_stdcall=
+
+#
+# ALPHA
+#
+ALPHA_FLAGS=-D_stdcall=
+
+
+UMTYPE=console
+NTDEBUG=ntsd
diff --git a/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c
new file mode 100644
index 000000000..3141ef7c5
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c
@@ -0,0 +1,2527 @@
+/*++
+
+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;
+
+}
diff --git a/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h
new file mode 100644
index 000000000..a811a8a97
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h
@@ -0,0 +1,213 @@
+#define MULTIPLIER sizeof(ULONG)
+#define MAX_LINE_SIZE 64*MULTIPLIER
+#define MAX_SECTION_DESC_SIZE 64*MULTIPLIER
+#define MAX_RESULTS_COUNT 32
+#define UCHAR_REMAINDER (MULTIPLIER-sizeof(UCHAR))
+
+
+#define SECTION_START 0
+#define SECTION_END 1
+#define OPTIONALS 2
+#define TOKEN_MATCH 3
+#define SECTION_DESC 4
+
+#define LINE_TYPE_SECTION_START ((UCHAR)1)
+#define LINE_TYPE_SECTION_END ((UCHAR)2)
+#define LINE_TYPE_REGULAR ((UCHAR)3)
+
+
+#define SECTIONHDR_SECTIONHDR ((UCHAR)1)
+#define SECTIONHDR_SECTIONEND ((UCHAR)2)
+#define SECTIONHDR_REGLINE ((UCHAR)3)
+#define SECTIONEND_SECTIONEND ((UCHAR)4)
+#define SECTIONEND_REGLINE ((UCHAR)5)
+#define REGLINE_REGLINE ((UCHAR)6)
+
+
+#define COMPARE_SUCCESS 0x0UL
+#define COMPARE_EQUAL_LAST 0x1UL
+#define COMPARE_LINE 0x2UL
+#define COMPARE_START 0x3UL
+#define COMPARE_END 0x4UL
+#define COMPARE_TOKEN 0x5UL
+#define COMPARE_BETWEEN_VALUES 0x6UL
+
+#define RESULTS_EQUAL ((UCHAR)0)
+#define RESULTS_UNEQUAL ((UCHAR)1)
+#define RESULTS_NOT_PRESENT ((UCHAR)2)
+#define RESULTS_MINMAX ((UCHAR)3)
+
+
+#define TOKEN_MATCHING_ALL 0xFFFFFFFF
+#define TOKEN_UNMATCHED 0x0UL
+#define TOKEN_MATCHED 0x1UL
+
+
+#if !( defined(lint) || defined(_lint) )
+#if i386
+#pragma warning(disable:4103)
+#endif
+#pragma pack(1)
+#endif
+
+
+typedef ULONG RESULT;
+typedef double DOUBLE;
+
+typedef struct _MFILE {
+
+ ULONG CurrentFileLine;
+ PCHAR FileName;
+ FILE *FileP ;
+
+} MFILE, *PMFILE;
+
+
+typedef struct _LINE {
+
+ UINT NormalLineSize ;
+ UINT CompressedLineSize ;
+
+ CHAR NormalLine[MAX_LINE_SIZE] ;
+ CHAR CompressedLine[MAX_LINE_SIZE];
+
+ UCHAR LineType ;
+ UCHAR Padding[UCHAR_REMAINDER] ;
+
+} LINE, *PLINE;
+
+
+typedef struct _TOKEN_LIST {
+
+ ULONG LinePosition ;
+ ULONG FileLinePosition ;
+ ULONG TokenState ;
+
+ struct _TOKEN_LIST *NextToken ;
+
+ CHAR NormalToken[MAX_LINE_SIZE] ;
+ CHAR CompressedToken[MAX_LINE_SIZE];
+
+} TOKEN_LIST, *PTOKEN_LIST;
+
+typedef struct _SECTION_CONTROL {
+
+ ULONG SectionLineCount ;
+ ULONG TokenMatchStartLine;
+ ULONG TokenMatchStopLine ;
+
+ PTOKEN_LIST HeadUnmatchedTokens;
+
+ DOUBLE SectionIdentifier ;
+
+ BOOLEAN OptionalMatching ;
+ BOOLEAN TokenMatching ;
+ BOOLEAN BaseControlSection ;
+ BOOLEAN Padding ;
+
+} SECTION_CONTROL, *PSECTION_CONTROL;
+
+typedef struct _SECTION {
+
+ RESULT LastResults[MAX_RESULTS_COUNT] ;
+ RESULT CurrentResults[MAX_RESULTS_COUNT] ;
+ ULONG NumberOfLastResults ;
+ ULONG NumberOfCurrentResults ;
+ UCHAR ResultsError[MAX_RESULTS_COUNT] ;
+
+ RESULT MinimumValue ;
+ RESULT MaximumValue ;
+
+ PMFILE File;
+ PLINE CurrentLine;
+
+ SECTION_CONTROL Control;
+
+ CHAR SectionDescription[MAX_SECTION_DESC_SIZE];
+
+
+} SECTION, *PSECTION;
+
+
+typedef struct _FUNCTION_ELEMENTS {
+
+ ULONG ErrorCount ;
+
+ PSECTION NewFirstSection ;
+ PSECTION NewSecondSection ;
+
+ DOUBLE FirstSectionID ;
+ DOUBLE SecondSectionID ;
+
+ BOOLEAN FirstSectionSynchronize ;
+ BOOLEAN SecondSectionSynchronize ;
+ BOOLEAN SectionEndsNotSynchronized;
+ BOOLEAN SkipLine ;
+
+ LINE FirstSectionCurrentLine ;
+ LINE SecondSectionCurrentLine ;
+
+ UCHAR CombinedLineVariation ;
+ UCHAR Padding[UCHAR_REMAINDER] ;
+
+} FUNCTION_ELEMENTS, *PFUNCTION_ELEMENTS;
+
+#if !( defined(lint) || defined(_lint) )
+#if i386
+#pragma warning(disable:4103)
+#endif
+#pragma pack()
+#endif
+
+
+
+
+//
+// MACROS
+//
+#define CloseFiles( a, b ) { \
+ if ( a.FileP != (FILE *)NULL ) fclose( a.FileP ); \
+ if ( b.FileP != (FILE *)NULL ) fclose( b.FileP ); \
+ }
+
+#define CreateSection() calloc( 1, sizeof( SECTION ) )
+#define DestroySection( a ) free( a )
+#define ClearAndSetLine( a, b ) { memset( (b), 0, sizeof( LINE ) ); (a)->CurrentLine = (b); }
+#define CreateFunctionElements() calloc( 1, sizeof( FUNCTION_ELEMENTS ) )
+#define DestroyFunctionElements( a ) free( a )
+
+#define InsertToken( a, b ) { \
+ a->NextToken = b; \
+ b = a; \
+ }
+#define DestroyToken( a ) free( a )
+
+
+
+//
+// Function definitions
+//
+VOID _cdecl main ( INT , CHAR ** );
+VOID Usage ( VOID );
+BOOLEAN GetFilePair ( PCHAR * , PCHAR * , PCHAR );
+BOOLEAN CompareFiles ( PMFILE , PMFILE , FILE * , ULONG * );
+BOOLEAN OpenFiles ( PMFILE , PCHAR , PMFILE , PCHAR );
+BOOLEAN CompareFiles ( PMFILE , PMFILE , FILE * , PULONG );
+BOOLEAN CompareSections ( PSECTION, PSECTION, FILE * , PULONG );
+BOOLEAN GetNextLine ( PSECTION );
+BOOLEAN DoNotSkipThisLine ( PSECTION );
+VOID LineType ( PSECTION );
+BOOLEAN ExtractResults ( PSECTION );
+BOOLEAN ExtractBetweenValues ( PSECTION );
+BOOLEAN CombinedVariation ( PSECTION, PSECTION, PUCHAR );
+RESULT CompareLines ( PSECTION, PSECTION );
+BOOLEAN InitializeSectionControl ( PSECTION, PSECTION );
+VOID PrintComparisonResults ( PSECTION, PSECTION, RESULT , ULONG , FILE * );
+VOID PrintSectionInformation ( PSECTION, FILE * );
+DOUBLE ExtractSectionIDFromLine ( PSECTION );
+BOOLEAN CheckSectionIDFromCurrentLines ( PSECTION, PSECTION );
+BOOLEAN CompareLinesAndPrintResults ( PSECTION, PSECTION, PULONG , FILE * );
+VOID TokenInsertInSection ( PSECTION );
+RESULT MatchTopToken ( PTOKEN_LIST, PTOKEN_LIST );
+VOID CompareTokensAndPrintResults ( PSECTION, PSECTION, PULONG , FILE * );
+BOOLEAN MayDifferExistsInOneOrMoreLines( PSECTION, PSECTION );
diff --git a/private/ntos/ndis/testprot/tpdiff/makefile b/private/ntos/ndis/testprot/tpdiff/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/testprot/tpdiff/sources b/private/ntos/ndis/testprot/tpdiff/sources
new file mode 100644
index 000000000..ca52757fa
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=testprot
+MINORCOMP=tpdiff
+
+TARGETNAME=tpdiff
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=..\..\wrapper;..\inc;..\..\..\inc
+
+SOURCES=tpdiff.c
+
+i860_SOURCES=
+
+i386_SOURCES=
+
+MIPS_SOURCES=
+
+RELATIVE_DEPTH=..\..\..
+NTTEST=
+OPTIONAL_NTTEST=
+
+UMTYPE=console
+UMAPPL=tpdiff
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\setargv.obj
diff --git a/private/ntos/ndis/testprot/tpdiff/tpdiff.c b/private/ntos/ndis/testprot/tpdiff/tpdiff.c
new file mode 100644
index 000000000..739227889
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdiff/tpdiff.c
@@ -0,0 +1,1749 @@
+/*++
+
+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:
+
+ Tom Adams (tomad) 2-Apr-1992
+
+Revision History:
+
+ 2-Apr-1992 tomad
+
+ created
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+//
+// TpDiff function prototypes
+//
+
+DWORD
+TpDiffInitializeFiles(
+ IN WORD argc,
+ IN LPSTR argv[]
+ );
+
+VOID
+TpDiffFreeFiles(
+ VOID
+ );
+
+
+DWORD
+TpDiffInitLogFileList(
+ IN LPSTR LogFileList
+ );
+
+VOID
+TpDiffFreeLogFileList(
+ VOID
+ );
+
+DWORD
+TpDiffLoadNextLogFilePair(
+ VOID
+ );
+
+DWORD
+TpDiffOpenLogFiles(
+ VOID
+ );
+
+VOID
+TpDiffFreeLogFiles(
+ VOID
+ );
+
+DWORD
+TpDiffInitDiffFile(
+ IN LPSTR DiffFile
+ );
+
+DWORD
+TpDiffWriteToDiffFile(
+ IN LPSTR Buffer
+ );
+
+DWORD
+TpDiffWriteErrorToDiffFile(
+ IN LPSTR Buffer
+ );
+
+
+VOID
+TpDiffFreeDiffFile(
+ VOID
+ );
+
+DWORD
+TpDiffCompareLogFiles(
+ VOID
+ );
+
+DWORD
+TpDiffGetNextLine(
+ IN PBYTE Buffer,
+ IN PDWORD BufOffSet,
+ IN DWORD BufSize,
+ IN PDWORD LineNumber,
+ OUT PBYTE Line
+ );
+
+DWORD
+TpDiffGetResults(
+ IN PBYTE Buffer
+ );
+
+BOOL
+TpDiffMayValuesDiffer(
+ IN PBYTE Buffer
+ );
+
+BOOL
+TpDiffMustLastTwoValuesEqual(
+ IN PBYTE Buffer
+ );
+
+VOID
+TpDiffUsage (
+ VOID
+ );
+
+//
+// TpDiff Global variables
+//
+
+BYTE LogFileListName[256];
+BYTE LogFileName[256];
+BYTE KnownLogFileName[256];
+BYTE DiffFileName[256];
+
+HANDLE DiffFileHandle = NULL;
+
+PBYTE LogFileListBuffer = NULL;
+DWORD LogFileListSize = 0;
+DWORD LogFileListOffset = 0;
+
+PBYTE LogFileBuffer = NULL;
+DWORD LogFileSize = 0;
+DWORD LogFileOffset;
+DWORD LogFileLineNumber;
+
+PBYTE KnownLogFileBuffer = NULL;
+DWORD KnownLogFileSize = 0;
+DWORD KnownLogFileOffset;
+DWORD KnownLogFileLineNumber;
+
+PBYTE DiffBuffer = NULL;
+BOOL LoggingToScreen = FALSE;
+
+BOOL MoreFilesToDiff = FALSE;
+
+BYTE LogFileLine[256];
+BYTE KnownLogFileLine[265];
+
+DWORD ResultsValue = 0;
+DWORD LastResultsValue = 0;
+
+DWORD LogFileDifferences = 0;
+DWORD TotalDifferences = 0;
+
+//
+// the main routine for TpDiff.
+//
+
+
+VOID _cdecl
+main(
+ IN WORD argc,
+ IN LPSTR argv[]
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ IN WORD argc - Supplies the number of parameters
+ IN LPSTR argv[] - Supplies the parameter list.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD Status;
+
+ //
+ // Read the command line, and open the requested files and set
+ // them up to be processed.
+ //
+
+ Status = TpDiffInitializeFiles( argc,argv );
+
+ if ( Status != NO_ERROR ) {
+ ExitProcess( Status );
+ }
+
+ //
+ // We have at least two files to compare so ...
+ //
+
+ do {
+
+ //
+ // Compare the LOG_FILE and KNOWN_LOG_FILE.
+ //
+
+ Status = TpDiffCompareLogFiles();
+
+ if ( Status != NO_ERROR ) {
+ break;
+ }
+
+ //
+ // Then see if there are any more files to compare.
+ //
+
+ Status = TpDiffLoadNextLogFilePair();
+
+ if ( Status != NO_ERROR ) {
+ break;
+ }
+
+ //
+ // and if so open them, and set up their respective buffers
+ // to be compared.
+ //
+
+ Status = TpDiffOpenLogFiles();
+
+ if (( Status == ERROR_FILE_NOT_FOUND ) &&
+ ( MoreFilesToDiff == TRUE )) {
+
+ //
+ // We failed to open one of the logs files due to the fact
+ // that it did not exist, AND we are reading from a list of
+ // log/known log file pairs. We should get the next pair
+ // and try to open them.
+ //
+
+ do {
+
+ Status = TpDiffLoadNextLogFilePair();
+
+ if ( Status != NO_ERROR ) {
+ break;
+ }
+
+ Status = TpDiffOpenLogFiles();
+
+ if (( Status != NO_ERROR ) &&
+ ( Status != ERROR_FILE_NOT_FOUND )) {
+ break;
+ }
+
+ } while (( MoreFilesToDiff == TRUE ) &&
+ ( Status == ERROR_FILE_NOT_FOUND ));
+
+ if ( Status != NO_ERROR ) {
+ break;
+ }
+ } else if ( Status != NO_ERROR ) {
+ break;
+ }
+
+ } while ( MoreFilesToDiff == TRUE );
+
+ printf("\n\tTpDiff Pass Contained %d Total Differences.\n",TotalDifferences);
+
+ if ( LoggingToScreen == FALSE ) {
+
+ LPSTR TmpBuf = DiffBuffer;
+
+ TmpBuf += (BYTE)sprintf(TmpBuf,"\nTpDiff: Contained %d Total Differences.\n",
+ TotalDifferences);
+
+ Status = TpDiffWriteToDiffFile( TmpBuf );
+
+ if ( Status != NO_ERROR ) {
+ printf("\n\tTpDiff: failed to write statistics to logfile, return %d\n",
+ Status);
+ }
+ }
+
+ //
+ // Free all the files handles, and buffers previously allocated.
+ //
+
+ TpDiffFreeFiles();
+
+ ExitProcess( (DWORD)NO_ERROR );
+}
+
+
+DWORD
+TpDiffInitializeFiles(
+ IN WORD argc,
+ IN LPSTR argv[]
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the command line arguments, and opens the files
+ that are passed in on the command line.
+
+Arguments:
+
+ IN WORD argc - Supplies the number of arguments passed in at startup.
+
+ IN LPTSTR argv[] - Supplies the argument vector containing the arguments
+ passed in from the command line.
+
+Return Value:
+
+ DWORD - NO_ERROR if all the arguments are valid and the files are opened
+ successfully. If the files fail to open, then the error returned
+ from the open routines are returned. ERROR_INALID_PARAMETER
+ otherwise.
+
+--*/
+
+{
+ DWORD Status;
+
+ //
+ // See if we have enough arguments on the commmand line.
+ //
+
+ if ( argc == 1 ) {
+ TpDiffUsage();
+ return ERROR_INVALID_PARAMETER;
+ } else if (( argc != 4 ) && ( argc != 3 )) {
+ printf("\n\tTpDiff: ERROR - Invalid number of arguments\n");
+ TpDiffUsage();
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Is the first argument a LOG_FILE_NAME or the LOG_FILES_LIST switch ?
+ //
+
+ if (!strcmp(argv[1],"-f")) {
+
+ //
+ // It is the LOG_FILES_LIST switch. We need four arguments for
+ // this case, so make sure we have them.
+
+ if ( argc != 4 ) {
+ printf("\n\tTpDiff: ERROR - Invalid number of arguments\n");
+ TpDiffUsage();
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // It is the LOG_FILES_LIST switch. First set the flag indicating
+ // that there are possible more then one pair of files to diff.
+ //
+
+ MoreFilesToDiff = TRUE;
+
+ //
+ // We have a file containing the logfile/knownlogfile name pairs.
+ // Set up the name to be opened, and then open it now and read
+ // the contents.
+ //
+
+ Status = TpDiffInitLogFileList( argv[2] );
+
+ if ( Status != NO_ERROR ) {
+ return Status;
+ }
+
+ //
+ // Now read the first file pair from the list. The names
+ // will be stored in the global vars LogFileName and
+ // KnownLogFileName.
+ //
+
+ Status = TpDiffLoadNextLogFilePair();
+
+ if ( Status != NO_ERROR ) {
+ return Status;
+ }
+ } else {
+
+ //
+ // We have been passed two files to diff. set up the names to
+ // be opened.
+ //
+
+ strcpy( LogFileName,argv[1] );
+ strcpy( KnownLogFileName,argv[2] );
+ }
+
+ //
+ // Now open the first two log files to diff. The file handles will be
+ // stored in the global vars LogFileNameHandle and KnownLogFileNameHandle.
+ //
+
+ Status = TpDiffOpenLogFiles();
+
+ if (( Status == ERROR_FILE_NOT_FOUND ) &&
+ ( MoreFilesToDiff == TRUE )) {
+
+ //
+ // We failed to open one of the logs files due to the fact
+ // that it did not exist, AND we are reading from a list of
+ // log/known log file pairs. We should get the next pair
+ // and try to open them.
+ //
+
+ do {
+
+ Status = TpDiffLoadNextLogFilePair();
+
+ if ( Status != NO_ERROR ) {
+ break;
+ }
+
+ Status = TpDiffOpenLogFiles();
+
+ if (( Status != NO_ERROR ) &&
+ ( Status != ERROR_FILE_NOT_FOUND )) {
+ break;
+ }
+
+ } while (( MoreFilesToDiff == TRUE ) &&
+ ( Status == ERROR_FILE_NOT_FOUND ));
+
+ if ( Status != NO_ERROR ) {
+ return Status;
+ }
+ } else if ( Status != NO_ERROR ) {
+ return Status;
+ }
+
+ //
+ // Finally setup the results file name and open it. This is the file
+ // any differences between the two log files will be written to.
+ //
+
+ Status = TpDiffInitDiffFile( argv[3] );
+
+ if ( Status != NO_ERROR ) {
+ return Status;
+ }
+
+ return NO_ERROR;
+}
+
+
+VOID
+TpDiffFreeFiles(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine closes all open file handles and frees any corresponding
+ buffers.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Free the LOG_FILE_LIST resources.
+ //
+
+ TpDiffFreeLogFileList();
+
+ //
+ // Free the LOG_FILE and KNOWN_LOG_FILE resources.
+ //
+
+ TpDiffFreeLogFiles();
+
+ //
+ // Free the DIFF_FILE resources.
+ //
+
+ TpDiffFreeDiffFile();
+}
+
+
+DWORD
+TpDiffInitLogFileList(
+ IN LPSTR LogFileList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens and reads the LOG_FILE_LIST file into a newly
+ allocated buffer. The handle, buffer and filename are all attached
+ to global LOG_FILE_LIST variables.
+
+Arguments:
+
+ IN LPSTR LogFileList - Supplies the name of the LOG_FILE_LIST file
+ to open.
+
+Return Value:
+
+ DWORD - If NO_ERROR the file was opened and read into the buffer.
+ otherwise there was a failure that will cause the application
+ to un-initialize and exit.
+
+--*/
+
+{
+ DWORD Status;
+ HANDLE LogFileListHandle = NULL;
+ HANDLE LogFileListMapHandle = NULL;
+
+ //
+ // First Open the LOG_FILE_LIST file.
+ //
+
+ strcpy( LogFileListName,LogFileList );
+
+ LogFileListHandle = CreateFile(
+ LogFileListName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if ( LogFileListHandle == (HANDLE)-1 ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Failed to open LOG_FILE_LIST \"%s\", returned %ld.\n",
+ LogFileListName,Status);
+ return Status;
+ }
+
+ //
+ // then find its size.
+ //
+
+ LogFileListSize = GetFileSize( LogFileListHandle,NULL );
+
+ if ( LogFileListSize == -1 ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: failed find LOG_FILE_LIST size, returned %ld.\n",Status);
+ CloseHandle( LogFileListHandle );
+ return Status;
+ } else if ( LogFileListSize == 0 ) {
+ printf("\n\tTpDiff: LOG_FILE_LIST is empty, nothing to compare.\n");
+ CloseHandle( LogFileListHandle );
+ return ERROR_FILE_NOT_FOUND;
+ }
+
+ //
+ // and create a file mapping.
+ //
+
+ LogFileListMapHandle = CreateFileMapping(
+ LogFileListHandle,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ LogFileListSize,
+ NULL
+ );
+
+ if ( LogFileListMapHandle == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map LOG_FILE_LIST \"%s\", returned %d",
+ LogFileListName,Status);
+ CloseHandle( LogFileListHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the file handle so close it now.
+ //
+
+ CloseHandle( LogFileListHandle );
+
+ //
+ // Now create a View of the mapped file.
+ //
+
+ LogFileListBuffer = MapViewOfFile(
+ LogFileListMapHandle,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ LogFileListSize
+ );
+
+ if ( LogFileListBuffer == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map view of LOG_FILE_LIST \"%s\", returned %d",
+ LogFileListName,Status);
+ CloseHandle( LogFileListMapHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the map handle so close it now.
+ //
+
+ CloseHandle( LogFileListMapHandle );
+
+ return NO_ERROR;
+}
+
+
+VOID
+TpDiffFreeLogFileList(
+ VOID
+ )
+{
+ //
+ // Simply UnMap the log file list buffer and null it out.
+ //
+
+ if ( LogFileListBuffer != NULL ) {
+ UnmapViewOfFile( LogFileListBuffer );
+ LogFileListBuffer = NULL;
+ }
+}
+
+
+DWORD
+TpDiffLoadNextLogFilePair(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the next two log file names from the log file list
+ buffer and moves the log file list pointer past them. The format of
+ the log file list is pairs of LOG_FILE_NAME KNOWN_LOG_FILE_NAME with
+ each pair residing on the same line in the file.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ DWORD - NO_ERROR if the next two files are found, ERROR_INVALID_PARAMETER
+ if the log file list is the wrong format.
+
+--*/
+
+{
+ DWORD TmpOffset;
+ DWORD Length;
+
+ //
+ // If we are not reading files from a loglistfile the MoreFilesToDiff
+ // flag will be set to FALSE, so just return.
+ //
+
+ if ( MoreFilesToDiff == FALSE ) {
+ return ERROR_NO_MORE_FILES;
+ }
+
+ //
+ // Move the LOG_FILE_LIST pointer to the beginning of the next
+ // file name in the list.
+ //
+
+ while ((((( LogFileListBuffer[LogFileListOffset] == ' ' ) ||
+ ( LogFileListBuffer[LogFileListOffset] == '\t')) ||
+ ( LogFileListBuffer[LogFileListOffset] == '\r')) ||
+ ( LogFileListBuffer[LogFileListOffset] == '\n')) &&
+ ( LogFileListOffset < LogFileListSize )) {
+
+ LogFileListOffset++;
+ }
+
+ if ( LogFileListOffset == LogFileListSize ) {
+ LogFileName[0] = '\0';
+ KnownLogFileName[0] = '\0';
+ return ERROR_NO_MORE_FILES;
+ }
+
+ //
+ // then find the length of the next file name.
+ //
+
+ Length = 0;
+ TmpOffset = LogFileListOffset;
+
+ while ((((( LogFileListBuffer[TmpOffset] != ' ' ) &&
+ ( LogFileListBuffer[TmpOffset] != '\t' )) &&
+ ( LogFileListBuffer[TmpOffset] != '\r')) &&
+ ( LogFileListBuffer[TmpOffset] != '\n')) &&
+ ( TmpOffset < LogFileListSize )) {
+
+ Length++;
+ TmpOffset++;
+ }
+
+ //
+ // copy it to the global var LogFileName, and null terminate it.
+ //
+
+ strncpy( LogFileName,&LogFileListBuffer[LogFileListOffset],Length );
+
+ LogFileName[Length] = '\0';
+
+ //
+ // then move the LOG_FILE_LIST pointer past the LogFileName
+ //
+
+ LogFileListOffset = TmpOffset + 1;
+
+ //
+ // and search to the beginning of the next file name
+ //
+
+ while ((( LogFileListBuffer[LogFileListOffset] == ' ' ) ||
+ ( LogFileListBuffer[LogFileListOffset] == '\t' )) &&
+ ( LogFileListOffset < LogFileListSize )) {
+
+ LogFileListOffset++;
+
+ if (( LogFileListBuffer[LogFileListOffset] == '\n' ) ||
+ ( LogFileListBuffer[LogFileListOffset] == '\r' )) {
+
+ KnownLogFileName[0] = '\0';
+
+ MoreFilesToDiff = FALSE;
+
+ printf("\tTpDiff: ERROR - LOG_FILE_LIST must have filename pairs on\n");
+ printf("\t same line in file.\n");
+
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // then find the length of the next file name.
+ //
+
+ Length = 0;
+ TmpOffset = LogFileListOffset;
+
+ while ((((( LogFileListBuffer[TmpOffset] != ' ' ) &&
+ ( LogFileListBuffer[TmpOffset] != '\t' )) &&
+ ( LogFileListBuffer[TmpOffset] != '\r')) &&
+ ( LogFileListBuffer[TmpOffset] != '\n')) &&
+ ( TmpOffset < LogFileListSize )) {
+
+ Length++;
+ TmpOffset++;
+ }
+
+ //
+ // copy it to the global var KnownLogFileName, and null terminate it.
+ //
+
+ strncpy( KnownLogFileName,&LogFileListBuffer[LogFileListOffset],Length );
+
+ KnownLogFileName[Length] = '\0';
+
+ //
+ // then move the LOG_FILE_LIST pointer past the KnownLogFileName
+ //
+
+ LogFileListOffset = TmpOffset + 1;
+
+ return NO_ERROR;
+}
+
+
+DWORD
+TpDiffOpenLogFiles(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens the file names stored in the global variables
+ LogFileName and KnownLogFile name, creates a buffer for each and
+ reads the file contents into the respective buffer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ DWORD - If NO_ERROR the files were opened and read into the buffers.
+ otherwise there was a failure that will cause the application
+ to un-initialize and exit.
+
+--*/
+
+{
+ DWORD Status;
+ HANDLE LogFileHandle = NULL;
+ HANDLE LogFileMapHandle = NULL;
+ HANDLE KnownLogFileHandle = NULL;
+ HANDLE KnownLogFileMapHandle = NULL;
+
+ //
+ // First open the LOG_FILE file.
+ //
+
+ if (( LogFileName[0] == '\0' ) || ( KnownLogFileName[0] == '\0' )) {
+ return ERROR_NO_MORE_FILES;
+ }
+
+ LogFileHandle = CreateFile(
+ LogFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if ( LogFileHandle == (HANDLE)-1 ) {
+ Status = GetLastError();
+
+ if ( Status == ERROR_FILE_NOT_FOUND ) {
+ TpDiffWriteErrorToDiffFile( "Tpdiff: WARNING - Failed to open LOG_FILE \"" );
+ TpDiffWriteErrorToDiffFile( LogFileName );
+ TpDiffWriteErrorToDiffFile( "\".\n");
+ }
+
+ printf("\n\tTpDiff: Failed to open LOG_FILE \"%s\", returned %ld.\n",
+ LogFileName,Status);
+ return Status;
+ }
+
+ //
+ // then find its size.
+ //
+
+ LogFileSize = GetFileSize( LogFileHandle,NULL );
+
+ if ( LogFileSize == -1 ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: failed find LOG_FILE size - returned %ld.\n",Status);
+ CloseHandle( LogFileHandle );
+ return Status;
+ } else if ( LogFileSize == 0 ) {
+ printf("\n\tTpDiff: LOG_FILE \"%s\" is empty, nothing to compare.\n",LogFileName);
+ CloseHandle( LogFileHandle );
+ return ERROR_NO_MORE_FILES;
+
+ }
+
+ //
+ // and create a file mapping.
+ //
+
+ LogFileMapHandle = CreateFileMapping(
+ LogFileHandle,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ LogFileSize,
+ NULL
+ );
+
+ if ( LogFileMapHandle == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map LOG_FILE \"%s\", returned %d",
+ LogFileName,Status);
+ CloseHandle( LogFileHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the file handle so close it now.
+ //
+
+ CloseHandle( LogFileHandle );
+
+ //
+ // Now create a View of the mapped file.
+ //
+
+ LogFileBuffer = MapViewOfFile(
+ LogFileMapHandle,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ LogFileSize
+ );
+
+ if ( LogFileBuffer == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map view of LOG_FILE \"%s\", returned %d",
+ LogFileName,Status);
+ CloseHandle( LogFileMapHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the map handle so close it now.
+ //
+
+ CloseHandle( LogFileMapHandle );
+
+ //
+ // Now reset the offset into the LogFilebuffer and the line number
+ // counter to zero.
+ //
+
+ LogFileOffset = 0;
+ LogFileLineNumber = 1;
+
+ //
+ // Then open the KNOWN_LOG_FILE file.
+ //
+
+ KnownLogFileHandle = CreateFile(
+ KnownLogFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if ( KnownLogFileHandle == (HANDLE)-1 ) {
+ Status = GetLastError();
+
+ if ( Status == ERROR_FILE_NOT_FOUND ) {
+ TpDiffWriteErrorToDiffFile("TpDiff: WARNING Failed to open KNOWN_LOG_FILE \"");
+ TpDiffWriteErrorToDiffFile(KnownLogFileName);
+ TpDiffWriteErrorToDiffFile("\".\n");
+ }
+
+ printf("\n\tTpDiff: Failed to open KNOWN_LOG_FILE \"%s\", returned %ld.\n",
+ KnownLogFileName,Status);
+ return Status;
+ }
+
+ //
+ // then find its size.
+ //
+
+ KnownLogFileSize = GetFileSize( KnownLogFileHandle,NULL );
+
+ if ( KnownLogFileSize == -1 ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: failed find KNOWN_LOG_FILE size - returned %ld.\n",Status);
+ CloseHandle( KnownLogFileHandle );
+ return Status;
+ } else if ( KnownLogFileSize == 0 ) {
+ printf("\n\tTpDiff: KNOWN_LOG_FILE \"%s\" is empty, nothing to compare.\n",KnownLogFileName);
+ CloseHandle( KnownLogFileHandle );
+ return ERROR_NO_MORE_FILES;
+ }
+
+ //
+ // and create a file mapping.
+ //
+
+ KnownLogFileMapHandle = CreateFileMapping(
+ KnownLogFileHandle,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ KnownLogFileSize,
+ NULL
+ );
+
+ if ( KnownLogFileMapHandle == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map KNOWN_LOG_FILE \"%s\", returned %d",
+ KnownLogFileName,Status);
+ CloseHandle( KnownLogFileHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the file handle so close it now.
+ //
+
+ CloseHandle( KnownLogFileHandle );
+
+ //
+ // Now create a View of the mapped file.
+ //
+
+ KnownLogFileBuffer = MapViewOfFile(
+ KnownLogFileMapHandle,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ KnownLogFileSize
+ );
+
+ if ( KnownLogFileBuffer == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Unable to map view of KNOWN_LOG_FILE \"%s\", returned %d",
+ KnownLogFileName,Status);
+ CloseHandle( KnownLogFileMapHandle );
+ return Status;
+ }
+
+ //
+ // We're done with the map handle so close it now.
+ //
+
+ CloseHandle( KnownLogFileMapHandle );
+
+ //
+ // Now reset the offset into the KnownLogFilebuffer to zero.
+ // and return.
+ //
+
+ KnownLogFileOffset = 0;
+ KnownLogFileLineNumber = 1;
+
+ return NO_ERROR;
+}
+
+
+VOID
+TpDiffFreeLogFiles(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the LOG_FILE and KNOWN_LOG_FILE buffers and
+ nulls their respective pointers.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if ( LogFileBuffer != NULL ) {
+ UnmapViewOfFile( LogFileBuffer );
+ LogFileBuffer = NULL;
+ }
+
+ if ( KnownLogFileBuffer != NULL ) {
+ UnmapViewOfFile( KnownLogFileBuffer );
+ KnownLogFileBuffer = NULL;
+ }
+}
+
+
+DWORD
+TpDiffInitDiffFile(
+ IN LPSTR DiffFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens the DIFF_FILE. The handle and file name are
+ attached to global DIFF_FILE variables. A buffer is also allocated
+ that is used to any output to the DIFF_FILE.
+
+Arguments:
+
+ IN LPSTR DiffFile - Supplies the name of the DIFF_FILE to open.
+
+Return Value:
+
+ DWORD - The Status of the OPEN.
+
+--*/
+
+{
+ DWORD Status;
+
+ //
+ // If a Diff file name was passed in on the command line,
+ // Open the DIFF_FILE file.
+ //
+
+ if ( DiffFile != NULL ) {
+
+ strcpy( DiffFileName,DiffFile );
+
+ DiffFileHandle = CreateFile(
+ DiffFileName,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if ( DiffFileHandle == (HANDLE)-1 ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: Failed to open DIFFS_FILE \"%s\", returned %ld.\n",
+ DiffFileName,Status);
+ return Status;
+ }
+
+ } else { // We will just write the DIFFS to the console.
+
+ DiffFileHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ LoggingToScreen = TRUE;
+ }
+
+ DiffBuffer = GlobalAlloc(
+ GMEM_FIXED | GMEM_ZEROINIT,
+ 0x1000
+ );
+
+ if ( DiffBuffer == NULL ) {
+ Status = GetLastError();
+ printf("\n\tTpDiff: failed to alloc DIFF_FILE buffer, returned %ld.\n",
+ Status);
+
+ if ( strlen( DiffFile ) != 0 ) { // close the diff file
+ CloseHandle( DiffFileHandle );
+ }
+
+ DiffFileHandle = NULL;
+ return Status;
+ }
+
+ return NO_ERROR;
+}
+
+
+DWORD
+TpDiffWriteToDiffFile(
+ IN LPSTR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine simply writes a string to the DIFF_FILE.
+
+Arguments:
+
+ IN LPSTR Buffer - Supplies the string to write to the DIFF_FILE.
+
+Return Value:
+
+ DWORD - The Status of the call to WriteFile.
+
+--*/
+
+
+{
+ DWORD Status;
+ DWORD BytesWritten;
+
+ if ( !WriteFile(
+ DiffFileHandle,
+ DiffBuffer,
+ (Buffer-DiffBuffer),
+ &BytesWritten,
+ NULL
+ )) {
+
+ Status = GetLastError();
+ printf("\n\tTpDiff: Write to DIFFS_FILE failed, returned %ld\n",Status);
+ return Status;
+ }
+
+ return NO_ERROR;
+}
+
+
+DWORD
+TpDiffWriteErrorToDiffFile(
+ IN LPSTR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine simply writes a string to the DIFF_FILE.
+
+Arguments:
+
+ IN LPSTR Buffer - Supplies the string to write to the DIFF_FILE.
+
+Return Value:
+
+ DWORD - The Status of the call to WriteFile.
+
+--*/
+
+
+{
+ DWORD Status;
+ DWORD BytesWritten;
+ DWORD BufLength = 0;
+
+ BufLength = strlen( Buffer );
+
+ if ( !WriteFile(
+ DiffFileHandle,
+ Buffer,
+ BufLength,
+ &BytesWritten,
+ NULL
+ )) {
+
+ Status = GetLastError();
+ printf("\n\tTpDiff: Write to DIFFS_FILE failed, returned %ld\n",Status);
+ return Status;
+ }
+
+ return NO_ERROR;
+}
+
+
+VOID
+TpDiffFreeDiffFile(
+ VOID
+ )
+{
+ //
+ // Close the DIFF_FILE, deallocate the diff buffer, and null out
+ // their pointers.
+ //
+
+ if ( DiffFileHandle != NULL ) {
+
+ if ( strlen( DiffFileName ) != 0 ) {
+ CloseHandle( DiffFileHandle );
+ }
+
+ DiffFileHandle = NULL;
+ }
+
+ if ( DiffBuffer != NULL ) {
+ GlobalFree( DiffBuffer );
+ DiffBuffer = NULL;
+ }
+}
+
+
+DWORD
+TpDiffCompareLogFiles(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This is the main compare routine of the TpDiff utility. It compares the
+ log file and known log file line by line for diffences.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD Status;
+ DWORD Length;
+ DWORD KnownLength;
+ DWORD CmpLength;
+ LPSTR TmpBuf = DiffBuffer;
+
+ printf("\n\tTpDiff: comparing %s and %s ...\n",
+ LogFileName,KnownLogFileName);
+ do {
+
+ //
+ // Get the next line of the Log File.
+ //
+
+ Length = TpDiffGetNextLine(
+ LogFileBuffer,
+ &LogFileOffset,
+ LogFileSize,
+ (PDWORD)&LogFileLineNumber,
+ (PBYTE)&LogFileLine
+ );
+
+ if ( Length != 0 ) {
+
+ //
+ // Get the value of the Statitics results for that line,
+ // first storing away the last lines value.
+ //
+
+ LastResultsValue = ResultsValue;
+
+ ResultsValue = TpDiffGetResults( LogFileLine );
+ }
+
+ //
+ // And the next line of the Known Log File.
+ //
+
+ KnownLength = TpDiffGetNextLine(
+ KnownLogFileBuffer,
+ &KnownLogFileOffset,
+ KnownLogFileSize,
+ (PDWORD)&KnownLogFileLineNumber,
+ (PBYTE)&KnownLogFileLine
+ );
+
+ //
+ // Compare them with respect to the length of the longer of the
+ // two lines.
+ //
+
+ if ( Length >= KnownLength ) {
+ CmpLength = Length;
+ } else {
+ CmpLength = KnownLength;
+ }
+
+ if (( CmpLength != 0 ) &&
+ ( memcmp( LogFileLine,KnownLogFileLine,CmpLength ) != 0 )) {
+
+ if (( TpDiffMayValuesDiffer( LogFileLine )) ||
+ ( TpDiffMayValuesDiffer( KnownLogFileLine ))) {
+
+ //
+ // The line contains a MAY_DIFFER flag, so ignore the
+ // differences.
+ //
+
+ } else if (( TpDiffMustLastTwoValuesEqual( LogFileLine )) &&
+ ( LastResultsValue == ResultsValue )) {
+ } else {
+
+ LogFileDifferences++;
+
+ //
+ // If lines did not match, and the line does not contain the
+ // MAY_DIFFER string, or It contained EQUAL_LAST, but the
+ // stats value weren't equal, then write the info to the
+ // diff file.
+ //
+
+ TmpBuf += (BYTE)sprintf(TmpBuf,"Logfile: %s - Line Number: %ld\n",
+ LogFileName,LogFileLineNumber);
+ TmpBuf += (BYTE)sprintf(TmpBuf,"Found: %s\n",LogFileLine);
+ TmpBuf += (BYTE)sprintf(TmpBuf,"Expected: %s\n\n",KnownLogFileLine);
+
+ if (( TpDiffMustLastTwoValuesEqual( LogFileLine )) &&
+ ( LastResultsValue != ResultsValue )) {
+
+ TmpBuf += (BYTE)sprintf(TmpBuf,"TpDiff: ERROR - The last two test values (%ld) and (%ld) did not equal.\n\n",
+ LastResultsValue,ResultsValue);
+ }
+
+ Status = TpDiffWriteToDiffFile( TmpBuf );
+
+ if ( Status != NO_ERROR ) {
+ printf("\n\tTpDiff: failed to write difference to logfile, return %d\n",
+ Status);
+ return Status;
+ }
+
+ //
+ // and then reset the TmpBuf for the next go round.
+ //
+
+ TmpBuf = DiffBuffer;
+ }
+ }
+
+ } while (( Length != 0 ) || ( KnownLength != 0 ));
+
+ //
+ // We have finished this log file, print the number of differences
+ // to the log, and to the screen, update the total errors counter,
+ // and reset the script error counter.
+ //
+
+ printf("\n\tLogFile %s Contained %d Differences.\n",
+ LogFileName,LogFileDifferences);
+
+ if ( LoggingToScreen == FALSE ) {
+
+ TmpBuf += (BYTE)sprintf(TmpBuf,"\nLogFile %s Contained %d Differences.\n",
+ LogFileName,LogFileDifferences);
+
+ Status = TpDiffWriteToDiffFile( TmpBuf );
+
+ if ( Status != NO_ERROR ) {
+ printf("\n\tTpDiff: failed to write statistics to logfile, return %d\n",
+ Status);
+ return Status;
+ }
+ }
+
+ TotalDifferences += LogFileDifferences;
+ LogFileDifferences = 0;
+
+ return NO_ERROR;
+}
+
+
+DWORD
+TpDiffGetNextLine(
+ IN PBYTE Buffer,
+ IN PDWORD BufOffset,
+ IN DWORD BufSize,
+ IN PDWORD LineNumber,
+ OUT PBYTE Line
+ )
+
+/*++
+
+Routine Description:
+
+ This routine take a file buffer and writes the next line of the
+ file into a line buffer.
+
+Arguments:
+
+ IN PBYTE FileBuffer - Supplies the buffer to read the next line from.
+ IN PDWORD *BufOffset - Supplies the current offset in to the file buffer.
+ IN DWORD BufSize - Supplies the size of the file buffer.
+ OUT PBYTE FileLine - Returns the next line of the buffer.
+
+Return Value:
+
+ DWORD - The length of the line written into the buffer. Zero if the
+ file is empty.
+
+--*/
+
+{
+ DWORD Length = 0;
+ DWORD i;
+ DWORD Offset = (DWORD)*BufOffset;
+ PBYTE TmpLine;
+
+ TmpLine = Line;
+
+ //
+ // Ignore any empty lines, and the last lines carriage
+ // returns/line feed pair.
+ //
+
+ while (((( Buffer[Offset] == '\n' ) ||
+ ( Buffer[Offset] == '\r' )) ||
+ ( Buffer[Offset] == 0x1a )) && // my editor quirk
+ ( Offset < BufSize )) {
+
+ if ( Buffer[Offset] == '\n' ) {
+ (*LineNumber)++;
+ }
+
+ Offset++;
+
+ if ( Offset >= BufSize ) {
+
+ //
+ // We have run off the end of this log file.
+ // Null terminate the Line buffer.
+ //
+
+ Line[0] = '\0';
+
+ //
+ // Update the Buffer Offset with the new offset value.
+ //
+
+ *BufOffset = (DWORD)Offset;
+
+ //
+ // and return a length of zero for the Line buffer.
+ //
+
+ return Length;
+ }
+ }
+
+ //
+ // while we are on the same line, copy the characters to the
+ // Line buffer.
+ //
+
+ while ((((( Buffer[Offset] != EOF ) &&
+ ( Buffer[Offset] != '\n' )) &&
+ ( Buffer[Offset] != '\r' )) &&
+ ( Buffer[Offset] != 0x1a )) && // my editor quirk
+ ( Offset <= BufSize )) {
+
+ *Line++ = Buffer[Offset++];
+ Length++;
+ }
+
+ //
+ // Now Null terminate the Line buffer, and then null out any spaces,
+ // tabs or carriage returns and line feeds that may exist at the
+ // end of the string.
+ //
+
+ *Line = '\0';
+ i = Length;
+
+ while ( --i > 0 ) {
+
+ if (( TmpLine[i] == 0x20 ) || // Space
+ ( TmpLine[i] == 0x09 )) { // Tab
+
+ TmpLine[i] = '\0';
+ Length--;
+ } else {
+ break;
+ }
+ }
+
+ //
+ // Update the Buffer Offset with the new offset value.
+ //
+
+ *BufOffset = (DWORD)Offset;
+
+ //
+ // and return the length of the Line buffer.
+ //
+
+ return Length;
+}
+
+
+DWORD
+TpDiffGetResults(
+ IN PBYTE Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds the string result value in the buffer, converts
+ it to an integer, and returns the integer value.
+
+Arguments:
+
+ IN PBYTE Buffer - Supplies a null terminated buffer containing
+ the possible string value.
+
+Return Value:
+
+ DWORD - the integer result value found in the string. -1 otherwise.
+
+--*/
+
+{
+ DWORD Results = 0xFFFFFFFF;
+ LPSTR Char = (LPSTR)Buffer;
+ LPSTR NextChar = (LPSTR)Buffer; // Anything that isn't NULL.
+
+ if ( Buffer == NULL ) {
+ return Results;
+ }
+
+ NextChar = strpbrk( Char,"=" );
+
+ if ( NextChar != NULL ) {
+ *NextChar++;
+ } else {
+ return Results;
+ }
+
+ while (( *NextChar == ' ' ) || ( *NextChar == '\t' )) {
+ *NextChar++;
+ }
+
+ Results = atol( NextChar ) ;
+
+ return Results;
+}
+
+
+BOOL
+TpDiffMayValuesDiffer(
+ IN PBYTE Buffer
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ IN PBYTE Buffer - Supplies a null terminated buffer containing the
+ possible text string "EQUAL_LAST" value.
+
+Return Value:
+
+ BOOL - TRUE if "MAY_DIFFER" exists in the string, FALSE otherwise.
+
+--*/
+
+{
+ LPSTR String;
+
+ String = strstr( Buffer,"MAY_DIFFER" );
+
+ if ( String == NULL ) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL
+TpDiffMustLastTwoValuesEqual(
+ IN PBYTE Buffer
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ IN PBYTE Buffer - Supplies a null terminated buffer containing the
+ possible text string "EQUAL_LAST" value.
+
+Return Value:
+
+ BOOL - TRUE if "EQUAL_LAST" exists in the string, FALSE otherwise.
+
+--*/
+
+{
+ LPSTR String;
+
+ String = strstr( Buffer,"EQUAL_LAST" );
+
+ if ( String == NULL ) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+TpDiffUsage (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints out the TpDiff Usage statement.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ printf("\n\tUSAGE: TPDIFF [LOG_FILE] [KNOWN_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 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.\n");
+}
+
+