#include <WinAPIFiles.au3>
Global $sAutoItExe = @AutoItExe ;Should be 3.3.12.0 / 3.3.9.4 / 3.3.8.X / 3.3.6.X
;Global $sAutoItExe = 'D:\AutoIt_Versions\AutoIt_3.3.12.0\AutoIt3.exe'
$sFile = FileOpenDialog('Select script file (source from your compiled script)...', @ScriptDir, 'AutoIt v3 Script (*.au3)')
If @error Then Exit
$iLine = InputBox('Get error code line', 'Please enter error line number from compiled script:' & @CRLF & @CRLF & '(the AutoIt version of selected source file should match the version that used to compile the script)', '')
If @error Then Exit
SplashTextOn('Generating error code line', 'Please wait...', 200, 50, -1, -1, BitOR(16, 32), '', 12, 800)
$sCodeLine = _AU3_GetErrLineCode($sFile, $iLine)
SplashOff()
MsgBox(64, 'Result', StringFormat('Error code line (#%i) for <%s>:\r\n%s', $iLine, StringRegExpReplace($sFile, '^.*\\', ''), $sCodeLine))
Func _AU3_GetErrLineCode($sScript_File, $iLine)
Local $sSrc_Raw, $iPos1, $iPos2, $iLen
$sSrc_Raw = _AU3_StripToRaw($sScript_File)
If @error Then
Return SetError(1, 0, '')
EndIf
$sSrc_Raw = StringStripWS($sSrc_Raw, 3)
$iPos1 = StringInStr($sSrc_Raw, @LF, 2, $iLine - 1)
$iPos2 = StringInStr($sSrc_Raw, @LF, 2, $iLine)
$iLen = ($iPos2 > 0 ? $iPos2 - $iPos1 : -1)
Return StringStripWS(StringMid($sSrc_Raw, $iPos1, $iLen), 3)
EndFunc
Func _AU3_StripToRaw($sSrcFile, $bReset = False)
If $sSrcFile = '' Or Not FileExists($sSrcFile) Then
Return SetError(1, 0, 0)
EndIf
Local Static $sSrcRaw = ''
Local Static $sInclds = '|'
If $bReset Then
$sSrcRaw = ''
$sInclds = '|'
EndIf
Local $sInclude = '', $sLine = '', $iPos = 0, $sFName = '', $sFnc = '', $aFnc, $aVars
Local $sScriptDir = StringRegExpReplace($sSrcFile, '\\[^\\]+$', '')
Local $sRead = FileRead($sSrcFile)
;!!! Strip comment block here (before checking #include-once)...
_AU3_StringStripCommentBlocks($sRead)
If StringRegExp($sRead, '(?mi)^\h*#include-once') Then
If StringInStr($sInclds, '|' & $sSrcFile & '|', 2) Then
$sRead = StringRegExpReplace($sRead, '(?msi)\R?^\h*#include-once.*', '')
Else
$sInclds &= $sSrcFile & '|'
EndIf
EndIf
$sRead = StringStripCR($sRead)
Local $aRead = StringSplit($sRead, @LF)
For $i = 1 To $aRead[0]
If StringStripWS($aRead[$i], 8) = '' Then
ContinueLoop
EndIf
If StringRegExp($aRead[$i], '(?i)^\h*(;|#include-once|#pragma\h+compile\()') Then
ContinueLoop
EndIf
_AU3_StringStripComments($aRead[$i])
If Not StringRegExp($aRead[$i], '(?i)^\h*#include\h*[<"'']') Then
$sLine = $aRead[$i]
;Merge broken (with _) lines
If StringRegExp($aRead[$i], '_\h*$') Then
$sLine = StringRegExpReplace($aRead[$i], '^\h+|[_\h]+$', '')
While 1
$i += 1
If $i >= $aRead[0] Then
ExitLoop
EndIf
_AU3_StringStripComments($aRead[$i])
$aRead[$i] = StringRegExpReplace($aRead[$i], '[_\h]+$', '')
If @extended = 0 Then
$sLine &= ' ' & StringStripWS($aRead[$i], 1)
ExitLoop
EndIf
$sLine &= ' ' & StringStripWS($aRead[$i], 1)
WEnd
EndIf
$sSrcRaw &= StringStripWS($sLine, 1) & @CRLF
ContinueLoop
EndIf
;Get include path
$sInclude = _AU3_IncludeToPath($aRead[$i], $sScriptDir)
If Not @error Then
;Recursive call for include
$sSrcRaw = _AU3_StripToRaw($sInclude)
EndIf
Next
Return $sSrcRaw
EndFunc
Func _AU3_IncludeToPath($sInclude, $sScriptDir = @ScriptDir)
Local $aRegExp, $aRet, $sSYS, $sAU3, $sWorkDir
Local $iError = 0, $sRet = ''
$aRegExp = StringRegExp($sInclude, '(?i)^\h*#include\h+(<|"|'')([^>"'']+)(?:>|"|'')\h*(;.*?)?$', 3)
If UBound($aRegExp) < 2 Then
Return SetError(1, 0, '')
EndIf
$sInclude = $aRegExp[1]
;Get AutoIt Include folder
Local Static $sAutoIt_Incl_Dir = StringRegExpReplace($sAutoItExe, '\\[^\\]+$', '') & '\Include'
;Get User Include folders
Local Static $aUDL = StringRegExp(RegRead('HKCU\Software\AutoIt v3\AutoIt', 'Include'), '([^;]+)(?:;|$)', 3)
While 1
;Check include type 4 (include with full path)
If Not _WinAPI_PathIsRelative($sInclude) Then
If FileExists($sInclude) Then
$sRet = $sInclude
Else
$iError = 2
EndIf
ExitLoop
EndIf
;Set Current & AutoIt Include file
$sAU3 = $sScriptDir & '\' & $sInclude
$sSYS = $sAutoIt_Incl_Dir & '\' & $sInclude
;Check include type 1 and 2 (before user includes check)
If $aRegExp[0] == '<' Then
If FileExists($sSYS) Then
$sRet = $sSYS
ExitLoop
EndIf
ElseIf $aRegExp[0] == '"' Or $aRegExp[0] == "'" Then
If FileExists($sAU3) Then
$sRet = $sAU3
ExitLoop
EndIf
EndIf
;Check include type 3 (search in user includes)
For $i = 0 To UBound($aUDL) - 1
$aUDL[$i] &= '\' & $sInclude
If FileExists($aUDL[$i]) Then
$sRet = $aUDL[$i]
ExitLoop 2
EndIf
Next
;Check include type 1 and 2 (after user includes check)
If $aRegExp[0] == '<' Then
If FileExists($sAU3) Then
$sRet = $sAU3
ExitLoop
EndIf
ElseIf $aRegExp[0] == '"' Or $aRegExp[0] == "'" Then
If FileExists($sSYS) Then
$sRet = $sSYS
ExitLoop
EndIf
EndIf
;Include file not found
$iError = 3
ExitLoop
WEnd
If Not $iError Then
$sWorkDir = @WorkingDir
If $sWorkDir <> $sScriptDir Then
FileChangeDir($sScriptDir)
EndIf
$sRet = _WinAPI_GetFullPathName($sRet)
If @error Or $sRet = '' Then
$iError = 4
EndIf
If $sWorkDir <> $sScriptDir Then
FileChangeDir($sWorkDir)
EndIf
Else
$sRet = ''
EndIf
Return SetError($iError, 0, $sRet)
EndFunc
Func _AU3_StringStripCommentBlocks(ByRef $sString)
Local $aSplit = StringSplit(StringStripCR($sString), @LF)
Local $iCmntsStart_Count
$sString = ''
For $i = 1 To $aSplit[0]
If StringRegExp($aSplit[$i], '(?i)^\h*#(cs|comments-start)([\h;].*)?$') Then
$iCmntsStart_Count = 1
While 1
If $i + 1 >= $aSplit[0] Then
ExitLoop
EndIf
$i += 1
If StringRegExp($aSplit[$i], '(?i)^\h*#(cs|comments-start)([\h;].*)?') Then
$iCmntsStart_Count += 1
ContinueLoop
EndIf
If StringRegExp($aSplit[$i], '(?i)^\h*#(ce|comments-end)([\h;].*)?') Then
$iCmntsStart_Count -= 1
If $iCmntsStart_Count <= 0 Then
ExitLoop
EndIf
EndIf
WEnd
ContinueLoop
EndIf
$sString &= $aSplit[$i] & @CRLF
Next
EndFunc
Func _AU3_StringStripComments(ByRef $sString)
Local $aStrs = StringRegExp($sString, '("[^"]*"|''[^'']*'')', 3)
Local $sStrs = StringRegExpReplace($sString, '("[^"]*"|''[^'']*'')', '#~_~@~_~#')
Local $iInStr = StringInStr($sStrs, ';', 2)
If $iInStr = 0 Then
Return
EndIf
$sString = StringStripWS(StringLeft($sStrs, $iInStr - 1), 2)
For $i = 0 To UBound($aStrs) - 1
$sString = StringReplace($sString, '#~_~@~_~#', $aStrs[$i], 1, 2)
Next
EndFunc