; :collapseFolds=0:maxLineLen=80:mode=autoitscript:tabSize=8:indentSize=8:folding=indent: Global Const $__DEBUG__ = False ;#__DEBUG__ #include ;#__DEBUG__ Main() Func Main() Local Const $sFile = "c:\\test" FileWrite(FileOpen($sFile & "_opt.au3", 130), _Au3Optim(FileRead($sFile & ".au3"))) EndFunc ;==>Main ; #FUNCTION# =================================================================== ; Name ..........: _Au3Optim ; Description ...: Optmizes au3-source-code, replaces inline-functions, replaces #define ; AutoIt Version : V3.3.0.0 ; Syntax ........: ; Parameter(s): .: $__sAu3__ - au3-source-code ; Return Value ..: Success - string ; @extended - StringLen ; Failure - string ; Author(s) .....: Thorsten Willert ; Date ..........: Mon Dec 21 21:41:27 CET 2009 ; Version .......: 0.37-8 #cs ToDo: - adding commandline paramters - prevent the calculation in strings - fixing the error with Global Const arrays - optimzing the math calculation - removing unused vars - replacing Local Const V0.37-8 fixed: error by removing () #ce ; ============================================================================== Func _Au3Optim($sAu3) If Not StringLen($sAu3) Then Return "" If @AutoItVersion > "3.3.0.0" Then Local Const $sFileInclude = "_Patch.au3" Local $sInclude = FileRead(@ProgramFilesDir & "\AutoIt3\Include\" & $sFileInclude) $sInclude = StringRegExpReplace($sInclude, '[ \t]*;.*?[\n\r]', @CRLF) ; removing line comments $sInclude = StringRegExpReplace($sInclude, '[\n\r]+', @CRLF) $sInclude = StringRegExpReplace($sInclude, '([\n\r])[ \t]+', '$1') $sAu3 = $sInclude & @CRLF & $sAu3 EndIf Local $aTMP, $sTMP, $sStr = "", $c = 0, $iE ; merging lines $sAu3 = StringRegExpReplace($sAu3, '\b\s*_\s*\n\s*', ' ') ConsoleWrite("Merged - Lines: " & @extended & @CRLF) ; merging strings $sAu3 = StringRegExpReplace($sAu3, '("|'')\s*&\s*\1', '') ConsoleWrite("Merged - Strings: " & @extended & @CRLF) ; caching all strings $aTMP = StringRegExp($sAu3, '((''|").*?\2)', 3) ;_ArrayDisplay($aTMP) ;#__DEBUG__ $iE = UBound($aTMP) - 1 For $i = 0 To $iE Step 2 $sStr &= $aTMP[$i] Next $sAu3 = __Define($sAu3) ; replacing #define directives If @error Then Exit 1 $sAu3 = __ReplaceInlineFunc($sAu3) ; replacing "inline" functions ;Return $sAu3 ; GLOBAL constants ; 1) split all const in one line: While True $sAu3 = StringRegExpReplace($sAu3, '(?i)(Global\s+Const\s+\$\w+\s*=.*?\s*)(,\s*)(\$.*?)', '$1' & @CRLF & 'Global Const $3') If Not @extended Or @error Then ExitLoop If $__DEBUG__ Then MsgBox(0, "DEBUG:", "DEBUG (" & @ScriptLineNumber - 2 & ") ==> $sAu3: " & $sAu3) ;#__DEBUG__ WEnd ; 2) replacing contants While True $aTMP = StringRegExp($sAu3, '(?i)Global\s+Const\s+\$(\w+)\s*=\s*(.*?)\s*\n', 1) If @error Then ExitLoop $sAu3 = StringRegExpReplace($sAu3, '\$' & $aTMP[0] & '\b', $aTMP[1]) $c += @extended WEnd $sAu3 = StringRegExpReplace($sAu3, '(?i)Global\s+Const\s+.*?\n', "") ConsoleWrite("Replaced - Global constants: " & $c - @extended & @CRLF) ; replace StringFormat $c = 0 $aTMP = StringRegExp($sAu3, '(?i)(StringFormat\(("|'').*?\2.*\))', 3) If Not @error Then $iE = UBound($aTMP) - 1 For $i = 0 To $iE Step 2 If Not StringInStr($aTMP[$i], "$") Then $sAu3 = StringReplace($sAu3, $aTMP[$i], '"' & __Exec($aTMP[$i]) & '"') $c += 1 EndIf Next EndIf ConsoleWrite("Replaced - StringFormat: " & $c & @CRLF) ; replace StringLower/Upper/Left/Right/Mid/Len/StripWS/StripCR/TrimLeft|TrimRight|Replace $c = 0 $aTMP = StringRegExp($sAu3, '(?i)(String(?:Lower|Upper|Left|Right|Mid|Len|StripWS|StripCR|TrimLeft|TrimRight|Replace)\(("|'').*?\2\))', 3) If Not @error Then $iE = UBound($aTMP) - 1 For $i = 0 To $iE Step 2 If Not StringInStr($aTMP[$i], "$") Then $sAu3 = StringRegExpReplace($sAu3, '\b' & __RegExMask($aTMP[$i]), '"' & __Exec($aTMP[$i]) & '"') $c += 1 EndIf Next EndIf ConsoleWrite("Replaced - String-functions: " & $c & @CRLF) ; replace Math-functions $c = 0 $aTMP = StringRegExp($sAu3, '(?i)((?:A?Sin|A?Cos|A?Tan|Abs|Ceiling|Exp|Floor|Log|Mod|Round|Sqrt)\(.*?\))', 3) If Not @error Then ;_ArrayDisplay($aTMP) ;#__DEBUG__ $iE = UBound($aTMP) - 1 For $i = 0 To $iE If Not StringInStr($aTMP[$i], "$") And Not StringInStr($aTMP[$i], "random", 2) Then $sAu3 = StringRegExpReplace($sAu3, __RegExMask($aTMP[$i]), __Exec($aTMP[$i])) $c += 1 EndIf Next EndIf ConsoleWrite("Replaced - Math-functions: " & $c & @CRLF) ; replace BitAnd/BitOr $c = 0 $aTMP = StringRegExp($sAu3, '(?i)(Bit(?:Or|And|Xor|Not)\(.*?\))', 3) If Not @error Then $iE = UBound($aTMP) - 1 For $i = 0 To $iE If Not StringInStr($aTMP[$i], "$") Then $sAu3 = StringRegExpReplace($sAu3, __RegExMask($aTMP[$i]), "0x" & Hex(__Exec($aTMP[$i]))) $c += 1 EndIf Next EndIf ConsoleWrite("Replaced - Bit-functions: " & $c & @CRLF) ; replace simple calculations $c = 0 While True $aTMP = StringRegExp($sAu3, '\s*((?:(?:\$?\d*\.?\w+)\s*[\+\-\*\^/]\s*)+(?:\s*\$?\d*\.?\w+))\s*', 3) If Not @error Then ;_ArrayDisplay($aTMP) ;#__DEBUG__ $iE = UBound($aTMP) - 1 For $i = 0 To $iE If Not StringInStr($sStr, $aTMP[$i]) Then $sTMP = __Exec($aTMP[$i]) If $sTMP Then $sAu3 = StringReplace($sAu3, $aTMP[$i], $sTMP) $c += 1 EndIf Next EndIf While True $aTMP = StringRegExp($sAu3, '\b(\d*\.?\d+\b\s*[/\*\^]\s*\b\d*\.?\d+)\b', 1) If @error Then ExitLoop $iE = UBound($aTMP) - 1 For $i = 0 To $iE $sAu3 = StringReplace($sAu3, $aTMP[$i], __Exec($aTMP[$i]), 1) Next $c += 1 WEnd $sAu3 = StringRegExpReplace($sAu3, '(=\s*\(?|\s+|\W)\(\s*(\d*\.?\d+)\s*\)', '$1 $2') If Not @extended Or @error Then ExitLoop WEnd ConsoleWrite("Replaced - Calculations: " & $c & @CRLF) ; replace $i = $i [+*/-&] $j with $i [+*/-&]= $j $sAu3 = StringRegExpReplace($sAu3, '(\$[\w]+(?:\[.*/&])?)\s*=\s*\1\s*([\+\-\*/&])', '$1 $2= ') ConsoleWrite("Optimized - $a +|*|-|/=: " & @extended & @CRLF) ; removing "Step 1" $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(For\s+.*?)Step\s*1\b', '$1') ConsoleWrite("Removed - For ... Step 1: " & @extended & @CRLF) ; replace If $a = [false|0] Then / with If Not $a Then $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(ElseIf|If|Or|And|Case)\s+(\$?[\w\(\),\[\]''"]+|@ERROR)\s*=\s*(?:false|0)\b', '$1 Not $2') ConsoleWrite("Optimized - If $v = False|0: " & @extended & @CRLF) ; replace If $a = [true|1] Then / with If $a Then $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(ElseIf|If|Or|And|Case)\s+(\$?[\w\(\),\[\]''"]+|@ERROR)\s*=\s*(?:true)\b', '$1 $2') ConsoleWrite("Optimized - If $v = True|1: " & @extended & @CRLF) ; replace If $a = [""|''] Then / with If Not $a Then $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(ElseIf|If|Or|And|Case)\s+(\$?[\w\(\),\[\]''"]+)\s*=\s*[''"]{2}', '$1 Not $2 ') ConsoleWrite("Optimized - If $v = ""|'': " & @extended & @CRLF) ; replace If $a <> [""|''] Then / with If $a Then $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(ElseIf|If|Or|And|Case)\s+(\$?[\w\(\),\[\]]+)\s*<>\s*[''"]{2}', '$1 $2') ConsoleWrite("Optimized - If $v <> ""|'': " & @extended & @CRLF) ; merging one-line If-block $sAu3 = StringRegExpReplace($sAu3, '(?i)\bIf(.*?)Then\s*\n\s*(.*?)\n\s*EndIf\s*', 'If$1Then $2') ConsoleWrite("Optimized - One-line If-blocks: " & @extended & @CRLF) $sAu3 = StringRegExpReplace($sAu3, '(?i)\bIf\s*(.*?)\s*Then If\s+(.*?)\s*Then\s+(.*?)', 'If ($1) And ($2) Then $3') ConsoleWrite("Merged - One-line If-blocks: " & @extended & @CRLF) ; removing redunant ElseIf $sAu3 = StringRegExpReplace($sAu3, '(?is)\bIf\s+(.*?)\s+Then(.*?)ElseIf\s+Not\s+\1\s+Then(.*?)EndIf', 'If $1 Then$2Else$3EndIf') ConsoleWrite("Optimized - ElseIf Not: " & @extended & @CRLF) $sAu3 = StringRegExpReplace($sAu3, '(?is)\bIf\s+Not\s+(.*?)\s+Then(.*?)ElseIf\s+\1\s+Then(.*?)EndIf', 'If Not $1 Then$2Else$3EndIf') ConsoleWrite("Optimized - ElseIf: " & @extended & @CRLF) ; removing some useless () $sAu3 = StringRegExpReplace($sAu3, '(?i)\b(Return|Exit)\s*\((.*?)\)', '$1 $2') ConsoleWrite("Optimized - Return: " & @extended & @CRLF) ;$sAu3 = StringRegExpReplace($sAu3, '(?i)\W\((\b\w+\(.*?\)|\$\w+)\)', ' $1') ;$c = 0;@extended ;$sAu3 = StringRegExpReplace($sAu3, '(?i)=\s*\((.*?)\)', '= $1') ;ConsoleWrite("Optimized - (): " & @extended + $c & @CRLF) ; merging strings again $sAu3 = StringRegExpReplace($sAu3, '("|'')\s*&\s*\1', '') ConsoleWrite("Merged - Strings: " & @extended & @CRLF) $sAu3 = StringRegExpReplace($sAu3, '[\n\r]+', @CRLF) SetExtended(StringLen($sAu3)) Return $sAu3 EndFunc ;==>_Au3Optim ;=============================================================================== Func __Exec($s) ; nicht !!! optimieren Return Execute($s) EndFunc ;==>__Exec Func __RegExMask($s) Return StringRegExpReplace($s, '(\$|\\|\+|\-|\.|\*|\(|\)|\[|\]|\{|\})+', '\\$1') EndFunc ;==>__RegExMask ; #FUNCTION# =================================================================== ; Name ..........: __Define ; Description ...: Replaces #define statements ; AutoIt Version : V3.3.0.0 ; Syntax ........: __Define($sAu3) ; Parameter(s): .: $sAu3 - au3-source-code ; Return Value ..: Success - string ; Failure - string ; Author(s) .....: Thorsten Willert ; Date ..........: Wed Dec 23 09:46:20 CET 2009 ; Version .......: 0.5 ; ============================================================================== Func __Define($sAu3) Local $sCall, $aCall, $aArgsC, $aArgs, $sDef ; searching constant-definitions .. Local $aTMP = StringRegExp($sAu3, '(?i)#define\s+([@\$].*?)\s+(.*)', 3) $sAu3 = StringRegExpReplace($sAu3, '(?i)#define\s+[@\$].*?\n', "") ; ... replacing them Local $iE = UBound($aTMP) - 1 For $i = 0 To $iE Step 2 $sAu3 = StringRegExpReplace($sAu3, __RegExMask($aTMP[$i]) & '\b', StringStripWS($aTMP[$i + 1], 3)) Next ; searching macro-definitions Local $aDef = StringRegExp($sAu3, '(?i)\s*#define\s+(\w+\(.*?\))\s+(\w+\(.*?\))', 3) For $i = 0 To UBound($aDef) - 1 Step 2 ; extracting macro-name $sCall = StringMid($aDef[$i], 1, StringInStr($aDef[$i], "(") - 1) ; searching macro-calls $aCall = StringRegExp($sAu3, '(?i)\s*' & $sCall & '\((.*?)\)\s*', 3) ; splitting arguments in macro-definition $aArgsC = __SplitArgs($aCall[0]) For $j = 1 To UBound($aCall) - 1 $sDef = $aDef[$i + 1] ; splitting arguments in macro-call $aArgs = __SplitArgs($aCall[$j]) ; error if number of parameters in definition and call are different If UBound($aArgsC) <> UBound($aArgs) Then ConsoleWriteError("Error: #define: " & $aDef[$i] & " / Call: " & $sCall & "(" & $aCall[$j] & ")" & _ @CRLF & "==> Incorrect number of parameters in macro call" & @CRLF) Return SetError(1) EndIf ; replacing arguments For $k = 0 To UBound($aArgs) - 1 $sDef = StringReplace($sDef, $aArgsC[$k], StringStripWS($aArgs[$k], 3)) Next ; replacing macro ConsoleWrite("Replacing: " & $sCall & "(" & $aCall[$j] & ") ==> " & $sDef & @CRLF) $sAu3 = StringReplace($sAu3, $sCall & "(" & $aCall[$j] & ")", $sDef) Next Next ; removing definitions $sAu3 = StringRegExpReplace($sAu3, '(?i)#define\s+\w+\(.*?\n', "") Return $sAu3 EndFunc ;==>__Define ; #FUNCTION# =================================================================== ; Name ..........: __ReplaceInlineFunc ; Description ...: ; AutoIt Version : V3.3.0.0 ; Syntax ........: __ReplaceInlineFunc($sAu3) ; Parameter(s): .: $sAu3 - au3-source-code ; Return Value ..: Success - string ; Failure - string ; Author(s) .....: Thorsten Willert ; Date ..........: Wed Dec 23 09:49:38 CET 2009 ; Version .......: 0.45 #cs V0.45 - fixed: Errors with some function calls V0.44: - removed: function optimizations V0.43: - fixed: Error replacing parameters - fixed: Error replacing function-calls V0.42: - fixed: removing functions before replacing the calls V0.41: - fixed: Error with functions without parameters #ce ; ============================================================================== Func __ReplaceInlineFunc($sAu3) Local $aArgsC[1], $aArgs[1], $aCall ; search "inline" functions Local $aInl = StringRegExp($sAu3, '(?i)\n\s*Func (.*)\((.*?)\).*\n\s*Return(.*?)\n\s*EndFunc', 3) ; array: ; [0] Func-name ; [1] Arguments ; [2] Function Local $iT, $iAC, $sArg ; Parse and replace functions Local $iE = UBound($aInl) - 1 For $i = 0 To $iE Step 3 ; splitting arguments $aArgs = __SplitArgs($aInl[$i + 1]) If @error Then $aArgs[0] = $aInl[$i + 1] ; search functions-calls $aCall = StringRegExp($sAu3, '.*' & $aInl[$i] & '\((.*?)\)', 3) ;_ArrayDisplay($aCall) ; parse and replace function-calls $iT = UBound($aCall) - 1 For $k = 0 To $iT $sArg = $aInl[$i + 2] ; splitting arguments $aArgsC = __SplitArgs($aCall[$k]) If @error Then $aArgsC[0] = $aCall[$k] If UBound($aArgs) <> UBound($aArgsC) Then ConsoleWriteError("Error: " & $aCall[$k] & " :: " & $sArg & @CRLF & "==> parsing parameters" & @CRLF) ContinueLoop 2 EndIf ; replace arguments from function-call inside the function $iAC = UBound($aArgsC) - 1 If $aArgsC[0] Then For $j = 0 To $iAC $sArg = StringReplace(StringStripWS($sArg, 3), StringStripWS($aArgs[$j], 3), StringStripWS($aArgsC[$j], 3), 0, 2) Next EndIf ; removing the function $sAu3 = StringRegExpReplace($sAu3, '(?i)\s*Func\s+' & __RegExMask($aInl[$i]) & '.*?\n\s*Return.*?\n\s*EndFunc.*?\n', @CRLF) ; replacing the function-calls ConsoleWrite("Replacing: " & $aInl[$i] & "(" & $aCall[$k] & ") ==> " & $sArg & @CRLF) $sAu3 = StringRegExpReplace($sAu3, '(?i)(.*?)' & $aInl[$i] & '\(.*?\)', '${1}' & StringStripWS($sArg, 3), 1) Next Next Return $sAu3 EndFunc ;==>__ReplaceInlineFunc ; #FUNCTION# =================================================================== ; Name ..........: __SplitArgs ; Description ...: ; AutoIt Version : V3.3.0.0 ; Syntax ........: __SplitArgs($s) ; Parameter(s): .: $s - Arguments as string ; Return Value ..: Success - Array ; Failure - ; Author(s) .....: Thorsten Willert ; Date ..........: Wed Dec 23 18:40:57 CET 2009 ; Version .......: 2.0 ; ============================================================================== Func __SplitArgs($s) Local $r[1] = [""], $t, $b1 = False, $b2 = False, $iP = 0 For $i = 1 To StringLen($s) $t = StringMid($s, $i, 1) Select Case $t = " " And Not $b1 And Not $b2 And Not $iP ContinueLoop Case $t = '"' And $b1 $b1 = False Case $t = '"' And Not $b2 $b1 = True Case $t = "'" And $b2 $b2 = False Case $t = "'" And Not $b1 $b2 = True Case $t = ")" And $iP $iP -= 1 Case $t = "(" $iP += 1 Case $t = "," And Not $b1 And Not $b2 And Not $iP $t = '' ReDim $r[UBound($r) + 1] EndSelect $r[UBound($r) - 1] &= $t Next If Not $r[0] Then Return SetError(1,0,$r) Return $r EndFunc ;==>_SplitArgs