Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  

Показать сообщение отдельно

Аватара для Creat0R

Must AutoIt


Сообщения: 3054
Благодарности: 1009

Профиль | Сайт | Отправить PM | Цитировать


amel27, Я тут в придачу к твоим функциям _AU3_* написал ещё одну, _AU3_MergeAllLibs() - превращает исходный скрипт в один целый, со всеми инклюдами (указанными в нём) и константами. Для это мне пришлось немного изменить _AU3_GetAllLibUDF, чтобы возвращала ещё и полный путь к инклюду.

Код: Выделить весь код
_AU3_MergeAllLibs(@ScriptDir & "\Test.au3", 0, 0, 1)

; ===============================================================
; _AU3_MergeAllLibs($sScriptFile, $iIncludeComments=0, $iRemoveIncludes=1)
; ---------------------------------------------------------------
; Смешивает вложенные библиотеки в тело скрипта
;  (таким образом преобразовывая один цельный скрипт со всеим функциями и переменными)
; Использован AutoIT v3.2.12.1
;
; $sScriptFile        : AutoIT-скрипт для смешивания
; $iIncludeComments   : Определяет, нужно ли обрабатывать закомментированные строки
; $iIncludeEmptyLines : Определяет, нужно ли обрабатывать пустые строки
; $iRemoveIncludes    : Определяет, нужно ли удалять строки #include'ов с исходного скрипта
;
; Автор               : G.Sandler (a.k.a CreatoR)
; ===============================================================
Func _AU3_MergeAllLibs($sScriptFile, $iIncludeComments=0, $iIncludeEmptyLines=0, $iRemoveIncludes=1)
    Local $aGetAllLibs, $aScript_Content, $sRead_SrcScript, $sHeader_Content, $hFOpen, $iIsFuncBody = 0
    $sRead_SrcScript = FileRead($sScriptFile)

    _AU3_GetAllLibUDF($sRead_SrcScript, $aGetAllLibs)

    If $iRemoveIncludes Then $sRead_SrcScript = StringRegExpReplace($sRead_SrcScript, "(?i)(?s)#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
            If Not $iIncludeComments And StringLeft($aScript_Content[$j], 1) = ";" Then ContinueLoop

            If StringLeft($aScript_Content[$j], 8) = "#include" Then
                ContinueLoop ;We don't need the #includes, right?
            ElseIf StringLeft($aScript_Content[$j], 4) = "Func" Then
                $sRead_SrcScript &= @CRLF
                $iIsFuncBody = 1
            ElseIf StringLeft($aScript_Content[$j], 7) = "EndFunc" Then
                $sRead_SrcScript &= $aScript_Content[$j] & @CRLF
                $iIsFuncBody = 0

                ContinueLoop
            EndIf

            If Not $iIsFuncBody Then ;Write to the Begining of file (Collecting the variables/constants Header)
                $sHeader_Content &= $aScript_Content[$j] & @CRLF
            Else ;Write to the End of file (UDF functions)
                $sRead_SrcScript &= $aScript_Content[$j] & @CRLF
            EndIf
        Next
    Next

    If $sHeader_Content <> "" Then $sRead_SrcScript = $sHeader_Content & @CRLF & $sRead_SrcScript

    $hFOpen = FileOpen($sScriptFile, 2)
    FileWrite($hFOpen, $sRead_SrcScript)
    FileClose($hFOpen)
EndFunc ; ==> _AU3_MergeAllLibs

; ===============================================================
; _AU3_GetAllLibUDF($sScript_Content, $aIncludes_Arr)
; ---------------------------------------------------------------
; Возвращает массив всех загруженных UDF и библиотечных файлов
; Использован AutoIT v3.2.12.0
;
; $sScript_Content       : текст AutoIT-скрипта
; $aIncludes_Arr         : ссылка на переменную для выходного массива,
;                 по выходу содержит двумерный массив:
;                   $aIncludes_Arr[0][0]  - количество элементов в массиве
;                   $aIncludes_Arr[$i][0] - тип библиотечного файла
;                   $aIncludes_Arr[$i][1] - Полный путь библиотечного файла
;                   $aIncludes_Arr[$i][2] - Только имя библиотечного файла
;                   $aIncludes_Arr[$i][3] - массив UDF, определенных в файле
;
; Функция рекурсивная, поэтому выход по ошибке не предусмотрен
;
; Автор                  : amel27
; ===============================================================
Func _AU3_GetAllLibUDF($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]+)'

    ; Инициализация массива при первом входе / сохранение списка UDF
    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_LibIncToPath($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_GetAllLibUDF($sText, $aIncludes_Arr)
        Next
    EndIf
EndFunc ; ==> _AU3_GetAllLibUDF

; ===============================================================
; _AU3_LibIncToPath($sInclude)
; ---------------------------------------------------------------
; Возвращает полный путь к библиотечному файлу по строке загрузки
; Использован AutoIT v3.2.12.0
;
; $sInclude   : строка загрузки в формате #include, примеры:
;               '<array.au3>'
;               '"array.au3"'
;               '"c:\Program Files\AutoIT3\Include\array.au3"'
;
; При успехе  : возвращает полное имя файла, содержащее путь,
;               макрос @extended указывает на тип библиотеки:
;               1 - системная библиотека (каталог установки)
;               2 - текущая библиотека (каталог скрипта)
;               3 - пользовательская библиотека (путь из реестра)
;               4 - путь к библиотеке явно указан при загрузке
;
; При неудаче : возвращает пустую строку и устанавливает @error:
;               1 - ошибка формата строки
;               2 - файл не найден
;
; Автор       : amel27
; ===============================================================
Func _AU3_LibIncToPath($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)

        ; Проверка типов 1 и 2 (до пользовательских библиотек)
        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

        ; Проверка типа 3 (поиск среди пользовательских библиотек)
        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

        ; Проверка типов 1 и 2 (после пользовательских библиотек)
        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
        ; Проверка типа 4 (файл с указанием полного пути)
        If FileExists($sInclude) Then Return SetError(0, 4, $sInclude)
    EndIf

    ; ОШИБКА: файл не найден
    Return SetError(2, 0, "")
EndFunc ; ==>  _AU3_LibIncToPath
Скрипт для тестирования - Test.au3:

Код: Выделить весь код
#include <Array.au3>

$GUI = GUICreate("Test Script", 300, 200)

$Button = GUICtrlCreateButton("Button", 20, 40, 60, 20)

GUISetState(@SW_SHOW, $GUI)

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
    EndSwitch
WEnd
Если запустить в AutoIt 3.2.8.1, то можно убедиться, что изменение структуры #includ'ов в новых версиях было оправдано, в одной лишь Array сколько констант и UDF'ов.

-------
“Сделай так просто, как возможно, но не проще этого.”... “Ты никогда не решишь проблему, если будешь думать так же, как те, кто её создал.”

Альберт Эйнштейн

P.S «Не оказываю техподдержку через ПМ/ICQ, и по email - для этого есть форум. ©»

http://creator-lab.ucoz.ru/Images/Icons/autoit_icon.png Русское сообщество AutoIt | http://creator-lab.ucoz.ru/Images/Ic...eator_icon.png CreatoR's Lab | http://creator-lab.ucoz.ru/Images/Icons/oac_icon.png Opera AC Community


Отправлено: 01:33, 14-11-2008 | #1144