Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Win32: Find Differences in WIN32API.INC and other text files

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Win32: Find Differences in WIN32API.INC and other text files

    If you ever wondered what PowerBASIC has changed between its releases of the Windows API file, well, you are not alone.

    So I wrote this to report which FUNCTIONs, DECLAREd functions, User-Defined types and equates were added or subtracted from the various versions of the file. While it will not show you if parameters or UDT definitions have been changed, this should be at least a good start. (I have enough difficulty with parameters anyway!)

    Don't care about the Windows API files? OK, then: use this program as the basis for almost any text-file comparison utility!

    MCM
    4/21/00

    Code:
    $IF 0
    '  FILE: APICOMP.BAS FOR PB/CC 2.0 OR PB/DLL 6 (will require a small amount OF work)
    '  Take two "Win32API.inc" files from PB, find the differences
    '  Use: Figuring out what's been added or deleted from one version to the next.
    '  OR  - find out what is in one file but not in another.
    '  AS released, finds TYPE xxxx
    '                     FUNCTION xxxx
    '                     DECLARE FUNCTION xxxx
    '                     %xxxx  (equates)
    '  Just change the filenames in WinMain for your system.
    '
    '  Author: Michael Mattias Racine WI
    '  Copyright: This code placed in the public domain April 21, 2000 by the author,
    '             Michael C Mattias Racine WI USA, who expressly disclaims any
    '             patent or copyright interest therein.
    '
    '             //s// Michael C Mattias  4/21/2000
    '
    $ENDIF
    
    
    ' don't allow PB to assign REGISTER variables.
    #REGISTER NONE
    '#DEBUG ERROR ON
    $INCLUDE "WIN32API.INC"
    
    DECLARE FUNCTION LoadFile (FileName AS STRING) AS STRING
    DECLARE FUNCTION ParseApiFiles (FileA AS STRING, FileB AS STRING, OutputFile AS STRING) AS LONG
    DECLARE FUNCTION CompareToken (TokenType AS LONG, TokenA() AS STRING, TokenB() AS STRING, OutputFile AS STRING) AS LONG
    
    FUNCTION WinMain (BYVAL hCurInstance  AS LONG, _
                      BYVAL hPrevInstance AS LONG, _
                      lpszCmdLine         AS ASCIIZ PTR, _
                      BYVAL nCmdShow      AS LONG) EXPORT AS LONG
    
       DIM ThisFile AS ASCIIZ * 128
       DIM Stat AS LONG
       $IF %PB_CC32
         Stat = GetModuleFileName (hCurInstance, ThisFile, SIZEOF(ThisFile) )
         PRINT "Hello World from Program " & ThisFile
       $ENDIF
       DIM FileA AS STRING, FileB AS STRING, OutputFile AS STRING, OFH AS LONG
       FileA = "C:\Software_Development\Testdata\win32apiA.inc"
       FileB = "C:\Software_Development\Testdata\win32apiB.inc"
       OutputFile = "C:\Software_Development\Testdata\win32apiCompare.txt"
    
       OFH=FREEFILE
       OPEN OutputFile FOR OUTPUT AS OFH
       PRINT #OFH, "Compare Files on " & DATE$ & " at " & TIME$
       PRINT #OFH, "FileA=" & FileA
       PRINT #OFH, "FileB=" & FileB
       ' show on PB/CC console
       $IF %PB_CC32
        PRINT  "FileA      =" & FileA
        PRINT  "FileB      =" & FileB
        PRINT  "Output File=" & OutputFile
       $ENDIF
       CLOSE OFH
       Stat = ParseApiFiles (FileA, FileB, OutputFile)
    
       OFH = FREEFILE
       OPEN OutputFile FOR APPEND AS OFH
       PRINT #OFH,
       PRINT #OFH, " ***  E N D    O F    R E P O R T   ***"
       CLOSE OFH
       $IF %PB_CC32
         PRINT "End of Job. Press Any Key...";
         J$ = WAITKEY$
       $ENDIF
    
    END FUNCTION
    %TYPE_SUB = 0
    %FUNCTION_SUB = 1
    %DECLARE_FUNCTION_SUB = 2
    %EQUATE_SUB           = 3
    %MAX_SUB              = 3
    %FILE_A_SUB           = 0
    %FILE_B_SUB           = 1
    
    
    FUNCTION ParseApiFiles (FileA AS STRING, FileB AS STRING, OutputFile AS STRING) AS LONG
       ' looks for TYPE and FUNCTION in FileA and FILE B, Identifies which are prosent in one
       ' but not the other, writes a report text file to OutputFile.
       ' Returns: 0 = operation successful
       ' -1 operation succesfull but not differences found
       ' anything else, error = PB error number
    
       DIM FindMask (%Max_Sub) AS STRING, ReplaceMask(%Max_Sub) AS STRING, NewlineMask AS STRING
       DIM OFH AS LONG                             ' file handle for output report
       DIM MyKey AS STRING
       REDIM TokenA(0) AS STRING                   ' gets redimed to correct size later.
       REDIM TokenB(0) AS STRING                   ' tokenA =current literal in FileA
                                                   ' tokenB =current literals in FileB
       DIM TokenCount (%Max_Sub,1) AS LONG         ' n,0 = stuff in FileA; n,1 = stuff in FileB
       DIM FileData(1)AS STRING                    ' hold file data
    
       DIM IBuffer AS STRING                        ' to load the files.
       DIM Stat AS LONG                             ' did we blow up yet?
       DIM I AS LONG, J AS LONG, K AS LONG          ' work fields
       DIM Mask AS STRING, PosVar AS LONG, StartVar AS LONG, LenVar AS LONG, TextLine AS STRING
       DIM NewTextLine AS STRING, NewPosVar AS LONG, NewLenVar AS LONG
       DIM Space AS STRING : Space = CHR$(&h20)
       FindMask (%TYPE_SUB) = "^[\x20]*TYPE[\x20]+([a-z0-9_]+)"
       FindMask (%FUNCTION_SUB) = "^[\x20]*FUNCTION[\x20]+([a-z0-9_]+)"
       FindMask (%DECLARE_FUNCTION_SUB) = "^[\x20]*DECLARE[\x20]+FUNCTION[\x20]+([a-z0-9_]+)"
       FindMask (%EQUATE_SUB)           ="^[\x20]*(%[a-z0-9_]+)"
    
       ReplaceMask(%TYPE_SUB) = "\01"
       ReplaceMask(%FUNCTION_SUB) = "\01"
       ReplaceMask(%DECLARE_FUNCTION_SUB)= "\01"
       ReplaceMask(%EQUATE_SUB)= "\01"
    
       FileData(%File_A_SUB) = LoadFile(FileA):    FileData(%FILE_B_SUB)= LoadFile(FileB)  '    load the two files into memory...
       RESET TokenCount()                          ' initialize
    
       FOR I = 0 TO %MAX_SUB                         ' for each token to be found
           Mask = FindMask(I)                        ' what are we looking for this trip?
           FOR J = 0 TO 1                            ' for each file
               IBuffer = FileData(J)
               ' First, just get a count  of this token in this file
               StartVar = 1: PosVar = 1
               WHILE PosVar
                 REGEXPR Mask IN IBuffer AT StartVar TO PosVar,LenVar
                 IF PosVar THEN                      ' we found a target string
                   INCR TokenCount(I, J)
                  StartVar = PosVar + LenVar
                  END IF
               WEND
               ' set the token array to the correct size..
               ' if there were no items found by REGEXPR, the UBOUND of these arrays will be minus one
               ' and we will get a GPF later. In this case, REDIM the array with one element = null string
               IF J = %FILE_A_SUB THEN
                  REDIM TokenA (TokenCount (I,J) -1, 0)
                  IF TokenCount(I,J) = 0 THEN
                    REDIM TokenA(0)
                    TokenA(0) = $NUL
                  END IF
               ELSEIF J = %FILE_B_SUB THEN
                  REDIM TokenB(TokenCount(I,J) -1)
                  IF TokenCount(I,J) = 0 THEN
                    REDIM TokenB(0)
                    TokenB(0) = $NUL
                  END IF
               END IF
               ' now go through the file again, finding the same tokens, this time
               ' retrieving the string, then using REGREPL to replace the whole string
               ' with only the part we want (the name of the TYPE or FUNCTION):
               ' we will retrieve only a single line of text to keep the string overhead down
               ' on the REGREPL
               K = 0: StartVar = 1: PosVar = 1
               WHILE PosVar
                 REGEXPR Mask IN IBuffer AT StartVar TO PosVar,LenVar
                 IF PosVar THEN                              ' we found a target string
                   TextLine = MID$(iBuffer, PosVar, Lenvar)  ' get it
                   REGREPL Mask IN TextLine WITH ReplaceMask(I) TO NewPosVar, NewTextLine
                   ' and store the replacement string in the token array..
                   IF J = %FILE_A_SUB THEN
                      TokenA(K) = NewTextLine
                   ELSEIF J = %FILE_B_SUB THEN
                      TokenB(K) = NewTextLine
                   END IF
                   INCR K                       ' so the next trip will use the next array element
                   StartVar = PosVar + LenVar   'advance through the input file
                 END IF
               WEND
           NEXT J      ' get both "B" and "A
          ' compare and report:
          Stat = CompareToken (I, TokenA(), TokenB(), OutputFile)
    
        NEXT I    ' next token
    
    END FUNCTION
    
    FUNCTION LoadFile (FileName AS STRING) AS STRING
       DIM H AS LONG, FData AS STRING
       H = FREEFILE
       OPEN FileNAme FOR BINARY AS H BASE =0
       GET$ H, LOF(H), FData
       CLOSE H
       FUNCTION = FData
    END FUNCTION
    
    
    FUNCTION  CompareToken (TokenType AS LONG, TokenA() AS STRING, TokenB() AS STRING, OutputFile AS STRING) AS LONG
       ' two comparisons: Found in A, not in B; Found in B not in A
    
       DIM ASub AS LONG, BSub AS LONG
       DIM OFH AS LONG
       DIM OutLine AS STRING
    
    ' Worst case scenario is that the two files are completely different, so allow for that:
       REDIM NotInB(UBOUND(TokenA,1)) AS STRING
       REDIM NotInA(UBOUND(TokenB,1)) AS STRING
       DIM NotInBSub AS LONG, NotInASub AS LONG
       DIM Blanks AS STRING
       Blanks = SPACE$(6)
    ' sort the input so we can find the differences
       ARRAY SORT TokenA()
       ARRAY SORT TokenB()
       ASub = 0: BSub = 0
       NotInASub = 0: NotInBSub = 0
    
    ' used for testing, removed for production...
    '   ON ERROR GOTO CompareTrap
       
       DO
    
          IF BSub > UBOUND (TokenB,1) THEN         ' whatever is in A is not in B
             NotInB(NotInBSub) = TokenA(ASub)
             INCR ASub
             INCR NotInBSub
          ELSEIF ASub > UBOUND (TokenA, 1) THEN    ' whatever is in B is not in A
             NotInA(NotInASub) = TokenB(Bsub)
             INCR BSub
             INCR NotInASub
          ELSE                                     ' we just don't know yet; we have to compare
            IF TokenA(ASub) = TokenB(BSub) THEN   ' it's in both
                INCR ASub
                INCR BSub
            ELSEIF TokenA(ASub) < TokenB (Bsub) THEN  ' Its in A, but not in B
                NotInB(NotInBSub) = TokenA(ASub)
               INCR NotInBSub
               INCR ASub
            ELSEIF TokenA (Asub) > TokenB(BSub) THEN   ' Its in B, but not in A
              NotInA(NotInASub) = TokenB(BSub)
              INCR NotInASub
              INCR BSub
           END IF
        END IF
    
      LOOP UNTIL Asub > UBOUND (TokenA,1) AND BSub > UBOUND(TokenB,1)
    
      ' when we get here, NotinASub and NotinBSub are one more than the number of elements in the
      ' corresponding arrays, unless they are zero, in which case there were no differences
    
      SELECT CASE TokenType
         CASE %TYPE_SUB
            Outline = "*** Type Definitions"
         CASE %FUNCTION_SUB
            Outline = "*** Functions Defined"
         CASE %DECLARE_FUNCTION_SUB
            Outline = "*** DECLAREd FUNCTIONs"
         CASE %EQUATE_SUB
            OutLine = "*** Equates Defined"
      END SELECT
    
     OFH = FREEFILE
     OPEN OutputFile FOR APPEND AS OFH
    
     PRINT #OFH, Outline &  " Found in FileA, Not in FileB ***"
     PRINT #OFH, "Found total " & FORMAT$(UBOUND(TokenA,1) + 1) & " in FileA  and " & FORMAT$(UBOUND(TokenB,1)+1) & " in FileB"
    
      IF NotInBSub = 0 THEN
          PRINT #OFH, "    None"
      ELSE
          FOR ASub = 0 TO NotInBSub -1
              PRINT #OFH, Blanks;
              PRINT #OFH, NotInB(ASub)
          NEXT ASub
      END IF
    
      PRINT #OFH, Outline &  " Found in FileB, Not in FileA ***"
      IF NotInASub = 0 THEN
         PRINT #OFH, "   None "
      ELSE
         FOR Asub = 0 TO NotInASub -1
             PRINT #OFH,Blanks;
             PRINT #OFH, NotInA (ASub)
         NEXT Asub
      END IF
      
    CompareResume:
      CLOSE OFH
      FUNCTION = 0
      EXIT FUNCTION
      
    CompareTrap:
      $IF %PB_CC32
       PRINT "HitError Trap, Error=" & STR$(ERRCLEAR)
       PRINT "Array limits A, B =" & STR$(UBOUND(TokenA,1)) & STR$(UBOUND(TokenB,1))
       PRINT "Array limits NotinA, NotinB =" & STR$(UBOUND(NotInA,1)) & STR$(UBOUND(NotinB,1))
       PRINT "ASub BSub=" & STR$(Asub) & STR$(BSub)
       PRINT "NotInASub, NotInBSub=" & STR$(NotInASub) & STR$(NotInBSub)
       PRINT "Any Key to Exit...
       WAITKEY$
      $ENDIF
       RESUME CompareResume
    
    END FUNCTION



    -------------
    Michael Mattias
    Racine WI USA
    [email protected]
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com
Working...
X