Jump to content

junkew
 Share

Recommended Posts

Working on a new version of iuiautomation and uia wrappers I needed a better way of getting my interface's

Concept version 0.6 to generate based on idl file an au3 file with the definitions.

As allways its more complicated then I thought ;-) due to small differences in the idl files on closing braces, separating inheritance colon inconsistencies in the idl tool that generates them so most likely its better to write a lexer/parser then the search/replace I do now

Alternatives

  • typelibinspector but could not generate them all at once
  • aiowrappergenerator was generating for aio and not for objcreateinterface
  • based on tli interfaces / xml but seemed incomplete

Known issues

  • Enums without given constant values to be filled in manually
  • Enum adding fix first parameter to have a $
  • Empty interfaces fail on _ to be replaced with ""
  • propput and propget deal with methods with same name
  • Must be wrapped in main function
  • $i counting to be done differently
  • Working on the typedef's and replacements of identifiers in the string (some are replaced)
    • enum automatically is a long
    • typedefs are automatically assumed an int (which is not perfect but a start)
      • struct like POINT pt is now generated as int
  • Testing/debugging

Choices done

  • get_ and put_ prefixing only for put_ as that will have less impact on existing scripts that do not use get_ like ControlViewWalker, Current.. properties etc.

    So instead of
    Global Const $sIID_IUIAutomationCacheRequest = "{B32A92B5-BC25-4078-9C08-D7EE95C48E03}"
    Global $dtagIUIAutomationCacheRequest = _
        "AddProperty hresult(int);" & _
        "AddPattern hresult(int);" & _
        "Clone hresult(ptr*);" & _
        "get_TreeScope hresult(long*);" & _
        "put_TreeScope hresult(long);" & _
        "get_TreeFilter hresult(ptr*);" & _
        "put_TreeFilter hresult(ptr);" & _
        "get_AutomationElementMode hresult(long*);" & _
        "put_AutomationElementMode hresult(long);"

    it will be like (see for example TreeScope and put_TreeScope)

    Global Const $sIID_IUIAutomationCacheRequest = "{b32a92b5-bc25-4078-9c08-d7ee95c48e03}"
    Global $dtagIUIAutomationCacheRequest= _
        "AddProperty hresult(struct);" & _ 
        "AddPattern hresult(int);" & _ 
        "Clone hresult(ptr*);" & _ 
        "TreeScope hresult(long*);" & _ 
        "put_TreeScope hresult(long);" & _ 
        "TreeFilter hresult(ptr*);" & _ 
        "put_TreeFilter hresult(ptr);" & _ 
        "AutomationElementMode hresult(long*);" & _ 
        "put_AutomationElementMode hresult(long);"

     

Prerequisites

  • Win 10 SDK installed at location as given in constants to have IDL file

Output

  • File with same name as idl in scriptdir with  extension au3 having the definitions for OBJCreateInterface
     

Example output

;~    //
;~    //  IUIAutomation
;~    //
;~[object, uuid(30cbe57d-d9d0-452a-ab13-7ac5ac4825ee), pointer_default(unique)]
;~interface IUIAutomation : IUnknown
Global Const $sIID_IUIAutomation = "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}"
Global $dtag_IUIAutomation= _
    "CompareElements hresult(IUIAutomationElement*el1,IUIAutomationElement*el2,int*);" & _
    "CompareRuntimeIds hresult(SAFEARRAY(int)runtimeId1,SAFEARRAY(int)runtimeId2,intareSame);" & _
    "GetRootElement hresult(IUIAutomationElement**);" & _
    "ElementFromHandle hresult(UIA_inthwnd,IUIAutomationElement**);" & _
    "ElementFromPoint hresult(intpt,IUIAutomationElement**);" & _
    "GetFocusedElement hresult(IUIAutomationElement**);" & _
    "GetRootElementBuildCache hresult(IUIAutomationCacheRequest*cacheRequest,IUIAutomationElement**);" & _
    "ElementFromHandleBuildCache hresult(UIA_inthwnd,IUIAutomationCacheRequest*cacheRequest,IUIAutomationElement**);" & _
    "ElementFromPointBuildCache hresult(intpt,IUIAutomationCacheRequest*cacheRequest,IUIAutomationElement**);" & _
    "GetFocusedElementBuildCache hresult(IUIAutomationCacheRequest*cacheRequest,IUIAutomationElement**);" & _
    "CreateTreeWalker hresult(IUIAutomationCondition*pCondition,IUIAutomationTreeWalker**);" & _
    "ControlViewWalker hresult(IUIAutomationTreeWalker**);" & _
    "ContentViewWalker hresult(IUIAutomationTreeWalker**);" & _
    "RawViewWalker hresult(IUIAutomationTreeWalker**);" & _
    "RawViewCondition hresult(IUIAutomationCondition**);" & _
    "ControlViewCondition hresult(IUIAutomationCondition**);" & _
    "ContentViewCondition hresult(IUIAutomationCondition**);" & _
    "CreateCacheRequest hresult(IUIAutomationCacheRequest**);" & _
    "CreateTrueCondition hresult(IUIAutomationCondition**);" & _
    "CreateFalseCondition hresult(IUIAutomationCondition**);" & _
    "CreatePropertyCondition hresult(intpropertyId,variantvalue,IUIAutomationCondition**);" & _
    "CreatePropertyConditionEx hresult(intpropertyId,variantvalue,longflags,IUIAutomationCondition**);" & _
    "CreateAndCondition hresult(IUIAutomationCondition*condition1,IUIAutomationCondition*condition2,IUIAutomationCondition**);" & _
    "CreateAndConditionFromArray hresult(SAFEARRAY(IUIAutomationCondition)conditions,IUIAutomationCondition**);" & _
    "CreateAndConditionFromNativeArray hresult(IUIAutomationCondition**conditions,intconditionCount,IUIAutomationCondition**);" & _
    "CreateOrCondition hresult(IUIAutomationCondition*condition1,IUIAutomationCondition*condition2,IUIAutomationCondition**);" & _
    "CreateOrConditionFromArray hresult(SAFEARRAY(IUIAutomationCondition)conditions,IUIAutomationCondition**);" & _
    "CreateOrConditionFromNativeArray hresult(IUIAutomationCondition**conditions,intconditionCount,IUIAutomationCondition**);" & _
    "CreateNotCondition hresult(IUIAutomationCondition*condition,IUIAutomationCondition**);" & _
    "AddAutomationEventHandler hresult(inteventId,IUIAutomationElement*element,longscope,IUIAutomationCacheRequest*cacheRequest,IUIAutomationEventHandler*);" & _
    "RemoveAutomationEventHandler hresult(inteventId,IUIAutomationElement*element,IUIAutomationEventHandler*);" & _
    "AddPropertyChangedEventHandlerNativeArray hresult(IUIAutomationElement*element,longscope,IUIAutomationCacheRequest*cacheRequest,IUIAutomationPropertyChangedEventHandler*handler,int*propertyArray,int);" & _
    "AddPropertyChangedEventHandler hresult(IUIAutomationElement*element,longscope,IUIAutomationCacheRequest*cacheRequest,IUIAutomationPropertyChangedEventHandler*handler,SAFEARRAY(PROPERTYID));" & _
    "RemovePropertyChangedEventHandler hresult(IUIAutomationElement*element,IUIAutomationPropertyChangedEventHandler*);" & _
    "AddStructureChangedEventHandler hresult(IUIAutomationElement*element,longscope,IUIAutomationCacheRequest*cacheRequest,IUIAutomationStructureChangedEventHandler*);" & _
    "RemoveStructureChangedEventHandler hresult(IUIAutomationElement*element,IUIAutomationStructureChangedEventHandler*);" & _
    "AddFocusChangedEventHandler hresult(IUIAutomationCacheRequest*cacheRequest,IUIAutomationFocusChangedEventHandler*);" & _
    "RemoveFocusChangedEventHandler hresult(IUIAutomationFocusChangedEventHandler*);" & _
    "RemoveAllEventHandlers hresult);" & _
    "IntNativeArrayToSafeArray hresult(int*array,intarrayCount,SAFEARRAY(int)*);" & _
    "IntSafeArrayToNativeArray hresult(SAFEARRAY(int)intArray,int**array,int*);" & _
    "RectTovariant hresult(intrc,variant*);" & _
    "variantToRect hresult(variantvar,int*);" & _
    "SafeArrayToRectNativeArray hresult(SAFEARRAY(double)rects,int**rectArray,int*);" & _
    "CreateProxyFactoryEntry(IUIAutomationProxyFactory hresult*factory,IUIAutomationProxyFactoryEntry);" & _
    "ProxyFactoryMapping(IUIAutomationProxyFactoryMapping hresult);" & _
    "GetPropertyProgrammaticName(int hresultproperty,int*);" & _
    "GetPatternProgrammaticName(int hresultpattern,int*);" & _
    "PollForPotentialSupportedPatterns(IUIAutomationElement hresult*pElement,SAFEARRAY(int)*patternIds,SAFEARRAY(BSTR)patternNames);" & _
    "PollForPotentialSupportedProperties(IUIAutomationElement hresult*pElement,SAFEARRAY(int)*propertyIds,SAFEARRAY(BSTR)propertyNames);" & _
    "CheckNotSupported(variant hresultvalue,intisNotSupported);" & _
    "ReservedNotSupportedValue(IUnknown hresult**notSupportedValue);" & _
    "ReservedMixedAttributeValue(IUnknown hresult**mixedAttributeValue);" & _
    "ElementFromIAccessible hresult(IAccessible*accessible,intchildId,IUIAutomationElement**);" & _
    "ElementFromIAccessibleBuildCache hresult(IAccessible*accessible,intchildId,IUIAutomationCacheRequest*cacheRequest,IUIAutomationElement**);"
;~}

 

Script

#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <Array.au3>
;~ testit()
;~ Exit

Local $IDLFolder="C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um\"
Local $IDLFileName="UIAutomationClient.idl"

Local $IDLFullFileName = $IDLFolder & $IDLFileName
Local $IDLArray = FileReadToArray($IDLFullFileName)
Local $iLineCount = @extended

Local $IDLAU3FullFileName=@ScriptDir & "\" & $IDLFileName
$IDLAU3FullFileName=stringreplace($IDLAU3FullFileName,".idl",".au3")

If @error Then
    MsgBox($MB_SYSTEMMODAL, "", "There was an error reading the file. @error: " & @error) ; An error occurred reading the current script file.
    exit
EndIf

Local $hFileOpen = FileOpen($IDLAU3FullFileName, $FO_OVERWRITE )
If $hFileOpen = -1 Then
    MsgBox($MB_SYSTEMMODAL, "", "An error occurred whilst writing the new au3 file.")
    exit
EndIf

;~TODO: Naming prefixing
Global $interfaceName
Global $GUID
Global $i=0

while $i < $iLineCount - 1
;~      consolewrite($i)
    $tLine=$IDLArray[$i]

    $blockType=0

    if stringleft($tLine,2)="//" then $blockType=1
    if stringleft($tLine,4)="cpp_" then $blockType=1
    if stringleft($tLine,1)="#" then $blockType=1
    if stringleft($tLine,6)="import" then $blockType=1
    if stringleft($tLine,4)="midl" then $blockType=1
    if $blockType=1 Then
        writeCommentedLine()
        continueloop;
    EndIf

    if stringleft($tLine,4)="enum" then
        $blockType=2
        handleEnumBlock()
    EndIf

    if stringinstr($tLine, "module ") > 0 then
        $blockType=3
        handleModuleBlock()
    EndIf

    if stringinstr($tLine, "[object") > 0 then
        $blockType=4
        handleObjectBlock()
    EndIf

    if stringinstr($tLine, "interface ") > 0 then
        $blockType=5
        handleInterfaceBlock()
    EndIf

    if $blockType=0 Then
        writeUnhandledLine()
    EndIf
WEnd


func writeUnhandledLine()
    filewriteline($hFileOpen,";~" & $tline)
    $i=$i+1
EndFunc

func writeCommentedLine()
    $tLineOut=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    if $tLineOut <> "" Then $tLineOut=";~" & $tLineOut
    filewriteline($hFileOpen, $tLineOut)
    $i=$i+1
EndFunc

func handleEnumBlock()
    writeCommentedLine() ;~ Copy enum line
    $tLine=$IDLArray[$i]
    writeCommentedLine() ;~ Copy curly brace line
    $tLine=$IDLArray[$i]
    while stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING) <> "};"
        $tPos=getPosFirstNonWhiteSpace($tLine)
        if ($tpos=0) or (stringmid($tLine,$tPos+1,2)="//") Then
            writeCommentedLine()
        Else
            $tLine=stringleft($tLine,$tPos) & "Global Const $" & stringmid($tline,$tPos+1)
            $tLine=stringreplace($tLine, ",","")
            $tLine=stringreplace($tLine, "| ","+ $")
            writeEnumLine()
        EndIf
        $tLine=$IDLArray[$i]
    WEnd
EndFunc

func writeEnumLine()
    filewriteline($hFileOpen, $tline)
    $i=$i+1
EndFunc

func handleModuleBlock()
    writeCommentedLine() ;~ Copy module line
    $tLine=$IDLArray[$i]
    writeCommentedLine() ;~ Copy curly brace line
    $tLine=$IDLArray[$i]

    $tValue=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
;~  Some end with }; and some with }
    while  stringleft($tValue,1) <> "}"
        $tPos=getPosFirstNonWhiteSpace($tLine)
        if ($tpos=0) or (stringmid($tLine,$tPos+1,2)="//") Then
            if ($tpos=0) then
                $i=$i+1  ;~ Do no output
            Else
                writeCommentedLine()
            EndIf
        Else
            $tLine=stringreplace($tline,"const long ", "Global Const $")
            $tLine=stringreplace($tLine, ";","")
            writeModuleLine()
        EndIf
        $tLine=$IDLArray[$i]
        $tValue=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    WEnd
    writeCommentedLine() ;~ Copy curly closing brace line
EndFunc

func writeModuleLine()
    filewriteline($hFileOpen, $tline)
    $i=$i+1
EndFunc

func handleObjectBlock()
    writeCommentedLine()
    $tPos=stringinstr($tLine,"(")
    $tPos2=stringinstr($tLine,")")
    $GUID=stringmid($tLine,$tpos+1, $tPos2-1 - $tpos)
;~  consolewrite($GUID & @CRLF)
EndFunc

func handleInterfaceBlock()
    if stringright($tLine,1)=";" Then
        writeCommentedLine() ;~ Copy Interface line its just a definition line
        Return
    EndIf

    writeCommentedLine() ;~ Copy interface line
    $interfaceName=getInterfaceName()
    writeInterFaceLine1()

    $tLine=$IDLArray[$i]
;~  writeCommentedLine() ;~ Copy curly brace line
    $i=$i+1  ;~ Do no output
    $tLine=$IDLArray[$i]

    $tValue=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
;~  Some end with }; and some with }
    while  stringleft($tValue,1) <> "}"

        $tPos=getPosFirstNonWhiteSpace($tLine)
        if ($tpos=0) or (stringmid($tLine,$tPos+1,2)="//") Then
            if ($tpos=0) then
                $i=$i+1  ;~ Do no output
            Else
                $i=$i+1  ;~ Do no output, AU3 does not like it in multiline strings
;~              writeCommentedLine()
            EndIf
        Else
            while stringright($tLine,1) <> ";"
                $i=$i+1
                $tLine=$tLine & stringstripws($IDLArray[$i], $STR_STRIPLEADING +  $STR_STRIPTRAILING)
            wend
            writeInterfaceLine()
        EndIf
        $tLine=$IDLArray[$i]
        $tValue=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    WEnd

;~  consolewrite($IDLArray[$i-1] & @CRLF)
;~  consolewrite($IDLArray[$i] & @CRLF)
;~  consolewrite($IDLArray[$i+1] & @CRLF)

    writeCommentedLine() ;~ Copy curly closing brace line

EndFunc

func writeInterFaceLine1()
    $tOutputLine="Global Const $sIID_" & getInterfaceName() & " = "
    $tOutputLine=$tOutputLine & """"
    $tOutputLine=$tOutputLine & "{" & $GUID & "}"
    $tOutputLine=$tOutputLine & """"
    filewriteline($hFileOpen, $tOutputLine)

    $toutputLine = "Global $dtag" & getInterfaceName() & "= _" & @CRLF
    filewriteline($hFileOpen, $tOutputLine)
EndFunc

func writeInterfaceLine()
    $tmpLine=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    if stringleft($tmpLine,1)="}" Then
        filewriteline($hFileOpen, $tmpLine)
        $i=$i+1
        return
    EndIf

;~ Handle get/put properties prefix
    local $strPrefix=""
    if stringinstr($tmpLine,"[propget]")>0 then
;~ no prefix for the get as its more logical/natural in AutoIt to do it without (as oppossed to C where get_ is more logical
;~      $strPrefix="get_"
;~      consolewrite($tmpLine & @CRLF)
        $tmpLine=stringreplace($tmpLine, "[propget] ", "", 0, $STR_CASESENSE)
    EndIf

    if stringinstr($tmpLine,"[propput]")>0 then
;~ prefix for the put as it can get in conflict with the get duplicate name
        $strPrefix="put_"
;~      consolewrite($tmpLine & @CRLF)
        $tmpLine=stringreplace($tmpLine, "[propput] ", "", 0, $STR_CASESENSE)
    EndIf

;       $tmpLine ="HRESULT FindAll ([in] enum TreeScope scope,[in] IUIAutomationCondition * condition, [out, retval] IUIAutomationElementArray ** found );"
;~     $tmpLine="[propget] HRESULT PropertyId ([out, retval] PROPERTYID * propertyId );"
;~  $tmpLine="HRESULT GetCurrentPropertyValue ([in] PROPERTYID propertyId,[out, retval] VARIANT * retVal);"
;~  $tmpLine="HRESULT FindAllBuildCache ([in] enum TreeScope scope,[in] IUIAutomationCondition * condition,[in] IUIAutomationCacheRequest * cacheRequest,[out, retval] IUIAutomationElementArray ** found );"
    $tmpLine=stringreplace($tmpLine, "HRESULT", "hresult", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "VARIANT", "variant", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "BSTR", "bstr", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "BOOL", "bool", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "void", "none", 0, $STR_CASESENSE)

;~ Some where we are sure it should not be an int
    $tmpLine=stringreplace($tmpLine, "POINT", "struct", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "PROPERTYID", "struct", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "RECT", "struct", 0, $STR_CASESENSE)
    $tmpLine=stringreplace($tmpLine, "UIA_HWND", "hwnd", 0, $STR_CASESENSE)

;~ Some cleanup for parsing later
    $tmpLine=stringreplace($tmpLine, "(", " (")
    $tmpLine=stringreplace($tmpLine, "  (", " (")

    $tmpLine=stringreplace($tmpLine, " );", ");")

;~  remove the pointer references for in/out parameters
    if stringinstr($tmpLine,"[in")>0 then
        $tmpLine=stringreplace($tmpLine, "[propget] ", "", 0, $STR_CASESENSE)
        $tmpLine=stringreplace($tmpLine, "**", "SINGLESTAR")
        $tmpLine=stringreplace($tmpLine, "*", "")
        $tmpLine=stringreplace($tmpLine, "SINGLESTAR", "*")
    EndIf
;~  For out parameter we keep the pointer *
    if stringinstr($tmpLine,"[out")>0 then
        $tmpLine=stringreplace($tmpLine, "[propget] ", "", 0, $STR_CASESENSE)
        $tmpLine=stringreplace($tmpLine, "**", "SINGLESTAR")
;~      $tmpLine=stringreplace($tmpLine, "*", "")
        $tmpLine=stringreplace($tmpLine, "SINGLESTAR", "*")
    EndIf


    $tmpLine=StringRegExpReplace($tmpLine,"[A-Z]+ ","int ")     ;~ TODO: assumption full uppercase is a TYPEDEF frequently int but definitily not sure
    $tmpLine=StringRegExpReplace($tmpLine,"enum [A-Za-z_]+ ","long ")  ;~ An enum followed by an identifier is normally a long
    $tmpLine=StringRegExpReplace($tmpLine,"\[.*?] "," ")          ;~ [in, out]  stuff followed by space we normally ignore, space we keep for separator

;~ reshuffle and remove varnames
    $aArray=stringsplit($tmpLine," ")

    if ($aArray[0] < 2) then
        _arraydisplay($aArray)
        consolewrite(stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING))
        consolewrite($tmpLine)
    EndIf
    $tOutputLine= $strPrefix & $aArray[2] & " " & $aArray[1]

    For $j = 3 To $aArray[0]
        $strAppend= $aArray[$j]
        if (stringright($aArray[$j],1))= "," then $strAppend= ";"
        if (stringright($aArray[$j],1))= ";" then
            if $aArray[$j]<>"();" then $strAppend= ");"
        EndIf
        $strAppend=getnewtype($strAppend)
        $tOutputLine= $tOutputLine & $strAppend
    Next

;~  $tOutputLine= $tOutputLine & $aarray[$aArray[0]]

    $tOutputline = @TAB & """" & $tOutputLine & """"
    $tValue=stringstripws($IDLArray[$i+1], $STR_STRIPLEADING +  $STR_STRIPTRAILING)
;~  sometimes its not just 1 line ahead for closing but 2 lines ahead
    if $tValue="" then
        $tValue=stringstripws($IDLArray[$i+2], $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    endif
    if (stringleft($tValue,1) <> "}") then $tOutputLine= $tOutputLine & " & _ "

    filewriteline($hFileOpen, $tOutputLine)
    $i=$i+1
EndFunc

func getPosFirstNonWhiteSpace($str)
    Local $aArray = StringToASCIIArray($str)

    for $i=0 to ubound($aArray)-1
        if $aArray[$i]<>32 Then return $i
    Next

    return 0
EndFunc

func getInterfaceName()
    $tmpLine=stringstripws($tLine, $STR_STRIPLEADING +  $STR_STRIPTRAILING)
    $tArr=stringsplit($tmpLine," ")
    $tName=$tarr[2]
    if stringright($tname,1)=":" then $tName=stringleft($tname,stringlen($tname)-1)
    return $tname
EndFunc

func testIt()
;~  $tmpline="HRESULT SetFocus ( );"

;       $tmpLine ="HRESULT FindAll ([in] enum TreeScope scope,[in] IUIAutomationCondition * condition, [out, retval] IUIAutomationElementArray ** found );"
    $tmpLine="[propget] HRESULT PropertyId ([out, retval] PROPERTYID * propertyId );"
;~  $tmpLine="HRESULT GetCurrentPropertyValue ([in] PROPERTYID propertyId,[out, retval] VARIANT * retVal);"
;~  $tmpLine="HRESULT FindAllBuildCache ([in] enum TreeScope scope,[in] IUIAutomationCondition * condition,[in] IUIAutomationCacheRequest * cacheRequest,[out, retval] IUIAutomationElementArray ** found );"
    $strPrefix=""
    if stringinstr($tmpLine,"[propget]")>0 then $strPrefix="get_"
    if stringinstr($tmpLine,"[propput]")>0 then $strPrefix="put_"
consolewrite($strPrefix)
;~      consolewrite($tOutputline & @CRLF)
;~      consolewrite($tmpLine)
;~      _arraydisplay($aArray)
EndFunc

func getNewType($str)
    $retVal=stringregexp($str, "[A-Za-z0-9_]+", $STR_REGEXPMATCH)
;~  if stringleft($str,"3") = "ret" then consolewrite($retVal & $str & @CRLF)
    if $retval=0 then return $str
    $tStr=$str & ","
    $objTypes="none,byte,boolean,short,word,ushort,int,long,bool,dword," & _
              "ulong,uint,hresult,int64,uint64,ptr,hwnd,handle,float," & _
              "double,int_ptr,long_ptr,lresult,lparam,uint_ptr,ulong_ptr,"& _
              "dword_ptr,wparam,str,wstr,bstr,variant,idispatch,object," & _
              "clsid,struct,*,**"

    if stringinstr($objtypes,$tstr)>0 Then return $str
    return "ptr"
EndFunc

 

Edited by junkew
01/01/2019 many small enhancements in script
Link to comment
Share on other sites

  • 3 months later...

Small steps created a lexer for an idl file

#include <MsgBoxConstants.au3>
#include <Array.au3> ; Required for _ArrayDisplay() only.


global const $TOKEN_OPERATOR_OPENBLOCK=1
global const $TOKEN_OPERATOR_CLOSEBLOCK=2
global const $TOKEN_IDENTIFIER=3
global const $TOKEN_KEYWORD=4
global const $TOKEN_NUMBER=5
global const $TOKEN_STRING=6
global const $TOKEN_STRING_UID=7
global const $TOKEN_SINGLECHAR=8
global const $TOKEN_COMMENT=9

global $MIDLkeywords="" & _
"aggregatable,allocate,annotate,appobject,arrays,async,async_uuid,auto_handle,bindable," & _
"Boolean,broadcast,byte,byte_count,call_as,callback,char,coclass,code,comm_status,const," & _
"context_handle,context_handle_noserialize,context_handle_serialize,control,cpp_quote," & _
"custom,decode,default,defaultbind,defaultcollelem,defaultvalue,defaultvtable," & _
"disable_consistency_check,dispinterface,displaybind,dllname,double,dual,enable_allocate," & _
"encode,endpoint,entry,enum,error_status_t,explicit_handle,fault_status,first_is,float," & _
"force_allocate,handle,handle_t,helpcontext,helpfile,helpstring,helpstringcontext,helpstringdll," & _
"hidden,hyper,id,idempotent,ignore,iid_is,immediatebind,implicit_handle,import,importlib,in,include," & _
"in_line,int,__int32,__int64,interface,last_is,lcid,length_is,library,licensed,local,long,max_is," & _
"maybe,message,midl_pragma,warning,midl_user_allocate,midl_user_free,min_is,module,ms_union,ncacn_at_dsp," & _
"ncacn_dnet_nsp,ncacn_http,ncacn_ip_tcp,ncacn_nb_ipx,ncacn_nb_nb,ncacn_nb_tcp,ncacn_np,ncacn_spx,ncacn_vns_spp," & _
"ncadg_ip_udp,ncadg_ipx,ncadg_mq,ncalrpc,nocode,nonbrowsable,noncreatable,nonextensible,notify,notify_flag," & _
"object,odl,oleautomation,optimize,optional,out,out_of_line,partial_ignore,pipe,pointer_default,pragma," & _
"propget,propput,propputref,proxy,ptr,public,range,readonly,ref,represent_as,requestedit,restricted," & _
"retval,shape,short,signed,size_is,small,source,strict_context_handle,string,struct,switch,switch_is," & _
"switch_type,transmit_as,typedef,uidefault,unique,union,unsigned,user_marshal,usesgetlasterror,uuid," & _
"v1_enum,vararg,version,void,wchar_t,wire_marshal,"

global $g_keywords=$MIDLkeywords
global $g_value=""
global $g_tokenIndex=0
global $g_tokens[2500][2]
;~ example()

func example()
;~  local $test[0][2]
;~  _ArrayAdd($test, "1|AAP")
;~  _ArrayAdd($test, "2|NOOT")
;~  _ARRAYDISPLAY($test)

    tokenizer("This is 1234 void 0x123 " & """" & "ni  ce doublequoted" & """" & "  just 'more string 123 singlequoted' object<> odl a SIMPLE[] way of tokenizing();123//nice comment at the end" & @CRLF)
    tokenizer("cpp_quote("& """" & "// -------------------------------------------------------------" & """" & ")" & @CRLF)

    $testString = "struct ExtendedProperty {" & @CRLF & _
                  "BSTR PropertyName;" & @CRLF & _
                  "BSTR PropertyValue;" & @CRLF & _
                  "};" & @CRLF

    tokenizer($teststring)

$testString = "typedef void * UIA_HWND;" & @CRLF & _
"" & @CRLF & _
"[" & @CRLF & _
"    uuid(944de083-8fb8-45cf-bcb7-c477acb2f897)," & @CRLF & _
"    lcid(0)," & @CRLF & _
"    version(1.0)," & @CRLF & _
"]" & @CRLF

    tokenizer($teststring)

    $testString = "typedef void * UIA_HWND;" & @CRLF & _
"" & @CRLF & _
"[" & @CRLF & _
"    uuid(""944de083-8fb8-45cf-bcb7-c477acb2f897"")," & @CRLF & _
"    lcid(0)," & @CRLF & _
"    version(1.0)," & @CRLF & _
"]" & @CRLF

tokenizer($teststring)

EndFunc
Func _TokenAdd($tokentype, $tokenvalue)
    $g_value=$tokenvalue
    $g_tokens[$g_tokenIndex][0]=$tokenType
    $g_tokens[$g_tokenIndex][1]=$tokenValue

    $g_tokenIndex=$g_tokenIndex+1
    if $g_tokenIndex >= ubound($g_tokens) Then
        redim $g_tokens[$g_tokenIndex+2500][2]
    EndIf
EndFunc
func tokenizer($input)
    local $index=0
    local $lineId=1
;~  local $tokens[0][2]  ;~= ObjCreate("WIA.vector")  ;~ Any array/list type would be fine
    local $allChars=stringregexp($input,"(?s).", $STR_REGEXPARRAYGLOBALMATCH)  ;~ include mathcing on characters CR LF
;~  local $allChars2=StringToASCIIArray($input)

;~  _ArrayDisplay($allchars)

    $inputLength=stringlen($input)
    while ($index < $inputLength)
        local $singleChar=$allChars[$index]

;~ Open blocks
        if stringinstr("[({<",$singleChar) > 0 then
;~          _ArrayAdd($tokens, $TOKEN_OPERATOR_OPENCLOSE & "|" & $singleChar)
            _TokenAdd($TOKEN_OPERATOR_OPENBLOCK , $singleChar)
            $index=$index+1
            ContinueLoop
        EndIf

;~      Whitespace
        if ($singleChar=" ") _
            or ($singleChar=@tab) _
            or ($singleChar=@cr) _
            or ($singleChar=@lf) Then
            if ($singleChar=@lf) then
                $lineId=$lineId+1;
            EndIf
            $index=$index+1
            ContinueLoop
        EndIf

;~      Comment
        if ($singleChar="/") Then
            if $allChars[$index+1]="/" Then
                $value=""

                while ($singleChar<>@CR) and ($singleChar<>@LF)
                    $value = $value & $singleChar
                    $index=$index+1
                    $singleChar = $allChars[$index]
                wend
;~              _ArrayAdd($tokens, $TOKEN_COMMENT & "|" & $value)
                _TokenAdd($TOKEN_COMMENT , $value)

                $index=$index+1
                ContinueLoop
            endif
        EndIf

;~      Decimal, Octal, Hex numbers
        if stringinstr("0123456789",$singleChar) > 0 Then
            $value=""
            while stringinstr("0123456789ABCDEFabcdefxX",$singleChar,$STR_CASESENSE) > 0
                $value = $value & $singleChar
                $index=$index+1
                $singleChar = $allChars[$index]
            wend
;~          _ArrayAdd($tokens, $TOKEN_NUMBER & "|" & $value)
            _TokenAdd($TOKEN_NUMBER , $value)
            ContinueLoop
        EndIf

;~      string doublequoted
        if $singleChar="""" Then
            $value=""
            $index=$index+1
            $singleChar = $allChars[$index]
            while $singleChar<>""""
                $value = $value & $singleChar
                $index=$index+1
                $singleChar = $allChars[$index]
            wend
;~          _ArrayAdd($tokens, $TOKEN_STRING & "|" & $value)
            _TokenAdd($TOKEN_STRING , $value)
            $index=$index+1 ;~ skip the doublequote
            ContinueLoop
        EndIf

;~      string singlequoted
        if $singleChar="'" Then
            $value=""
            $index=$index+1
            $singleChar = $allChars[$index]
            while $singleChar<>"'"
                $value = $value & $singleChar
                $index=$index+1
                $singleChar = $allChars[$index]
            wend
;~          _ArrayAdd($tokens, $TOKEN_STRING & "|" & $value)
            _TokenAdd($TOKEN_STRING , $value)
            $index=$index+1 ;~ skip the single quote
            ContinueLoop
        EndIf

;~      Identifier_or_keyword
        if stringinstr("abcdefghijklmnopqrstuvwxyz_",$singleChar) > 0 Then
            $value=""
            while stringinstr("abcdefghijklmnopqrstuvwxyz_",$singleChar) > 0
                $value = $value & $singleChar
                $index=$index+1
                $singleChar = $allChars[$index]
            wend
            IF stringinstr($g_keywords,$value & ",",$STR_CASESENSE) then
;~              Handle specific keywords directly to make parsing easier
                if (stringlower($value)="uuid") or (stringlower($value)="async_uuid") Then
                    $value=""
                    $index=$index+1
                    $singleChar = $allChars[$index]
                    while $singleChar<>")"
                        if stringinstr("0123456789abcdefABCDEF-",$singleChar) then
                            $value = $value & $singleChar
                        EndIf
                        $index=$index+1
                        $singleChar = $allChars[$index]
                    wend
;~                  _ArrayAdd($tokens, $TOKEN_STRING_UID & "|" & $value)
                    _TokenAdd($TOKEN_STRING_UID , $value)
                    $index=$index+1 ;~ skip the doublequote
                    ContinueLoop
                EndIf
;~              _ArrayAdd($tokens, $TOKEN_KEYWORD & "|" & $value)
                _TokenAdd($TOKEN_KEYWORD , $value)

            Else
;~              _ArrayAdd($tokens, $TOKEN_IDENTIFIER & "|" & $value)
                _TokenAdd($TOKEN_IDENTIFIER , $value)
            EndIf
            ContinueLoop
        EndIf

        if stringinstr(",#;+-*/=:!.|",$singleChar) Then
;~              _ArrayAdd($tokens, $TOKEN_SINGLECHAR & "|" & $value)
            _TokenAdd($TOKEN_SINGLECHAR , $singleChar)
            $index=$index+1
            ContinueLoop
        EndIf

;~      Open Close block characters
        if stringinstr("])}>",$singleChar) > 0 then
            if $allChars[$index+1]=";" Then
;~              _ArrayAdd($tokens, $TOKEN_OPERATOR_CLOSEBLOCK & "|" & $singleChar)
                _TokenAdd($TOKEN_OPERATOR_CLOSEBLOCK, $singleChar)
                $index=$index+1
                $index=$index+1
                ContinueLoop
            endif
;~          if $allChars[$index-1]="""" Then
;~              _ArrayAdd($tokens, $TOKEN_OPERATOR_CLOSEBLOCK & "|" & $singleChar)
                _TokenAdd($TOKEN_OPERATOR_CLOSEBLOCK, $singleChar)
                $index=$index+1
                ContinueLoop
;~          endif
        EndIf

;~ unmatched stuff, should not happen
        consolewrite("Lexing error: " & $lineId & " :<" & $allChars[$index-5] & $allChars[$index-4] & $allChars[$index-3] & $allChars[$index-2] & $allChars[$index-1] & $singlechar & " >" & @CRLF)

        $index=$index+1
    Wend
;~  _arraydisplay($tokens)
;~  return $tokens

endFunc

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...