Attribute VB_Name = "LibBuild_Main"
' Copyright (C) 2008-2012 Jan Vorel
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation; either version 2 of the License, or
' (at your option) any later version.

' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.

' You should have received a copy of the GNU General Public License
' along with this program; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

' If you have any questions, suggestions or bug reports about this product,
' contact me: info@ctuser.net; Do not contact me about general B.A.S.I.C.
' language or A.P.I. issues

Option Explicit
Option Base 0

Public gLabel As Label
Public gList As ListBox

Private xPrjBasePath As String
Private Declare Function GetModuleFileNameA Lib "kernel32" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private xLibBuildIncBase As String
'Public VBInstance As VBIDE.VBE
Private Declare Function GetFileAttributesA Lib "kernel32" (ByVal lpFileName As String) As Long

Private xAssemblyString(999) As String
Private xAssemblyLC(999) As String
Private xAssemblyPublic(999) As Boolean
Private MyASMCount As Long

Private xUsedApiString(999) As String
Private xUsedApiLC(999) As String
Private xUsedApiPublic(999) As Boolean
Private xUsedApiFoundDefinition(999) As Boolean
Private xUsedApiVerCompatible(999) As Boolean
Private ApiCount As Long

Private xLegalString(999) As String
Private xLegalStringLC(999) As String
Private xLegalStringCount As Long
Private xLegalTxt As String
Private MyLegal As String

Private xDevIntern As String
Private xDevPublic As String

Private MyFuncs As String
Private xAPI(9999) As String
Private xAPIDefinitionString(9999) As String
Private xAPIDefinitionLC(9999) As String
Private xAPIDefinitionCode(9999) As String
Private xApiDefinitionIsStruc(9999) As Boolean
Private xAPIDefinitionVerCompatible(9999) As Boolean
Private xAPIDefinitionCount As Long

Private xDoubleDeclarationsStringLC(9999) As String
Private xDoubleDeclarationsFilename(9999) As String
Private xDoubleDeclarationsLineNumber(9999) As Long
Private xDoubleDeclarationsErrorOut(9999) As String
Private xAPICountN As Long

Private xTrusted(9999) As String
Private xTrustedCount As Long

Private xIncudesString(1999) As String
Private xIncudesLCRP(1999) As String
Private xIncudesPublic(1999) As Boolean
Private xIncudesCount As Long

Private xCompilerDirectiveString(999) As String
Private xCompilerDirectiveLC(999) As String ' not really needed
Private xCompilerDirectiveCount As Long


Private MyDefines As String

Private HasError As Boolean
Private HasWarning As Boolean
Public xCanOutput As Boolean
'Private IsWorking As Boolean










Public WholeNewCode As String

Public Sub RealOut(ByVal xText As String)
  #If Test Then
    Debug.Print xText
    #Else
    WholeNewCode = WholeNewCode + xText + vbCrLf
    #End If
  End Sub

Private Function CheckDoubleDeclarationsLine(ByVal CheckDeclarePrefixLC As String, ByVal xLineStr As String, ByVal xLineID As Long, ByVal xFilename As String, ByVal AddCheck As Boolean) As Boolean
  Dim xLong1 As Long
  Dim xChar1 As String ' real api name
  Dim xChar2 As String ' real api name lc

  If LCase(Left(xLineStr, Len(CheckDeclarePrefixLC))) = CheckDeclarePrefixLC Then
    CheckDoubleDeclarationsLine = True
    xLong1 = InStr(Len(CheckDeclarePrefixLC) + 1&, xLineStr, " ")
    If xLong1 = 0& Then xLong1 = Len(xLineStr) + 1&
    xChar1 = Mid(xLineStr, Len(CheckDoubleDeclarationsLine) + 1&, xLong1 - Len(CheckDoubleDeclarationsLine) - 1&)
    xChar2 = LCase(xChar1)
    
    For xLong1 = 0& To xAPICountN - 1&
      If Len(xDoubleDeclarationsStringLC(xLong1)) = Len(xChar2) Then
        If xDoubleDeclarationsStringLC(xLong1) = xChar2 Then
          If xDoubleDeclarationsLineNumber(xLong1) = 0& Then
            xDoubleDeclarationsErrorOut(xLong1) = xDoubleDeclarationsErrorOut(xLong1) + vbCrLf + "  " + xFilename + " in line " + CStr(xLineID)
            Else
            xDoubleDeclarationsErrorOut(xLong1) = xChar1 + vbCrLf + "  " + xDoubleDeclarationsFilename(xLong1) + " in line " + CStr(xDoubleDeclarationsLineNumber(xLong1)) + vbCrLf + "  " + xFilename + " in line " + CStr(xLineID)
            xDoubleDeclarationsLineNumber(xLong1) = 0&
            End If
          GoTo UnFor
          End If
        End If
      Next
    
    
    xDoubleDeclarationsStringLC(xAPICountN) = xChar2
    xDoubleDeclarationsLineNumber(xAPICountN) = xLineID
    xDoubleDeclarationsFilename(xAPICountN) = xFilename
    
    If AddCheck Then
      For xLong1 = 0& To xTrustedCount - 1&
        If Len(xTrusted(xLong1)) = Len(xChar2) Then
          If xTrusted(xLong1) = xChar1 Then
            xAPIDefinitionVerCompatible(xAPICountN) = True
            GoTo Ok1
            End If
          End If
        Next
      For xLong1 = 0& To ApiCount - 1&
'        Stop
        If Len(xUsedApiString(xLong1)) = Len(xChar2) Then
          If xUsedApiLC(xLong1) = xChar2 Then
            xAPIDefinitionVerCompatible(xAPICountN) = True
            GoTo Ok1
            End If
          End If
        Next
      xAPIDefinitionString(xAPICountN) = xChar1
Ok1:
      Else
      xAPIDefinitionVerCompatible(xAPICountN) = True
      End If
    
    xAPICountN = xAPICountN + 1&
UnFor:
    End If
'Stop
  End Function

Private Sub CheckDoubleDeclarationsFile(ByVal xFile As String)
  Dim xLine As Long
  Dim xChar1 As String

  Select Case LCase(Right(xFile, 4))
    Case ".bas"
    Case ".frm"
    Case ".cls"
    Case ".ctl"
      xFile = Trim(Mid(xFile, InStr(xFile, ";") + 1&))
      SubLog "Checking: " + xFile
      On Error GoTo Er1
      Open xFile For Input As 2
      On Error GoTo Er2
      Do Until EOF(2)
        Line Input #2, xChar1
        On Error GoTo 0
        xChar1 = LTrim(xChar1)
        xLine = xLine + 1&
    '    Stop
        On Error GoTo Er3
        If CheckDoubleDeclarationsLine("private declare sub ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("public declare sub ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("declare sub ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("private declare function ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("public declare function ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("declare function ", xChar1, xLine, xFile, True) Then
          ElseIf CheckDoubleDeclarationsLine("private type ", xChar1, xLine, xFile, False) Then
          ElseIf CheckDoubleDeclarationsLine("public type ", xChar1, xLine, xFile, False) Then
          ElseIf CheckDoubleDeclarationsLine("type ", xChar1, xLine, xFile, False) Then
          ElseIf CheckDoubleDeclarationsLine("private enum ", xChar1, xLine, xFile, False) Then
          ElseIf CheckDoubleDeclarationsLine("public enum ", xChar1, xLine, xFile, False) Then
          ElseIf CheckDoubleDeclarationsLine("enum ", xChar1, xLine, xFile, False) Then
          Else
          End If
        Loop
Rs1:
      On Error GoTo 0
      Close 2
      Exit Sub
    
Er1:
      SetError "  Error opening " + xFile
      Resume Rs1
      
Er2:
      SetError "  Error reading " + xFile
      Resume Rs1
      
Er3:
      SetError "  Error processing " + xFile
      Resume Rs1
    End Select
  End Sub

Private Sub CmbLineWithPublic(ByRef xString() As String, ByRef xLC() As String, ByRef xPublic() As Boolean, ByRef xCount As Long, ByVal xStringNew As String, ByVal MkPublic As Boolean)
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xChar1 As String

  xChar1 = LCase(xStringNew)
  xLong2 = Len(xStringNew)
  For xLong1 = 0& To xCount - 1&
    If Len(xString(xLong1)) = xLong2 Then
      If xLC(xLong1) = xChar1 Then
        If MkPublic Then xPublic(xLong1) = True
        Exit Sub
        End If
      End If
    Next
  xString(xCount) = xStringNew
  xLC(xCount) = xChar1
  xPublic(xCount) = MkPublic
  xCount = xCount + 1&
  End Sub

Private Sub CmbLineLite(ByRef xString() As String, ByRef xLC() As String, ByRef xCount As Long, ByVal xStringNew As String)
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xChar1 As String

  xChar1 = LCase(xStringNew)
  xLong2 = Len(xStringNew)
  For xLong1 = 0& To xCount - 1&
    If Len(xString(xLong1)) = xLong2 Then
      If xLC(xLong1) = xChar1 Then
        Exit Sub
        End If
      End If
    Next
  xString(xCount) = xStringNew
  xLC(xCount) = xChar1
  xCount = xCount + 1&
  End Sub

Private Sub CmbLineWPath(ByRef xString() As String, ByRef xLC() As String, ByRef xPublic() As Boolean, ByRef xCount As Long, ByVal xStringNew As String)
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xChar1 As String
  Dim xMkPublic As Boolean

'Stop
  If Left(xStringNew, 1&) = "." Or Left(xStringNew, 1&) = "\" Or Mid(xStringNew, 2&, 2&) = ":\" Then
    xChar1 = LCase(GetRelativeFilename(xPrjBasePath, xStringNew))
    Select Case Right(xChar1, 4&)
      Case ".inc"
      Case ".def"
        xMkPublic = True
      Case Else
        xChar1 = xChar1 + ".inc"
      End Select
    ElseIf InStr(xStringNew, "\") = 0& Then
    xChar1 = LCase(xLibBuildIncBase + "inc\" + xStringNew) + ".inc"
    Else
    xChar1 = LCase(xLibBuildIncBase + xStringNew) + ".inc"
    End If
  xLong2 = Len(xStringNew)
  For xLong1 = 0& To xCount - 1&
    If Len(xString(xLong1)) = xLong2 Then
      If xLC(xLong1) = xChar1 Then
        Exit Sub
        End If
      End If
    Next
  xString(xCount) = xStringNew
  xLC(xCount) = xChar1
  xPublic(xCount) = xMkPublic
  xCount = xCount + 1&
  End Sub

Private Sub RealCombine(ByVal xChar1 As String, ByVal MkPublic As Boolean)
  Dim xMode As Long

  On Error GoTo Er1
  Open xChar1 For Input As 1
  On Error GoTo Er2
  Do Until EOF(1)
    Line Input #1, xChar1
    On Error GoTo Er3
    If Not Len(xChar1) = 0& Then
      Select Case Trim(UCase(xChar1))
        Case "[API]"
          xMode = 0&
        Case "[INCLUDE]"
          xMode = 1&
        Case "[DIRECTIVE]"
          xMode = 2&
        Case "[DEFINE]"
          xMode = 3&
        Case "[ASSEMBLY]"
          xMode = 4&
        Case "[LEGAL]"
          xMode = 5&
        Case "[LEGALTEXT]"
          If MkPublic Then
            xMode = 6&
            Call xStripBRs(MyLegal)
            Else
            xMode = 7&
            Call xStripBRs(xLegalTxt)
            End If
        Case "[DEVINTERN]"
          xMode = 8&
        Case "[DEVPUBLIC]"
          xMode = 9&
        Case "[CODE]"
          Do Until EOF(1)
            Line Input #1, xChar1
            MyFuncs = MyFuncs + vbCrLf + xChar1
            Loop
          If Not Right(MyFuncs, 4&) = vbCrLf + vbCrLf Then
            MyFuncs = MyFuncs + vbCrLf
            End If
          Exit Do
        Case Else
          If Not xMode = 3& Then
            xChar1 = Trim(xChar1)
            End If
          If Not Len(Trim(xChar1)) = 0& Then
            Select Case xMode
              Case 0&
                If LCase(Left(xChar1, 7&)) = "public " Then
                  CmbLineWithPublic xUsedApiString(), xUsedApiLC(), xUsedApiPublic(), ApiCount, LTrim(Mid(xChar1, 8)), True
                  Else
                  CmbLineWithPublic xUsedApiString(), xUsedApiLC(), xUsedApiPublic(), ApiCount, xChar1, MkPublic
                  End If
              Case 1&
                xChar1 = Trim(xChar1)
                CmbLineWPath xIncudesString(), xIncudesLCRP(), xIncudesPublic(), xIncudesCount, xChar1   ', False
              Case 2&: CmbLineLite xCompilerDirectiveString(), xCompilerDirectiveLC(), xCompilerDirectiveCount, xChar1
              Case 3&: MyDefines = MyDefines + vbCrLf + xChar1
              Case 4&
                If MyASMCount = 0& Then
                  'CmbLineWPath xIncudesString(),xIncudesLCRP(),  xIncudesCount, "GenericInit", False
                  CmbLineWPath xIncudesString(), xIncudesLCRP(), xIncudesPublic(), xIncudesCount, "CreateCodeFromHexAssembly"  ', False
                  End If
                If LCase(Left(xChar1, 7&)) = "public " Then
                  CmbLineWithPublic xAssemblyString(), xAssemblyLC(), xAssemblyPublic(), MyASMCount, LTrim(Mid(xChar1, 8&)), True
                  Else
                  CmbLineWithPublic xAssemblyString(), xAssemblyLC(), xAssemblyPublic(), MyASMCount, xChar1, MkPublic
                  End If
              Case 5&: CmbLineLite xLegalString(), xLegalStringLC(), xLegalStringCount, xChar1
              Case 6&: MyLegal = MyLegal + PatchLegalLine(xChar1) + vbCrLf
              Case 7&: xLegalTxt = xLegalTxt + PatchLegalLine(xChar1) + vbCrLf
              Case 8&: xDevIntern = xDevIntern + xChar1 + vbCrLf
              Case 9&: xDevPublic = xDevPublic + xChar1 + vbCrLf
              End Select
            End If
        End Select
      End If
    On Error GoTo Er2
    Loop
  
Rs1:
  On Error GoTo 0
  Close 1
  Exit Sub
  
Er1:
  SetError "  Error opening file" ': " + xChar1
  Resume Rs1
  
Er2:
  SetError "  Error reading file" ': " + xChar1
  Resume Rs1
  
Er3:
  SetError "  Error processing data"
  Resume Rs1
  End Sub

Private Sub RealWriteTo(ByVal xMode As Boolean)
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xLong3 As Long

  For xLong1 = 0& To ApiCount - 1&
    xLong3 = Len(xUsedApiString(xLong1))
    For xLong2 = 0& To xAPIDefinitionCount - 1&
      If xApiDefinitionIsStruc(xLong2) = xMode Then
        If xLong3 = Len(xAPIDefinitionString(xLong2)) Then
          If xUsedApiLC(xLong1) = xAPIDefinitionLC(xLong2) Then
            If xUsedApiPublic(xLong1) Then
              RealOut "Public " + xAPI(xLong2)
              Else
              RealOut "Private " + xAPI(xLong2)
              End If
            xUsedApiFoundDefinition(xLong1) = True
            If xMode Then xUsedApiVerCompatible(xLong1) = True
            End If
          End If
        End If
      Next
    Next
  End Sub

Private Function MakeAssembly(ByVal Index As Long) As String
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xByteA1() As Byte

  #If Test Then
    SubLog "  " + xAssemblyString(Index)
    #End If
  On Error GoTo Er1
  Open xLibBuildIncBase + "assembly\" + xAssemblyString(Index) + ".bin" For Input As 1
  Close 1
  Open xLibBuildIncBase + "assembly\" + xAssemblyString(Index) + ".bin" For Binary Access Read Lock Read Write As 1
  xLong1 = LOF(1)
  ReDim xByteA1(xLong1 - 1&)
  Get 1, , xByteA1()
  Close 1
  
  For xLong2 = 0& To xLong1 - 1&
    MakeAssembly = MakeAssembly + Hex((xByteA1(xLong2) And &HF0&) \ &H10&) + Hex(xByteA1(xLong2) And &HF&)
    Next
  
Rs1:
  On Error GoTo 0
  Exit Function
  
Er1:
  #If Test Then
    SetError "    Error opening assembly file"
    #Else
    SetError "  Error opening assembly file: " + xAssemblyString(Index)
    #End If
  Resume Rs1
  End Function

Private Function AddAPILib(ByVal DefCode As String, ByVal DLLName As String) As String
  Dim xLong1 As Long
  Dim xLong2 As Long
  xLong1 = InStr(DefCode, " ")
  xLong2 = InStr(xLong1 + 1&, DefCode, "(")
  xLong1 = InStr(xLong1 + 1&, DefCode, " ")
  If (xLong1 = 0& Or xLong2 < xLong1) And Not xLong2 = 0& Then xLong1 = xLong2
  If xLong1 = 0& Then xLong1 = Len(DefCode) + 1&
  AddAPILib = Left(DefCode, xLong1 - 1&) + " Lib " + Chr(34) + DLLName + Chr(34) + " " + LTrim(Mid(DefCode, xLong1))
  End Function

Private Function PatchLegalLine(ByVal xChar1 As String) As String
  PatchLegalLine = RTrim(xChar1)
  If Not Len(PatchLegalLine) = 0& Then
    If Not Left(LTrim(PatchLegalLine), 1&) = "'" Then
      PatchLegalLine = "' " + PatchLegalLine
      End If
    End If
  End Function

Public Sub xStripBRs(ByVal xChar1 As String)
  While Left(xChar1, 2&) = vbCrLf
    xChar1 = Mid(xChar1, 3&)
    Wend
  While Right(xChar1, 2&) = vbCrLf
    xChar1 = Left(xChar1, Len(xChar1) - 2&)
    Wend
  End Sub

Private Sub IncludeLegalFile(ByVal Filename As String)
  Dim xChar1 As String
  Dim xChar2 As String

'Stop
  On Error GoTo Er1
  Open xLibBuildIncBase + "legal\" + Filename + ".leg" For Input As 1
  Do Until EOF(1)
    Line Input #1, xChar1
    xChar2 = xChar2 + PatchLegalLine(xChar1) + vbCrLf
    Loop
  Call xStripBRs(xChar2)
  RealOut xChar2

Rs1:
  On Error GoTo 0
  Close 1
  Exit Sub
  
Er1:
  MainLog "  File not found: legal\" + Filename + ".leg"
  Resume Rs1
  End Sub

Private Sub DefineAPI(ByVal Filename As String)
  Dim xLong1 As Long
  Dim xLong2 As Long
  Dim xLong3 As Long
  Dim xLong4 As Long
  Dim xChar2 As String
  Dim xChar3 As String
  Dim xChar4 As String
  Dim xApiUnCheck As Boolean
  'Dim xComp1 As VBComponent
  Dim xCurDLLName As String
  
  Open xLibBuildIncBase + "api\" + Filename For Input As 1
  Do Until EOF(1)
    Line Input #1, xChar2
    If Left(xChar2, 1) = "!" Then
      'xApiUnCheck(xAPIDefinitionCount) = True
      xApiUnCheck = True
      xChar2 = Mid(xChar2, 2&)
      Else
      'xApiUnCheck(xAPIDefinitionCount) = False
      xApiUnCheck = False
      End If
    If Not Len(xChar2) = 0& Then
      xLong1 = InStr(xChar2, " ")
      xLong3 = InStr(xLong1 + 1&, xChar2, " ")
      If xLong3 = 0& Then xLong3 = Len(xChar2) + 1&
      xChar4 = Mid(xChar2, xLong1 + 1&, xLong3 - xLong1 - 1&)
      'xChar3 = LCase(Mid(xChar2, xLong1 + 1&, xLong3 - xLong1 - 1&))
      xChar3 = LCase(xChar4)
      xLong4 = Len(xChar3)
      For xLong2 = 0& To xAPIDefinitionCount - 1&
        If Len(xAPI(xLong2)) = xLong4 Then
          If xAPI(xLong2) = xChar3 Then
            GoTo UnFor
            End If
          End If
        Next
      Select Case LCase(Left(xChar2, xLong1 - 1&))
        Case "lib"
          xCurDLLName = xChar4
        Case "function"
          'xApiDefinitionIsStruc(xAPIDefinitionCount) = False
          xAPI(xAPIDefinitionCount) = "Declare " + AddAPILib(xChar2, xCurDLLName)
          GoTo CheckWStuff
        Case "sub"
          'xApiDefinitionIsStruc(xAPIDefinitionCount) = false
          xAPI(xAPIDefinitionCount) = "Declare " + AddAPILib(xChar2, xCurDLLName)
CheckWStuff:
          'Stop
          Select Case Asc(Right(xChar4, 1&))
            Case 65&, 87& '"A", "W"
              If Not InStr(1&, Mid(xChar2, xLong3 + 5), " as any", vbTextCompare) = 0& Then
                If Not xApiUnCheck Then
                  #If Test Then
                    SetWarning "  Parameter missmatch in " + Filename + " for " + xChar4
                    #Else
                    SetWarning "  Parameter missmatch for " + xChar4
                    #End If
                  End If
                End If
            End Select

        Case "type"
          xApiDefinitionIsStruc(xAPIDefinitionCount) = True
  '        Stop
          xAPI(xAPIDefinitionCount) = Left(xChar2, xLong3 - 1&) + vbCrLf + "  " + Replace(Mid(xChar2, xLong3 + 2&, Len(xChar2) - xLong3 - 2), ", ", vbCrLf + "  ") + vbCrLf + "  End Type"
        Case "enum"
          xApiDefinitionIsStruc(xAPIDefinitionCount) = True
  '        Stop
          xAPI(xAPIDefinitionCount) = Left(xChar2, xLong3 - 1&) + vbCrLf + "  " + Replace(Mid(xChar2, xLong3 + 2&, Len(xChar2) - xLong3 - 2), ", ", vbCrLf + "  ") + vbCrLf + "  End Enum"
        End Select
      xAPIDefinitionString(xAPIDefinitionCount) = xChar4
      xAPIDefinitionLC(xAPIDefinitionCount) = xChar3
      xAPIDefinitionCount = xAPIDefinitionCount + 1&
      End If
UnFor:
    Loop
  Close 1
  End Sub

Private Sub VerifyAPI(ByVal Filename As String)
  Dim xLong1 As Long
  Dim xChar1 As String

  Open xLibBuildIncBase + "compat\" + Filename For Input As 1
  Do Until EOF(1)
    Line Input #1, xChar1
    xChar1 = LCase(xChar1)
    'Stop
    If Not Len(xChar1) = 0& Then
      For xLong1 = 0& To ApiCount - 1&
        If Len(xUsedApiString(xLong1)) = Len(xChar1) Then
          If xUsedApiLC(xLong1) = xChar1 Then
            'Stop
            xUsedApiVerCompatible(xLong1) = True
            GoTo NoAdd
            End If
          End If
        Next
NoAdd:
      xTrusted(xTrustedCount) = xChar1
      xTrustedCount = xTrustedCount + 1&
      End If
    Loop
  Close 1
  End Sub

#If Test Then
  #Else
  Public Function CheckDefObject(ByRef xComp As VBComponent, ByRef BaseFileName As String) As Boolean
    For Each xComp In VBInstance.ActiveVBProject.VBComponents
      If xComp.FileCount = 1& Then
        If LCase(Right(xComp.FileNames(1), 4)) = ".bas" Then
          'eList.AddItem "UseThis? " + xComp.FileNames(1)
          BaseFileName = Left(xComp.FileNames(1), Len(xComp.FileNames(1)) - 3&)
          'eList.AddItem "  " + BaseFileName
          'eList.AddItem "  " + Hex(GetFileAttributesA(BaseFileName))
          'eList.AddItem "  " + Hex(GetFileAttributesA(BaseFileName) And &H10&)
          If (GetFileAttributesA(BaseFileName + "def") And &H10&) = 0& Then
            'eList.AddItem "Found DEF match for " + xComp.FileNames(1) + ":"
            'eList.AddItem "  " + BaseFileName
            CheckDefObject = True
            Exit Function
            End If
          End If
        End If
      Next
    Set xComp = Nothing
    End Function
  #End If

Public Function BuildLib(ByVal Filename As String) As Boolean
  Dim xLong1 As Long
  Dim xLong2 As Long
  'Dim xLong3 As Long
  'Dim xLong4 As Long
  Dim xChar2 As String
  'Dim xChar3 As String
  'Dim xChar4 As String
  'Dim xApiUnCheck As Boolean
  #If Test Then
    #Else
    Dim xComp1 As VBComponent
    #End If

  CleanUp

  If Not Right(xLibBuildIncBase, 1&) = "\" Then xLibBuildIncBase = xLibBuildIncBase + "\"


  MainLog "Processing: " + Filename + "def"
  xLong2 = InStrRev(Filename, "\")
  If Not xLong2 = 0& Then
    xPrjBasePath = Left(Filename, xLong2 - 1&)
    End If
  
  RealCombine Filename + "def", True
  If Not HasError Then
    Do Until (xLong1 = xIncudesCount)
      MainLog "Including: " + xIncudesString(xLong1)
      RealCombine xIncudesLCRP(xLong1), xIncudesPublic(xLong1)
      If HasError Then Exit Do
      xLong1 = xLong1 + 1&
      Loop
    If Not HasError Then
      MainLog "Loading API definitions"
      xChar2 = Dir(xLibBuildIncBase + "api\*.def", &H2F&)
      Do Until (Len(xChar2) = 0&)
        #If Test Then
          MainLog "  " + xChar2
          #End If
        DefineAPI xChar2
        xChar2 = Dir
        Loop
      
      
      
      MainLog "Loading API verification"
      xChar2 = Dir(xLibBuildIncBase + "compat\*.ver", &H2F&)
      Do Until (Len(xChar2) = 0&)
        #If Test Then
          MainLog "  " + xChar2
          #End If
        VerifyAPI xChar2
        xChar2 = Dir
        Loop
      
      
      
      xCanOutput = True
      MainLog "Gathering legal information"
      'Stop
      'Open FileName + "bas" For Output As 1
      'RealOut "Attribute VB_Name = " + Chr(34) + ModName + Chr(34)
    
      IncludeLegalFile "Default"
      If Not Len(MyLegal) = 0& Then
        Call xStripBRs(MyLegal)
        RealOut MyLegal
        End If
      If Not Len(xLegalTxt) = 0& Then
        Call xStripBRs(xLegalTxt)
        RealOut xLegalTxt
        End If
      If Not xLegalStringCount = 0& Then
        For xLong1 = 0& To xLegalStringCount - 1&
          IncludeLegalFile xLegalString(xLong1)
          Next
        End If
      
      If Not xCompilerDirectiveCount = 0& Then
        For xLong1 = 0& To xCompilerDirectiveCount - 1&
          RealOut "#Const " + xCompilerDirectiveString(xLong1) + " = True"
          Next
        RealOut ""
        End If
      'If Not Len(MyASMs) = 0& Then
      '  RealOut "#Const UseAssemblies = True"
      '  End If
      If Not xIncudesCount = 0& Then
        For xLong1 = 0& To xIncudesCount - 1&
          If InStr(xIncudesString(xLong1), "\") = 0& Then
            RealOut "#Const " + xIncudesString(xLong1) + " = True"
            End If
          Next
        RealOut ""
        End If
      If Not MyASMCount = 0& Then
        For xLong1 = 0& To MyASMCount - 1&
          RealOut "#Const asm_" + xAssemblyString(xLong1) + "  = True"
          Next
        RealOut ""
        End If
    
      SubLog "Creating Headers"
      RealWriteTo 1&
      RealOut ""
      RealWriteTo 0&
      RealOut ""
      RealOut MyDefines
      
      
      If Not MyASMCount = 0& Then
        SubLog "Creating assemblies"
        For xLong1 = 0& To MyASMCount - 1&
          xChar2 = MakeAssembly(xLong1)
          If Len(xChar2) > 400& Then
            RealOut "Private Const " + xAssemblyString(xLong1) + "_Bin As String = " + Chr(34) + Left(xChar2, 400&) + Chr(34&) + " + _"
            xChar2 = Mid(xChar2, 401&)
            While Len(xChar2) > 400&
              RealOut "  " + Chr(34) + Left(xChar2, 400&) + Chr(34&) + " + _"
              xChar2 = Mid(xChar2, 401&)
              Wend
            RealOut "  " + Chr(34) + xChar2 + Chr(34&)
            Else
            RealOut "Private Const " + xAssemblyString(xLong1) + "_Bin As String = " + Chr(34) + xChar2 + Chr(34&)
            End If
          RealOut "Private " + xAssemblyString(xLong1) + "_Mem As Long"
          If xAssemblyPublic(xLong1) Then
            RealOut "Public " + xAssemblyString(xLong1) + "_Exe As Long"
            Else
            RealOut "Private " + xAssemblyString(xLong1) + "_Exe As Long"
            End If
          Next
        End If
      RealOut MyFuncs
      Close 1

      MainLog "Checking for missing API declarations"
      For xLong1 = 0& To ApiCount - 1&
        If Not xUsedApiFoundDefinition(xLong1) Then
          SetError "  " + xUsedApiString(xLong1)
          End If
        Next




      'Erase xAPI()
      MainLog "Checking for multiple API declarations"
      On Error GoTo 0
      #If Test Then
        #Else
        For Each xComp1 In VBInstance.ActiveVBProject.VBComponents
          For xLong1 = 1& To xComp1.FileCount
            Call CheckDoubleDeclarationsFile(xComp1.FileNames(xLong1))
            Next
          Next
        Set xComp1 = Nothing
        #End If
    
      For xLong1 = 0& To xAPICountN - 1&
        If Not Len(xDoubleDeclarationsErrorOut(xLong1)) = 0& Then
          SetErrorEx xDoubleDeclarationsErrorOut(xLong1)
          End If
        Next
      
      
      
      
      MainLog "Checking for incompatible API declarations"
      For xLong1 = 0& To ApiCount - 1&
        If Not xUsedApiVerCompatible(xLong1) Then
          SetError "  " + xUsedApiString(xLong1)
          End If
        Next
      For xLong1 = 0& To xAPICountN - 1&
        'Stop
        If Not xAPIDefinitionVerCompatible(xLong1) Then
          SetError "  " + xAPIDefinitionString(xLong1)
          End If
        Next
      
      End If
    End If

Rs1:
  On Error GoTo 0
  Close 1
  If Not (HasError Or HasWarning) Then
    MainLogDL CStr(xIncudesCount) + " includes, " + CStr(ApiCount) + "/" + CStr(xAPIDefinitionCount) + " APIs, " + CStr(xCompilerDirectiveCount) + " directives, " + CStr(MyASMCount) + " assemblies,", MkKB(Len(MyDefines)) + " declarations, " + MkKB(Len(MyFuncs)) + " code"
    End If
  Exit Function
  
Er1:
  SetError "  Error opening project file"
  Resume Rs1
  
Er2:
  SetError "  Error reading project file"
  Resume Rs1
  End Function

Private Function MkKB(ByVal xLong1 As Long) As String
  MkKB = CStr(Fix((xLong1 + 500&) / 1000&)) + "kb"
  End Function

Private Sub MainLogDL(ByVal xChar1 As String, ByVal xChar2 As String)
  gLabel.Caption = xChar1 + vbCr + xChar2
  gLabel.Refresh
  gList.AddItem xChar1
  gList.AddItem xChar2
  'DoEvents
  End Sub

Private Sub MainLog(ByVal xChar1 As String)
  gLabel.Caption = xChar1
  gLabel.Refresh
  gList.AddItem xChar1
  'DoEvents
  End Sub

Private Sub SubLog(ByVal xChar1 As String)
  gList.AddItem xChar1
  End Sub

Private Sub SetError(ByVal xChar1 As String)
  HasError = True
  gList.AddItem xChar1
  End Sub

Private Sub SetWarning(ByVal xChar1 As String)
  HasWarning = True
  gList.AddItem xChar1
  End Sub

Private Sub SetErrorEx(ByVal xChar1 As String)
  Dim xLong1 As Long
  
  HasError = True
  Do
    xLong1 = InStr(xChar1, vbCrLf)
    If xLong1 = 0& Then Exit Do
    gList.AddItem Left(xChar1, xLong1 - 1&)
    xChar1 = Mid(xChar1, xLong1 + 2&)
    Loop
  gList.AddItem xChar1
  End Sub

Public Sub CleanUp()
  HasWarning = False
  HasError = False
  xCanOutput = False
  
  Erase xUsedApiString()
  Erase xUsedApiLC()
  Erase xUsedApiPublic()
  Erase xUsedApiFoundDefinition()
  Erase xUsedApiVerCompatible()
  Erase xAssemblyString()
  Erase xAssemblyPublic()
  MyASMCount = 0&
  xTrustedCount = 0&
  Erase xTrusted()
  ApiCount = 0&
  MyFuncs = ""
  Erase xAPI()
  Erase xAPIDefinitionString()
  Erase xAPIDefinitionCode()
  Erase xApiDefinitionIsStruc()
  Erase xAPIDefinitionVerCompatible()
  xAPIDefinitionCount = 0&
  Erase xIncudesString()
  Erase xIncudesLCRP()
  Erase xIncudesPublic()
  xIncudesCount = 0&
  Erase xCompilerDirectiveString()
  Erase xCompilerDirectiveLC()
  xCompilerDirectiveCount = 0
  MyDefines = ""
  
  'Erase xAPI()
  Erase xDoubleDeclarationsStringLC()
  Erase xDoubleDeclarationsFilename()
  Erase xDoubleDeclarationsLineNumber()
  Erase xDoubleDeclarationsErrorOut()
  xAPICountN = 0&
  End Sub

Public Sub IDE_SelectIncludeDir()
  Dim xChar1 As String
  
  xChar1 = CommonDLG_OpenPath(0&, "Choose include directory", xLibBuildIncBase)
  If Not Len(xChar1) = 0& Then
    xLibBuildIncBase = xChar1
    SaveSetting "LibBuild", "Settings", "IncludeDir", xLibBuildIncBase
    End If
  End Sub

Public Sub IDE_Initialize()
  Dim xLong1 As Long
  xLibBuildIncBase = String(260, vbNullChar)
  Call GetModuleFileNameA(0&, xLibBuildIncBase, 258)
  xLong1 = InStrRev(xLibBuildIncBase, "\")
  xLibBuildIncBase = Left(xLibBuildIncBase, xLong1) + "LibBuild\"
  
  
  On Error Resume Next
  xLibBuildIncBase = GetSetting("LibBuild", "Settings", "IncludeDir", xLibBuildIncBase)
  
  'eList.AddItem "Base: " + xLibBuildIncBase
  End Sub
