diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/testprot/tpdiff | |
download | NT4.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/makefile | 11 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff.new/sources | 63 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff.new/tpdiff.c | 2527 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff.new/tpdiff.h | 213 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff/makefile | 6 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff/sources | 48 | ||||
-rw-r--r-- | private/ntos/ndis/testprot/tpdiff/tpdiff.c | 1749 |
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"); +} + + |