#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
$sAutoItError_Info = WinGetText("[CLASS:#32770; TITLE:AutoIt Error]")
If $sAutoItError_Info == 0 Then $sAutoItError_Info = ""
$sErrorLine = StringRegExpReplace($sAutoItError_Info, "(?ism).*Line (\d+).*", "\1")
$sScriptFile = StringRegExpReplace($sAutoItError_Info, '(?ism).*\(File "(.*)\.exe"\).*', '\1.au3')
$hGUI = GUICreate("AutoIt script Error Finder", 400, 300)
$nScript_Input = GUICtrlCreateInput($sScriptFile, 20, 30, 340, 20)
$nOpenScript_Btn = GUICtrlCreateButton("...", 360, 29, 22, 22)
GUICtrlCreateLabel("Please enter Error Line (shown by compiled script):", 20, 80)
$nErrLine_Input = GUICtrlCreateInput($sErrorLine, 260, 77, 120, 20, BitOR($ES_NUMBER, $ES_CENTER))
$nErrorLine_Edit = GUICtrlCreateEdit("", 20, 120, 360, 140, BitOR($GUI_SS_DEFAULT_EDIT, $ES_READONLY))
$nGetErrorLine_Btn = GUICtrlCreateButton("Get Error Line", 120, 270, 160, 20)
GUISetState(@SW_SHOW, $hGUI)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $nOpenScript_Btn
Local $sScript = FileOpenDialog("Open AutoIt Script", "", "AutoIt Script (*.au3)", 0, "", $hGUI)
If @error Then ContinueLoop
GUICtrlSetData($nScript_Input, $sScript)
Case $nGetErrorLine_Btn
$sScriptFile = GUICtrlRead($nScript_Input)
$iErrLine = GUICtrlRead($nErrLine_Input)
If Not FileExists($sScriptFile) Or $iErrLine = "" Then
ContinueLoop
EndIf
$sMergedScript = _AU3_LibMergeAllUDFs($sScriptFile)
$aMergedScript = StringSplit(_AU3_LibStripEmptyLines($sMergedScript), @LF)
GUICtrlSetData($nErrorLine_Edit, $aMergedScript[$iErrLine])
EndSwitch
WEnd
Func _AU3_LibMergeAllUDFs($sScriptFile, $iIncludeComments=0, $iIncludeEmptyLines=0, $iRemoveIncludes=1, $iRetData=1)
Local $aGetAllLibs, $aScript_Content, $sRead_SrcScript, $sHeader_Content, $hFOpen, $iIsFuncBody = 0
$sRead_SrcScript = FileRead($sScriptFile)
_AU3_LibGetAllUDFs($sRead_SrcScript, $aGetAllLibs)
If $iRemoveIncludes Then $sRead_SrcScript = StringRegExpReplace($sRead_SrcScript, "(?si)#include.*?[\r\n]+", "")
For $i = $aGetAllLibs[0][0] To 1 Step -1
$iIsFuncBody = 0
$aScript_Content = StringSplit(StringStripCR(StringStripWS(FileRead($aGetAllLibs[$i][1]), 3)), @LF)
For $j = 1 To $aScript_Content[0]
If Not $iIncludeEmptyLines And $aScript_Content[$j] = "" Then
ContinueLoop
EndIf
If Not $iIncludeComments And StringRegExp($aScript_Content[$j], "^(\s+)?;") Then
ContinueLoop
EndIf
If StringRegExp($aScript_Content[$j], "(?i)^(\s+)?#include") Then
ContinueLoop
ElseIf StringRegExp($aScript_Content[$j], "(?i)^(\s+)?Func") Then
$sRead_SrcScript &= @CRLF
$iIsFuncBody = 1
ElseIf StringRegExp($aScript_Content[$j], "(?i)^(\s+)?EndFunc") Then
$sRead_SrcScript &= $aScript_Content[$j] & @CRLF
$iIsFuncBody = 0
ContinueLoop
EndIf
If Not $iIsFuncBody Then
$sHeader_Content &= $aScript_Content[$j] & @CRLF
Else
$sRead_SrcScript &= $aScript_Content[$j] & @CRLF
EndIf
Next
Next
If $sHeader_Content <> "" Then $sRead_SrcScript = $sHeader_Content & @CRLF & $sRead_SrcScript
If $iRetData Then
Return $sRead_SrcScript
Else
$hFOpen = FileOpen(StringTrimRight($sScriptFile, 4) & "_au3lib_merged.au3", 2)
FileWrite($hFOpen, $sRead_SrcScript)
FileClose($hFOpen)
EndIf
EndFunc
Func _AU3_LibGetAllUDFs($sScript_Content, ByRef $aIncludes_Arr)
Local Const $rFile = '(?i)(?:^|[\n\r])[ \t]*#include[ \t]+((?:\<|")[^\n\r\"\>]+(?:\>|"))'
Local Const $rUDFs = '(?i)(?:^|[\n\r])[ \t]*Func[ \t]+([\w\d]+)'
If UBound($aIncludes_Arr, 2) <> 4 Then Dim $aIncludes_Arr[2][4] = [[1, 0, 0], [0, "", 0]]
$aIncludes_Arr[$aIncludes_Arr[0][0]][3] = StringRegExp($sScript_Content, $rUDFs, 3)
Local $sPath, $iType, $sName, $sText
Local $aFile = StringRegExp($sScript_Content, $rFile, 3)
If IsArray($aFile) Then
For $i = 0 To UBound($aFile)-1
$sPath = _AU3_LibIncludeToPath($aFile[$i])
If @error Then ContinueLoop
$iType = @extended
$sName = StringRegExpReplace($sPath, "(?:[^\\]+\\)+", "")
For $j = 1 To $aIncludes_Arr[0][0]
If $aIncludes_Arr[$j][0] == $iType And $aIncludes_Arr[$j][2] == $sName Then ContinueLoop 2
Next
$sText = FileRead($sPath)
If @error Then ContinueLoop
$aIncludes_Arr[0][0] += 1
ReDim $aIncludes_Arr[$aIncludes_Arr[0][0]+1][4]
$aIncludes_Arr[$aIncludes_Arr[0][0]][0] = $iType
$aIncludes_Arr[$aIncludes_Arr[0][0]][1] = $sPath
$aIncludes_Arr[$aIncludes_Arr[0][0]][2] = $sName
_AU3_LibGetAllUDFs($sText, $aIncludes_Arr)
Next
EndIf
EndFunc
Func _AU3_LibIncludeToPath($sInclude)
Local $aRegExp = StringRegExp($sInclude, '^(<|"|'')([^>"]+)(?:>|"|'')$', 3)
If Not IsArray($aRegExp) Then Return SetError(1, 0, "")
$sInclude = $aRegExp[1]
If StringInStr($sInclude, "\") = 0 Then
Local $sSYS, $sUDL, $aUDL, $sAU3 = @ScriptDir & "\" & $sInclude
$sSYS = StringRegExpReplace(@AutoItExe, "\\[^\\]+$", "")
$sSYS &= "\Include\"& $sInclude
$sUDL = RegRead("HKCU\Software\AutoIt v3\AutoIt", "Include")
$aUDL = StringRegExp($sUDL, "([^;]+)(?:;|$)", 3)
If $aRegExp[0] == '<' Then
If FileExists($sSYS) Then Return SetError(0, 1, $sSYS)
ElseIf $aRegExp[0] == '"' Then
If FileExists($sAU3) Then Return SetError(0, 2, $sAU3)
EndIf
If IsArray($aUDL) Then
For $i = 0 To UBound($aUDL)-1
$aUDL[$i] &= "\" & $sInclude
If FileExists($aUDL[$i]) Then Return SetError(0, 3, $aUDL[$i])
Next
EndIf
If $aRegExp[0] == '<' Then
If FileExists($sAU3) Then Return SetError(0, 2, $sAU3)
ElseIf $aRegExp[0] == '"' Then
If FileExists($sSYS) Then Return SetError(0, 1, $sSYS)
EndIf
Else
If FileExists($sInclude) Then Return SetError(0, 4, $sInclude)
EndIf
Return SetError(2, 0, "")
EndFunc
Func _AU3_LibStripEmptyLines($sFileContent)
If FileExists($sFileContent) Then
$sFileContent = FileRead($sFileContent)
EndIf
$sFileContent = StringRegExpReplace($sFileContent, "(?i)#include-once", "")
$sFileContent = StringRegExpReplace($sFileContent, "[\r?\n]{2,}", @CRLF)
$sFileContent = StringRegExpReplace($sFileContent, "\r?\n\s*;.*?", "")
Return $sFileContent
EndFunc