Module refinery.lib.thirdparty.pcode2code

The code of this module is based on the source code of pcode2code, originally available at the following location:

https://github.com/Big5-sec/pcode2code

The following is the original docstring:

pcode2code is a module aiming at decompiling VBA pcode. It's based on Dr. Vesselin Vladimirov Bontchev(@VessOnSecurity)'s tool pcodedmp, which makes the disassembly, while this module is only an interface to print out readable VBA code. How it works: Basically, pcodedmp gives out a bytecode interpretation, representing operations made on a somewhat stack, with opcodes translation. This program simply parses the opcodes and manipulates the stack to rectonstruct the original VBA code. Author: Nicolas Zilio - @Big5_sec License: GPL

The code was altered and modified for work within Binary Refinery, but remains subject to the original license text, which is as follows:

                 GNU GENERAL PUBLIC LICENSE
                  Version 3, 29 June 2007

a vba p-code decompiler based on pcodedmp
Copyright (C) 2019  Nicolas Zilio

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/.>

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see: http://www.gnu.org/licenses/.

The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read: http://www.gnu.org/philosophy/why-not-lgpl.html.

Expand source code Browse git
#!/usr/bin/env python
"""
The code of this module is based on the source code of pcode2code, originally
available at the following location:

https://github.com/Big5-sec/pcode2code

The following is the original docstring:

pcode2code is a module aiming at decompiling VBA pcode. It's based on Dr. Vesselin
Vladimirov Bontchev(@VessOnSecurity)'s tool pcodedmp, which makes the disassembly,
while this module is only an interface to print out readable VBA code.
 How it works:
Basically, pcodedmp gives out a bytecode interpretation, representing operations
made on a somewhat stack, with opcodes translation. This program simply parses the
opcodes and manipulates the stack to rectonstruct the original VBA code.
 Author: Nicolas Zilio - @Big5_sec
 License: GPL

The code was altered and modified for work within Binary Refinery, but remains
subject to the original license text, which is as follows:

                     GNU GENERAL PUBLIC LICENSE
                      Version 3, 29 June 2007

    a vba p-code decompiler based on pcodedmp
    Copyright (C) 2019  Nicolas Zilio

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see http://www.gnu.org/licenses/.

Also add information on how to contact you by electronic and paper mail.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see:
  http://www.gnu.org/licenses/.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read:
  http://www.gnu.org/philosophy/why-not-lgpl.html.
"""
import struct


class Pcode2codeException(Exception):
    """
    Simply a custom exception class, permitting to make the difference between generic python exceptions and the one we are pushing
    """
    pass


class Stack:
    """
    Our stack class. Used to implement the operations made in the VBA bytecode, which is somehow stack based
    """

    def __init__(self):
        self.stack = []

    def pop(self):
        if len(self.stack) == 0:
            return None
        return self.stack.pop()

    def push(self, item):
        self.stack.append(item)

    def size(self):
        return len(self.stack)

    def top(self):
        return self.stack[-1]

    def bottom(self):
        return self.stack[0]

    def clearstack(self):
        self.stack = []


class Operations:

    def __init__(self, opstack: Stack):
        self.opstack = opstack
        # number of blocks that will be ignored for indentation
        self.unindented = 0
        # current indentation level
        self.indentlevel = 0
        # boolean indicating if indentation level should be increased after the current command
        self.indentincrease_future = False
        # boolean indicating to print all stack, like in one liner cases
        self.has_bos = False
        # boolean indicating if we are on a onelineif. In this case, closing should not be treated the same as other if blocks
        self.onelineif = False
        self.ops = {
            'Imp'                   : self.imp,
            'Eqv'                   : self.eqv,
            'Xor'                   : self.xor,
            'Or'                    : self.or_,
            'And'                   : self.and_,
            'Eq'                    : self.eq,
            'Ne'                    : self.ne,
            'Le'                    : self.le,
            'Ge'                    : self.ge,
            'Lt'                    : self.lt,
            'Gt'                    : self.gt,
            'Add'                   : self.add,
            'Sub'                   : self.sub,
            'Mod'                   : self.mod,
            'IDiv'                  : self.idiv,
            'Mul'                   : self.mul,
            'Div'                   : self.div,
            'Concat'                : self.concat,
            'Like'                  : self.like,
            'Pwr'                   : self.pwr,
            'Is'                    : self.is_,
            'Not'                   : self.not_,
            'UMi'                   : self.umi,
            'FnAbs'                 : self.fnabs,
            'FnFix'                 : self.fnfix,
            'FnInt'                 : self.fnint,
            'FnSgn'                 : self.fnsgn,
            'FnLen'                 : self.fnlen,
            'FnLenB'                : self.fnlenb,
            'Paren'                 : self.paren,
            'Sharp'                 : self.sharp,
            'LdLHS'                 : self.ldlhs,
            'Ld'                    : self.ld,
            'MemLd'                 : self.memld,
            'DictLd'                : self.dictld,
            'IndexLd'               : self.indexld,
            'ArgsLd'                : self.argsld,
            'ArgsMemLd'             : self.argsmemld,
            'ArgsDictLd'            : self.argsdictld,
            'St'                    : self.st,
            'MemSt'                 : self.memst,
            'DictSt'                : self.dictst,
            'IndexSt'               : self.indexst,
            'ArgsSt'                : self.argsst,
            'ArgsMemSt'             : self.argsmemst,
            'ArgsDictSt'            : self.argsdictst,
            'Set'                   : self.set_,
            'Memset'                : self.memset,
            'Dictset'               : self.dictset,
            'Indexset'              : self.indexset,
            'ArgsSet'               : self.argsset,
            'ArgsMemSet'            : self.argsmemset,
            'ArgsDictSet'           : self.argsdictset,
            'MemLdWith'             : self.memldwith,
            'DictLdWith'            : self.dictldwith,
            'ArgsMemLdWith'         : self.argsmemldwith,
            'ArgsDictLdWith'        : self.argsdictldwith,
            'MemStWith'             : self.memstwith,
            'DictStWith'            : self.dictstwith,
            'ArgsMemStWith'         : self.argsmemstwith,
            'ArgsDictStWith'        : self.argsdictstwith,
            'MemSetWith'            : self.memsetwith,
            'DictSetWith'           : self.dictsetwith,
            'ArgsMemSetWith'        : self.argsmemsetwith,
            'ArgsDictSetWith'       : self.argsdictsetwith,
            'ArgsCall'              : self.argscall,
            'ArgsMemCall'           : self.argsmemcall,
            'ArgsMemCallWith'       : self.argsmemcallwith,
            'ArgsArray'             : self.argsarray,
            'Assert'                : self.assert_,
            'BoS'                   : self.bos,
            'BoSImplicit'           : self.bosimplicit,
            'BoL'                   : self.bol,
            'LdAddressOf'           : self.ldaddressof,
            'MemAddressOf'          : self.memaddressof,
            'Case'                  : self.case,
            'CaseTo'                : self.caseto,
            'CaseGt'                : self.casegt,
            'CaseLt'                : self.caselt,
            'CaseGe'                : self.casege,
            'CaseLe'                : self.casele,
            'CaseNe'                : self.casene,
            'CaseEq'                : self.caseeq,
            'CaseElse'              : self.caseelse,
            'CaseDone'              : self.casedone,
            'Circle'                : self.circle,
            'Close'                 : self.close,
            'CloseAll'              : self.closeall,
            'Coerce'                : self.coerce_,
            'CoerceVar'             : self.coercevar,
            'Context'               : self.context,
            'Debug'                 : self.debug,
            'DefType'               : self.deftype,
            'Dim'                   : self.dim,
            'DimImplicit'           : self.dimimplicit,
            'Do'                    : self.do,
            'DoEvents'              : self.doevents,
            'DoUnitil'              : self.dounitil,
            'DoWhile'               : self.dowhile,
            'Else'                  : self.else_,
            'ElseBlock'             : self.elseblock,
            'ElseIfBlock'           : self.elseifblock,
            'ElseIfTypeBlock'       : self.elseiftypeblock,
            'End'                   : self.end,
            'EndContext'            : self.endcontext,
            'EndFunc'               : self.endfunc,
            'EndIf'                 : self.endif,
            'EndIfBlock'            : self.endifblock,
            'EndImmediate'          : self.endimmediate,
            'EndProp'               : self.endprop,
            'EndSelect'             : self.endselect,
            'EndSub'                : self.endsub,
            'EndType'               : self.endtype,
            'EndWith'               : self.endwith,
            'Erase'                 : self.erase,
            'Error'                 : self.error,
            'EventDecl'             : self.eventdecl,
            'RaiseEvent'            : self.raiseevent,
            'ArgsMemRaiseEvent'     : self.argsmemraiseevent,
            'ArgsMemRaiseEventWith' : self.argsmemraiseeventwith,
            'ExitDo'                : self.exitdo,
            'ExitFor'               : self.exitfor,
            'ExitFunc'              : self.exitfunc,
            'ExitProp'              : self.exitprop,
            'ExitSub'               : self.exitsub,
            'FnCurDir'              : self.fncurdir,
            'FnDir'                 : self.fndir,
            'Empty0'                : self.empty0,
            'Empty1'                : self.empty1,
            'FnError'               : self.fnerror,
            'FnFormat'              : self.fnformat,
            'FnFreeFile'            : self.fnfreefile,
            'FnInStr'               : self.fninstr,
            'FnInStr3'              : self.fninstr3,
            'FnInStr4'              : self.fninstr4,
            'FnInStrB'              : self.fninstrb,
            'FnInStrB3'             : self.fninstrb3,
            'FnInStrB4'             : self.fninstrb4,
            'FnLBound'              : self.fnlbound,
            'FnMid'                 : self.fnmid,
            'FnMidB'                : self.fnmidb,
            'FnStrComp'             : self.fnstrcomp,
            'FnStrComp3'            : self.fnstrcomp3,
            'FnStringVar'           : self.fnstringvar,
            'FnStringStr'           : self.fnstringstr,
            'FnUBound'              : self.fnubound,
            'For'                   : self.for_,
            'ForEach'               : self.foreach,
            'ForEachAs'             : self.foreachas,
            'ForStep'               : self.forstep,
            'FuncDefn'              : self.funcdefn,
            'FuncDefnSave'          : self.funcdefnsave,
            'GetRec'                : self.getrec,
            'GoSub'                 : self.gosub,
            'GoTo'                  : self.goto,
            'If'                    : self.if_,
            'IfBlock'               : self.ifblock,
            'TypeOf'                : self.typeof,
            'IfTypeBlock'           : self.iftypeblock,
            'Implements'            : self.implements,
            'Input'                 : self.input_,
            'InputDone'             : self.inputdone,
            'InputItem'             : self.inputItem,
            'Label'                 : self.label,
            'Let'                   : self.let,
            'Line'                  : self.line,
            'LineCont'              : self.linecont,
            'LineInput'             : self.lineInput,
            'LineNum'               : self.linenum,
            'LitCy'                 : self.litcy,
            'LitDate'               : self.litdate,
            'LitDefault'            : self.litdefault,
            'LitDI2'                : self.litdi2,
            'LitDI4'                : self.litdi4,
            'LitDI8'                : self.litdi8,
            'LitHI2'                : self.lithi2,
            'LitHI4'                : self.lithi4,
            'LitHI8'                : self.lithi8,
            'LitNothing'            : self.litnothing,
            'LitOI2'                : self.litoi2,
            'LitOI4'                : self.litoi4,
            'LitOI8'                : self.litoi8,
            'LitR4'                 : self.litr4,
            'LitR8'                 : self.litr8,
            'LitSmallI2'            : self.litsmalli2,
            'LitStr'                : self.litstr,
            'LitVarSpecial'         : self.litvarspecial,
            'Lock'                  : self.lock,
            'Loop'                  : self.loop,
            'LoopUntil'             : self.loopuntil,
            'LoopWhile'             : self.loopwhile,
            'LSet'                  : self.lset,
            'Me'                    : self.me,
            'MeImplicit'            : self.meimplicit,
            'MemRedim'              : self.memredim,
            'MemRedimWith'          : self.memredimwith,
            'MemRedimAs'            : self.memredimas,
            'MemRedimAsWith'        : self.memredimaswith,
            'Mid'                   : self.mid,
            'MidB'                  : self.midb,
            'Name'                  : self.name,
            'New'                   : self.new,
            'Next'                  : self.next_,
            'NextVar'               : self.nextvar,
            'OnError'               : self.onerror,
            'OnGosub'               : self.ongosub,
            'OnGoto'                : self.ongoto,
            'Open'                  : self.open_,
            'Option'                : self.option,
            'OptionBase'            : self.optionbase,
            'ParamByVal'            : self.parambyval,
            'ParamOmitted'          : self.paramomitted,
            'ParamNamed'            : self.paramnamed,
            'PrintChan'             : self.printchan,
            'PrintComma'            : self.printcomma,
            'PrintEoS'              : self.printeos,
            'PrintItemComma'        : self.printitemcomma,
            'PrintItemNL'           : self.printitemnl,
            'PrintItemSemi'         : self.printitemsemi,
            'PrintNL'               : self.printnl,
            'PrintObj'              : self.printobj,
            'PrintSemi'             : self.printsemi,
            'PrintSpc'              : self.printspc,
            'PrintTab'              : self.printtab,
            'PrintTabComma'         : self.printtabcomma,
            'PSet'                  : self.pset,
            'PutRec'                : self.putrec,
            'QuoteRem'              : self.quoterem,
            'Redim'                 : self.redim,
            'RedimAs'               : self.redimas,
            'Reparse'               : self.reparse,
            'Rem'                   : self.rem,
            'Resume'                : self.resume,
            'Return'                : self.return_,
            'RSet'                  : self.rset,
            'Scale'                 : self.scale,
            'Seek'                  : self.seek,
            'SelectCase'            : self.selectcase,
            'SelectIs'              : self.selectis,
            'SelectType'            : self.selecttype,
            'SetStmt'               : self.setstmt,
            'Stack'                 : self.stack,
            'Stop'                  : self.stop,
            'Type'                  : self.type_,
            'Unlock'                : self.unlock,
            'VarDefn'               : self.vardefn,
            'Wend'                  : self.wend,
            'While'                 : self.while_,
            'With'                  : self.with_,
            'WriteChan'             : self.writechan,
            'ConstFuncExpr'         : self.constfuncexpr,
            'LbConst'               : self.lbconst,
            'LbIf'                  : self.lbif,
            'LbElse'                : self.lbelse,
            'LbElseIf'              : self.lbelseif,
            'LbEndIf'               : self.lbendif,
            'LbMark'                : self.lbmark,
            'EndForVariable'        : self.endforvariable,
            'StartForVariable'      : self.startforvariable,
            'NewRedim'              : self.newredim,
            'StartWithExpr'         : self.startwithexpr,
            'SetOrSt'               : self.setorst,
            'EndEnum'               : self.endenum,
            'Illegal'               : self.illegal,
            'NewLine'               : self.newline
        }

    def imp(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Imp ' + arg2
        self.opstack.push(val)

    def eqv(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Eqv ' + arg2
        self.opstack.push(val)

    def xor(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Xor ' + arg2
        self.opstack.push(val)

    def or_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Or ' + arg2
        self.opstack.push(val)

    def and_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' And ' + arg2
        self.opstack.push(val)

    def eq(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' = ' + arg2
        self.opstack.push(val)

    def ne(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' <> ' + arg2
        self.opstack.push(val)

    def le(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' <= ' + arg2
        self.opstack.push(val)

    def ge(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' >= ' + arg2
        self.opstack.push(val)

    def lt(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' < ' + arg2
        self.opstack.push(val)

    def gt(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' > ' + arg2
        self.opstack.push(val)

    # ex opeline: "Add"
    # gets the two values on stack, pop them, add them and push again
    def add(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' + ' + arg2
        self.opstack.push(val)

    def sub(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' - ' + arg2
        self.opstack.push(val)

    def mod(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Mod ' + arg2
        self.opstack.push(val)

    def idiv(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' \\ ' + arg2
        self.opstack.push(val)

    def mul(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' * ' + arg2
        self.opstack.push(val)

    def div(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' / ' + arg2
        self.opstack.push(val)

    def concat(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' & ' + arg2
        self.opstack.push(val)

    def like(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Like ' + arg2
        self.opstack.push(val)

    def pwr(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' ^ ' + arg2
        self.opstack.push(val)

    def is_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Is ' + arg2
        self.opstack.push(val)

    def not_(self):
        val = 'Not ' + self.opstack.pop()
        self.opstack.push(val)

    def umi(self):
        val = '-' + self.opstack.pop()
        self.opstack.push(val)

    def fnabs(self):
        arg = self.opstack.pop()
        val = 'Abs(' + arg + ')'
        self.opstack.push(val)

    def fnfix(self):
        arg = self.opstack.pop()
        val = 'Fix(' + arg + ')'
        self.opstack.push(val)

    def fnint(self):
        arg = self.opstack.pop()
        val = 'int(' + arg + ')'
        self.opstack.push(val)

    def fnsgn(self):
        arg = self.opstack.pop()
        val = 'Sgn(' + arg + ')'
        self.opstack.push(val)

    def fnlen(self):
        arg = self.opstack.pop()
        val = 'Len(' + arg + ')'
        self.opstack.push(val)

    def fnlenb(self):
        arg = self.opstack.pop()
        val = 'LenB(' + arg + ')'
        self.opstack.push(val)

    def paren(self):
        arg = self.opstack.pop()
        val = '(' + arg + ')'
        self.opstack.push(val)

    def sharp(self):
        arg = self.opstack.pop()
        val = '#' + arg
        self.opstack.push(val)

    def ldlhs(self):
        raise Pcode2codeException('not implemented ldlhs')

    def ld(self, var):
        """
        command defining a variable
        example: X = Y
        gives:
             # Ld Y
             # St X
        """
        if var == 'id_FFFF': #hacky way to do it because me does not seem to be fully
            var = 'Me'       #parsed by pcodedmp
        self.opstack.push(var)

    def memld(self, var):
        val = self.opstack.pop() + '.' + var
        self.opstack.push(val)

    def dictld(self, var):
        """
        cf fields and collections, also index???
        example: Debug.Print rsTable!Title
        gives:
             # Debug
             # PrintObj
             # Ld rsTable
             # DictLd Title
             # PrintItemNL
        """
        self.opstack.push(self.opstack.pop()+ '!' + var)

    def indexld(self, *args):
        raise Pcode2codeException('not implemented indexld')

    def argsld(self, varname, numparams):
        val = varname + '('
        nb_parameters = int(numparams, 16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def argsmemld(self, var, numparams):
        nb_parameters = int(numparams, 16)
        val = self.opstack.pop() + '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def argsdictld(self, var, numparams):
        """
        command used when an index of an object with an argument is accessed
        example: Debug.Print myobj!toto("titi") 
        gives:
             # Debug
             # PrintObj
             # LitStr 0x0004 "titi"
             # Ld myobj
             # ArgsDictLd toto 0x0001
             # PrintItemNL
        """
        nb_parameters = int(numparams, 16)
        val = self.opstack.pop() + '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    # example line : Function giqw(str As String) As Variant: Dim bytes() As Byte: bytes = str: giqw = bytes: End Function
    # op line:
    # Line #13:
    #     FuncDefn (Function giqw(str As String) As Variant)
    #     BoS 0x0000 
    #     Dim 
    #     VarDefn bytes (As Byte)
    #     BoS 0x0000 
    #     Ld str 
    #     St bytes 
    #     BoS 0x0000 
    #     Ld bytes 
    #     St giqw 
    #     BoS 0x0000 
    #     EndFunc 
    def st(self, arg):
        param = self.opstack.pop()
        val = arg + ' = ' + param
        self.opstack.push(val)

    def memst(self, var):
        val = self.opstack.pop() + '.' + var
        val = val + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def dictst(self, var):
        """
        command used when an index is defined directly
        example: myobj!titi = "toto"
        gives:
             # LitStr 0x0004 "toto"
             # Ld myobj
             # DictSt titi
        """
        val = self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def indexst(self, *args):
        raise Pcode2codeException('not implemented indexst')

    # TODO: to check
    def argsst(self, var, numparams):
        nb_parameters = int(numparams, 16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)

    def argsmemst(self, var, numparams):
        #TODO: to check
        val = self.opstack.pop() + '.'
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)

    def argsdictst(self, var, numparams):
        """
        used when an index of an obj with an argument is defined
        example: myobj!titi2("toto") = "toto"
        gives:
             # LitStr 0x0004 "toto"
             # LitStr 0x0004 "toto"
             # Ld myobj
             # ArgsDictSt titi2 0x0001
        """
        val = self.opstack.pop() + '!' 
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)
        
        
        
    def set_(self, var):
        val = 'Set ' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def memset(self, var):
        """
        obtained when a property of an object is set
        example: Set YourObject.Text = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld YourObject
             # Memset Text
        """
        val = 'Set ' + self.opstack.pop() + '.' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)
        
    def dictset(self, var):
        """
        obtained when an index of an object is set
        example: Set YourObject!Text = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld YourObject
             # Dictset Text
        """
        val = 'Set ' + self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)


    def indexset(self, *args):
        raise Pcode2codeException('not implemented indexset')

    def argsset(self, var, nb):
        """
        obtained when an argument of an object is set
        example: Set YourObject(ggg) = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld ggg
             # ArgsSet YourObject 0x0001
        """
        val = 'Set ' + var + '(' + self.opstack.pop() + ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsmemset(self, var, numparams):
        """
        obtained when an argument of a property of an object is set
        example: Set YourObject.Text2("titi") = lobject
        gives:
             # SetStmt
             # Ld lobject
             # LitStr 0x0004 "titi"
             # Ld YourObject
             # ArgsMemSet Text2 0x0001
        """
        nb_parameters = int(numparams, 16)
        val = 'Set ' + self.opstack.pop() + '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

        
    def argsdictset(self, var, numparams):
        """
        obtained when an argument of a property of an object is set
        example: Set YourObject.Text2("titi") = lobject
        gives:
             # SetStmt
             # Ld lobject
             # LitStr 0x0004 "titi"
             # Ld YourObject
             # ArgsMemSet Text2 0x0001
        """
        nb_parameters = int(numparams, 16)
        val = 'Set ' + self.opstack.pop() + '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)


    def memldwith(self, var):
        """
        command defining a part of an object like .<prop>
        example: with blah <....> .Name 
        gives:  # MemLdWith Name
        """
        self.opstack.push('.' + var)

    def dictldwith(self, var):
        """
        accessing an index in a with block
        example: With <smth>.... Debug.Print !au_lname ... end with
        gives:
             # Debug
             # PrintObj
             # DictLdWith au_lname
             # PrintItemNL
        """
        self.opstack.push('!' + var)

    def argsmemldwith(self, var, numparams):
        """
        example: .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1
        gives:
             # Ld sProc
             # Ld ProcType
             # ArgsMemLdWith ProcStartLine 0x0002
             # Ld lLine
             # Add
             # LitDI2 0x0001
             # Ld sProc
             # Ld ProcType
             # ArgsMemLdWith ProcStartLine 0x0002
             # Ld lLine
             # Add
             # LitDI2 0x0001
             # Add
             # LitDI2 0x0001
             # MemLdWith CodePane
             # ArgsMemCall SetSelection 0x0004
        """
        nb_parameters = int(numparams, 16)
        val = '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

        
    def argsdictldwith(self, var, numparams):
        """
        command used when an index of an object with an argument is accessed with a with block
        example: With myobj ... Debug.Print !toto("titi") ... end with
        gives:
             # Debug
             # PrintObj
             # LitStr 0x0004 "titi"
             # ArgsDictLdWith toto 0x0001
             # PrintItemNL
        """
        nb_parameters = int(numparams, 16)
        val = '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)


    def memstwith(self, var):
        """
        command defining a part of an object like .<prop> = <smthg>
        example: .Name = "Coho Vineyard"
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # MemStWith Name
        """
        self.opstack.push('.' + var + ' = ' + self.opstack.pop())

        
    def dictstwith(self, var):
        """
        command defining a part of an object like !<index> = <smthg>
        example: With ... !Name = "Coho Vineyard" ... end with
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # DictStWith Name
        """
        self.opstack.push('!' + var + ' = ' + self.opstack.pop())

        
    def argsmemstwith(self, var, numparams):
        """
        command defining a property of an object with arguments in a with statement
        example: With ... .Name(1,2) = b ... end with
        gives:
             # Ld B
             # LitDI2 0x0001
             # LitDI2 0x0002
             # ArgsMemStWith Name 0x0002
        """
        nb_parameters = int(numparams, 16)
        val = '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsdictstwith(self, var, *args):
        """
        command defining a part of an object like !<index> = <smthg> in a with block
        example: !Name = "Coho Vineyard"
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # DictStWith Name
        """
        self.opstack.push('!' + var + ' = ' + self.opstack.pop())


    def memsetwith(self, var):
        """
        command defining a set on an index of an object in a with block
        example: with <smth> ... Set .Name = "Coho Vineyard"
        gives:
             # SetStmt
             # LitStr 0x000D "Coho Vineyard"
             # memSetWith Name
        """
        self.opstack.push('Set .' + var + ' = ' + self.opstack.pop())

        
    def dictsetwith(self, var):
        """
        command defining a set on an index of an object in a with block
        example: with <smth> ... Set !Name = "Coho Vineyard"
        gives:
             # SetStmt
             # LitStr 0x000D "Coho Vineyard"
             # DictSetWith Name
        """
        self.opstack.push('Set !' + var + ' = ' + self.opstack.pop())

    def argsmemsetwith(self, var, numparams):
        """
        command defining a set on an index with an argument of an object in a with block
        example: with <smth> ... Set .nini("gg", "ff", "uu") = "toto"
        gives:
             # SetStmt
             # LitStr 0x0004 "toto"
             # LitStr 0x0002 "gg"
             # LitStr 0x0002 "ff"
             # LitStr 0x0002 "uu"
             # ArgsMemSetWith nini 0x0003
        """
        nb_parameters = int(numparams, 16)
        val = 'Set !' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsdictsetwith(self, var, numparams):
        """
        command defining a set on an index with an argument of an object in a with block
        example: with <smth> ... Set !nini("gg", "ff", "uu") = "toto"
        gives:
             # SetStmt
             # LitStr 0x0004 "toto"
             # LitStr 0x0002 "gg"
             # LitStr 0x0002 "ff"
             # LitStr 0x0002 "uu"
             # ArgsDictSetWith nini 0x0003
        """
        nb_parameters = int(numparams, 16)
        val = 'Set !' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    
    def argscall(self, *args):

        if args[0] == '(Call)':
            nb_parameters = int(args[2],16)
            val = 'Call ' + args[1] + '('
            end_val = ')'
        else:
            val = args[0]
            nb_parameters = int(args[1],16)           
            end_val = ''
            
        params = []
        #print 'func:' + funcname
        #print 'nbparameters : ' + str(nb_parameters)
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if ((params[0].startswith('(')) or (args[0] == '(Call)')):               
                val = val + params[0]
            else:
                val = val + ' ' + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += end_val
        self.opstack.push(val)

    def argsmemcall(self, *args):
        """
        command to call a function of an object
        example: a43g0xT.run ayUBnLK01, 0
        gives : 
           # Ld ayUBnLK01
           # LitDI2 0x0000
           # Ld a43g0xT
           # ArgsMemCall run 0x0002
        """
        args = list(args)
        parenthesis = False
        if args[0] == '(Call)':
            args.pop(0)
            val = 'Call ' + self.opstack.pop() + '.' + args[0] + '('
            parenthesis = True
        else:
            val = self.opstack.pop() + '.' + args[0]

        nb_parameters = int(args[1],16)           
        end_val = ''
            
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if params[0].startswith('('):               
                val = val + params[0]
                end_val = ')'
            else:
                if not parenthesis:
                    val = val + ' ' +params[0]
                else:
                    val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        if parenthesis == True:
            end_val = ')'
        self.opstack.push(val + end_val)

    def argsmemcallwith(self, *args):
        """
        command when a function of an object is called in a with definition
        example: With a ... call .a(1,2) ... end with
        gives: 
             # LitDI2 0x0001
             # LitDI2 0x0002
             # ArgsMemCallWith (Call) a 0x0002
        """
        parenthesis = False
        args = list(args)
        if args[0] == '(Call)':
            args.pop(0)
            parenthesis = True
            val = 'Call .' + args[0] + '('
        else:
            val = '.' + args[0]
            
        nb_parameters = int(args[1],16)           
        end_val = ''
            
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if params[0].startswith('('):               
                val = val + params[0]
                end_val = ')'
            else:
                if not parenthesis:
                    val = val + ' ' + params[0]
                else:
                    val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param

        if parenthesis:
            end_val = ')'
        self.opstack.push(val + end_val)
        

    def argsarray(self, var, numparams):
        val = var + '('
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def assert_(self):
        """
        command for debug.asser
        example: Debug.Assert blnAssert
        gives : 
              # Ld blnAssert
              # Assert
        """
        self.opstack.push('Debug.Assert ' + self.opstack.pop())

    def bos(self, valarg):
        arg = int(valarg,16)
        if arg == 0:
            val = self.opstack.pop() + ':'
        self.opstack.push(val)
        self.has_bos = True

    def bosimplicit(self, *args):
        """
        appears useless, but in this case we still need to print whole stack
        example: If Mid$(theString, i, 1) <> Chr$(0) Then Exit For
        gives:
             # Ld theString
             # Ld i
             # LitDI2 0x0001
             # ArgsLd Mid$ 0x0003
             # LitDI2 0x0000
             # ArgsLd Chr$ 0x0001
             # Ne
             # If
             # BoSImplicit
             # ExitFor
             # EndIf
        """
        self.has_bos = True
        
    def bol(self, *args):
        raise Pcode2codeException('not implemented bol')

    def ldaddressof(self, var):
        """
        command for AddressOf keyword
        example: EnumFontFamilies hDC, vbNullString, AddressOf EnumFontFamProc, LB
        gives:
             # Ld hDC
             # Ld vbNullString
             # LdAddressOf EnumFontFamProc
             # Ld LB
             # ArgsCall EnumFontFamilies 0x0004
        """
        self.opstack.push('AddressOf ' + var)

    def memaddressof(self, var):
        """
        command for AddressOf keyword on a property of an object
        example: MsgBox AddressOf myobj.toto
        gives:
             # Ld myobj
             # MemAddressOf toto
             # ArgsCall MsgBox 0x0001
        """
        self.opstack.push('AddressOf ' + self.opstack.pop() + '.' + var)

    def case(self):
        """
        command handling choice in select case where choice is one value 
        example: Case 0
        gives:
             # LitDI2 0x0000
             # Case
             # CaseDone

        """
        self.opstack.push('Case ' + self.opstack.pop())

    def caseto(self):
        """
        command handling choice in select case where choice is from one value to one other value
        example: Case 0 To 30
        gives:
             # LitDI2 0x0000
             # LitDI2 0x001E
             # CaseTo
             # CaseDone
        """
        val = self.opstack.pop()
        self.opstack.push('Case ' + self.opstack.pop() + ' To ' + val)


    def casegt(self):
        """
        command handling choice in select case where choice is lower than a value
        example: Case Is > 100
        gives:
             # LitDI2 0x0064
             # CaseGt
             # CaseDone
        """
        self.opstack.push('Case Is > ' + self.opstack.pop())

    def caselt(self):
        """
        command handling choice in select case where choice is lower than a value
        example: Case Is < 0
        gives:
             # LitDI2 0x0002
             # CaseLt
             # CaseDone
        """
        self.opstack.push('Case Is < ' + self.opstack.pop())

    def casege(self):
        """
        command handling choice in select case where choice is greater or equal than a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is >= ' + self.opstack.pop())

    def casele(self):
        """
        command handling choice in select case where choice is lower or equal than a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is <= ' + self.opstack.pop())

    def casene(self):
        """
        command handling choice in select case where choice is different to a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is <> ' + self.opstack.pop())

    def caseeq(self):
        """
        command handling choice in select case where choice is equal to a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is = ' + self.opstack.pop())

    def caseelse(self):
        """
        command defining a "Case Else" stmt
        example: Case Else
        gives: 
             # CaseElse
        """
        self.opstack.push('Case Else')

    def casedone(self):
        #pass on purpose, please see previous examples
        pass

    def circle(self, useless):
        """
        command used when the circle method of an object is called
        example: Me.Circle (sngHCtr, sngVCtr), sngRadius
        gives:
             # Ld sngHCtr
             # Ld sngVCtr
             # Ld sngRadius
             # LitDI2 0x0000
             # LitDI2 0x0000
             # LitDI2 0x0000
             # LitDI2 0x0000
             # Ld id_FFFF
             # Circle 0x001E
        """
        val = self.opstack.pop() + '.Circle ('
        params = []
        for i in range(7):
            params.append(self.opstack.pop())
        params = params[::-1]

        val += params[0] + ', ' + params[1] + '), ' + params[2]
        all_empty = True
        for param in params[3:]:
            if param != '0':
                all_empty = False

        if all_empty:
            self.opstack.push(val)
        else:
            for param in params[3:]:
                if param == '0':
                    val = val + ', <tbr>'
                else:
                    val = val + ', ' + param
            val = val.replace(', <tbr>' , '')
            self.opstack.push(val)


    def close(self, numparams):
        val = 'Close '
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        self.opstack.push(val)

    def closeall(self):
        """
        command used when close is called with no arguments, effectively closing all files
        example: Close
        gives: # CloseAll
        """
        self.opstack.push('Close')

    def coerce_(self, arg):
        """
        command used for variable conversion
        example1: MyLong2 = CLng(MyVal2)
        gives:
             # Ld MyVal2
             # Coerce (Lng)
             # St MyLong2
        example2: MyInt = CInt(MyDouble)
        gives:
             # Ld MyDouble
             # Coerce (Int)
             # St MyInt
        """
        if arg == '(Str)':
            self.opstack.push('CStr(' + self.opstack.pop() + ')')
        elif arg == '(Var)':
            self.opstack.push('CVar(' + self.opstack.pop() + ')')
        elif arg == '(Sng)':
            self.opstack.push('CSng(' + self.opstack.pop() + ')')
        elif arg == '(Lng)':
            self.opstack.push('CLng(' + self.opstack.pop() + ')')
        elif arg == '(Int)':
            self.opstack.push('CInt(' + self.opstack.pop() + ')')
        elif arg == '(Dbl)':
            self.opstack.push('CDbl(' + self.opstack.pop() + ')')
        elif arg == '(Date)':
            self.opstack.push('CDate(' + self.opstack.pop() + ')')
        elif arg == '(Cur)':
            self.opstack.push('CCur(' + self.opstack.pop() + ')')
        elif arg == '(Byte)':
            self.opstack.push('CByte(' + self.opstack.pop() + ')')
        elif arg == '(Bool)':
            self.opstack.push('CBool(' + self.opstack.pop() + ')')
        else:
            raise Pcode2codeException('not implemented coerce')
        
    def coercevar(self, arg):
        """
        example1: MyError = CVErr(32767)
        gives: # CoerceVar (Err)
        """
        if arg == '(Err)':
            self.opstack.push('CVErr(' + self.opstack.pop() + ')')
        else:
            raise Pcode2codeException('not implemented coercevar')

    def context(self, *args):
        raise Pcode2codeException('not implemented context')

    def debug(self):
        """
        seems used to invoke debug object
        example: Debug.Print MyVar
        gives:
             # Debug
             # PrintObj
             # Ld MyVar
             # PrintItemNL
        """
        self.opstack.push('Debug')

    def deftype(self, *args):
        """
        command used when def<type> is used.
        TODO: bytes to know ranges appear random. How to do it?
        """
        raise Pcode2codeException('not implemented deftype')

    # Dim hiz7dgus As String
    # Private Const DefaultBufferSize& = 32768
    # Private CRC_32_Tab(0 To 255) As Long
    # ======================
    # Line #7:
    #   Dim 
    #   VarDefn hiz7dgus (As String)
    # Line #8:
    # Line #9:
    #   Dim (Private Const) 
    #   LitDI4 0x8000 0x0000 
    #   VarDefn DefaultBufferSize
    # Line #10:
    # Line #11:
    #   Dim (Private) 
    #   LitDI2 0x0000 
    #   LitDI2 0x00FF 
    #   VarDefn CRC_32_Tab (As Long)
    def dim(self, *args):
        # args is a tuple, we treat it only when its not empty
        # example of args : (As String), (As Long)...
        if args != ():
            val = args[0]
            for arg in args[1:]:
                val += ' ' + arg
            val = val[1:-1]
        else:
            val = 'Dim'
        self.opstack.push(val)

    def dimimplicit(self):
        self.opstack.push('DimImplicit')

    def do(self):
        """
        command handling "Do" keyword
        example: Do (we have then the loop and so on)
        gives:
             # Do
        """
        self.opstack.push('Do')
        self.indentincrease_future = True

    def doevents(self, *args):
        raise Pcode2codeException('not implemented doevents')

    def dounitil(self):
        """
        command handling "do until" definitions
        example: Do Until Response = "youpi"
        gives:
             # Ld Response
             # ListStr 0x0005 "youpi"
             # Eq
             # DoUnitil
        """
        self.opstack.push('Do Until ' + self.opstack.pop())
        self.indentincrease_future = True

    def dowhile(self):
        """
        command handling "do while" definitions
        example: Do While Reponse <> "youpi"
        gives:
             # Ld Response
             # LitStr 0x0005 "youpi"
             # Ne
             # DoWhile
        """
        self.opstack.push('Do While ' + self.opstack.pop())
        self.indentincrease_future = True

    def else_(self):
        """
        command used for a "else" in a if oneliner
        example: If X < 4 Then MsgBox "hi" Else MsgBox "ho"
        gives:
             # Ld X
             # LitDI2 0x0004
             # Lt
             # If
             # BoSImplicit
             # LitStr 0x0002 "hi"
             # ArgsCall MsgBox 0x0001
             # Else
             # BoSImplicit
             # LitStr 0x0002 "Ho"
             # ArgsCall MsgBox 0x0001
             # EndIf
        """
        self.opstack.push('Else')

    def elseblock(self):
        """
        command defining a new "else" for a block
        example: Else
        gives: #Else
        """
        self.opstack.push('Else')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True

    def elseifblock(self):
        """
        command defining a new "else if" block
        example: ElseIf dayW = DayOfWeek.Thursday Then
        gives:
             # Ld dayW
             # Ld DayOfWeek
             # MemLd Thursday
             # Eq
             # ElseIfBlock
        """
        self.opstack.push('ElseIf ' + self.opstack.pop() + ' Then')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True

    def elseiftypeblock(self, *args):
        raise Pcode2codeException('not implemented elseiftypeblock')

    def end(self):
        self.opstack.push('End')

    def endcontext(self, *args):
        raise Pcode2codeException('not implemented endcontext')

    def endfunc(self):
        self.opstack.push('End Function')
        self.indentlevel = self.indentlevel - 1

    def endif(self):
        if self.onelineif == True:
            self.onelineif = False
        else:
            self.opstack.push('End If')
            self.indentlevel = self.indentlevel - 1

    def endifblock(self):
        self.opstack.push('End If')
        self.indentlevel = self.indentlevel - 1

    def endimmediate(self, *args):
        raise Pcode2codeException('not implemented endimmediate')

    def endprop(self):
        """
        command handling the end of a property
        example: End Property
        gives: 
             #EndProp
        """
        self.opstack.push('End Property')
        self.indentlevel = self.indentlevel -1

    def endselect(self):
        """
        command defining a stmt of "End Select", closing a select case.
        example: End Select
        gives: 
             # EndSelect
        """
        self.opstack.push('End Select')
        self.indentlevel = self.indentlevel - 1

    def endsub(self):
        self.opstack.push('End Sub')
        self.indentlevel = self.indentlevel - 1

    def endtype(self):
        """
        command to end a new type definition
        example: End Type
        gives:
             #EndType
        """
        self.opstack.push('End Type')
        self.indentlevel = self.indentlevel - 1

    def endwith(self):
        """
        command to end a new with definition
        example: End With
        gives: #EndWith
        """
        self.opstack.push('End With')
        self.indentlevel = self.indentlevel - 1
        

    def erase(self, nb_params):
        """
        command for Erase function keyword
        example: Erase threeDimArray, twoDimArray
        gives:
             # Ld threeDimArray
             # Ld twoDimArray
             # Erase 0x0002
        """
        nb_args = int(nb_params, 16)
        val = ''
        params = []
        for i in range(nb_args):
            params.append(self.opstack.pop())
            params = params[::-1]
        val = params[0]
            
        if nb_args > 1:
            for param in params[1:]:
                val = val + ', ' + param

        self.opstack.push('Erase ' + val)


    def error(self):
        """
        command used for Error keyword
        example: Error 11
        gives:
             # LitDI2 0x000B
             # Error
        """
        self.opstack.push('Error ' + self.opstack.pop())

    def eventdecl(self, *args):
        """
        command for declaring a new event in VBA
        example: Event LogonCompleted(UserName As String)
        gives : 
           # EventDecl (Sub LogonCompleted(UserName As String))
        """
        val = args[1]
        for arg in args[2:-1]: #strip parenthesis
            val += ' ' + arg
        self.opstack.push('Event ' + val + ' ' + args[-1][:-1])

    def raiseevent(self, evt_name, nb_params):
        """
        command when RaiseEvent is used
        example: RaiseEvent LogonCompleted("AntoineJean")
        gives:
             # LitStr 0x000A "AntoineJan"
             # RaiseEvent LogonCompleted 0x0001
        """
        nb_args = int(nb_params, 16)
        val = ''
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = '('+ params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
                    
        self.opstack.push('RaiseEvent ' + evt_name + val)
            

    def argsmemraiseevent(self, var, numparams):
        """
        command used when a raiseevent is called on a property of an object
        example: RaiseEvent myobj.LogonCompleted("AntoineJan")
        gives:
             # LitStr 0x000A "AntoineJan"
             # Ld myobj
             # ArgsMemRaiseEvent LogonCompleted 0x0001
        """
        nb_args = int(numparams, 16)
        val = 'RaiseEvent ' + self.opstack.pop() + '.' + var + '('
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val += params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
        self.opstack.push(val)

    def argsmemraiseeventwith(self, var, numparams):
        """
        command used when a raiseevent is called on a property of an object within a with block
        example: with myobj ... RaiseEvent .LogonCompleted("AntoineJan") ... end with
        gives:
             # LitStr 0x000A "AntoineJan"
             # ArgsMemRaiseEventWith LogonCompleted 0x0001
        """
        nb_args = int(numparams, 16)
        val = 'RaiseEvent .' + var + '('
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val += params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
        self.opstack.push(val)
    
    def exitdo(self):
        #TODO: comment
        self.opstack.push('Exit Do')

    def exitfor(self):
        #TODO: comment
        self.opstack.push('Exit For')

    def exitfunc(self):
        #TODO: comment
        self.opstack.push('Exit Function')
    
    def exitprop(self):
        #TODO: comment
        self.opstack.push('Exit Property')
    
    def exitsub(self):
        #TODO: comment
        self.opstack.push('Exit Sub')
    
    def fncurdir(self, *args):
        #val = 'CurDir(' + self.opstack.pop() + ')'
        #self.opstack.push(val)
        raise Pcode2codeException('not implemented fncurdir')
    
    def fndir(self, *args):
        raise Pcode2codeException('not implemented fndir')
    
    def empty0(self, *args):
        raise Pcode2codeException('not implemented empty0')
    
    def empty1(self, *args):
        raise Pcode2codeException('not implemented empty1')
    
    def fnerror(self, *args):
        raise Pcode2codeException('not implemented fnerror')
    
    def fnformat(self, *args):
        raise Pcode2codeException('not implemented format')
    
    def fnfreefile(self, *args):
        raise Pcode2codeException('not implemented fnfreefile')
    
    def fninstr(self):
        """
        command used when calling Instr function with 2 arguments
        example: MyPos = InStr(SearchString, SearchChar)
        gives:
             # Ld SearchString
             # Ld SearchChar
             # FnInStr
             # St MyPos
        """
        arg2 = self.opstack.pop()
        self.opstack.push('Instr(' + self.opstack.pop() + ', ' + arg2 + ')')
    
    def fninstr3(self):
        """
        command used when calling Instr function with 3 arguments
        example: MyPos = InStr(1, SearchString, "W")
        gives:
             # LitDI2 0x0001
             # Ld SearchString
             # LitStr 0x0001 "W"
             # FnInStr3
             # St MyPos
        """
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')
    
    def fninstr4(self):
        """
        command used when calling Instr function with 4 arguments
        example: MyPos = InStr(4, SearchString, SearchChar, 1)
        gives:
             # LitDI2 0x0004
             # Ld SearchString
             # Ld SearchChar
             # LitDI2 0x0001
             # FnInStr4
             # St MyPos
        """
        arg4 = self.opstack.pop()
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
    
    def fninstrb(self):
        """
        command used when calling InstrB function with 2 arguments
        example: TODO: make sure here
        gives:
        """
        arg2 = self.opstack.pop()
        self.opstack.push('InstrB(' + self.opstack.pop() + ', ' + arg2 + ')')

        
    def fninstrb3(self):
        """
        command used when calling InstrB function with 3 arguments
        example: TODO: make sure here
        gives:

        """
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('InstrB(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')

        
    def fninstrb4(self):
        """
        command used when calling InstrB function with 4 arguments
        example: TODO: make sure here
        gives:

        """
        arg4 = self.opstack.pop()
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
    
    def fnlbound(self, arg):
        """
        command indicating the use of the LBound function
        strangely enough, there is an indication of the number of arguments to be popped out of the stack
        but this number is not good.
        example: Lower = LBound(TwoDArray, 2)
        gives: 
             # Ld TwoDArray
             # LitDI2 0x0002
             # FnLBound 0x0001
             # St Lower
        """
        nb_parameters = int(arg,16) + 1
        params = []
        val = '('
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        val = 'LBound' + val
        self.opstack.push(val)
    
    def fnmid(self):
        val = 'Mid(' + self.opstack.pop() + ')'
        self.opstack.push(val)
    
    def fnmidb(self):
        val = 'MidB(' + self.opstack.pop() + ')'
        self.opstack.push(val)
    
    def fnstrcomp(self):
        """
        command used when strcomp function with 2 arguments is called
        example: MyComp = StrComp(MyStr2, MyStr1)
        gives:
             # Ld MyStr2
             # Ld MyStr1
             # FnStrComp
             # St MyComp
        """
        str2 = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('StrComp(' + str1 + ', ' + str2 + ')')
            
    def fnstrcomp3(self):
        """
        command used when strcomp function with 3 arguments is called
        example: MyComp = StrComp(MyStr1, MyStr2, 0)
        gives:
             # Ld MyStr1
             # Ld MyStr2
             # LitDI2 0x0000
             # FnStrComp3
             # St MyComp
        """
        third_arg = self.opstack.pop()
        str2 = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('StrComp(' + str1 + ', ' + str2 + ', ' + third_arg + ')')
    
    def fnstringvar(self, *args):
        raise Pcode2codeException('not implemented fnstringvar')
    
    def fnstringstr(self, *args):
        raise Pcode2codeException('not implemented fnstringstr')
   
    def fnubound(self, arg):
        """
        command used when calling Ubound function
        example: uL = UBound(sb_)
        gives:     
             # Ld sb_ 
             # FnUBound 0x0000 
             # St uL
        """
        nb_parameters = int(arg,16) + 1
        params = []
        val = '('
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        val = 'UBound' + val
        self.opstack.push(val)
            
    def for_(self):
        maxvar = self.opstack.pop()
        minvar = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar
        self.opstack.push(val)
        self.indentincrease_future = True
            
    def foreach(self):
        """
        command defining a new for each loop definition
        example: For Each MyObject In MyClasses
        gives:
             # StartForVariable
             # Ld MyObject
             # EndForVariable
             # Ld MyClasses
             # ForEach
        """
        collect = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For Each ' + loopvar + ' In ' + collect
        self.opstack.push(val)
        self.indentincrease_future = True
    
    def foreachas(self, *args):
        raise Pcode2codeException('not implemented foreachas')
            
    def forstep(self):
        step = self.opstack.pop()
        maxvar = self.opstack.pop()
        minvar = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar + ' Step ' + step
        self.opstack.push(val)
        self.indentincrease_future = True
            
    def funcdefn(self, *args: str):
        val = args[0]
        for arg in args[1:]:
            val += ' ' + arg
        val = val[1:-1]
        self.opstack.push(val)
        if not val.startswith('Declare'):
            self.indentincrease_future = True
            
    def funcdefnsave(self, *args):
        raise Pcode2codeException('not implemented funcdefnsave')
            
    def getrec(self):
        """
        command to Get from a channel with a record: get channel, record, var
        example: Get #1, RecordNumber, MyRecord
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # Ld MyRecord
             # GetRec
        """
        record = self.opstack.pop()
        record_num = self.opstack.pop()
        chan = self.opstack.pop()
        if chan is not None:
            self.opstack.push('Get ' + chan + ', ' + record_num + ', ' + record)
        else:
            self.opstack.push('Get ' + record_num + ', , ' + record) # kindly ugly
            
    def gosub(self, var):
        """
        command used when gosub is used
        example: If Num > 0 Then GoSub MyRoutine 
        gives:
             # Ld Num
             # LitDI2 0x0000
             # Gt
             # If
             # BoSImplicit
             # GoSub MyRoutine
             # EndIf
        """
        self.opstack.push('GoSub ' + var)
            
    def goto(self, var):
        """
        command used when a goto <label> is defined
        example: GoTo label1
        gives: # GoTo label1
        """
        self.opstack.push('GoTo ' + var)

            
    def if_(self, *args):
        val = 'If ' + self.opstack.pop() + ' Then'
        self.onelineif = True
        self.opstack.push(val)
    
    def ifblock(self):
        val = 'If ' + self.opstack.pop() + ' Then'
        self.opstack.push(val)
        self.indentincrease_future = True
    
    def typeof(self, *args):
        """
        command used when TypeOf function is used
        TODO: associated type is obscure for now
        """
        raise Pcode2codeException('not implemented typeof')
            
    def iftypeblock(self, *args):
        raise Pcode2codeException('not implemented iftypeblock')
            
    def implements(self, *args):
        """
        command used when Implements instruction is used
        TODO: associated type is obscure for now        
        """
        raise Pcode2codeException('not implemented implements')
            
    def input_(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        self.opstack.push('Input ' + self.opstack.pop())
        
    def inputdone(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += elmt
        self.opstack.push(val)

            
    def inputItem(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        self.opstack.push(', ' + self.opstack.pop())
            
    def label(self, arg):
        """
        command defining a new label
        example: MyString:
        gives:
             # Label MyString
        """
        self.opstack.push(arg+':')
            
    def let(self, *args):
        """
        command used when let keywork is used
        example: Let MyStr  = "Hello World"
        gives:
             # Let
             # LitStr 0x000B "Hello World"
             # St MyStr
        """
        self.opstack.push('Let')
        self.has_bos = True #we use this hackish way to print it even if not in stack top

            
    def line(self, *args):
        raise Pcode2codeException('not implemented line')
            
    def linecont(self, *args):
        #pass on purpose
        pass
            
    def lineInput(self):
        """
        command used when Line Input instruction is used (to read one line at a time a file)
        example: Line Input #1, TextLine
        gives:
             # LitDI2 0x0001
             # Ld TextLine
             # LineInput
        """
        var = self.opstack.pop()
        num_file = self.opstack.pop()
        self.opstack.push('Line Input #' + num_file + ', ' + var)
            
    def linenum(self, *args):
        # ignoring this seems to work fine.
        return
            
    def litcy(self, *args):
        raise Pcode2codeException('not implemented litcy')
            
    def litdate(self, *args):
        """
        command to define a date literal
        TODO: but wtf how to get date?
        example1: MyDate = #2/12/1969#
        gives: LitDate 0x0000 0x0000 0xA780 0x40D8
        example2: MyDate = #2/12/1970#
        gives: LitDate 0x0000 0x0000 0x02C0 0x40D9
        example3: MyDate = #2/12/1971#
        gives: LitDate 0x0000 0x0000 0x5E00 0x40D9
        example4: MyDate = #2/11/1969#
        gives: LitDate 0x0000 0x0000 0xA740 0x40D8
        example5: MyDate = #2/10/1969#
        gives: LitDate 0x0000 0x0000 0xA700 0x40D8
        example6: MyDate = #3/12/1969#
        gives: LitDate 0x0000 0x0000 0xAE80 0x40D8
        example7: MyDate = #4/12/1969#
        gives: LitDate 0x0000 0x0000 0xB640 0x40D8


        1 year = 23360 (0x5b40) si on fait last2bytes.first2bytes
        1 month = 64 (0x40) sur second octet
        1 day = 
        """
        raise Pcode2codeException('a date is defined here, but it cannot be reconstructed')
            
    def litdefault(self):
        """
        appears to be useless
        example: Open "TESTFILE" For Output As #1 
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Output)
        example2: Lock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Lock
        example3: same for unlock
        """
        #pass on purpose
        pass

    # integer representation on 2 bytes (decimal base10)
    def litdi2(self, value):
        self.opstack.push(str(int(value,16)))

    # integer representation on 4 bytes (decimal base10)
    def litdi4(self, byte1, byte2):
        val = int(byte2+byte1[2:], 16)
        self.opstack.push(str(val))
        
    def litdi8(self, *args):
        raise Pcode2codeException('not implemented litdi8')
            
    def lithi2(self, byte):
        val = byte[2:]
        while val.startswith('0') and len(val) > 1:
            val = val[1:]
        val = '&H' + val
        self.opstack.push(val)
            
    def lithi4(self, byte1, byte2):
        val = byte2[2:]+byte1[2:]
        while val.startswith('0') and len(val) > 1:
            val = val[1:]
        val = '&H' + val
        self.opstack.push(val)
            
    def lithi8(self, *args):
        raise Pcode2codeException('not implemented lithi8')
            
    def litnothing(self):
        """
        command defining the "Nothing" variable
        example: Set Inst = Nothing
        gives:
             # SetStmt
             # LitNothing
             # Set Inst
        """
        self.opstack.push('Nothing')
            
    def litoi2(self, value):
        """
        command used when an octal is defined on a two bytes byte array
        example: B = &O1
        gives:
             # LitOI2 0x0001
             # St B
        """
        var = int(value,16)
        var2 = str(oct(var))[2:]
        self.opstack.push('&O' + var2)
            
    def litoi4(self, byte1, byte2):
        """
        command used when an octal is defined on a two bytes byte array
        example: B = &O12345644444
        gives:
             # LitOI4 0x4924 0x5397
             # St B
        """        
        val = byte2[2:]+byte1[2:]
        var = int(val,16)
        var2 = str(oct(var))[2:]
        self.opstack.push('&O' + var2)
        
            
    def litoi8(self, *args):
        raise Pcode2codeException('not implemented litoi8')
            
    def litr4(self, byte1, byte2):
        """
        command used when a floating point on 32 bit is declared
        """
        val = byte2[2:]+byte1[2:]
        self.opstack.push(str(struct.unpack("!f", bytes.fromhex(val))[0]))
            
    def litr8(self, byte1, byte2, byte3, byte4):
        """
        command used when a floating point on 64 bit is declared
        """
        val = byte4[2:]+byte3[2:]+byte2[2:]+byte1[2:]
        self.opstack.push(str(struct.unpack("!d", bytes.fromhex(val))[0]))
            
    def litsmalli2(self, *args):
        raise Pcode2codeException('not implemented malli2')
            
    def litstr(self, mylen, *args):
        val = args[0]
        for arg in args[1:]:
            val += ' ' + arg
        if len(val)>=2:
            #assert(val[0]=='"' and val[-1]=='"')
            val = val[1:-1]
            val = val.replace('"', '""')
            val = '"' + val + '"'

        self.opstack.push(val)
            
    def litvarspecial(self, var):
        self.opstack.push(var[1:-1])
            
    def lock(self):
        """
        command to lock a record
        example: Lock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Lock
        """
        if self.opstack.size() == 3:
            last_record = self.opstack.pop()
            first_record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan + ', ' + first_record + ' To ' + last_record)
        elif self.opstack.size() == 2:
            record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan + ', ' + record)
        elif self.opstack.size() == 1:
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan)
            
    def loop(self):
        self.opstack.push('Loop')
        self.indentlevel = self.indentlevel - 1
            
    def loopuntil(self):
        """
        command defining a loop until statement for "do"
        example: Loop Until TheName = ""
        gives:
             # Ld TheName
             # LitStr 0x0000 ""
             # Eq
             # LoopUntil
        """
        self.opstack.push('Loop Until ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1
            
    def loopwhile(self):
        """
        command handling " while" definitions
        example: Loop While Reponse = 5
        gives:
             # Ld Response
             # LitDI2  0x0005
             # Eq
             # LoopWhile
        """
        self.opstack.push('Loop While ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1

            
    def lset(self):
        """
        command for RSet keyword
        example: LSet MyString = "Right->"
        gives:
             # LitStr 0x0007 "Right->"
             # Ld MyString
             # RSet
        """
        var = self.opstack.pop()
        val = self.opstack.pop()
        self.opstack.push('LSet ' + var + ' = ' + val)
            
    def me(self, *args):
        raise Pcode2codeException('not implemented me')
            
    def meimplicit(self, *args):
        """
        command used when the object is the current form
        example: Print 
        gives:
             # MeImplicit
             # PrintObj
             # PrintNL
        """
        self.opstack.push('MeImplicit') #just pushing a specific marker to change treatment later
            
    def memredim(self, *args):
        """
        command used when a property of an object is redim
        example: ReDim myobj.foo(30)
        gives:
             # OptionBase
             # LitDI2 0x001E
             # Ld myobj
             # MemRedim foo 0x0001 (As Variant)
        """
        val = self.opstack.pop()
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + val + '.' + args[0] + '('
        else:
            val2 = 'ReDim '
            if preserve:
                val2 += 'Preserve '
            val2 += val + '.' + args[0] + '('
            val = val2

        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)
            
    def memredimwith(self, *args):
        """
        command used when a property of an object is redim within a with
        example: with myobj ... ReDim .foo(30) .. end with
        gives:
             # OptionBase
             # LitDI2 0x001E
             # MemRedimWith foo 0x0001 (As Variant)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + '.' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += '.' + args[0] + '('

        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)

            
    def memredimas(self, *args):
        """
        command used when a redim is defined on a property of an object with a As in the end
        example: ReDim myobj.mytab(50) As Double
        gives:
             # OptionBase
             # LitDI2 0x003C
             # Ld myobj
             # MemRedimAs Tab 0x0001 (As Double)
        """
        val = self.opstack.pop()
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + val + '.' + args[0] + '('
        else:
            val2 = 'ReDim '
            if preserve:
                val2 += 'Preserve '
            val2 += val + '.' + args[0] + '('
            val = val2
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def memredimaswith(self, *args):
        """
        command used when a redim is defined on a property of an object with a As in the end, within a with block
        example: With myobj ... ReDim .mytab(70) As Integer ... End With 
        gives:
             # OptionBase
             # LitDI2 0x0046
             # MemRedimAsWith Tab 0x0001 (As Integer)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + '.' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += '.' + args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def mid(self):
        """
        command used when Mid funtion is used to set a sub string part, e.g. as an instruction
        example: Mid(MyString, 5, 3) = "fox"
        gives:
             # LitStr 0x0003 "fox"
             # Ld MyString
             # LitDI2 0x0005
             # LitDI2 0x0003
             # Mid
        """
        if self.opstack.size() > 3:
            length = self.opstack.pop()
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('Mid(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
        else:
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('Mid(' + obj + ', ' + start + ') = ' + str1)            
            
    def midb(self):
        """
        command used when Mid funtion is used to set a sub string part, e.g as an instruction
        example: MidB(MyString, 5, 3) = "fox"
        gives:
             # LitStr 0x0003 "fox"
             # Ld MyString
             # LitDI2 0x0005
             # LitDI2 0x0003
             # MidB
        """
        if self.opstack.size() > 3:
            length = self.opstack.pop()
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('MidB(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
        else:
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('MidB(' + obj + ', ' + start + ') = ' + str1)            

            
    def name(self):
        """
        command for the name keyword, permitting to rename variables
        example: Name OldName As NewName
        gives:
             # Ld OldName
             # Ld NewName
             # Name
        """
        newname = self.opstack.pop()
        oldname = self.opstack.pop()
        self.opstack.push('Name ' + oldname + ' As ' + newname) 
            
    def new(self, var):
        self.opstack.push('New ' + var)
            
    def next_(self):
        self.opstack.push('Next')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = False
            
    def nextvar(self):
        self.opstack.push('Next ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1
            
    def onerror(self, *args):
        """
        command defining "on error" statements
        example1: On Error GoTo ErrorHandler
        gives:
             # OnError ErrorHandler
        example2: On Error GoTo 0
        gives: 
             # OnError (GoTo 0)
        example3: On Error Resume Next
        gives: 
             # OnError (Resume Next)
        """
        if args[0] == '(Resume':
            self.opstack.push('On Error Resume Next')
        elif args[0] == '(GoTo':
            self.opstack.push('On Error GoTo 0')
        else:
            #TODO: to check
            self.opstack.push('On Error GoTo ' + args[0])
            
    def ongosub(self, nb, *args):
        """
        command used for gosub on a variable
        example: On Number GoSub Sub1, Sub2
        gives:
             # Ld Number
             # OnGoSub 0x0004 Sub1, Sub2
        """
        val = 'On ' + self.opstack.pop() + ' GoSub '
        val2 = args[0]
        for arg in args[1:]:
            val2 += ' ' + arg
        self.opstack.push(val + val2)
            
    def ongoto(self, nb, *args):
        """
        command used for goto on a variable
        example: On Number GoTo Line1, Line2
        gives:
             # Ld Number
             # OnGoto 0x0004 Line1, Line2
        """
        val = 'On ' + self.opstack.pop() + ' GoTo '
        val2 = args[0]
        for arg in args[1:]:
            val2 += ' ' + arg
        self.opstack.push(val + val2)
            
    def open_(self, *args):
        """
        command used for Open function
        example: Open "TESTFILE" For Output As #1
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Output)
        example2: Open "TESTFILE" For Binary Access Write Lock Write As #1
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Binary Access Write Lock Write)
        """
        chan = self.opstack.pop()
        val = args[0][1:] # avoid parenthesis
        for arg in args[1:]:
            val += ' ' + arg
        val = val[:-1] #avoid parenthesis
        self.opstack.push('Open ' + self.opstack.pop() + ' ' + val + ' As ' + chan)
            
    def option(self, *args):
        """
        command for option keyword
        example: Option Explicit
        gives : 
           # Option (Explicit)
        example2: Option Compare Binary
        gives :
           # Option (Compare Binary)
        """
        val = args[0][1:]
        if len(args)>1:
            for arg in args[1:]: #strip parenthesis
                val += ' ' + arg
        self.opstack.push('Option ' + val[:-1])
            
    def optionbase(self):
        """
        used in the following case: when a table dimension is not declared from base to end, but only size;
        to treat it, we will push a magic value on stack like for dim and dimimplicit, and vardef will treat it directly
        example1: Dim MyArray(20)
        gives: 
             # Dim
             # OptionBase
             # LitDI2 0x0014
             # VarDefn MyArray
        """
        self.opstack.push('OptionBase')
            
    def parambyval(self):
        """
        command used when Byval keyword is used
        example: a ByVal b
        gives:
             # Ld B
             # ParamByVal
             # ArgsCall a 0x0001
        """
        self.opstack.push('ByVal ' + self.opstack.pop())
            
    def paramomitted(self):
        """
        command used when a parameter is left blank in a function call
        example: MsgBox Msg, , "Deferred Error Test"
        gives:
             # Ld Msg
             # ParamOmitted
             # LitStr 0x0013 "Deferred Error Test"
             # ArgsCall MsgBox 0x0003
        """
        self.opstack.push('')
            
    def paramnamed(self, var):
        """
        command used when a call is made with named parameters
        example: MyClasses.Add Item:=Inst, Key:=CStr(Num)
        gives:
             # Ld Inst
             # ParamNamed Item
             # Ld Num
             # Coerce (Str)
             # ParamNamed Key
             # Ld MyClasses
             # ArgsMemCall Add 0x0002
        """
        self.opstack.push(var + ':=' + self.opstack.pop())
            
    def printchan(self):
        """
        command defining "print" to a channel
        example: Print #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # PrintChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        self.opstack.push('Print ' +self.opstack.pop() + ',')
    
    def printcomma(self, *args):
        """
        command used when a colon is used in Print
        example: Debug.Print Spc(30), "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintComma
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push(',')
            
    def printeos(self):
        """
        used at the end of some print when there is nothing, instead of printitemnl
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
                val+= elmt
            else:
                val += ' ' + elmt
        self.opstack.push(val)

            
    def printitemcomma(self):
        """
        command defining ",", used for example when writing 
        example: Write #1, "Hello World", 234
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # LitStr 0x000B "Hello World"
             # PrintItemComma
             # LitDI2 0x00EA
             # PrintItemNL
             # QuoteRem 0x0020 0x001C " Write comma-delimited data."
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val + ',')
            
    def printitemnl(self):
        """
        TODO: not sure what's it is used for
        example1: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        example2:  Debug.Print i
        gives:
             # Debug
             # PrintObj
             # Ld i
             # PrintItemNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
                val+= elmt
            else:
                val += ' ' + elmt
        self.opstack.push(val)
            
    def printitemsemi(self):
        """
        command defining ";", used for example when writing 
        example: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val + ';')
            
    def printnl(self):
        """
        really not sure about this one
        example: Write #1,     
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # PrintNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val)
    
    def printobj(self):
        """
        appears to call the print method of an object
        example:  Debug.Print i
        gives:
             # Debug
             # PrintObj
             # Ld i
             # PrintItemNL
        """
        if self.opstack.top() == 'MeImplicit':
            self.opstack.pop()
            self.opstack.push('Print')
        else:
            self.opstack.push(self.opstack.pop() + '.Print')
            
    def printsemi(self, *args):
        """
        command used when a semicolon is used in Print
        example: Debug.Print Spc(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push(';')
            
    def printspc(self):
        """
        command used when SPC(n) is used in Print
        example: Debug.Print Spc(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Spc(' + self.opstack.pop() + ')')
            
    def printtab(self, *args):
        """
        command used when Tab(n) is used in Print
        example: Debug.Print Tab(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintTab
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Tab(' + self.opstack.pop() + ')')
            
    def printtabcomma(self):
        """
        command used when Tab with no arg is used in Print
        example: Debug.Print Tab, "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # PrintTabComma
             # PrintComma
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Tab')
            
    def pset(self, numparams):
        """
        command used when the pset method of an object is called
        example: Me.PSet (intI, sngMidPt)
        gives:
             # Ld intI
             # Ld sngMidPt
             # LitDI2 0x0000
             # Ld id_FFFF
             # PSet 0x0002
        """
        val = self.opstack.pop() + '.PSet('
        first_arg = self.opstack.pop()
        if first_arg != '0':
            val += first_arg + ', '
            
        nb_args = int(numparams, 16)
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]

            val += params[0]
            for param in params[1:]:
                val = val + ', ' + param
        val +=')'
        self.opstack.push(val)
            
    def putrec(self):
        """
        command to Put to a channel with a record: Put channel, record, var
        example: Put #1, RecordNumber, MyRecord
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # Ld MyRecord
             # PutRec
        """
        record = self.opstack.pop()
        record_num = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push(F'Put {chan}, {record_num}, {record}')
            
    def quoterem(self, val1, lenvar, *args):
        """
        command handling comments definition with '
        multiple cases:
        example : MsgBox "toto" 'a message to send
        gives:
             # LitStr 0x0004 "toto"
             # ArgsCall MsgBox 0x0001
             # QuoteRem 0x000F 0x11

        example : TODO macaroni
        gives: TODO macaroni
        """
        val = "'" + args[0][1:]
        for arg in args[1:] :
            val += ' ' + arg
        val = val[:-1]
        if self.opstack.size() != 0:
            val = self.opstack.pop() + ' ' + val
        self.opstack.push(val)


    def redim(self, *args):
        """
        command used when redim function is used
        example : ReDim temp(4)
        gives:
             # OptionBase
             # LitDI2 0x0004
             # Redim temp 0x0001 (As Variant)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)

        
    def redimas(self, *args):
        """
        command used when a redim is defined with a As in the end
        example: ReDim mytab(50) As Double
        gives:
             # OptionBase
             # LitDI2 0x0032
             # RedimAs mytab 0x0001 (As Double)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def reparse(self, *args):
        """
        opcode used when a non valid statement is employed
        """
        val = args[1][1:]
        for arg in args[2:]:
            val += ' ' + arg
        val = val[:-1] # avoid double quotes
        self.opstack.push(val)


    def rem(self, *args):
        """
        command for Rem keyword
        example: Rem This entire line is a comment
        gives:  # Rem 0x001F " This entire line is a comment."
        """
        val = args[2] # avoid space+double quote
        for arg in args[3:]:
            val += ' ' + arg
        val = val[:-1] #avoid double quote
        self.opstack.push('Rem ' + val)
        
            
    def resume(self, *args):
        """
        command used when resume keyword is used 
        example1: Resume
        gives: # Resume
        example2: Resume Next
        gives: # Resume (Next)
        example3: Resume titi
        gives: # Resume titi
        """
        if args == ():
            self.opstack.push('Resume')
        else:
            if args[0] == '(Next)':
                self.opstack.push('Resume Next')
            else:
                self.opstack.push('Resume ' + args[0])
            
    def return_(self):
        #TODO: comment
        self.opstack.push('Return')
            
    def rset(self):
        """
        command for RSet keyword
        example: RSet MyString = "Right->"
        gives:
             # LitStr 0x0007 "Right->"
             # Ld MyString
             # RSet
        """
        var = self.opstack.pop()
        val = self.opstack.pop()
        self.opstack.push('RSet ' + var + ' = ' + val)
            
    def scale(self, *args):
        """
        command used when an object scale method is used
        example: Me.Scale 
        gives:
             # LitDI2 0x0000
             # LitDI2 0x0000
             # Ld sngNewH
             # Ld sngNewV
             # Ld id_FFFF
             # Scale 0x0000
        TODO: what to do with this command?
        """
        raise Pcode2codeException('not implemented scale')
            
    def seek(self):
        """
        opcode used when seek is used to search in a file
        example: Seek #1, 2
        gives:
             # LitDI2 0x0001
             # Sharp
             # LitDI2 0x0002
             # Seek
        """
        data = self.opstack.pop()
        self.opstack.push('Seek ' + self.opstack.pop() + ', ' + data)
            
    def selectcase(self):
        """
        command handling a "select case" definition against a variable
        example : Select Case x
        gives:
             # Ld x
             # SelectCase
        """
        self.opstack.push('Select Case ' + self.opstack.pop())
        self.indentincrease_future = True
    
    def selectis(self, *args):
        raise Pcode2codeException('not implemented selectis')
            
    def selecttype(self, *args):
        raise Pcode2codeException('not implemented selecttype')
            
    def setstmt(self):
        # TODO: comment
        #pass on purpose
        pass
            
    def stack(self, *args):
        raise Pcode2codeException('not implemented stack')
            
    def stop(self):
        #TODO: comment
        self.opstack.push('Stop')
            
    def type_(self, *args):
        """
        command for Type keyword, #TODO: beware because it's also used for enum keyword
        example: Type EmployeeRecord
        gives : 
           # Type EmployeeRecord
        """
        if args[0] == '(Private)':
            self.opstack.push('Private Type ' + args[1])
        elif args[0] == '(Public)':
            self.opstack.push('Public Type ' + args[1])
        else:
            self.opstack.push('Type ' + args[0])
        self.indentincrease_future = True
            
    def unlock(self):
        """
        command to unlock a record
        example: Unlock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Unlock
        """
        if self.opstack.size() == 3:
            last_record = self.opstack.pop()
            first_record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan + ', ' + first_record + ' To ' + last_record)
        elif self.opstack.size() == 2:
            record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan + ', ' + record)
        elif self.opstack.size() == 1:
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan)



    # Dim hiz7dgus As String
    # Private Const DefaultBufferSize& = 32768
    # Private CRC_32_Tab(0 To 255) As Long
    # ======================
    # Line #7:
    #   Dim 
    #   VarDefn hiz7dgus (As String)
    # Line #8:
    # Line #9:
    #   Dim (Private Const) 
    #   LitDI4 0x8000 0x0000 
    #   VarDefn DefaultBufferSize
    # Line #10:
    # Line #11:
    #   Dim (Private) 
    #   LitDI2 0x0000 
    #   LitDI2 0x00FF 
    #   VarDefn CRC_32_Tab (As Long)
    def vardefn(self, *args):      
        ending =''
        args = list(args) #quite ugly, but fu...
        if args[0] == '(WithEvents)':
            var = args.pop(0)[1:-1] + ' ' + args.pop(0)
        else:
            var = args.pop(0)

        spaces = 1
        if len(args) > 0:
            if args[-1].startswith('0x'):
                spaces = int(args.pop(-1),16) #TODO: treat spaces there
            ending = args[0]
            for arg in args[1:]:
                ending += ' ' + arg
            ending = ' ' + ending[1:-1]
            

        # first we check if this is only one literal definition
        # in this case, we get Dim definitions and we are all set up
        stacktop = self.opstack.pop()

        if stacktop == 'DimImplicit': #case where dim is implicit, 
            val = var + ending  # we have pushed in this case 'DimImplicit' on stack
            self.opstack.push(val)
            return

        # in this case we have a single variable declaration
        decls = ['Dim', 'Private', 'Public', 'Protected', 'Friend', 'Protected Friend', 'Shared', 'Shadows', 'Static', 'ReadOnly']
        if stacktop in decls:
            val = stacktop + ' ' + var + ending
            self.opstack.push(val)
            return

        else:
            # in this case, our variable is either a table, or there is also some const declarations
            # if so, walk the stack and check for declaration
            self.opstack.push(stacktop)
            values = []

            # gather all stack
            while self.opstack.size() > 0:
                values.append(self.opstack.pop())
            values = values[::-1]

            # if we have multiple vardefn with dim, then we are here
            # because all previous vardef should have been pushed correctly on stack
            if len(values) == 1 :
                for decl in decls:
                    if values[0].startswith(decl):
                        val = values[0] +', ' + var + ending
                        self.opstack.push(val)
                        return
                    
            # if const is used for declaration, then a value is attributed to variable
            # appears somehow not possible to declare a table as const, so far so good, no need to check this case
            if 'Const' in values[0]:
                val = values.pop(0)
                end_val = ' = ' + values.pop(0)
                if len(values) > 0:
                    # how to say what is dimensions to what is attribution
                    #val = 'Undefined variable declaration'
                    raise Pcode2codeException('undefined variable declaration')
                else:
                    val = val + ' ' + var + ending + end_val
                self.opstack.push(val)
                return
            
            #so here we have a table
            val = ''
            if values[0] in decls: #first we check if this is the first definition
                val += values.pop(0) + ' ' + var + '('
            elif values[0] == 'DimImplicit': #not sure about this one
                values.pop(0)
                val += var + '('
            else:
                #next we check for a previous declaration
                prev_decl = False
                for decl in decls:
                    if values[0].startswith(decl):
                        val += values.pop(0) +', ' + var + '('
                        prev_decl = True
                if prev_decl is False: #in this case, nothing before
                    val+= var + '('

            #first occurence
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

            #other occurences
            while len(values) > 0:
                val += ', '
                curr_val1 = values.pop(0)
                curr_val2 = values.pop(0)
                if curr_val1 == 'OptionBase':
                    val += curr_val2 
                else:
                    val += curr_val1 + ' To ' + curr_val2 

            #closing
            val += ')' + ending
            self.opstack.push(val)

    def wend(self):
        """
        command handling end of while loop "Wend"
        example: Wend
        gives : 
              # Wend
        """
        self.opstack.push('Wend')
        self.indentlevel = self.indentlevel - 1
            
    def while_(self):
        """
        command handling "while" loops definitions
        example: While numero <= 12
        gives:
             # Ld numero
             # LitDI2 0x000C
             # Le
             # While
        """
        self.opstack.push('While ' + self.opstack.pop())
        self.indentincrease_future = True
            
    def with_(self):
        """
        command handling "with" definitions
        example: with theWindow 
        gives:
             # StartWithExpr
             # Ld theWindow
             # With
        """
        self.opstack.push('With ' + self.opstack.pop())
        self.indentincrease_future = True
            
    def writechan(self):
        """
        command defining "write" to a channel
        example: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        self.opstack.push('Write ' +self.opstack.pop() + ',')
            
    def constfuncexpr(self, *args):
        raise Pcode2codeException('not implemented constfuncexpr')
            
    def lbconst(self, var):
        """
        opcode used when #Const is used
        example: #Const x = y
        gives:
             # LbMark
             # Ld B
             # LbConst a
        """
        self.opstack.push('#Const ' + var + ' = ' + self.opstack.pop())
    
    def lbif(self):
        """
        opcode used when #If is used
        example: #If a = b Then
        gives:
             # LbMark
             # Ld a
             # Ld B
             # Eq
             # LbIf
        """
        self.opstack.push('#If ' + self.opstack.pop() + ' Then')
        self.indentincrease_future = True
    
    def lbelse(self):
        """
        opcode used when #Else is used
        example: #Else 
        gives: lbElse
        """
        self.opstack.push('#Else')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True
            
    def lbelseif(self):
        """
        opcode used when #Elseif is used
        example: #ElseIf a = c Then
        gives:
             # LbMark
             # Ld a
             # Ld c
             # Eq
             # LbElseIf
        """
        self.opstack.push('#ElseIf ' + self.opstack.pop() + ' Then')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True
            
    def lbendif(self):
        """
        opcode used when "#End If" is used
        example: #End If
        gives: #LbEndIf
        """
        self.opstack.push('#End If')
        self.indentlevel = self.indentlevel - 1
            
    def lbmark(self):
        """
        appears to be used to indicate the start of a lb statement, appears quite useless
        """
        pass #pass on purposes

    def endforvariable(self):
        """
        This command ends out a for loop variable definition. Gives nothing interesting in fact
        example: TODO macaroni
        gives: TODO macaroni
        """
        #pass on purposes
        pass
            
    def startforvariable(self):
        """
        This command starts out a for loop variable definition. Gives nothing interesting in fact
        example: TODO macaroni
        gives: TODO macaroni
        """
        #pass on purposes
        pass
            
    def newredim(self, *args):
        raise Pcode2codeException('not implemented newredim')
            
    def startwithexpr(self):
        """
        used like startforvariable, eg, simply an indicator of when a with variable is declared.
        pretty useless for us.
        example: With theWindow
        gives:
             # StartWithExpr
             # Ld theWindow
             # With
        """
        #pass on purposes
        pass
            
    def setorst(self, *args):
        raise Pcode2codeException('not implemented setorst')
            
    def endenum(self):
        """
        command to end an enum
        example: End Enum
        gives:
             #EndEnum
        """
        self.opstack.push('End Enum')
        self.indentlevel = self.indentlevel - 1
            
    def illegal(self, *args):
        raise Pcode2codeException('not implemented illegal')

    def newline(self):
        """
        defines a blank line. Used for internal processing, for blank streams and lines
        """
        self.opstack.push('')
    
    def clearstack(self):
        self.opstack.clearstack()

    def getstacktop(self):
        return self.opstack.top()

    def getstackpop(self):
        return self.opstack.pop()

    def getstacksize(self):
        return self.opstack.size()

    def increaseindentlevel_future(self):
        """
        when we increase the indent level, we need to first print out the line, and then to increase the indent level. 
        to do so, when a line has been printed, this function checks if the indent level need to be increased and do so.
        """
        if self.unindented > 0:
            self.unindented -= 1
        elif self.indentincrease_future:
            self.indentlevel = self.indentlevel + 1
        self.indentincrease_future = False
    
    def getindentlevel(self):
        """
         function retrieving the class indentlevel parameter, used to print out code with correct indent
        """
        return self.indentlevel

    def hasbos(self):
        return self.has_bos

    def resethasbos(self):
        self.has_bos = False
    
class Parser:

    def __init__(self, myinput):
        self.myinput = myinput  # input to be processed, is always a dump of pcodedmp module there
        self.opstack = Stack()  # vba bytecode is somewhat stack based, so we declare a new one 
        self.operations = Operations(self.opstack) # all operations that can be found in vba bytecode
        self.output = ''        # the output of global processing
        self.output_queue = []
        self.unindented = 0

    def queueLineOutput(self, line, linenum, print_linenum=False, has_end=True):
        self.output_queue.append((line, linenum, print_linenum, has_end))

    def addlineOutput(self, line, linenum, print_linenum=False, has_end=True, _checking_queue=False):
        """
            Because we can choose what is the output for our module, this function somehow bufferize the
            output before it's printed in the latter.
        """
        if not line.strip():
            return
        while not _checking_queue and self.output_queue:
            self.addlineOutput(*self.output_queue.pop(), True)
        if print_linenum:
            self.output += str(linenum) + ': '           
        if not has_end:
            self.output += line
            return
        self.output += line + '\n' 

    def getOutput(self):
        """
        simply a getter to output, used in the end of global processing
        """
        return self.output

    def parseInput(self):
        """
            Function parsing pcodedmp dump to create a dictionary of all lines of the input with the operation lines associated.
            Basically, to explain, a pcodedmp dump would look like so:
               ' Line #7:
               '   Dim 
               '   VarDefn hiz7dgus (As String)
            Here the first line gives out the line number, and the rest are operation lines.
        """
        splittedInput = self.myinput.splitlines()
        lines = {}
        i = 0
        started = False
        streams = {}
        laststream = None
        opelinesblock = []
        # we parse each lines, and cut them by line blocks, to put them in "lines"
        #TODO: simplify
        for inputLine in splittedInput:
            inputLine = inputLine.strip()

            if 'VBA/' in inputLine and inputLine.endswith('bytes'): # here we have a new stream in the document
                if laststream is None: #eg first occurence
                    laststream = inputLine
                else:
                    if opelinesblock == []:
                        opelinesblock = ['NewLine']
                    lines[i] = opelinesblock
                    streams[laststream] = lines
                    opelinesblock = []
                    i = 0
                    lines = {}
                    started = False
                    laststream = inputLine
            if inputLine.startswith('Line #'): # here is our new line block
                started = True
                if not inputLine.startswith('Line #0'):
                    
                    if opelinesblock == []:             # when line is blank, it still appears in dump
                        opelinesblock = ['NewLine']     # so we treat it with a special new operation
                                                        # saying line is blank
                    lines[i] = opelinesblock
                    i+=1
                opelinesblock = []
            else:
                if started:
                    opelinesblock.append(inputLine)

        if opelinesblock == []:
            opelinesblock = ['NewLine']
            
        lines[i] = opelinesblock
        streams[laststream] = lines

        self.myinput = streams


    def parseOpLine(self, inputLine):
        """
            function to parse an operation line.
            to avoid using costly regexp, we split each operation line. The first element is always the operation
            to do, and the rest is potential args. In case there are args, they will be reconstructed by the underlying operation.
        """
        linelist = inputLine.split()
        ope = linelist[0]
        args = linelist[1:]
        func = self.operations.ops[ope]
        func(*args)

    def processInput(self, print_linenum):
        """
            When the input has been <<parsed>>, this function process it to disassemble the input, by calling parseOpLine for each line. 
            It is basically only a printing function.
            args: 
              - print_linenum: boolean indicating if line numbers should be printed in the output or not. Please refer to function named "process"
        """
        for stream in self.myinput.keys():
            if stream:
                self.queueLineOutput('# DECOMPILED STREAM : ' + stream, 0)
            unindented = 0
            for linenum, oplines in self.myinput[stream].items():
                for line in oplines:
                    if line.startswith('FuncDefn'):
                        unindented += 1
                    if line.startswith('EndFunc') or line.startswith('EndSub'):
                        unindented -= 1
            self.operations.unindented = unindented
            for linenum in self.myinput[stream]:
                try:
                    self.operations.clearstack()
                    for opline in self.myinput[stream][linenum]:
                        self.parseOpLine(opline)
                    if self.operations.hasbos():
                        output_parts = []
                        while self.operations.getstacksize() > 0:
                            output_parts.append(self.operations.getstackpop())
                        output_parts = output_parts[::-1]
                        self.addlineOutput(self.operations.getindentlevel() * '  ', linenum, print_linenum, False)
                        for part in output_parts[:-1]:
                            self.addlineOutput(part + ' ', linenum, has_end=False)
                        self.addlineOutput(output_parts[-1], linenum)
                        self.operations.resethasbos()
                    else:
                        self.addlineOutput(self.operations.getindentlevel() * '  ' + self.operations.getstacktop(), linenum, print_linenum)
                except Pcode2codeException as e:
                    self.addlineOutput("' pcode2code, cannot process line "+ str(linenum) + ' : ' + str(e), linenum, print_linenum)
                    for opline in self.myinput[stream][linenum]:
                        self.addlineOutput("'\t# " + opline, linenum)
                except Exception as e:
                    self.addlineOutput("' a generic exception occured at line " + str(linenum) + ": " + str(e), linenum, print_linenum)
                    for opline in self.myinput[stream][linenum]:
                        self.addlineOutput("'\t# " + opline, linenum)
                self.operations.increaseindentlevel_future()
            self.output_queue.clear()

Classes

class Pcode2codeException (*args, **kwargs)

Simply a custom exception class, permitting to make the difference between generic python exceptions and the one we are pushing

Expand source code Browse git
class Pcode2codeException(Exception):
    """
    Simply a custom exception class, permitting to make the difference between generic python exceptions and the one we are pushing
    """
    pass

Ancestors

  • builtins.Exception
  • builtins.BaseException
class Stack

Our stack class. Used to implement the operations made in the VBA bytecode, which is somehow stack based

Expand source code Browse git
class Stack:
    """
    Our stack class. Used to implement the operations made in the VBA bytecode, which is somehow stack based
    """

    def __init__(self):
        self.stack = []

    def pop(self):
        if len(self.stack) == 0:
            return None
        return self.stack.pop()

    def push(self, item):
        self.stack.append(item)

    def size(self):
        return len(self.stack)

    def top(self):
        return self.stack[-1]

    def bottom(self):
        return self.stack[0]

    def clearstack(self):
        self.stack = []

Methods

def pop(self)
Expand source code Browse git
def pop(self):
    if len(self.stack) == 0:
        return None
    return self.stack.pop()
def push(self, item)
Expand source code Browse git
def push(self, item):
    self.stack.append(item)
def size(self)
Expand source code Browse git
def size(self):
    return len(self.stack)
def top(self)
Expand source code Browse git
def top(self):
    return self.stack[-1]
def bottom(self)
Expand source code Browse git
def bottom(self):
    return self.stack[0]
def clearstack(self)
Expand source code Browse git
def clearstack(self):
    self.stack = []
class Operations (opstack)
Expand source code Browse git
class Operations:

    def __init__(self, opstack: Stack):
        self.opstack = opstack
        # number of blocks that will be ignored for indentation
        self.unindented = 0
        # current indentation level
        self.indentlevel = 0
        # boolean indicating if indentation level should be increased after the current command
        self.indentincrease_future = False
        # boolean indicating to print all stack, like in one liner cases
        self.has_bos = False
        # boolean indicating if we are on a onelineif. In this case, closing should not be treated the same as other if blocks
        self.onelineif = False
        self.ops = {
            'Imp'                   : self.imp,
            'Eqv'                   : self.eqv,
            'Xor'                   : self.xor,
            'Or'                    : self.or_,
            'And'                   : self.and_,
            'Eq'                    : self.eq,
            'Ne'                    : self.ne,
            'Le'                    : self.le,
            'Ge'                    : self.ge,
            'Lt'                    : self.lt,
            'Gt'                    : self.gt,
            'Add'                   : self.add,
            'Sub'                   : self.sub,
            'Mod'                   : self.mod,
            'IDiv'                  : self.idiv,
            'Mul'                   : self.mul,
            'Div'                   : self.div,
            'Concat'                : self.concat,
            'Like'                  : self.like,
            'Pwr'                   : self.pwr,
            'Is'                    : self.is_,
            'Not'                   : self.not_,
            'UMi'                   : self.umi,
            'FnAbs'                 : self.fnabs,
            'FnFix'                 : self.fnfix,
            'FnInt'                 : self.fnint,
            'FnSgn'                 : self.fnsgn,
            'FnLen'                 : self.fnlen,
            'FnLenB'                : self.fnlenb,
            'Paren'                 : self.paren,
            'Sharp'                 : self.sharp,
            'LdLHS'                 : self.ldlhs,
            'Ld'                    : self.ld,
            'MemLd'                 : self.memld,
            'DictLd'                : self.dictld,
            'IndexLd'               : self.indexld,
            'ArgsLd'                : self.argsld,
            'ArgsMemLd'             : self.argsmemld,
            'ArgsDictLd'            : self.argsdictld,
            'St'                    : self.st,
            'MemSt'                 : self.memst,
            'DictSt'                : self.dictst,
            'IndexSt'               : self.indexst,
            'ArgsSt'                : self.argsst,
            'ArgsMemSt'             : self.argsmemst,
            'ArgsDictSt'            : self.argsdictst,
            'Set'                   : self.set_,
            'Memset'                : self.memset,
            'Dictset'               : self.dictset,
            'Indexset'              : self.indexset,
            'ArgsSet'               : self.argsset,
            'ArgsMemSet'            : self.argsmemset,
            'ArgsDictSet'           : self.argsdictset,
            'MemLdWith'             : self.memldwith,
            'DictLdWith'            : self.dictldwith,
            'ArgsMemLdWith'         : self.argsmemldwith,
            'ArgsDictLdWith'        : self.argsdictldwith,
            'MemStWith'             : self.memstwith,
            'DictStWith'            : self.dictstwith,
            'ArgsMemStWith'         : self.argsmemstwith,
            'ArgsDictStWith'        : self.argsdictstwith,
            'MemSetWith'            : self.memsetwith,
            'DictSetWith'           : self.dictsetwith,
            'ArgsMemSetWith'        : self.argsmemsetwith,
            'ArgsDictSetWith'       : self.argsdictsetwith,
            'ArgsCall'              : self.argscall,
            'ArgsMemCall'           : self.argsmemcall,
            'ArgsMemCallWith'       : self.argsmemcallwith,
            'ArgsArray'             : self.argsarray,
            'Assert'                : self.assert_,
            'BoS'                   : self.bos,
            'BoSImplicit'           : self.bosimplicit,
            'BoL'                   : self.bol,
            'LdAddressOf'           : self.ldaddressof,
            'MemAddressOf'          : self.memaddressof,
            'Case'                  : self.case,
            'CaseTo'                : self.caseto,
            'CaseGt'                : self.casegt,
            'CaseLt'                : self.caselt,
            'CaseGe'                : self.casege,
            'CaseLe'                : self.casele,
            'CaseNe'                : self.casene,
            'CaseEq'                : self.caseeq,
            'CaseElse'              : self.caseelse,
            'CaseDone'              : self.casedone,
            'Circle'                : self.circle,
            'Close'                 : self.close,
            'CloseAll'              : self.closeall,
            'Coerce'                : self.coerce_,
            'CoerceVar'             : self.coercevar,
            'Context'               : self.context,
            'Debug'                 : self.debug,
            'DefType'               : self.deftype,
            'Dim'                   : self.dim,
            'DimImplicit'           : self.dimimplicit,
            'Do'                    : self.do,
            'DoEvents'              : self.doevents,
            'DoUnitil'              : self.dounitil,
            'DoWhile'               : self.dowhile,
            'Else'                  : self.else_,
            'ElseBlock'             : self.elseblock,
            'ElseIfBlock'           : self.elseifblock,
            'ElseIfTypeBlock'       : self.elseiftypeblock,
            'End'                   : self.end,
            'EndContext'            : self.endcontext,
            'EndFunc'               : self.endfunc,
            'EndIf'                 : self.endif,
            'EndIfBlock'            : self.endifblock,
            'EndImmediate'          : self.endimmediate,
            'EndProp'               : self.endprop,
            'EndSelect'             : self.endselect,
            'EndSub'                : self.endsub,
            'EndType'               : self.endtype,
            'EndWith'               : self.endwith,
            'Erase'                 : self.erase,
            'Error'                 : self.error,
            'EventDecl'             : self.eventdecl,
            'RaiseEvent'            : self.raiseevent,
            'ArgsMemRaiseEvent'     : self.argsmemraiseevent,
            'ArgsMemRaiseEventWith' : self.argsmemraiseeventwith,
            'ExitDo'                : self.exitdo,
            'ExitFor'               : self.exitfor,
            'ExitFunc'              : self.exitfunc,
            'ExitProp'              : self.exitprop,
            'ExitSub'               : self.exitsub,
            'FnCurDir'              : self.fncurdir,
            'FnDir'                 : self.fndir,
            'Empty0'                : self.empty0,
            'Empty1'                : self.empty1,
            'FnError'               : self.fnerror,
            'FnFormat'              : self.fnformat,
            'FnFreeFile'            : self.fnfreefile,
            'FnInStr'               : self.fninstr,
            'FnInStr3'              : self.fninstr3,
            'FnInStr4'              : self.fninstr4,
            'FnInStrB'              : self.fninstrb,
            'FnInStrB3'             : self.fninstrb3,
            'FnInStrB4'             : self.fninstrb4,
            'FnLBound'              : self.fnlbound,
            'FnMid'                 : self.fnmid,
            'FnMidB'                : self.fnmidb,
            'FnStrComp'             : self.fnstrcomp,
            'FnStrComp3'            : self.fnstrcomp3,
            'FnStringVar'           : self.fnstringvar,
            'FnStringStr'           : self.fnstringstr,
            'FnUBound'              : self.fnubound,
            'For'                   : self.for_,
            'ForEach'               : self.foreach,
            'ForEachAs'             : self.foreachas,
            'ForStep'               : self.forstep,
            'FuncDefn'              : self.funcdefn,
            'FuncDefnSave'          : self.funcdefnsave,
            'GetRec'                : self.getrec,
            'GoSub'                 : self.gosub,
            'GoTo'                  : self.goto,
            'If'                    : self.if_,
            'IfBlock'               : self.ifblock,
            'TypeOf'                : self.typeof,
            'IfTypeBlock'           : self.iftypeblock,
            'Implements'            : self.implements,
            'Input'                 : self.input_,
            'InputDone'             : self.inputdone,
            'InputItem'             : self.inputItem,
            'Label'                 : self.label,
            'Let'                   : self.let,
            'Line'                  : self.line,
            'LineCont'              : self.linecont,
            'LineInput'             : self.lineInput,
            'LineNum'               : self.linenum,
            'LitCy'                 : self.litcy,
            'LitDate'               : self.litdate,
            'LitDefault'            : self.litdefault,
            'LitDI2'                : self.litdi2,
            'LitDI4'                : self.litdi4,
            'LitDI8'                : self.litdi8,
            'LitHI2'                : self.lithi2,
            'LitHI4'                : self.lithi4,
            'LitHI8'                : self.lithi8,
            'LitNothing'            : self.litnothing,
            'LitOI2'                : self.litoi2,
            'LitOI4'                : self.litoi4,
            'LitOI8'                : self.litoi8,
            'LitR4'                 : self.litr4,
            'LitR8'                 : self.litr8,
            'LitSmallI2'            : self.litsmalli2,
            'LitStr'                : self.litstr,
            'LitVarSpecial'         : self.litvarspecial,
            'Lock'                  : self.lock,
            'Loop'                  : self.loop,
            'LoopUntil'             : self.loopuntil,
            'LoopWhile'             : self.loopwhile,
            'LSet'                  : self.lset,
            'Me'                    : self.me,
            'MeImplicit'            : self.meimplicit,
            'MemRedim'              : self.memredim,
            'MemRedimWith'          : self.memredimwith,
            'MemRedimAs'            : self.memredimas,
            'MemRedimAsWith'        : self.memredimaswith,
            'Mid'                   : self.mid,
            'MidB'                  : self.midb,
            'Name'                  : self.name,
            'New'                   : self.new,
            'Next'                  : self.next_,
            'NextVar'               : self.nextvar,
            'OnError'               : self.onerror,
            'OnGosub'               : self.ongosub,
            'OnGoto'                : self.ongoto,
            'Open'                  : self.open_,
            'Option'                : self.option,
            'OptionBase'            : self.optionbase,
            'ParamByVal'            : self.parambyval,
            'ParamOmitted'          : self.paramomitted,
            'ParamNamed'            : self.paramnamed,
            'PrintChan'             : self.printchan,
            'PrintComma'            : self.printcomma,
            'PrintEoS'              : self.printeos,
            'PrintItemComma'        : self.printitemcomma,
            'PrintItemNL'           : self.printitemnl,
            'PrintItemSemi'         : self.printitemsemi,
            'PrintNL'               : self.printnl,
            'PrintObj'              : self.printobj,
            'PrintSemi'             : self.printsemi,
            'PrintSpc'              : self.printspc,
            'PrintTab'              : self.printtab,
            'PrintTabComma'         : self.printtabcomma,
            'PSet'                  : self.pset,
            'PutRec'                : self.putrec,
            'QuoteRem'              : self.quoterem,
            'Redim'                 : self.redim,
            'RedimAs'               : self.redimas,
            'Reparse'               : self.reparse,
            'Rem'                   : self.rem,
            'Resume'                : self.resume,
            'Return'                : self.return_,
            'RSet'                  : self.rset,
            'Scale'                 : self.scale,
            'Seek'                  : self.seek,
            'SelectCase'            : self.selectcase,
            'SelectIs'              : self.selectis,
            'SelectType'            : self.selecttype,
            'SetStmt'               : self.setstmt,
            'Stack'                 : self.stack,
            'Stop'                  : self.stop,
            'Type'                  : self.type_,
            'Unlock'                : self.unlock,
            'VarDefn'               : self.vardefn,
            'Wend'                  : self.wend,
            'While'                 : self.while_,
            'With'                  : self.with_,
            'WriteChan'             : self.writechan,
            'ConstFuncExpr'         : self.constfuncexpr,
            'LbConst'               : self.lbconst,
            'LbIf'                  : self.lbif,
            'LbElse'                : self.lbelse,
            'LbElseIf'              : self.lbelseif,
            'LbEndIf'               : self.lbendif,
            'LbMark'                : self.lbmark,
            'EndForVariable'        : self.endforvariable,
            'StartForVariable'      : self.startforvariable,
            'NewRedim'              : self.newredim,
            'StartWithExpr'         : self.startwithexpr,
            'SetOrSt'               : self.setorst,
            'EndEnum'               : self.endenum,
            'Illegal'               : self.illegal,
            'NewLine'               : self.newline
        }

    def imp(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Imp ' + arg2
        self.opstack.push(val)

    def eqv(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Eqv ' + arg2
        self.opstack.push(val)

    def xor(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Xor ' + arg2
        self.opstack.push(val)

    def or_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Or ' + arg2
        self.opstack.push(val)

    def and_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' And ' + arg2
        self.opstack.push(val)

    def eq(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' = ' + arg2
        self.opstack.push(val)

    def ne(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' <> ' + arg2
        self.opstack.push(val)

    def le(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' <= ' + arg2
        self.opstack.push(val)

    def ge(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' >= ' + arg2
        self.opstack.push(val)

    def lt(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' < ' + arg2
        self.opstack.push(val)

    def gt(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' > ' + arg2
        self.opstack.push(val)

    # ex opeline: "Add"
    # gets the two values on stack, pop them, add them and push again
    def add(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' + ' + arg2
        self.opstack.push(val)

    def sub(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' - ' + arg2
        self.opstack.push(val)

    def mod(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Mod ' + arg2
        self.opstack.push(val)

    def idiv(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' \\ ' + arg2
        self.opstack.push(val)

    def mul(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' * ' + arg2
        self.opstack.push(val)

    def div(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' / ' + arg2
        self.opstack.push(val)

    def concat(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' & ' + arg2
        self.opstack.push(val)

    def like(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Like ' + arg2
        self.opstack.push(val)

    def pwr(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' ^ ' + arg2
        self.opstack.push(val)

    def is_(self):
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        val = arg1 + ' Is ' + arg2
        self.opstack.push(val)

    def not_(self):
        val = 'Not ' + self.opstack.pop()
        self.opstack.push(val)

    def umi(self):
        val = '-' + self.opstack.pop()
        self.opstack.push(val)

    def fnabs(self):
        arg = self.opstack.pop()
        val = 'Abs(' + arg + ')'
        self.opstack.push(val)

    def fnfix(self):
        arg = self.opstack.pop()
        val = 'Fix(' + arg + ')'
        self.opstack.push(val)

    def fnint(self):
        arg = self.opstack.pop()
        val = 'int(' + arg + ')'
        self.opstack.push(val)

    def fnsgn(self):
        arg = self.opstack.pop()
        val = 'Sgn(' + arg + ')'
        self.opstack.push(val)

    def fnlen(self):
        arg = self.opstack.pop()
        val = 'Len(' + arg + ')'
        self.opstack.push(val)

    def fnlenb(self):
        arg = self.opstack.pop()
        val = 'LenB(' + arg + ')'
        self.opstack.push(val)

    def paren(self):
        arg = self.opstack.pop()
        val = '(' + arg + ')'
        self.opstack.push(val)

    def sharp(self):
        arg = self.opstack.pop()
        val = '#' + arg
        self.opstack.push(val)

    def ldlhs(self):
        raise Pcode2codeException('not implemented ldlhs')

    def ld(self, var):
        """
        command defining a variable
        example: X = Y
        gives:
             # Ld Y
             # St X
        """
        if var == 'id_FFFF': #hacky way to do it because me does not seem to be fully
            var = 'Me'       #parsed by pcodedmp
        self.opstack.push(var)

    def memld(self, var):
        val = self.opstack.pop() + '.' + var
        self.opstack.push(val)

    def dictld(self, var):
        """
        cf fields and collections, also index???
        example: Debug.Print rsTable!Title
        gives:
             # Debug
             # PrintObj
             # Ld rsTable
             # DictLd Title
             # PrintItemNL
        """
        self.opstack.push(self.opstack.pop()+ '!' + var)

    def indexld(self, *args):
        raise Pcode2codeException('not implemented indexld')

    def argsld(self, varname, numparams):
        val = varname + '('
        nb_parameters = int(numparams, 16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def argsmemld(self, var, numparams):
        nb_parameters = int(numparams, 16)
        val = self.opstack.pop() + '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def argsdictld(self, var, numparams):
        """
        command used when an index of an object with an argument is accessed
        example: Debug.Print myobj!toto("titi") 
        gives:
             # Debug
             # PrintObj
             # LitStr 0x0004 "titi"
             # Ld myobj
             # ArgsDictLd toto 0x0001
             # PrintItemNL
        """
        nb_parameters = int(numparams, 16)
        val = self.opstack.pop() + '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    # example line : Function giqw(str As String) As Variant: Dim bytes() As Byte: bytes = str: giqw = bytes: End Function
    # op line:
    # Line #13:
    #     FuncDefn (Function giqw(str As String) As Variant)
    #     BoS 0x0000 
    #     Dim 
    #     VarDefn bytes (As Byte)
    #     BoS 0x0000 
    #     Ld str 
    #     St bytes 
    #     BoS 0x0000 
    #     Ld bytes 
    #     St giqw 
    #     BoS 0x0000 
    #     EndFunc 
    def st(self, arg):
        param = self.opstack.pop()
        val = arg + ' = ' + param
        self.opstack.push(val)

    def memst(self, var):
        val = self.opstack.pop() + '.' + var
        val = val + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def dictst(self, var):
        """
        command used when an index is defined directly
        example: myobj!titi = "toto"
        gives:
             # LitStr 0x0004 "toto"
             # Ld myobj
             # DictSt titi
        """
        val = self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def indexst(self, *args):
        raise Pcode2codeException('not implemented indexst')

    # TODO: to check
    def argsst(self, var, numparams):
        nb_parameters = int(numparams, 16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)

    def argsmemst(self, var, numparams):
        #TODO: to check
        val = self.opstack.pop() + '.'
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)

    def argsdictst(self, var, numparams):
        """
        used when an index of an obj with an argument is defined
        example: myobj!titi2("toto") = "toto"
        gives:
             # LitStr 0x0004 "toto"
             # LitStr 0x0004 "toto"
             # Ld myobj
             # ArgsDictSt titi2 0x0001
        """
        val = self.opstack.pop() + '!' 
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + var + '(' + params[0]
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'

        param2 = self.opstack.pop()
        val += ' = ' + param2
        self.opstack.push(val)
        
        
        
    def set_(self, var):
        val = 'Set ' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)

    def memset(self, var):
        """
        obtained when a property of an object is set
        example: Set YourObject.Text = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld YourObject
             # Memset Text
        """
        val = 'Set ' + self.opstack.pop() + '.' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)
        
    def dictset(self, var):
        """
        obtained when an index of an object is set
        example: Set YourObject!Text = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld YourObject
             # Dictset Text
        """
        val = 'Set ' + self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
        self.opstack.push(val)


    def indexset(self, *args):
        raise Pcode2codeException('not implemented indexset')

    def argsset(self, var, nb):
        """
        obtained when an argument of an object is set
        example: Set YourObject(ggg) = lobject
        gives:
             # SetStmt
             # Ld lobject
             # Ld ggg
             # ArgsSet YourObject 0x0001
        """
        val = 'Set ' + var + '(' + self.opstack.pop() + ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsmemset(self, var, numparams):
        """
        obtained when an argument of a property of an object is set
        example: Set YourObject.Text2("titi") = lobject
        gives:
             # SetStmt
             # Ld lobject
             # LitStr 0x0004 "titi"
             # Ld YourObject
             # ArgsMemSet Text2 0x0001
        """
        nb_parameters = int(numparams, 16)
        val = 'Set ' + self.opstack.pop() + '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

        
    def argsdictset(self, var, numparams):
        """
        obtained when an argument of a property of an object is set
        example: Set YourObject.Text2("titi") = lobject
        gives:
             # SetStmt
             # Ld lobject
             # LitStr 0x0004 "titi"
             # Ld YourObject
             # ArgsMemSet Text2 0x0001
        """
        nb_parameters = int(numparams, 16)
        val = 'Set ' + self.opstack.pop() + '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)


    def memldwith(self, var):
        """
        command defining a part of an object like .<prop>
        example: with blah <....> .Name 
        gives:  # MemLdWith Name
        """
        self.opstack.push('.' + var)

    def dictldwith(self, var):
        """
        accessing an index in a with block
        example: With <smth>.... Debug.Print !au_lname ... end with
        gives:
             # Debug
             # PrintObj
             # DictLdWith au_lname
             # PrintItemNL
        """
        self.opstack.push('!' + var)

    def argsmemldwith(self, var, numparams):
        """
        example: .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1
        gives:
             # Ld sProc
             # Ld ProcType
             # ArgsMemLdWith ProcStartLine 0x0002
             # Ld lLine
             # Add
             # LitDI2 0x0001
             # Ld sProc
             # Ld ProcType
             # ArgsMemLdWith ProcStartLine 0x0002
             # Ld lLine
             # Add
             # LitDI2 0x0001
             # Add
             # LitDI2 0x0001
             # MemLdWith CodePane
             # ArgsMemCall SetSelection 0x0004
        """
        nb_parameters = int(numparams, 16)
        val = '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

        
    def argsdictldwith(self, var, numparams):
        """
        command used when an index of an object with an argument is accessed with a with block
        example: With myobj ... Debug.Print !toto("titi") ... end with
        gives:
             # Debug
             # PrintObj
             # LitStr 0x0004 "titi"
             # ArgsDictLdWith toto 0x0001
             # PrintItemNL
        """
        nb_parameters = int(numparams, 16)
        val = '!' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)


    def memstwith(self, var):
        """
        command defining a part of an object like .<prop> = <smthg>
        example: .Name = "Coho Vineyard"
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # MemStWith Name
        """
        self.opstack.push('.' + var + ' = ' + self.opstack.pop())

        
    def dictstwith(self, var):
        """
        command defining a part of an object like !<index> = <smthg>
        example: With ... !Name = "Coho Vineyard" ... end with
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # DictStWith Name
        """
        self.opstack.push('!' + var + ' = ' + self.opstack.pop())

        
    def argsmemstwith(self, var, numparams):
        """
        command defining a property of an object with arguments in a with statement
        example: With ... .Name(1,2) = b ... end with
        gives:
             # Ld B
             # LitDI2 0x0001
             # LitDI2 0x0002
             # ArgsMemStWith Name 0x0002
        """
        nb_parameters = int(numparams, 16)
        val = '.' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsdictstwith(self, var, *args):
        """
        command defining a part of an object like !<index> = <smthg> in a with block
        example: !Name = "Coho Vineyard"
        gives:
             # LitStr 0x000D "Coho Vineyard"
             # DictStWith Name
        """
        self.opstack.push('!' + var + ' = ' + self.opstack.pop())


    def memsetwith(self, var):
        """
        command defining a set on an index of an object in a with block
        example: with <smth> ... Set .Name = "Coho Vineyard"
        gives:
             # SetStmt
             # LitStr 0x000D "Coho Vineyard"
             # memSetWith Name
        """
        self.opstack.push('Set .' + var + ' = ' + self.opstack.pop())

        
    def dictsetwith(self, var):
        """
        command defining a set on an index of an object in a with block
        example: with <smth> ... Set !Name = "Coho Vineyard"
        gives:
             # SetStmt
             # LitStr 0x000D "Coho Vineyard"
             # DictSetWith Name
        """
        self.opstack.push('Set !' + var + ' = ' + self.opstack.pop())

    def argsmemsetwith(self, var, numparams):
        """
        command defining a set on an index with an argument of an object in a with block
        example: with <smth> ... Set .nini("gg", "ff", "uu") = "toto"
        gives:
             # SetStmt
             # LitStr 0x0004 "toto"
             # LitStr 0x0002 "gg"
             # LitStr 0x0002 "ff"
             # LitStr 0x0002 "uu"
             # ArgsMemSetWith nini 0x0003
        """
        nb_parameters = int(numparams, 16)
        val = 'Set !' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    def argsdictsetwith(self, var, numparams):
        """
        command defining a set on an index with an argument of an object in a with block
        example: with <smth> ... Set !nini("gg", "ff", "uu") = "toto"
        gives:
             # SetStmt
             # LitStr 0x0004 "toto"
             # LitStr 0x0002 "gg"
             # LitStr 0x0002 "ff"
             # LitStr 0x0002 "uu"
             # ArgsDictSetWith nini 0x0003
        """
        nb_parameters = int(numparams, 16)
        val = 'Set !' + var + '('
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ') = ' + self.opstack.pop()
        self.opstack.push(val)

    
    def argscall(self, *args):

        if args[0] == '(Call)':
            nb_parameters = int(args[2],16)
            val = 'Call ' + args[1] + '('
            end_val = ')'
        else:
            val = args[0]
            nb_parameters = int(args[1],16)           
            end_val = ''
            
        params = []
        #print 'func:' + funcname
        #print 'nbparameters : ' + str(nb_parameters)
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if ((params[0].startswith('(')) or (args[0] == '(Call)')):               
                val = val + params[0]
            else:
                val = val + ' ' + params[0]

            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += end_val
        self.opstack.push(val)

    def argsmemcall(self, *args):
        """
        command to call a function of an object
        example: a43g0xT.run ayUBnLK01, 0
        gives : 
           # Ld ayUBnLK01
           # LitDI2 0x0000
           # Ld a43g0xT
           # ArgsMemCall run 0x0002
        """
        args = list(args)
        parenthesis = False
        if args[0] == '(Call)':
            args.pop(0)
            val = 'Call ' + self.opstack.pop() + '.' + args[0] + '('
            parenthesis = True
        else:
            val = self.opstack.pop() + '.' + args[0]

        nb_parameters = int(args[1],16)           
        end_val = ''
            
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if params[0].startswith('('):               
                val = val + params[0]
                end_val = ')'
            else:
                if not parenthesis:
                    val = val + ' ' +params[0]
                else:
                    val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        if parenthesis == True:
            end_val = ')'
        self.opstack.push(val + end_val)

    def argsmemcallwith(self, *args):
        """
        command when a function of an object is called in a with definition
        example: With a ... call .a(1,2) ... end with
        gives: 
             # LitDI2 0x0001
             # LitDI2 0x0002
             # ArgsMemCallWith (Call) a 0x0002
        """
        parenthesis = False
        args = list(args)
        if args[0] == '(Call)':
            args.pop(0)
            parenthesis = True
            val = 'Call .' + args[0] + '('
        else:
            val = '.' + args[0]
            
        nb_parameters = int(args[1],16)           
        end_val = ''
            
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            if params[0].startswith('('):               
                val = val + params[0]
                end_val = ')'
            else:
                if not parenthesis:
                    val = val + ' ' + params[0]
                else:
                    val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param

        if parenthesis:
            end_val = ')'
        self.opstack.push(val + end_val)
        

    def argsarray(self, var, numparams):
        val = var + '('
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        self.opstack.push(val)

    def assert_(self):
        """
        command for debug.asser
        example: Debug.Assert blnAssert
        gives : 
              # Ld blnAssert
              # Assert
        """
        self.opstack.push('Debug.Assert ' + self.opstack.pop())

    def bos(self, valarg):
        arg = int(valarg,16)
        if arg == 0:
            val = self.opstack.pop() + ':'
        self.opstack.push(val)
        self.has_bos = True

    def bosimplicit(self, *args):
        """
        appears useless, but in this case we still need to print whole stack
        example: If Mid$(theString, i, 1) <> Chr$(0) Then Exit For
        gives:
             # Ld theString
             # Ld i
             # LitDI2 0x0001
             # ArgsLd Mid$ 0x0003
             # LitDI2 0x0000
             # ArgsLd Chr$ 0x0001
             # Ne
             # If
             # BoSImplicit
             # ExitFor
             # EndIf
        """
        self.has_bos = True
        
    def bol(self, *args):
        raise Pcode2codeException('not implemented bol')

    def ldaddressof(self, var):
        """
        command for AddressOf keyword
        example: EnumFontFamilies hDC, vbNullString, AddressOf EnumFontFamProc, LB
        gives:
             # Ld hDC
             # Ld vbNullString
             # LdAddressOf EnumFontFamProc
             # Ld LB
             # ArgsCall EnumFontFamilies 0x0004
        """
        self.opstack.push('AddressOf ' + var)

    def memaddressof(self, var):
        """
        command for AddressOf keyword on a property of an object
        example: MsgBox AddressOf myobj.toto
        gives:
             # Ld myobj
             # MemAddressOf toto
             # ArgsCall MsgBox 0x0001
        """
        self.opstack.push('AddressOf ' + self.opstack.pop() + '.' + var)

    def case(self):
        """
        command handling choice in select case where choice is one value 
        example: Case 0
        gives:
             # LitDI2 0x0000
             # Case
             # CaseDone

        """
        self.opstack.push('Case ' + self.opstack.pop())

    def caseto(self):
        """
        command handling choice in select case where choice is from one value to one other value
        example: Case 0 To 30
        gives:
             # LitDI2 0x0000
             # LitDI2 0x001E
             # CaseTo
             # CaseDone
        """
        val = self.opstack.pop()
        self.opstack.push('Case ' + self.opstack.pop() + ' To ' + val)


    def casegt(self):
        """
        command handling choice in select case where choice is lower than a value
        example: Case Is > 100
        gives:
             # LitDI2 0x0064
             # CaseGt
             # CaseDone
        """
        self.opstack.push('Case Is > ' + self.opstack.pop())

    def caselt(self):
        """
        command handling choice in select case where choice is lower than a value
        example: Case Is < 0
        gives:
             # LitDI2 0x0002
             # CaseLt
             # CaseDone
        """
        self.opstack.push('Case Is < ' + self.opstack.pop())

    def casege(self):
        """
        command handling choice in select case where choice is greater or equal than a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is >= ' + self.opstack.pop())

    def casele(self):
        """
        command handling choice in select case where choice is lower or equal than a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is <= ' + self.opstack.pop())

    def casene(self):
        """
        command handling choice in select case where choice is different to a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is <> ' + self.opstack.pop())

    def caseeq(self):
        """
        command handling choice in select case where choice is equal to a value
        example: TODO: to check
        gives:
        """
        self.opstack.push('Case Is = ' + self.opstack.pop())

    def caseelse(self):
        """
        command defining a "Case Else" stmt
        example: Case Else
        gives: 
             # CaseElse
        """
        self.opstack.push('Case Else')

    def casedone(self):
        #pass on purpose, please see previous examples
        pass

    def circle(self, useless):
        """
        command used when the circle method of an object is called
        example: Me.Circle (sngHCtr, sngVCtr), sngRadius
        gives:
             # Ld sngHCtr
             # Ld sngVCtr
             # Ld sngRadius
             # LitDI2 0x0000
             # LitDI2 0x0000
             # LitDI2 0x0000
             # LitDI2 0x0000
             # Ld id_FFFF
             # Circle 0x001E
        """
        val = self.opstack.pop() + '.Circle ('
        params = []
        for i in range(7):
            params.append(self.opstack.pop())
        params = params[::-1]

        val += params[0] + ', ' + params[1] + '), ' + params[2]
        all_empty = True
        for param in params[3:]:
            if param != '0':
                all_empty = False

        if all_empty:
            self.opstack.push(val)
        else:
            for param in params[3:]:
                if param == '0':
                    val = val + ', <tbr>'
                else:
                    val = val + ', ' + param
            val = val.replace(', <tbr>' , '')
            self.opstack.push(val)


    def close(self, numparams):
        val = 'Close '
        nb_parameters = int(numparams,16)
        params = []
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        self.opstack.push(val)

    def closeall(self):
        """
        command used when close is called with no arguments, effectively closing all files
        example: Close
        gives: # CloseAll
        """
        self.opstack.push('Close')

    def coerce_(self, arg):
        """
        command used for variable conversion
        example1: MyLong2 = CLng(MyVal2)
        gives:
             # Ld MyVal2
             # Coerce (Lng)
             # St MyLong2
        example2: MyInt = CInt(MyDouble)
        gives:
             # Ld MyDouble
             # Coerce (Int)
             # St MyInt
        """
        if arg == '(Str)':
            self.opstack.push('CStr(' + self.opstack.pop() + ')')
        elif arg == '(Var)':
            self.opstack.push('CVar(' + self.opstack.pop() + ')')
        elif arg == '(Sng)':
            self.opstack.push('CSng(' + self.opstack.pop() + ')')
        elif arg == '(Lng)':
            self.opstack.push('CLng(' + self.opstack.pop() + ')')
        elif arg == '(Int)':
            self.opstack.push('CInt(' + self.opstack.pop() + ')')
        elif arg == '(Dbl)':
            self.opstack.push('CDbl(' + self.opstack.pop() + ')')
        elif arg == '(Date)':
            self.opstack.push('CDate(' + self.opstack.pop() + ')')
        elif arg == '(Cur)':
            self.opstack.push('CCur(' + self.opstack.pop() + ')')
        elif arg == '(Byte)':
            self.opstack.push('CByte(' + self.opstack.pop() + ')')
        elif arg == '(Bool)':
            self.opstack.push('CBool(' + self.opstack.pop() + ')')
        else:
            raise Pcode2codeException('not implemented coerce')
        
    def coercevar(self, arg):
        """
        example1: MyError = CVErr(32767)
        gives: # CoerceVar (Err)
        """
        if arg == '(Err)':
            self.opstack.push('CVErr(' + self.opstack.pop() + ')')
        else:
            raise Pcode2codeException('not implemented coercevar')

    def context(self, *args):
        raise Pcode2codeException('not implemented context')

    def debug(self):
        """
        seems used to invoke debug object
        example: Debug.Print MyVar
        gives:
             # Debug
             # PrintObj
             # Ld MyVar
             # PrintItemNL
        """
        self.opstack.push('Debug')

    def deftype(self, *args):
        """
        command used when def<type> is used.
        TODO: bytes to know ranges appear random. How to do it?
        """
        raise Pcode2codeException('not implemented deftype')

    # Dim hiz7dgus As String
    # Private Const DefaultBufferSize& = 32768
    # Private CRC_32_Tab(0 To 255) As Long
    # ======================
    # Line #7:
    #   Dim 
    #   VarDefn hiz7dgus (As String)
    # Line #8:
    # Line #9:
    #   Dim (Private Const) 
    #   LitDI4 0x8000 0x0000 
    #   VarDefn DefaultBufferSize
    # Line #10:
    # Line #11:
    #   Dim (Private) 
    #   LitDI2 0x0000 
    #   LitDI2 0x00FF 
    #   VarDefn CRC_32_Tab (As Long)
    def dim(self, *args):
        # args is a tuple, we treat it only when its not empty
        # example of args : (As String), (As Long)...
        if args != ():
            val = args[0]
            for arg in args[1:]:
                val += ' ' + arg
            val = val[1:-1]
        else:
            val = 'Dim'
        self.opstack.push(val)

    def dimimplicit(self):
        self.opstack.push('DimImplicit')

    def do(self):
        """
        command handling "Do" keyword
        example: Do (we have then the loop and so on)
        gives:
             # Do
        """
        self.opstack.push('Do')
        self.indentincrease_future = True

    def doevents(self, *args):
        raise Pcode2codeException('not implemented doevents')

    def dounitil(self):
        """
        command handling "do until" definitions
        example: Do Until Response = "youpi"
        gives:
             # Ld Response
             # ListStr 0x0005 "youpi"
             # Eq
             # DoUnitil
        """
        self.opstack.push('Do Until ' + self.opstack.pop())
        self.indentincrease_future = True

    def dowhile(self):
        """
        command handling "do while" definitions
        example: Do While Reponse <> "youpi"
        gives:
             # Ld Response
             # LitStr 0x0005 "youpi"
             # Ne
             # DoWhile
        """
        self.opstack.push('Do While ' + self.opstack.pop())
        self.indentincrease_future = True

    def else_(self):
        """
        command used for a "else" in a if oneliner
        example: If X < 4 Then MsgBox "hi" Else MsgBox "ho"
        gives:
             # Ld X
             # LitDI2 0x0004
             # Lt
             # If
             # BoSImplicit
             # LitStr 0x0002 "hi"
             # ArgsCall MsgBox 0x0001
             # Else
             # BoSImplicit
             # LitStr 0x0002 "Ho"
             # ArgsCall MsgBox 0x0001
             # EndIf
        """
        self.opstack.push('Else')

    def elseblock(self):
        """
        command defining a new "else" for a block
        example: Else
        gives: #Else
        """
        self.opstack.push('Else')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True

    def elseifblock(self):
        """
        command defining a new "else if" block
        example: ElseIf dayW = DayOfWeek.Thursday Then
        gives:
             # Ld dayW
             # Ld DayOfWeek
             # MemLd Thursday
             # Eq
             # ElseIfBlock
        """
        self.opstack.push('ElseIf ' + self.opstack.pop() + ' Then')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True

    def elseiftypeblock(self, *args):
        raise Pcode2codeException('not implemented elseiftypeblock')

    def end(self):
        self.opstack.push('End')

    def endcontext(self, *args):
        raise Pcode2codeException('not implemented endcontext')

    def endfunc(self):
        self.opstack.push('End Function')
        self.indentlevel = self.indentlevel - 1

    def endif(self):
        if self.onelineif == True:
            self.onelineif = False
        else:
            self.opstack.push('End If')
            self.indentlevel = self.indentlevel - 1

    def endifblock(self):
        self.opstack.push('End If')
        self.indentlevel = self.indentlevel - 1

    def endimmediate(self, *args):
        raise Pcode2codeException('not implemented endimmediate')

    def endprop(self):
        """
        command handling the end of a property
        example: End Property
        gives: 
             #EndProp
        """
        self.opstack.push('End Property')
        self.indentlevel = self.indentlevel -1

    def endselect(self):
        """
        command defining a stmt of "End Select", closing a select case.
        example: End Select
        gives: 
             # EndSelect
        """
        self.opstack.push('End Select')
        self.indentlevel = self.indentlevel - 1

    def endsub(self):
        self.opstack.push('End Sub')
        self.indentlevel = self.indentlevel - 1

    def endtype(self):
        """
        command to end a new type definition
        example: End Type
        gives:
             #EndType
        """
        self.opstack.push('End Type')
        self.indentlevel = self.indentlevel - 1

    def endwith(self):
        """
        command to end a new with definition
        example: End With
        gives: #EndWith
        """
        self.opstack.push('End With')
        self.indentlevel = self.indentlevel - 1
        

    def erase(self, nb_params):
        """
        command for Erase function keyword
        example: Erase threeDimArray, twoDimArray
        gives:
             # Ld threeDimArray
             # Ld twoDimArray
             # Erase 0x0002
        """
        nb_args = int(nb_params, 16)
        val = ''
        params = []
        for i in range(nb_args):
            params.append(self.opstack.pop())
            params = params[::-1]
        val = params[0]
            
        if nb_args > 1:
            for param in params[1:]:
                val = val + ', ' + param

        self.opstack.push('Erase ' + val)


    def error(self):
        """
        command used for Error keyword
        example: Error 11
        gives:
             # LitDI2 0x000B
             # Error
        """
        self.opstack.push('Error ' + self.opstack.pop())

    def eventdecl(self, *args):
        """
        command for declaring a new event in VBA
        example: Event LogonCompleted(UserName As String)
        gives : 
           # EventDecl (Sub LogonCompleted(UserName As String))
        """
        val = args[1]
        for arg in args[2:-1]: #strip parenthesis
            val += ' ' + arg
        self.opstack.push('Event ' + val + ' ' + args[-1][:-1])

    def raiseevent(self, evt_name, nb_params):
        """
        command when RaiseEvent is used
        example: RaiseEvent LogonCompleted("AntoineJean")
        gives:
             # LitStr 0x000A "AntoineJan"
             # RaiseEvent LogonCompleted 0x0001
        """
        nb_args = int(nb_params, 16)
        val = ''
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = '('+ params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
                    
        self.opstack.push('RaiseEvent ' + evt_name + val)
            

    def argsmemraiseevent(self, var, numparams):
        """
        command used when a raiseevent is called on a property of an object
        example: RaiseEvent myobj.LogonCompleted("AntoineJan")
        gives:
             # LitStr 0x000A "AntoineJan"
             # Ld myobj
             # ArgsMemRaiseEvent LogonCompleted 0x0001
        """
        nb_args = int(numparams, 16)
        val = 'RaiseEvent ' + self.opstack.pop() + '.' + var + '('
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val += params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
        self.opstack.push(val)

    def argsmemraiseeventwith(self, var, numparams):
        """
        command used when a raiseevent is called on a property of an object within a with block
        example: with myobj ... RaiseEvent .LogonCompleted("AntoineJan") ... end with
        gives:
             # LitStr 0x000A "AntoineJan"
             # ArgsMemRaiseEventWith LogonCompleted 0x0001
        """
        nb_args = int(numparams, 16)
        val = 'RaiseEvent .' + var + '('
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]
            val += params[0]
            
            if nb_args > 1:
                for param in params[1:]:
                    val = val + ', ' + param
            val += ')'
        self.opstack.push(val)
    
    def exitdo(self):
        #TODO: comment
        self.opstack.push('Exit Do')

    def exitfor(self):
        #TODO: comment
        self.opstack.push('Exit For')

    def exitfunc(self):
        #TODO: comment
        self.opstack.push('Exit Function')
    
    def exitprop(self):
        #TODO: comment
        self.opstack.push('Exit Property')
    
    def exitsub(self):
        #TODO: comment
        self.opstack.push('Exit Sub')
    
    def fncurdir(self, *args):
        #val = 'CurDir(' + self.opstack.pop() + ')'
        #self.opstack.push(val)
        raise Pcode2codeException('not implemented fncurdir')
    
    def fndir(self, *args):
        raise Pcode2codeException('not implemented fndir')
    
    def empty0(self, *args):
        raise Pcode2codeException('not implemented empty0')
    
    def empty1(self, *args):
        raise Pcode2codeException('not implemented empty1')
    
    def fnerror(self, *args):
        raise Pcode2codeException('not implemented fnerror')
    
    def fnformat(self, *args):
        raise Pcode2codeException('not implemented format')
    
    def fnfreefile(self, *args):
        raise Pcode2codeException('not implemented fnfreefile')
    
    def fninstr(self):
        """
        command used when calling Instr function with 2 arguments
        example: MyPos = InStr(SearchString, SearchChar)
        gives:
             # Ld SearchString
             # Ld SearchChar
             # FnInStr
             # St MyPos
        """
        arg2 = self.opstack.pop()
        self.opstack.push('Instr(' + self.opstack.pop() + ', ' + arg2 + ')')
    
    def fninstr3(self):
        """
        command used when calling Instr function with 3 arguments
        example: MyPos = InStr(1, SearchString, "W")
        gives:
             # LitDI2 0x0001
             # Ld SearchString
             # LitStr 0x0001 "W"
             # FnInStr3
             # St MyPos
        """
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')
    
    def fninstr4(self):
        """
        command used when calling Instr function with 4 arguments
        example: MyPos = InStr(4, SearchString, SearchChar, 1)
        gives:
             # LitDI2 0x0004
             # Ld SearchString
             # Ld SearchChar
             # LitDI2 0x0001
             # FnInStr4
             # St MyPos
        """
        arg4 = self.opstack.pop()
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
    
    def fninstrb(self):
        """
        command used when calling InstrB function with 2 arguments
        example: TODO: make sure here
        gives:
        """
        arg2 = self.opstack.pop()
        self.opstack.push('InstrB(' + self.opstack.pop() + ', ' + arg2 + ')')

        
    def fninstrb3(self):
        """
        command used when calling InstrB function with 3 arguments
        example: TODO: make sure here
        gives:

        """
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('InstrB(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')

        
    def fninstrb4(self):
        """
        command used when calling InstrB function with 4 arguments
        example: TODO: make sure here
        gives:

        """
        arg4 = self.opstack.pop()
        arg3 = self.opstack.pop()
        arg2 = self.opstack.pop()
        arg1 = self.opstack.pop()
        self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
    
    def fnlbound(self, arg):
        """
        command indicating the use of the LBound function
        strangely enough, there is an indication of the number of arguments to be popped out of the stack
        but this number is not good.
        example: Lower = LBound(TwoDArray, 2)
        gives: 
             # Ld TwoDArray
             # LitDI2 0x0002
             # FnLBound 0x0001
             # St Lower
        """
        nb_parameters = int(arg,16) + 1
        params = []
        val = '('
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        val = 'LBound' + val
        self.opstack.push(val)
    
    def fnmid(self):
        val = 'Mid(' + self.opstack.pop() + ')'
        self.opstack.push(val)
    
    def fnmidb(self):
        val = 'MidB(' + self.opstack.pop() + ')'
        self.opstack.push(val)
    
    def fnstrcomp(self):
        """
        command used when strcomp function with 2 arguments is called
        example: MyComp = StrComp(MyStr2, MyStr1)
        gives:
             # Ld MyStr2
             # Ld MyStr1
             # FnStrComp
             # St MyComp
        """
        str2 = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('StrComp(' + str1 + ', ' + str2 + ')')
            
    def fnstrcomp3(self):
        """
        command used when strcomp function with 3 arguments is called
        example: MyComp = StrComp(MyStr1, MyStr2, 0)
        gives:
             # Ld MyStr1
             # Ld MyStr2
             # LitDI2 0x0000
             # FnStrComp3
             # St MyComp
        """
        third_arg = self.opstack.pop()
        str2 = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('StrComp(' + str1 + ', ' + str2 + ', ' + third_arg + ')')
    
    def fnstringvar(self, *args):
        raise Pcode2codeException('not implemented fnstringvar')
    
    def fnstringstr(self, *args):
        raise Pcode2codeException('not implemented fnstringstr')
   
    def fnubound(self, arg):
        """
        command used when calling Ubound function
        example: uL = UBound(sb_)
        gives:     
             # Ld sb_ 
             # FnUBound 0x0000 
             # St uL
        """
        nb_parameters = int(arg,16) + 1
        params = []
        val = '('
        if nb_parameters > 0:
            for i in range(nb_parameters):
                params.append(self.opstack.pop())
            params = params[::-1]
            val = val + params[0]
            
            if nb_parameters > 1:
                for param in params[1:]:
                    val = val + ', ' + param
        val += ')'
        val = 'UBound' + val
        self.opstack.push(val)
            
    def for_(self):
        maxvar = self.opstack.pop()
        minvar = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar
        self.opstack.push(val)
        self.indentincrease_future = True
            
    def foreach(self):
        """
        command defining a new for each loop definition
        example: For Each MyObject In MyClasses
        gives:
             # StartForVariable
             # Ld MyObject
             # EndForVariable
             # Ld MyClasses
             # ForEach
        """
        collect = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For Each ' + loopvar + ' In ' + collect
        self.opstack.push(val)
        self.indentincrease_future = True
    
    def foreachas(self, *args):
        raise Pcode2codeException('not implemented foreachas')
            
    def forstep(self):
        step = self.opstack.pop()
        maxvar = self.opstack.pop()
        minvar = self.opstack.pop()
        loopvar = self.opstack.pop()
        val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar + ' Step ' + step
        self.opstack.push(val)
        self.indentincrease_future = True
            
    def funcdefn(self, *args: str):
        val = args[0]
        for arg in args[1:]:
            val += ' ' + arg
        val = val[1:-1]
        self.opstack.push(val)
        if not val.startswith('Declare'):
            self.indentincrease_future = True
            
    def funcdefnsave(self, *args):
        raise Pcode2codeException('not implemented funcdefnsave')
            
    def getrec(self):
        """
        command to Get from a channel with a record: get channel, record, var
        example: Get #1, RecordNumber, MyRecord
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # Ld MyRecord
             # GetRec
        """
        record = self.opstack.pop()
        record_num = self.opstack.pop()
        chan = self.opstack.pop()
        if chan is not None:
            self.opstack.push('Get ' + chan + ', ' + record_num + ', ' + record)
        else:
            self.opstack.push('Get ' + record_num + ', , ' + record) # kindly ugly
            
    def gosub(self, var):
        """
        command used when gosub is used
        example: If Num > 0 Then GoSub MyRoutine 
        gives:
             # Ld Num
             # LitDI2 0x0000
             # Gt
             # If
             # BoSImplicit
             # GoSub MyRoutine
             # EndIf
        """
        self.opstack.push('GoSub ' + var)
            
    def goto(self, var):
        """
        command used when a goto <label> is defined
        example: GoTo label1
        gives: # GoTo label1
        """
        self.opstack.push('GoTo ' + var)

            
    def if_(self, *args):
        val = 'If ' + self.opstack.pop() + ' Then'
        self.onelineif = True
        self.opstack.push(val)
    
    def ifblock(self):
        val = 'If ' + self.opstack.pop() + ' Then'
        self.opstack.push(val)
        self.indentincrease_future = True
    
    def typeof(self, *args):
        """
        command used when TypeOf function is used
        TODO: associated type is obscure for now
        """
        raise Pcode2codeException('not implemented typeof')
            
    def iftypeblock(self, *args):
        raise Pcode2codeException('not implemented iftypeblock')
            
    def implements(self, *args):
        """
        command used when Implements instruction is used
        TODO: associated type is obscure for now        
        """
        raise Pcode2codeException('not implemented implements')
            
    def input_(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        self.opstack.push('Input ' + self.opstack.pop())
        
    def inputdone(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += elmt
        self.opstack.push(val)

            
    def inputItem(self):
        """
        command used when Input function is called
        example : Input #1, MyString, MyNumber
        gives: 
             # LitDI2 0x0001
             # Sharp
             # Input
             # Ld MyString
             # InputItem
             # Ld MyNumber
             # InputItem
             # InputDone        
        """
        self.opstack.push(', ' + self.opstack.pop())
            
    def label(self, arg):
        """
        command defining a new label
        example: MyString:
        gives:
             # Label MyString
        """
        self.opstack.push(arg+':')
            
    def let(self, *args):
        """
        command used when let keywork is used
        example: Let MyStr  = "Hello World"
        gives:
             # Let
             # LitStr 0x000B "Hello World"
             # St MyStr
        """
        self.opstack.push('Let')
        self.has_bos = True #we use this hackish way to print it even if not in stack top

            
    def line(self, *args):
        raise Pcode2codeException('not implemented line')
            
    def linecont(self, *args):
        #pass on purpose
        pass
            
    def lineInput(self):
        """
        command used when Line Input instruction is used (to read one line at a time a file)
        example: Line Input #1, TextLine
        gives:
             # LitDI2 0x0001
             # Ld TextLine
             # LineInput
        """
        var = self.opstack.pop()
        num_file = self.opstack.pop()
        self.opstack.push('Line Input #' + num_file + ', ' + var)
            
    def linenum(self, *args):
        # ignoring this seems to work fine.
        return
            
    def litcy(self, *args):
        raise Pcode2codeException('not implemented litcy')
            
    def litdate(self, *args):
        """
        command to define a date literal
        TODO: but wtf how to get date?
        example1: MyDate = #2/12/1969#
        gives: LitDate 0x0000 0x0000 0xA780 0x40D8
        example2: MyDate = #2/12/1970#
        gives: LitDate 0x0000 0x0000 0x02C0 0x40D9
        example3: MyDate = #2/12/1971#
        gives: LitDate 0x0000 0x0000 0x5E00 0x40D9
        example4: MyDate = #2/11/1969#
        gives: LitDate 0x0000 0x0000 0xA740 0x40D8
        example5: MyDate = #2/10/1969#
        gives: LitDate 0x0000 0x0000 0xA700 0x40D8
        example6: MyDate = #3/12/1969#
        gives: LitDate 0x0000 0x0000 0xAE80 0x40D8
        example7: MyDate = #4/12/1969#
        gives: LitDate 0x0000 0x0000 0xB640 0x40D8


        1 year = 23360 (0x5b40) si on fait last2bytes.first2bytes
        1 month = 64 (0x40) sur second octet
        1 day = 
        """
        raise Pcode2codeException('a date is defined here, but it cannot be reconstructed')
            
    def litdefault(self):
        """
        appears to be useless
        example: Open "TESTFILE" For Output As #1 
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Output)
        example2: Lock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Lock
        example3: same for unlock
        """
        #pass on purpose
        pass

    # integer representation on 2 bytes (decimal base10)
    def litdi2(self, value):
        self.opstack.push(str(int(value,16)))

    # integer representation on 4 bytes (decimal base10)
    def litdi4(self, byte1, byte2):
        val = int(byte2+byte1[2:], 16)
        self.opstack.push(str(val))
        
    def litdi8(self, *args):
        raise Pcode2codeException('not implemented litdi8')
            
    def lithi2(self, byte):
        val = byte[2:]
        while val.startswith('0') and len(val) > 1:
            val = val[1:]
        val = '&H' + val
        self.opstack.push(val)
            
    def lithi4(self, byte1, byte2):
        val = byte2[2:]+byte1[2:]
        while val.startswith('0') and len(val) > 1:
            val = val[1:]
        val = '&H' + val
        self.opstack.push(val)
            
    def lithi8(self, *args):
        raise Pcode2codeException('not implemented lithi8')
            
    def litnothing(self):
        """
        command defining the "Nothing" variable
        example: Set Inst = Nothing
        gives:
             # SetStmt
             # LitNothing
             # Set Inst
        """
        self.opstack.push('Nothing')
            
    def litoi2(self, value):
        """
        command used when an octal is defined on a two bytes byte array
        example: B = &O1
        gives:
             # LitOI2 0x0001
             # St B
        """
        var = int(value,16)
        var2 = str(oct(var))[2:]
        self.opstack.push('&O' + var2)
            
    def litoi4(self, byte1, byte2):
        """
        command used when an octal is defined on a two bytes byte array
        example: B = &O12345644444
        gives:
             # LitOI4 0x4924 0x5397
             # St B
        """        
        val = byte2[2:]+byte1[2:]
        var = int(val,16)
        var2 = str(oct(var))[2:]
        self.opstack.push('&O' + var2)
        
            
    def litoi8(self, *args):
        raise Pcode2codeException('not implemented litoi8')
            
    def litr4(self, byte1, byte2):
        """
        command used when a floating point on 32 bit is declared
        """
        val = byte2[2:]+byte1[2:]
        self.opstack.push(str(struct.unpack("!f", bytes.fromhex(val))[0]))
            
    def litr8(self, byte1, byte2, byte3, byte4):
        """
        command used when a floating point on 64 bit is declared
        """
        val = byte4[2:]+byte3[2:]+byte2[2:]+byte1[2:]
        self.opstack.push(str(struct.unpack("!d", bytes.fromhex(val))[0]))
            
    def litsmalli2(self, *args):
        raise Pcode2codeException('not implemented malli2')
            
    def litstr(self, mylen, *args):
        val = args[0]
        for arg in args[1:]:
            val += ' ' + arg
        if len(val)>=2:
            #assert(val[0]=='"' and val[-1]=='"')
            val = val[1:-1]
            val = val.replace('"', '""')
            val = '"' + val + '"'

        self.opstack.push(val)
            
    def litvarspecial(self, var):
        self.opstack.push(var[1:-1])
            
    def lock(self):
        """
        command to lock a record
        example: Lock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Lock
        """
        if self.opstack.size() == 3:
            last_record = self.opstack.pop()
            first_record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan + ', ' + first_record + ' To ' + last_record)
        elif self.opstack.size() == 2:
            record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan + ', ' + record)
        elif self.opstack.size() == 1:
            chan = self.opstack.pop()
            self.opstack.push('Lock ' + chan)
            
    def loop(self):
        self.opstack.push('Loop')
        self.indentlevel = self.indentlevel - 1
            
    def loopuntil(self):
        """
        command defining a loop until statement for "do"
        example: Loop Until TheName = ""
        gives:
             # Ld TheName
             # LitStr 0x0000 ""
             # Eq
             # LoopUntil
        """
        self.opstack.push('Loop Until ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1
            
    def loopwhile(self):
        """
        command handling " while" definitions
        example: Loop While Reponse = 5
        gives:
             # Ld Response
             # LitDI2  0x0005
             # Eq
             # LoopWhile
        """
        self.opstack.push('Loop While ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1

            
    def lset(self):
        """
        command for RSet keyword
        example: LSet MyString = "Right->"
        gives:
             # LitStr 0x0007 "Right->"
             # Ld MyString
             # RSet
        """
        var = self.opstack.pop()
        val = self.opstack.pop()
        self.opstack.push('LSet ' + var + ' = ' + val)
            
    def me(self, *args):
        raise Pcode2codeException('not implemented me')
            
    def meimplicit(self, *args):
        """
        command used when the object is the current form
        example: Print 
        gives:
             # MeImplicit
             # PrintObj
             # PrintNL
        """
        self.opstack.push('MeImplicit') #just pushing a specific marker to change treatment later
            
    def memredim(self, *args):
        """
        command used when a property of an object is redim
        example: ReDim myobj.foo(30)
        gives:
             # OptionBase
             # LitDI2 0x001E
             # Ld myobj
             # MemRedim foo 0x0001 (As Variant)
        """
        val = self.opstack.pop()
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + val + '.' + args[0] + '('
        else:
            val2 = 'ReDim '
            if preserve:
                val2 += 'Preserve '
            val2 += val + '.' + args[0] + '('
            val = val2

        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)
            
    def memredimwith(self, *args):
        """
        command used when a property of an object is redim within a with
        example: with myobj ... ReDim .foo(30) .. end with
        gives:
             # OptionBase
             # LitDI2 0x001E
             # MemRedimWith foo 0x0001 (As Variant)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + '.' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += '.' + args[0] + '('

        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)

            
    def memredimas(self, *args):
        """
        command used when a redim is defined on a property of an object with a As in the end
        example: ReDim myobj.mytab(50) As Double
        gives:
             # OptionBase
             # LitDI2 0x003C
             # Ld myobj
             # MemRedimAs Tab 0x0001 (As Double)
        """
        val = self.opstack.pop()
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + val + '.' + args[0] + '('
        else:
            val2 = 'ReDim '
            if preserve:
                val2 += 'Preserve '
            val2 += val + '.' + args[0] + '('
            val = val2
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def memredimaswith(self, *args):
        """
        command used when a redim is defined on a property of an object with a As in the end, within a with block
        example: With myobj ... ReDim .mytab(70) As Integer ... End With 
        gives:
             # OptionBase
             # LitDI2 0x0046
             # MemRedimAsWith Tab 0x0001 (As Integer)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + '.' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += '.' + args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def mid(self):
        """
        command used when Mid funtion is used to set a sub string part, e.g. as an instruction
        example: Mid(MyString, 5, 3) = "fox"
        gives:
             # LitStr 0x0003 "fox"
             # Ld MyString
             # LitDI2 0x0005
             # LitDI2 0x0003
             # Mid
        """
        if self.opstack.size() > 3:
            length = self.opstack.pop()
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('Mid(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
        else:
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('Mid(' + obj + ', ' + start + ') = ' + str1)            
            
    def midb(self):
        """
        command used when Mid funtion is used to set a sub string part, e.g as an instruction
        example: MidB(MyString, 5, 3) = "fox"
        gives:
             # LitStr 0x0003 "fox"
             # Ld MyString
             # LitDI2 0x0005
             # LitDI2 0x0003
             # MidB
        """
        if self.opstack.size() > 3:
            length = self.opstack.pop()
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('MidB(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
        else:
            start = self.opstack.pop()
            obj = self.opstack.pop()
            str1 = self.opstack.pop()
            self.opstack.push('MidB(' + obj + ', ' + start + ') = ' + str1)            

            
    def name(self):
        """
        command for the name keyword, permitting to rename variables
        example: Name OldName As NewName
        gives:
             # Ld OldName
             # Ld NewName
             # Name
        """
        newname = self.opstack.pop()
        oldname = self.opstack.pop()
        self.opstack.push('Name ' + oldname + ' As ' + newname) 
            
    def new(self, var):
        self.opstack.push('New ' + var)
            
    def next_(self):
        self.opstack.push('Next')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = False
            
    def nextvar(self):
        self.opstack.push('Next ' + self.opstack.pop())
        self.indentlevel = self.indentlevel - 1
            
    def onerror(self, *args):
        """
        command defining "on error" statements
        example1: On Error GoTo ErrorHandler
        gives:
             # OnError ErrorHandler
        example2: On Error GoTo 0
        gives: 
             # OnError (GoTo 0)
        example3: On Error Resume Next
        gives: 
             # OnError (Resume Next)
        """
        if args[0] == '(Resume':
            self.opstack.push('On Error Resume Next')
        elif args[0] == '(GoTo':
            self.opstack.push('On Error GoTo 0')
        else:
            #TODO: to check
            self.opstack.push('On Error GoTo ' + args[0])
            
    def ongosub(self, nb, *args):
        """
        command used for gosub on a variable
        example: On Number GoSub Sub1, Sub2
        gives:
             # Ld Number
             # OnGoSub 0x0004 Sub1, Sub2
        """
        val = 'On ' + self.opstack.pop() + ' GoSub '
        val2 = args[0]
        for arg in args[1:]:
            val2 += ' ' + arg
        self.opstack.push(val + val2)
            
    def ongoto(self, nb, *args):
        """
        command used for goto on a variable
        example: On Number GoTo Line1, Line2
        gives:
             # Ld Number
             # OnGoto 0x0004 Line1, Line2
        """
        val = 'On ' + self.opstack.pop() + ' GoTo '
        val2 = args[0]
        for arg in args[1:]:
            val2 += ' ' + arg
        self.opstack.push(val + val2)
            
    def open_(self, *args):
        """
        command used for Open function
        example: Open "TESTFILE" For Output As #1
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Output)
        example2: Open "TESTFILE" For Binary Access Write Lock Write As #1
        gives:
             # LitStr 0x0008 "TESTFILE"
             # LitDI2 0x0001
             # Sharp
             # LitDefault
             # Open (For Binary Access Write Lock Write)
        """
        chan = self.opstack.pop()
        val = args[0][1:] # avoid parenthesis
        for arg in args[1:]:
            val += ' ' + arg
        val = val[:-1] #avoid parenthesis
        self.opstack.push('Open ' + self.opstack.pop() + ' ' + val + ' As ' + chan)
            
    def option(self, *args):
        """
        command for option keyword
        example: Option Explicit
        gives : 
           # Option (Explicit)
        example2: Option Compare Binary
        gives :
           # Option (Compare Binary)
        """
        val = args[0][1:]
        if len(args)>1:
            for arg in args[1:]: #strip parenthesis
                val += ' ' + arg
        self.opstack.push('Option ' + val[:-1])
            
    def optionbase(self):
        """
        used in the following case: when a table dimension is not declared from base to end, but only size;
        to treat it, we will push a magic value on stack like for dim and dimimplicit, and vardef will treat it directly
        example1: Dim MyArray(20)
        gives: 
             # Dim
             # OptionBase
             # LitDI2 0x0014
             # VarDefn MyArray
        """
        self.opstack.push('OptionBase')
            
    def parambyval(self):
        """
        command used when Byval keyword is used
        example: a ByVal b
        gives:
             # Ld B
             # ParamByVal
             # ArgsCall a 0x0001
        """
        self.opstack.push('ByVal ' + self.opstack.pop())
            
    def paramomitted(self):
        """
        command used when a parameter is left blank in a function call
        example: MsgBox Msg, , "Deferred Error Test"
        gives:
             # Ld Msg
             # ParamOmitted
             # LitStr 0x0013 "Deferred Error Test"
             # ArgsCall MsgBox 0x0003
        """
        self.opstack.push('')
            
    def paramnamed(self, var):
        """
        command used when a call is made with named parameters
        example: MyClasses.Add Item:=Inst, Key:=CStr(Num)
        gives:
             # Ld Inst
             # ParamNamed Item
             # Ld Num
             # Coerce (Str)
             # ParamNamed Key
             # Ld MyClasses
             # ArgsMemCall Add 0x0002
        """
        self.opstack.push(var + ':=' + self.opstack.pop())
            
    def printchan(self):
        """
        command defining "print" to a channel
        example: Print #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # PrintChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        self.opstack.push('Print ' +self.opstack.pop() + ',')
    
    def printcomma(self, *args):
        """
        command used when a colon is used in Print
        example: Debug.Print Spc(30), "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintComma
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push(',')
            
    def printeos(self):
        """
        used at the end of some print when there is nothing, instead of printitemnl
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
                val+= elmt
            else:
                val += ' ' + elmt
        self.opstack.push(val)

            
    def printitemcomma(self):
        """
        command defining ",", used for example when writing 
        example: Write #1, "Hello World", 234
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # LitStr 0x000B "Hello World"
             # PrintItemComma
             # LitDI2 0x00EA
             # PrintItemNL
             # QuoteRem 0x0020 0x001C " Write comma-delimited data."
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val + ',')
            
    def printitemnl(self):
        """
        TODO: not sure what's it is used for
        example1: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        example2:  Debug.Print i
        gives:
             # Debug
             # PrintObj
             # Ld i
             # PrintItemNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
                val+= elmt
            else:
                val += ' ' + elmt
        self.opstack.push(val)
            
    def printitemsemi(self):
        """
        command defining ";", used for example when writing 
        example: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val + ';')
            
    def printnl(self):
        """
        really not sure about this one
        example: Write #1,     
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # PrintNL
        """
        elmts = []
        while self.opstack.size() >= 1:
            elmts.append(self.opstack.pop())
        elmts = elmts[::-1]
        val = elmts[0]
        for elmt in elmts[1:]:
            val += ' ' + elmt
        self.opstack.push(val)
    
    def printobj(self):
        """
        appears to call the print method of an object
        example:  Debug.Print i
        gives:
             # Debug
             # PrintObj
             # Ld i
             # PrintItemNL
        """
        if self.opstack.top() == 'MeImplicit':
            self.opstack.pop()
            self.opstack.push('Print')
        else:
            self.opstack.push(self.opstack.pop() + '.Print')
            
    def printsemi(self, *args):
        """
        command used when a semicolon is used in Print
        example: Debug.Print Spc(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push(';')
            
    def printspc(self):
        """
        command used when SPC(n) is used in Print
        example: Debug.Print Spc(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintSpc
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Spc(' + self.opstack.pop() + ')')
            
    def printtab(self, *args):
        """
        command used when Tab(n) is used in Print
        example: Debug.Print Tab(30); "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # LitDI2 0x001E
             # PrintTab
             # PrintSemi
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Tab(' + self.opstack.pop() + ')')
            
    def printtabcomma(self):
        """
        command used when Tab with no arg is used in Print
        example: Debug.Print Tab, "Thirty spaces later...
        gives:
             # Debug
             # PrintObj
             # PrintTabComma
             # PrintComma
             # LitStr 0x0016 "Thirty spaces later..."
             # PrintItemNL
        """
        self.opstack.push('Tab')
            
    def pset(self, numparams):
        """
        command used when the pset method of an object is called
        example: Me.PSet (intI, sngMidPt)
        gives:
             # Ld intI
             # Ld sngMidPt
             # LitDI2 0x0000
             # Ld id_FFFF
             # PSet 0x0002
        """
        val = self.opstack.pop() + '.PSet('
        first_arg = self.opstack.pop()
        if first_arg != '0':
            val += first_arg + ', '
            
        nb_args = int(numparams, 16)
        params = []
        if nb_args > 0:
            for i in range(nb_args):
                params.append(self.opstack.pop())
            params = params[::-1]

            val += params[0]
            for param in params[1:]:
                val = val + ', ' + param
        val +=')'
        self.opstack.push(val)
            
    def putrec(self):
        """
        command to Put to a channel with a record: Put channel, record, var
        example: Put #1, RecordNumber, MyRecord
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # Ld MyRecord
             # PutRec
        """
        record = self.opstack.pop()
        record_num = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push(F'Put {chan}, {record_num}, {record}')
            
    def quoterem(self, val1, lenvar, *args):
        """
        command handling comments definition with '
        multiple cases:
        example : MsgBox "toto" 'a message to send
        gives:
             # LitStr 0x0004 "toto"
             # ArgsCall MsgBox 0x0001
             # QuoteRem 0x000F 0x11

        example : TODO macaroni
        gives: TODO macaroni
        """
        val = "'" + args[0][1:]
        for arg in args[1:] :
            val += ' ' + arg
        val = val[:-1]
        if self.opstack.size() != 0:
            val = self.opstack.pop() + ' ' + val
        self.opstack.push(val)


    def redim(self, *args):
        """
        command used when redim function is used
        example : ReDim temp(4)
        gives:
             # OptionBase
             # LitDI2 0x0004
             # Redim temp 0x0001 (As Variant)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'
        self.opstack.push(val)

        
    def redimas(self, *args):
        """
        command used when a redim is defined with a As in the end
        example: ReDim mytab(50) As Double
        gives:
             # OptionBase
             # LitDI2 0x0032
             # RedimAs mytab 0x0001 (As Double)
        """
        val = ''
        args = list(args)
        preserve = False
        if args[0] == '(Preserve)':
            args.pop(0)
            preserve = True

        nb_params = int(args[1], 16)

        values = []
        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        if values[0].startswith('ReDim'): # in case redim of multiple variables
            val = values.pop(0) + ', ' + args[0] + '('
        else:
            val += 'ReDim '
            if preserve:
                val += 'Preserve '
            val += args[0] + '('
            
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        val += ')'

        args.pop(0) #remove var
        args.pop(0) # remove nb_params
        if len(args)> 0: # do we have smthng like "(As <type>)"
            if args[-1] != 'Variant)':
                val += ' ' + args[0][1:] + ' ' + args[1][:-1]
        self.opstack.push(val)
            
    def reparse(self, *args):
        """
        opcode used when a non valid statement is employed
        """
        val = args[1][1:]
        for arg in args[2:]:
            val += ' ' + arg
        val = val[:-1] # avoid double quotes
        self.opstack.push(val)


    def rem(self, *args):
        """
        command for Rem keyword
        example: Rem This entire line is a comment
        gives:  # Rem 0x001F " This entire line is a comment."
        """
        val = args[2] # avoid space+double quote
        for arg in args[3:]:
            val += ' ' + arg
        val = val[:-1] #avoid double quote
        self.opstack.push('Rem ' + val)
        
            
    def resume(self, *args):
        """
        command used when resume keyword is used 
        example1: Resume
        gives: # Resume
        example2: Resume Next
        gives: # Resume (Next)
        example3: Resume titi
        gives: # Resume titi
        """
        if args == ():
            self.opstack.push('Resume')
        else:
            if args[0] == '(Next)':
                self.opstack.push('Resume Next')
            else:
                self.opstack.push('Resume ' + args[0])
            
    def return_(self):
        #TODO: comment
        self.opstack.push('Return')
            
    def rset(self):
        """
        command for RSet keyword
        example: RSet MyString = "Right->"
        gives:
             # LitStr 0x0007 "Right->"
             # Ld MyString
             # RSet
        """
        var = self.opstack.pop()
        val = self.opstack.pop()
        self.opstack.push('RSet ' + var + ' = ' + val)
            
    def scale(self, *args):
        """
        command used when an object scale method is used
        example: Me.Scale 
        gives:
             # LitDI2 0x0000
             # LitDI2 0x0000
             # Ld sngNewH
             # Ld sngNewV
             # Ld id_FFFF
             # Scale 0x0000
        TODO: what to do with this command?
        """
        raise Pcode2codeException('not implemented scale')
            
    def seek(self):
        """
        opcode used when seek is used to search in a file
        example: Seek #1, 2
        gives:
             # LitDI2 0x0001
             # Sharp
             # LitDI2 0x0002
             # Seek
        """
        data = self.opstack.pop()
        self.opstack.push('Seek ' + self.opstack.pop() + ', ' + data)
            
    def selectcase(self):
        """
        command handling a "select case" definition against a variable
        example : Select Case x
        gives:
             # Ld x
             # SelectCase
        """
        self.opstack.push('Select Case ' + self.opstack.pop())
        self.indentincrease_future = True
    
    def selectis(self, *args):
        raise Pcode2codeException('not implemented selectis')
            
    def selecttype(self, *args):
        raise Pcode2codeException('not implemented selecttype')
            
    def setstmt(self):
        # TODO: comment
        #pass on purpose
        pass
            
    def stack(self, *args):
        raise Pcode2codeException('not implemented stack')
            
    def stop(self):
        #TODO: comment
        self.opstack.push('Stop')
            
    def type_(self, *args):
        """
        command for Type keyword, #TODO: beware because it's also used for enum keyword
        example: Type EmployeeRecord
        gives : 
           # Type EmployeeRecord
        """
        if args[0] == '(Private)':
            self.opstack.push('Private Type ' + args[1])
        elif args[0] == '(Public)':
            self.opstack.push('Public Type ' + args[1])
        else:
            self.opstack.push('Type ' + args[0])
        self.indentincrease_future = True
            
    def unlock(self):
        """
        command to unlock a record
        example: Unlock #1, RecordNumber
        gives:
             # LitDI2 0x0001
             # Sharp
             # Ld RecordNumber
             # LitDefault
             # Unlock
        """
        if self.opstack.size() == 3:
            last_record = self.opstack.pop()
            first_record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan + ', ' + first_record + ' To ' + last_record)
        elif self.opstack.size() == 2:
            record = self.opstack.pop()
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan + ', ' + record)
        elif self.opstack.size() == 1:
            chan = self.opstack.pop()
            self.opstack.push('Unlock ' + chan)



    # Dim hiz7dgus As String
    # Private Const DefaultBufferSize& = 32768
    # Private CRC_32_Tab(0 To 255) As Long
    # ======================
    # Line #7:
    #   Dim 
    #   VarDefn hiz7dgus (As String)
    # Line #8:
    # Line #9:
    #   Dim (Private Const) 
    #   LitDI4 0x8000 0x0000 
    #   VarDefn DefaultBufferSize
    # Line #10:
    # Line #11:
    #   Dim (Private) 
    #   LitDI2 0x0000 
    #   LitDI2 0x00FF 
    #   VarDefn CRC_32_Tab (As Long)
    def vardefn(self, *args):      
        ending =''
        args = list(args) #quite ugly, but fu...
        if args[0] == '(WithEvents)':
            var = args.pop(0)[1:-1] + ' ' + args.pop(0)
        else:
            var = args.pop(0)

        spaces = 1
        if len(args) > 0:
            if args[-1].startswith('0x'):
                spaces = int(args.pop(-1),16) #TODO: treat spaces there
            ending = args[0]
            for arg in args[1:]:
                ending += ' ' + arg
            ending = ' ' + ending[1:-1]
            

        # first we check if this is only one literal definition
        # in this case, we get Dim definitions and we are all set up
        stacktop = self.opstack.pop()

        if stacktop == 'DimImplicit': #case where dim is implicit, 
            val = var + ending  # we have pushed in this case 'DimImplicit' on stack
            self.opstack.push(val)
            return

        # in this case we have a single variable declaration
        decls = ['Dim', 'Private', 'Public', 'Protected', 'Friend', 'Protected Friend', 'Shared', 'Shadows', 'Static', 'ReadOnly']
        if stacktop in decls:
            val = stacktop + ' ' + var + ending
            self.opstack.push(val)
            return

        else:
            # in this case, our variable is either a table, or there is also some const declarations
            # if so, walk the stack and check for declaration
            self.opstack.push(stacktop)
            values = []

            # gather all stack
            while self.opstack.size() > 0:
                values.append(self.opstack.pop())
            values = values[::-1]

            # if we have multiple vardefn with dim, then we are here
            # because all previous vardef should have been pushed correctly on stack
            if len(values) == 1 :
                for decl in decls:
                    if values[0].startswith(decl):
                        val = values[0] +', ' + var + ending
                        self.opstack.push(val)
                        return
                    
            # if const is used for declaration, then a value is attributed to variable
            # appears somehow not possible to declare a table as const, so far so good, no need to check this case
            if 'Const' in values[0]:
                val = values.pop(0)
                end_val = ' = ' + values.pop(0)
                if len(values) > 0:
                    # how to say what is dimensions to what is attribution
                    #val = 'Undefined variable declaration'
                    raise Pcode2codeException('undefined variable declaration')
                else:
                    val = val + ' ' + var + ending + end_val
                self.opstack.push(val)
                return
            
            #so here we have a table
            val = ''
            if values[0] in decls: #first we check if this is the first definition
                val += values.pop(0) + ' ' + var + '('
            elif values[0] == 'DimImplicit': #not sure about this one
                values.pop(0)
                val += var + '('
            else:
                #next we check for a previous declaration
                prev_decl = False
                for decl in decls:
                    if values[0].startswith(decl):
                        val += values.pop(0) +', ' + var + '('
                        prev_decl = True
                if prev_decl is False: #in this case, nothing before
                    val+= var + '('

            #first occurence
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

            #other occurences
            while len(values) > 0:
                val += ', '
                curr_val1 = values.pop(0)
                curr_val2 = values.pop(0)
                if curr_val1 == 'OptionBase':
                    val += curr_val2 
                else:
                    val += curr_val1 + ' To ' + curr_val2 

            #closing
            val += ')' + ending
            self.opstack.push(val)

    def wend(self):
        """
        command handling end of while loop "Wend"
        example: Wend
        gives : 
              # Wend
        """
        self.opstack.push('Wend')
        self.indentlevel = self.indentlevel - 1
            
    def while_(self):
        """
        command handling "while" loops definitions
        example: While numero <= 12
        gives:
             # Ld numero
             # LitDI2 0x000C
             # Le
             # While
        """
        self.opstack.push('While ' + self.opstack.pop())
        self.indentincrease_future = True
            
    def with_(self):
        """
        command handling "with" definitions
        example: with theWindow 
        gives:
             # StartWithExpr
             # Ld theWindow
             # With
        """
        self.opstack.push('With ' + self.opstack.pop())
        self.indentincrease_future = True
            
    def writechan(self):
        """
        command defining "write" to a channel
        example: Write #1, MyBool; " is a Boolean value"
        gives:
             # LitDI2 0x0001
             # Sharp
             # WriteChan
             # Ld MyBool
             # PrintItemSemi
             # LitStr 0x0013 " is a Boolean value"
             # PrintItemNL
        """
        self.opstack.push('Write ' +self.opstack.pop() + ',')
            
    def constfuncexpr(self, *args):
        raise Pcode2codeException('not implemented constfuncexpr')
            
    def lbconst(self, var):
        """
        opcode used when #Const is used
        example: #Const x = y
        gives:
             # LbMark
             # Ld B
             # LbConst a
        """
        self.opstack.push('#Const ' + var + ' = ' + self.opstack.pop())
    
    def lbif(self):
        """
        opcode used when #If is used
        example: #If a = b Then
        gives:
             # LbMark
             # Ld a
             # Ld B
             # Eq
             # LbIf
        """
        self.opstack.push('#If ' + self.opstack.pop() + ' Then')
        self.indentincrease_future = True
    
    def lbelse(self):
        """
        opcode used when #Else is used
        example: #Else 
        gives: lbElse
        """
        self.opstack.push('#Else')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True
            
    def lbelseif(self):
        """
        opcode used when #Elseif is used
        example: #ElseIf a = c Then
        gives:
             # LbMark
             # Ld a
             # Ld c
             # Eq
             # LbElseIf
        """
        self.opstack.push('#ElseIf ' + self.opstack.pop() + ' Then')
        self.indentlevel = self.indentlevel - 1
        self.indentincrease_future = True
            
    def lbendif(self):
        """
        opcode used when "#End If" is used
        example: #End If
        gives: #LbEndIf
        """
        self.opstack.push('#End If')
        self.indentlevel = self.indentlevel - 1
            
    def lbmark(self):
        """
        appears to be used to indicate the start of a lb statement, appears quite useless
        """
        pass #pass on purposes

    def endforvariable(self):
        """
        This command ends out a for loop variable definition. Gives nothing interesting in fact
        example: TODO macaroni
        gives: TODO macaroni
        """
        #pass on purposes
        pass
            
    def startforvariable(self):
        """
        This command starts out a for loop variable definition. Gives nothing interesting in fact
        example: TODO macaroni
        gives: TODO macaroni
        """
        #pass on purposes
        pass
            
    def newredim(self, *args):
        raise Pcode2codeException('not implemented newredim')
            
    def startwithexpr(self):
        """
        used like startforvariable, eg, simply an indicator of when a with variable is declared.
        pretty useless for us.
        example: With theWindow
        gives:
             # StartWithExpr
             # Ld theWindow
             # With
        """
        #pass on purposes
        pass
            
    def setorst(self, *args):
        raise Pcode2codeException('not implemented setorst')
            
    def endenum(self):
        """
        command to end an enum
        example: End Enum
        gives:
             #EndEnum
        """
        self.opstack.push('End Enum')
        self.indentlevel = self.indentlevel - 1
            
    def illegal(self, *args):
        raise Pcode2codeException('not implemented illegal')

    def newline(self):
        """
        defines a blank line. Used for internal processing, for blank streams and lines
        """
        self.opstack.push('')
    
    def clearstack(self):
        self.opstack.clearstack()

    def getstacktop(self):
        return self.opstack.top()

    def getstackpop(self):
        return self.opstack.pop()

    def getstacksize(self):
        return self.opstack.size()

    def increaseindentlevel_future(self):
        """
        when we increase the indent level, we need to first print out the line, and then to increase the indent level. 
        to do so, when a line has been printed, this function checks if the indent level need to be increased and do so.
        """
        if self.unindented > 0:
            self.unindented -= 1
        elif self.indentincrease_future:
            self.indentlevel = self.indentlevel + 1
        self.indentincrease_future = False
    
    def getindentlevel(self):
        """
         function retrieving the class indentlevel parameter, used to print out code with correct indent
        """
        return self.indentlevel

    def hasbos(self):
        return self.has_bos

    def resethasbos(self):
        self.has_bos = False

Methods

def imp(self)
Expand source code Browse git
def imp(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Imp ' + arg2
    self.opstack.push(val)
def eqv(self)
Expand source code Browse git
def eqv(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Eqv ' + arg2
    self.opstack.push(val)
def xor(self)
Expand source code Browse git
def xor(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Xor ' + arg2
    self.opstack.push(val)
def or_(self)
Expand source code Browse git
def or_(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Or ' + arg2
    self.opstack.push(val)
def and_(self)
Expand source code Browse git
def and_(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' And ' + arg2
    self.opstack.push(val)
def eq(self)
Expand source code Browse git
def eq(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' = ' + arg2
    self.opstack.push(val)
def ne(self)
Expand source code Browse git
def ne(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' <> ' + arg2
    self.opstack.push(val)
def le(self)
Expand source code Browse git
def le(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' <= ' + arg2
    self.opstack.push(val)
def ge(self)
Expand source code Browse git
def ge(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' >= ' + arg2
    self.opstack.push(val)
def lt(self)
Expand source code Browse git
def lt(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' < ' + arg2
    self.opstack.push(val)
def gt(self)
Expand source code Browse git
def gt(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' > ' + arg2
    self.opstack.push(val)
def add(self)
Expand source code Browse git
def add(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' + ' + arg2
    self.opstack.push(val)
def sub(self)
Expand source code Browse git
def sub(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' - ' + arg2
    self.opstack.push(val)
def mod(self)
Expand source code Browse git
def mod(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Mod ' + arg2
    self.opstack.push(val)
def idiv(self)
Expand source code Browse git
def idiv(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' \\ ' + arg2
    self.opstack.push(val)
def mul(self)
Expand source code Browse git
def mul(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' * ' + arg2
    self.opstack.push(val)
def div(self)
Expand source code Browse git
def div(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' / ' + arg2
    self.opstack.push(val)
def concat(self)
Expand source code Browse git
def concat(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' & ' + arg2
    self.opstack.push(val)
def like(self)
Expand source code Browse git
def like(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Like ' + arg2
    self.opstack.push(val)
def pwr(self)
Expand source code Browse git
def pwr(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' ^ ' + arg2
    self.opstack.push(val)
def is_(self)
Expand source code Browse git
def is_(self):
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    val = arg1 + ' Is ' + arg2
    self.opstack.push(val)
def not_(self)
Expand source code Browse git
def not_(self):
    val = 'Not ' + self.opstack.pop()
    self.opstack.push(val)
def umi(self)
Expand source code Browse git
def umi(self):
    val = '-' + self.opstack.pop()
    self.opstack.push(val)
def fnabs(self)
Expand source code Browse git
def fnabs(self):
    arg = self.opstack.pop()
    val = 'Abs(' + arg + ')'
    self.opstack.push(val)
def fnfix(self)
Expand source code Browse git
def fnfix(self):
    arg = self.opstack.pop()
    val = 'Fix(' + arg + ')'
    self.opstack.push(val)
def fnint(self)
Expand source code Browse git
def fnint(self):
    arg = self.opstack.pop()
    val = 'int(' + arg + ')'
    self.opstack.push(val)
def fnsgn(self)
Expand source code Browse git
def fnsgn(self):
    arg = self.opstack.pop()
    val = 'Sgn(' + arg + ')'
    self.opstack.push(val)
def fnlen(self)
Expand source code Browse git
def fnlen(self):
    arg = self.opstack.pop()
    val = 'Len(' + arg + ')'
    self.opstack.push(val)
def fnlenb(self)
Expand source code Browse git
def fnlenb(self):
    arg = self.opstack.pop()
    val = 'LenB(' + arg + ')'
    self.opstack.push(val)
def paren(self)
Expand source code Browse git
def paren(self):
    arg = self.opstack.pop()
    val = '(' + arg + ')'
    self.opstack.push(val)
def sharp(self)
Expand source code Browse git
def sharp(self):
    arg = self.opstack.pop()
    val = '#' + arg
    self.opstack.push(val)
def ldlhs(self)
Expand source code Browse git
def ldlhs(self):
    raise Pcode2codeException('not implemented ldlhs')
def ld(self, var)

command defining a variable example: X = Y gives: # Ld Y # St X

Expand source code Browse git
def ld(self, var):
    """
    command defining a variable
    example: X = Y
    gives:
         # Ld Y
         # St X
    """
    if var == 'id_FFFF': #hacky way to do it because me does not seem to be fully
        var = 'Me'       #parsed by pcodedmp
    self.opstack.push(var)
def memld(self, var)
Expand source code Browse git
def memld(self, var):
    val = self.opstack.pop() + '.' + var
    self.opstack.push(val)
def dictld(self, var)

cf fields and collections, also index??? example: Debug.Print rsTable!Title gives: # Debug # PrintObj # Ld rsTable # DictLd Title # PrintItemNL

Expand source code Browse git
def dictld(self, var):
    """
    cf fields and collections, also index???
    example: Debug.Print rsTable!Title
    gives:
         # Debug
         # PrintObj
         # Ld rsTable
         # DictLd Title
         # PrintItemNL
    """
    self.opstack.push(self.opstack.pop()+ '!' + var)
def indexld(self, *args)
Expand source code Browse git
def indexld(self, *args):
    raise Pcode2codeException('not implemented indexld')
def argsld(self, varname, numparams)
Expand source code Browse git
def argsld(self, varname, numparams):
    val = varname + '('
    nb_parameters = int(numparams, 16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def argsmemld(self, var, numparams)
Expand source code Browse git
def argsmemld(self, var, numparams):
    nb_parameters = int(numparams, 16)
    val = self.opstack.pop() + '.' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def argsdictld(self, var, numparams)

command used when an index of an object with an argument is accessed example: Debug.Print myobj!toto("titi") gives: # Debug # PrintObj # LitStr 0x0004 "titi" # Ld myobj # ArgsDictLd toto 0x0001 # PrintItemNL

Expand source code Browse git
def argsdictld(self, var, numparams):
    """
    command used when an index of an object with an argument is accessed
    example: Debug.Print myobj!toto("titi") 
    gives:
         # Debug
         # PrintObj
         # LitStr 0x0004 "titi"
         # Ld myobj
         # ArgsDictLd toto 0x0001
         # PrintItemNL
    """
    nb_parameters = int(numparams, 16)
    val = self.opstack.pop() + '!' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def st(self, arg)
Expand source code Browse git
def st(self, arg):
    param = self.opstack.pop()
    val = arg + ' = ' + param
    self.opstack.push(val)
def memst(self, var)
Expand source code Browse git
def memst(self, var):
    val = self.opstack.pop() + '.' + var
    val = val + ' = ' + self.opstack.pop()
    self.opstack.push(val)
def dictst(self, var)

command used when an index is defined directly example: myobj!titi = "toto" gives: # LitStr 0x0004 "toto" # Ld myobj # DictSt titi

Expand source code Browse git
def dictst(self, var):
    """
    command used when an index is defined directly
    example: myobj!titi = "toto"
    gives:
         # LitStr 0x0004 "toto"
         # Ld myobj
         # DictSt titi
    """
    val = self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
    self.opstack.push(val)
def indexst(self, *args)
Expand source code Browse git
def indexst(self, *args):
    raise Pcode2codeException('not implemented indexst')
def argsst(self, var, numparams)
Expand source code Browse git
def argsst(self, var, numparams):
    nb_parameters = int(numparams, 16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = var + '(' + params[0]
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'

    param2 = self.opstack.pop()
    val += ' = ' + param2
    self.opstack.push(val)
def argsmemst(self, var, numparams)
Expand source code Browse git
def argsmemst(self, var, numparams):
    #TODO: to check
    val = self.opstack.pop() + '.'
    nb_parameters = int(numparams,16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + var + '(' + params[0]
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'

    param2 = self.opstack.pop()
    val += ' = ' + param2
    self.opstack.push(val)
def argsdictst(self, var, numparams)

used when an index of an obj with an argument is defined example: myobj!titi2("toto") = "toto" gives: # LitStr 0x0004 "toto" # LitStr 0x0004 "toto" # Ld myobj # ArgsDictSt titi2 0x0001

Expand source code Browse git
def argsdictst(self, var, numparams):
    """
    used when an index of an obj with an argument is defined
    example: myobj!titi2("toto") = "toto"
    gives:
         # LitStr 0x0004 "toto"
         # LitStr 0x0004 "toto"
         # Ld myobj
         # ArgsDictSt titi2 0x0001
    """
    val = self.opstack.pop() + '!' 
    nb_parameters = int(numparams,16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + var + '(' + params[0]
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'

    param2 = self.opstack.pop()
    val += ' = ' + param2
    self.opstack.push(val)
def set_(self, var)
Expand source code Browse git
def set_(self, var):
    val = 'Set ' + var + ' = ' + self.opstack.pop()
    self.opstack.push(val)
def memset(self, var)

obtained when a property of an object is set example: Set YourObject.Text = lobject gives: # SetStmt # Ld lobject # Ld YourObject # Memset Text

Expand source code Browse git
def memset(self, var):
    """
    obtained when a property of an object is set
    example: Set YourObject.Text = lobject
    gives:
         # SetStmt
         # Ld lobject
         # Ld YourObject
         # Memset Text
    """
    val = 'Set ' + self.opstack.pop() + '.' + var + ' = ' + self.opstack.pop()
    self.opstack.push(val)
def dictset(self, var)

obtained when an index of an object is set example: Set YourObject!Text = lobject gives: # SetStmt # Ld lobject # Ld YourObject # Dictset Text

Expand source code Browse git
def dictset(self, var):
    """
    obtained when an index of an object is set
    example: Set YourObject!Text = lobject
    gives:
         # SetStmt
         # Ld lobject
         # Ld YourObject
         # Dictset Text
    """
    val = 'Set ' + self.opstack.pop() + '!' + var + ' = ' + self.opstack.pop()
    self.opstack.push(val)
def indexset(self, *args)
Expand source code Browse git
def indexset(self, *args):
    raise Pcode2codeException('not implemented indexset')
def argsset(self, var, nb)

obtained when an argument of an object is set example: Set YourObject(ggg) = lobject gives: # SetStmt # Ld lobject # Ld ggg # ArgsSet YourObject 0x0001

Expand source code Browse git
def argsset(self, var, nb):
    """
    obtained when an argument of an object is set
    example: Set YourObject(ggg) = lobject
    gives:
         # SetStmt
         # Ld lobject
         # Ld ggg
         # ArgsSet YourObject 0x0001
    """
    val = 'Set ' + var + '(' + self.opstack.pop() + ') = ' + self.opstack.pop()
    self.opstack.push(val)
def argsmemset(self, var, numparams)

obtained when an argument of a property of an object is set example: Set YourObject.Text2("titi") = lobject gives: # SetStmt # Ld lobject # LitStr 0x0004 "titi" # Ld YourObject # ArgsMemSet Text2 0x0001

Expand source code Browse git
def argsmemset(self, var, numparams):
    """
    obtained when an argument of a property of an object is set
    example: Set YourObject.Text2("titi") = lobject
    gives:
         # SetStmt
         # Ld lobject
         # LitStr 0x0004 "titi"
         # Ld YourObject
         # ArgsMemSet Text2 0x0001
    """
    nb_parameters = int(numparams, 16)
    val = 'Set ' + self.opstack.pop() + '.' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ') = ' + self.opstack.pop()
    self.opstack.push(val)
def argsdictset(self, var, numparams)

obtained when an argument of a property of an object is set example: Set YourObject.Text2("titi") = lobject gives: # SetStmt # Ld lobject # LitStr 0x0004 "titi" # Ld YourObject # ArgsMemSet Text2 0x0001

Expand source code Browse git
def argsdictset(self, var, numparams):
    """
    obtained when an argument of a property of an object is set
    example: Set YourObject.Text2("titi") = lobject
    gives:
         # SetStmt
         # Ld lobject
         # LitStr 0x0004 "titi"
         # Ld YourObject
         # ArgsMemSet Text2 0x0001
    """
    nb_parameters = int(numparams, 16)
    val = 'Set ' + self.opstack.pop() + '!' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ') = ' + self.opstack.pop()
    self.opstack.push(val)
def memldwith(self, var)

command defining a part of an object like . example: with blah <....> .Name gives: # MemLdWith Name

Expand source code Browse git
def memldwith(self, var):
    """
    command defining a part of an object like .<prop>
    example: with blah <....> .Name 
    gives:  # MemLdWith Name
    """
    self.opstack.push('.' + var)
def dictldwith(self, var)

accessing an index in a with block example: With .... Debug.Print !au_lname … end with gives: # Debug # PrintObj # DictLdWith au_lname # PrintItemNL

Expand source code Browse git
def dictldwith(self, var):
    """
    accessing an index in a with block
    example: With <smth>.... Debug.Print !au_lname ... end with
    gives:
         # Debug
         # PrintObj
         # DictLdWith au_lname
         # PrintItemNL
    """
    self.opstack.push('!' + var)
def argsmemldwith(self, var, numparams)

example: .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1 gives: # Ld sProc # Ld ProcType # ArgsMemLdWith ProcStartLine 0x0002 # Ld lLine # Add # LitDI2 0x0001 # Ld sProc # Ld ProcType # ArgsMemLdWith ProcStartLine 0x0002 # Ld lLine # Add # LitDI2 0x0001 # Add # LitDI2 0x0001 # MemLdWith CodePane # ArgsMemCall SetSelection 0x0004

Expand source code Browse git
def argsmemldwith(self, var, numparams):
    """
    example: .CodePane.SetSelection .ProcStartLine(sProc, ProcType) + lLine, 1, .ProcStartLine(sProc, ProcType) + lLine + 1, 1
    gives:
         # Ld sProc
         # Ld ProcType
         # ArgsMemLdWith ProcStartLine 0x0002
         # Ld lLine
         # Add
         # LitDI2 0x0001
         # Ld sProc
         # Ld ProcType
         # ArgsMemLdWith ProcStartLine 0x0002
         # Ld lLine
         # Add
         # LitDI2 0x0001
         # Add
         # LitDI2 0x0001
         # MemLdWith CodePane
         # ArgsMemCall SetSelection 0x0004
    """
    nb_parameters = int(numparams, 16)
    val = '.' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def argsdictldwith(self, var, numparams)

command used when an index of an object with an argument is accessed with a with block example: With myobj … Debug.Print !toto("titi") … end with gives: # Debug # PrintObj # LitStr 0x0004 "titi" # ArgsDictLdWith toto 0x0001 # PrintItemNL

Expand source code Browse git
def argsdictldwith(self, var, numparams):
    """
    command used when an index of an object with an argument is accessed with a with block
    example: With myobj ... Debug.Print !toto("titi") ... end with
    gives:
         # Debug
         # PrintObj
         # LitStr 0x0004 "titi"
         # ArgsDictLdWith toto 0x0001
         # PrintItemNL
    """
    nb_parameters = int(numparams, 16)
    val = '!' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def memstwith(self, var)

command defining a part of an object like . = example: .Name = "Coho Vineyard" gives: # LitStr 0x000D "Coho Vineyard" # MemStWith Name

Expand source code Browse git
def memstwith(self, var):
    """
    command defining a part of an object like .<prop> = <smthg>
    example: .Name = "Coho Vineyard"
    gives:
         # LitStr 0x000D "Coho Vineyard"
         # MemStWith Name
    """
    self.opstack.push('.' + var + ' = ' + self.opstack.pop())
def dictstwith(self, var)

command defining a part of an object like ! = example: With … !Name = "Coho Vineyard" … end with gives: # LitStr 0x000D "Coho Vineyard" # DictStWith Name

Expand source code Browse git
def dictstwith(self, var):
    """
    command defining a part of an object like !<index> = <smthg>
    example: With ... !Name = "Coho Vineyard" ... end with
    gives:
         # LitStr 0x000D "Coho Vineyard"
         # DictStWith Name
    """
    self.opstack.push('!' + var + ' = ' + self.opstack.pop())
def argsmemstwith(self, var, numparams)

command defining a property of an object with arguments in a with statement example: With … .Name(1,2) = b … end with gives: # Ld B # LitDI2 0x0001 # LitDI2 0x0002 # ArgsMemStWith Name 0x0002

Expand source code Browse git
def argsmemstwith(self, var, numparams):
    """
    command defining a property of an object with arguments in a with statement
    example: With ... .Name(1,2) = b ... end with
    gives:
         # Ld B
         # LitDI2 0x0001
         # LitDI2 0x0002
         # ArgsMemStWith Name 0x0002
    """
    nb_parameters = int(numparams, 16)
    val = '.' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ') = ' + self.opstack.pop()
    self.opstack.push(val)
def argsdictstwith(self, var, *args)

command defining a part of an object like ! = in a with block example: !Name = "Coho Vineyard" gives: # LitStr 0x000D "Coho Vineyard" # DictStWith Name

Expand source code Browse git
def argsdictstwith(self, var, *args):
    """
    command defining a part of an object like !<index> = <smthg> in a with block
    example: !Name = "Coho Vineyard"
    gives:
         # LitStr 0x000D "Coho Vineyard"
         # DictStWith Name
    """
    self.opstack.push('!' + var + ' = ' + self.opstack.pop())
def memsetwith(self, var)

command defining a set on an index of an object in a with block example: with … Set .Name = "Coho Vineyard" gives: # SetStmt # LitStr 0x000D "Coho Vineyard" # memSetWith Name

Expand source code Browse git
def memsetwith(self, var):
    """
    command defining a set on an index of an object in a with block
    example: with <smth> ... Set .Name = "Coho Vineyard"
    gives:
         # SetStmt
         # LitStr 0x000D "Coho Vineyard"
         # memSetWith Name
    """
    self.opstack.push('Set .' + var + ' = ' + self.opstack.pop())
def dictsetwith(self, var)

command defining a set on an index of an object in a with block example: with … Set !Name = "Coho Vineyard" gives: # SetStmt # LitStr 0x000D "Coho Vineyard" # DictSetWith Name

Expand source code Browse git
def dictsetwith(self, var):
    """
    command defining a set on an index of an object in a with block
    example: with <smth> ... Set !Name = "Coho Vineyard"
    gives:
         # SetStmt
         # LitStr 0x000D "Coho Vineyard"
         # DictSetWith Name
    """
    self.opstack.push('Set !' + var + ' = ' + self.opstack.pop())
def argsmemsetwith(self, var, numparams)

command defining a set on an index with an argument of an object in a with block example: with … Set .nini("gg", "ff", "uu") = "toto" gives: # SetStmt # LitStr 0x0004 "toto" # LitStr 0x0002 "gg" # LitStr 0x0002 "ff" # LitStr 0x0002 "uu" # ArgsMemSetWith nini 0x0003

Expand source code Browse git
def argsmemsetwith(self, var, numparams):
    """
    command defining a set on an index with an argument of an object in a with block
    example: with <smth> ... Set .nini("gg", "ff", "uu") = "toto"
    gives:
         # SetStmt
         # LitStr 0x0004 "toto"
         # LitStr 0x0002 "gg"
         # LitStr 0x0002 "ff"
         # LitStr 0x0002 "uu"
         # ArgsMemSetWith nini 0x0003
    """
    nb_parameters = int(numparams, 16)
    val = 'Set !' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ') = ' + self.opstack.pop()
    self.opstack.push(val)
def argsdictsetwith(self, var, numparams)

command defining a set on an index with an argument of an object in a with block example: with … Set !nini("gg", "ff", "uu") = "toto" gives: # SetStmt # LitStr 0x0004 "toto" # LitStr 0x0002 "gg" # LitStr 0x0002 "ff" # LitStr 0x0002 "uu" # ArgsDictSetWith nini 0x0003

Expand source code Browse git
def argsdictsetwith(self, var, numparams):
    """
    command defining a set on an index with an argument of an object in a with block
    example: with <smth> ... Set !nini("gg", "ff", "uu") = "toto"
    gives:
         # SetStmt
         # LitStr 0x0004 "toto"
         # LitStr 0x0002 "gg"
         # LitStr 0x0002 "ff"
         # LitStr 0x0002 "uu"
         # ArgsDictSetWith nini 0x0003
    """
    nb_parameters = int(numparams, 16)
    val = 'Set !' + var + '('
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ') = ' + self.opstack.pop()
    self.opstack.push(val)
def argscall(self, *args)
Expand source code Browse git
def argscall(self, *args):

    if args[0] == '(Call)':
        nb_parameters = int(args[2],16)
        val = 'Call ' + args[1] + '('
        end_val = ')'
    else:
        val = args[0]
        nb_parameters = int(args[1],16)           
        end_val = ''
        
    params = []
    #print 'func:' + funcname
    #print 'nbparameters : ' + str(nb_parameters)
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        if ((params[0].startswith('(')) or (args[0] == '(Call)')):               
            val = val + params[0]
        else:
            val = val + ' ' + params[0]

        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += end_val
    self.opstack.push(val)
def argsmemcall(self, *args)

command to call a function of an object example: a43g0xT.run ayUBnLK01, 0 gives : # Ld ayUBnLK01 # LitDI2 0x0000 # Ld a43g0xT # ArgsMemCall run 0x0002

Expand source code Browse git
def argsmemcall(self, *args):
    """
    command to call a function of an object
    example: a43g0xT.run ayUBnLK01, 0
    gives : 
       # Ld ayUBnLK01
       # LitDI2 0x0000
       # Ld a43g0xT
       # ArgsMemCall run 0x0002
    """
    args = list(args)
    parenthesis = False
    if args[0] == '(Call)':
        args.pop(0)
        val = 'Call ' + self.opstack.pop() + '.' + args[0] + '('
        parenthesis = True
    else:
        val = self.opstack.pop() + '.' + args[0]

    nb_parameters = int(args[1],16)           
    end_val = ''
        
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        if params[0].startswith('('):               
            val = val + params[0]
            end_val = ')'
        else:
            if not parenthesis:
                val = val + ' ' +params[0]
            else:
                val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    if parenthesis == True:
        end_val = ')'
    self.opstack.push(val + end_val)
def argsmemcallwith(self, *args)

command when a function of an object is called in a with definition example: With a … call .a(1,2) … end with gives: # LitDI2 0x0001 # LitDI2 0x0002 # ArgsMemCallWith (Call) a 0x0002

Expand source code Browse git
def argsmemcallwith(self, *args):
    """
    command when a function of an object is called in a with definition
    example: With a ... call .a(1,2) ... end with
    gives: 
         # LitDI2 0x0001
         # LitDI2 0x0002
         # ArgsMemCallWith (Call) a 0x0002
    """
    parenthesis = False
    args = list(args)
    if args[0] == '(Call)':
        args.pop(0)
        parenthesis = True
        val = 'Call .' + args[0] + '('
    else:
        val = '.' + args[0]
        
    nb_parameters = int(args[1],16)           
    end_val = ''
        
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        if params[0].startswith('('):               
            val = val + params[0]
            end_val = ')'
        else:
            if not parenthesis:
                val = val + ' ' + params[0]
            else:
                val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param

    if parenthesis:
        end_val = ')'
    self.opstack.push(val + end_val)
def argsarray(self, var, numparams)
Expand source code Browse git
def argsarray(self, var, numparams):
    val = var + '('
    nb_parameters = int(numparams,16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    self.opstack.push(val)
def assert_(self)

command for debug.asser example: Debug.Assert blnAssert gives : # Ld blnAssert # Assert

Expand source code Browse git
def assert_(self):
    """
    command for debug.asser
    example: Debug.Assert blnAssert
    gives : 
          # Ld blnAssert
          # Assert
    """
    self.opstack.push('Debug.Assert ' + self.opstack.pop())
def bos(self, valarg)
Expand source code Browse git
def bos(self, valarg):
    arg = int(valarg,16)
    if arg == 0:
        val = self.opstack.pop() + ':'
    self.opstack.push(val)
    self.has_bos = True
def bosimplicit(self, *args)

appears useless, but in this case we still need to print whole stack example: If Mid$(theString, i, 1) <> Chr$(0) Then Exit For gives: # Ld theString # Ld i # LitDI2 0x0001 # ArgsLd Mid$ 0x0003 # LitDI2 0x0000 # ArgsLd Chr$ 0x0001 # Ne # If # BoSImplicit # ExitFor # EndIf

Expand source code Browse git
def bosimplicit(self, *args):
    """
    appears useless, but in this case we still need to print whole stack
    example: If Mid$(theString, i, 1) <> Chr$(0) Then Exit For
    gives:
         # Ld theString
         # Ld i
         # LitDI2 0x0001
         # ArgsLd Mid$ 0x0003
         # LitDI2 0x0000
         # ArgsLd Chr$ 0x0001
         # Ne
         # If
         # BoSImplicit
         # ExitFor
         # EndIf
    """
    self.has_bos = True
def bol(self, *args)
Expand source code Browse git
def bol(self, *args):
    raise Pcode2codeException('not implemented bol')
def ldaddressof(self, var)

command for AddressOf keyword example: EnumFontFamilies hDC, vbNullString, AddressOf EnumFontFamProc, LB gives: # Ld hDC # Ld vbNullString # LdAddressOf EnumFontFamProc # Ld LB # ArgsCall EnumFontFamilies 0x0004

Expand source code Browse git
def ldaddressof(self, var):
    """
    command for AddressOf keyword
    example: EnumFontFamilies hDC, vbNullString, AddressOf EnumFontFamProc, LB
    gives:
         # Ld hDC
         # Ld vbNullString
         # LdAddressOf EnumFontFamProc
         # Ld LB
         # ArgsCall EnumFontFamilies 0x0004
    """
    self.opstack.push('AddressOf ' + var)
def memaddressof(self, var)

command for AddressOf keyword on a property of an object example: MsgBox AddressOf myobj.toto gives: # Ld myobj # MemAddressOf toto # ArgsCall MsgBox 0x0001

Expand source code Browse git
def memaddressof(self, var):
    """
    command for AddressOf keyword on a property of an object
    example: MsgBox AddressOf myobj.toto
    gives:
         # Ld myobj
         # MemAddressOf toto
         # ArgsCall MsgBox 0x0001
    """
    self.opstack.push('AddressOf ' + self.opstack.pop() + '.' + var)
def case(self)

command handling choice in select case where choice is one value example: Case 0 gives: # LitDI2 0x0000 # Case # CaseDone

Expand source code Browse git
def case(self):
    """
    command handling choice in select case where choice is one value 
    example: Case 0
    gives:
         # LitDI2 0x0000
         # Case
         # CaseDone

    """
    self.opstack.push('Case ' + self.opstack.pop())
def caseto(self)

command handling choice in select case where choice is from one value to one other value example: Case 0 To 30 gives: # LitDI2 0x0000 # LitDI2 0x001E # CaseTo # CaseDone

Expand source code Browse git
def caseto(self):
    """
    command handling choice in select case where choice is from one value to one other value
    example: Case 0 To 30
    gives:
         # LitDI2 0x0000
         # LitDI2 0x001E
         # CaseTo
         # CaseDone
    """
    val = self.opstack.pop()
    self.opstack.push('Case ' + self.opstack.pop() + ' To ' + val)
def casegt(self)

command handling choice in select case where choice is lower than a value example: Case Is > 100 gives: # LitDI2 0x0064 # CaseGt # CaseDone

Expand source code Browse git
def casegt(self):
    """
    command handling choice in select case where choice is lower than a value
    example: Case Is > 100
    gives:
         # LitDI2 0x0064
         # CaseGt
         # CaseDone
    """
    self.opstack.push('Case Is > ' + self.opstack.pop())
def caselt(self)

command handling choice in select case where choice is lower than a value example: Case Is < 0 gives: # LitDI2 0x0002 # CaseLt # CaseDone

Expand source code Browse git
def caselt(self):
    """
    command handling choice in select case where choice is lower than a value
    example: Case Is < 0
    gives:
         # LitDI2 0x0002
         # CaseLt
         # CaseDone
    """
    self.opstack.push('Case Is < ' + self.opstack.pop())
def casege(self)

command handling choice in select case where choice is greater or equal than a value example: TODO: to check gives:

Expand source code Browse git
def casege(self):
    """
    command handling choice in select case where choice is greater or equal than a value
    example: TODO: to check
    gives:
    """
    self.opstack.push('Case Is >= ' + self.opstack.pop())
def casele(self)

command handling choice in select case where choice is lower or equal than a value example: TODO: to check gives:

Expand source code Browse git
def casele(self):
    """
    command handling choice in select case where choice is lower or equal than a value
    example: TODO: to check
    gives:
    """
    self.opstack.push('Case Is <= ' + self.opstack.pop())
def casene(self)

command handling choice in select case where choice is different to a value example: TODO: to check gives:

Expand source code Browse git
def casene(self):
    """
    command handling choice in select case where choice is different to a value
    example: TODO: to check
    gives:
    """
    self.opstack.push('Case Is <> ' + self.opstack.pop())
def caseeq(self)

command handling choice in select case where choice is equal to a value example: TODO: to check gives:

Expand source code Browse git
def caseeq(self):
    """
    command handling choice in select case where choice is equal to a value
    example: TODO: to check
    gives:
    """
    self.opstack.push('Case Is = ' + self.opstack.pop())
def caseelse(self)

command defining a "Case Else" stmt example: Case Else gives: # CaseElse

Expand source code Browse git
def caseelse(self):
    """
    command defining a "Case Else" stmt
    example: Case Else
    gives: 
         # CaseElse
    """
    self.opstack.push('Case Else')
def casedone(self)
Expand source code Browse git
def casedone(self):
    #pass on purpose, please see previous examples
    pass
def circle(self, useless)

command used when the circle method of an object is called example: Me.Circle (sngHCtr, sngVCtr), sngRadius gives: # Ld sngHCtr # Ld sngVCtr # Ld sngRadius # LitDI2 0x0000 # LitDI2 0x0000 # LitDI2 0x0000 # LitDI2 0x0000 # Ld id_FFFF # Circle 0x001E

Expand source code Browse git
def circle(self, useless):
    """
    command used when the circle method of an object is called
    example: Me.Circle (sngHCtr, sngVCtr), sngRadius
    gives:
         # Ld sngHCtr
         # Ld sngVCtr
         # Ld sngRadius
         # LitDI2 0x0000
         # LitDI2 0x0000
         # LitDI2 0x0000
         # LitDI2 0x0000
         # Ld id_FFFF
         # Circle 0x001E
    """
    val = self.opstack.pop() + '.Circle ('
    params = []
    for i in range(7):
        params.append(self.opstack.pop())
    params = params[::-1]

    val += params[0] + ', ' + params[1] + '), ' + params[2]
    all_empty = True
    for param in params[3:]:
        if param != '0':
            all_empty = False

    if all_empty:
        self.opstack.push(val)
    else:
        for param in params[3:]:
            if param == '0':
                val = val + ', <tbr>'
            else:
                val = val + ', ' + param
        val = val.replace(', <tbr>' , '')
        self.opstack.push(val)
def close(self, numparams)
Expand source code Browse git
def close(self, numparams):
    val = 'Close '
    nb_parameters = int(numparams,16)
    params = []
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    self.opstack.push(val)
def closeall(self)

command used when close is called with no arguments, effectively closing all files example: Close gives: # CloseAll

Expand source code Browse git
def closeall(self):
    """
    command used when close is called with no arguments, effectively closing all files
    example: Close
    gives: # CloseAll
    """
    self.opstack.push('Close')
def coerce_(self, arg)

command used for variable conversion example1: MyLong2 = CLng(MyVal2) gives: # Ld MyVal2 # Coerce (Lng) # St MyLong2 example2: MyInt = CInt(MyDouble) gives: # Ld MyDouble # Coerce (Int) # St MyInt

Expand source code Browse git
def coerce_(self, arg):
    """
    command used for variable conversion
    example1: MyLong2 = CLng(MyVal2)
    gives:
         # Ld MyVal2
         # Coerce (Lng)
         # St MyLong2
    example2: MyInt = CInt(MyDouble)
    gives:
         # Ld MyDouble
         # Coerce (Int)
         # St MyInt
    """
    if arg == '(Str)':
        self.opstack.push('CStr(' + self.opstack.pop() + ')')
    elif arg == '(Var)':
        self.opstack.push('CVar(' + self.opstack.pop() + ')')
    elif arg == '(Sng)':
        self.opstack.push('CSng(' + self.opstack.pop() + ')')
    elif arg == '(Lng)':
        self.opstack.push('CLng(' + self.opstack.pop() + ')')
    elif arg == '(Int)':
        self.opstack.push('CInt(' + self.opstack.pop() + ')')
    elif arg == '(Dbl)':
        self.opstack.push('CDbl(' + self.opstack.pop() + ')')
    elif arg == '(Date)':
        self.opstack.push('CDate(' + self.opstack.pop() + ')')
    elif arg == '(Cur)':
        self.opstack.push('CCur(' + self.opstack.pop() + ')')
    elif arg == '(Byte)':
        self.opstack.push('CByte(' + self.opstack.pop() + ')')
    elif arg == '(Bool)':
        self.opstack.push('CBool(' + self.opstack.pop() + ')')
    else:
        raise Pcode2codeException('not implemented coerce')
def coercevar(self, arg)

example1: MyError = CVErr(32767) gives: # CoerceVar (Err)

Expand source code Browse git
def coercevar(self, arg):
    """
    example1: MyError = CVErr(32767)
    gives: # CoerceVar (Err)
    """
    if arg == '(Err)':
        self.opstack.push('CVErr(' + self.opstack.pop() + ')')
    else:
        raise Pcode2codeException('not implemented coercevar')
def context(self, *args)
Expand source code Browse git
def context(self, *args):
    raise Pcode2codeException('not implemented context')
def debug(self)

seems used to invoke debug object example: Debug.Print MyVar gives: # Debug # PrintObj # Ld MyVar # PrintItemNL

Expand source code Browse git
def debug(self):
    """
    seems used to invoke debug object
    example: Debug.Print MyVar
    gives:
         # Debug
         # PrintObj
         # Ld MyVar
         # PrintItemNL
    """
    self.opstack.push('Debug')
def deftype(self, *args)

command used when def is used. TODO: bytes to know ranges appear random. How to do it?

Expand source code Browse git
def deftype(self, *args):
    """
    command used when def<type> is used.
    TODO: bytes to know ranges appear random. How to do it?
    """
    raise Pcode2codeException('not implemented deftype')
def dim(self, *args)
Expand source code Browse git
def dim(self, *args):
    # args is a tuple, we treat it only when its not empty
    # example of args : (As String), (As Long)...
    if args != ():
        val = args[0]
        for arg in args[1:]:
            val += ' ' + arg
        val = val[1:-1]
    else:
        val = 'Dim'
    self.opstack.push(val)
def dimimplicit(self)
Expand source code Browse git
def dimimplicit(self):
    self.opstack.push('DimImplicit')
def do(self)

command handling "Do" keyword example: Do (we have then the loop and so on) gives: # Do

Expand source code Browse git
def do(self):
    """
    command handling "Do" keyword
    example: Do (we have then the loop and so on)
    gives:
         # Do
    """
    self.opstack.push('Do')
    self.indentincrease_future = True
def doevents(self, *args)
Expand source code Browse git
def doevents(self, *args):
    raise Pcode2codeException('not implemented doevents')
def dounitil(self)

command handling "do until" definitions example: Do Until Response = "youpi" gives: # Ld Response # ListStr 0x0005 "youpi" # Eq # DoUnitil

Expand source code Browse git
def dounitil(self):
    """
    command handling "do until" definitions
    example: Do Until Response = "youpi"
    gives:
         # Ld Response
         # ListStr 0x0005 "youpi"
         # Eq
         # DoUnitil
    """
    self.opstack.push('Do Until ' + self.opstack.pop())
    self.indentincrease_future = True
def dowhile(self)

command handling "do while" definitions example: Do While Reponse <> "youpi" gives: # Ld Response # LitStr 0x0005 "youpi" # Ne # DoWhile

Expand source code Browse git
def dowhile(self):
    """
    command handling "do while" definitions
    example: Do While Reponse <> "youpi"
    gives:
         # Ld Response
         # LitStr 0x0005 "youpi"
         # Ne
         # DoWhile
    """
    self.opstack.push('Do While ' + self.opstack.pop())
    self.indentincrease_future = True
def else_(self)

command used for a "else" in a if oneliner example: If X < 4 Then MsgBox "hi" Else MsgBox "ho" gives: # Ld X # LitDI2 0x0004 # Lt # If # BoSImplicit # LitStr 0x0002 "hi" # ArgsCall MsgBox 0x0001 # Else # BoSImplicit # LitStr 0x0002 "Ho" # ArgsCall MsgBox 0x0001 # EndIf

Expand source code Browse git
def else_(self):
    """
    command used for a "else" in a if oneliner
    example: If X < 4 Then MsgBox "hi" Else MsgBox "ho"
    gives:
         # Ld X
         # LitDI2 0x0004
         # Lt
         # If
         # BoSImplicit
         # LitStr 0x0002 "hi"
         # ArgsCall MsgBox 0x0001
         # Else
         # BoSImplicit
         # LitStr 0x0002 "Ho"
         # ArgsCall MsgBox 0x0001
         # EndIf
    """
    self.opstack.push('Else')
def elseblock(self)

command defining a new "else" for a block example: Else gives: #Else

Expand source code Browse git
def elseblock(self):
    """
    command defining a new "else" for a block
    example: Else
    gives: #Else
    """
    self.opstack.push('Else')
    self.indentlevel = self.indentlevel - 1
    self.indentincrease_future = True
def elseifblock(self)

command defining a new "else if" block example: ElseIf dayW = DayOfWeek.Thursday Then gives: # Ld dayW # Ld DayOfWeek # MemLd Thursday # Eq # ElseIfBlock

Expand source code Browse git
def elseifblock(self):
    """
    command defining a new "else if" block
    example: ElseIf dayW = DayOfWeek.Thursday Then
    gives:
         # Ld dayW
         # Ld DayOfWeek
         # MemLd Thursday
         # Eq
         # ElseIfBlock
    """
    self.opstack.push('ElseIf ' + self.opstack.pop() + ' Then')
    self.indentlevel = self.indentlevel - 1
    self.indentincrease_future = True
def elseiftypeblock(self, *args)
Expand source code Browse git
def elseiftypeblock(self, *args):
    raise Pcode2codeException('not implemented elseiftypeblock')
def end(self)
Expand source code Browse git
def end(self):
    self.opstack.push('End')
def endcontext(self, *args)
Expand source code Browse git
def endcontext(self, *args):
    raise Pcode2codeException('not implemented endcontext')
def endfunc(self)
Expand source code Browse git
def endfunc(self):
    self.opstack.push('End Function')
    self.indentlevel = self.indentlevel - 1
def endif(self)
Expand source code Browse git
def endif(self):
    if self.onelineif == True:
        self.onelineif = False
    else:
        self.opstack.push('End If')
        self.indentlevel = self.indentlevel - 1
def endifblock(self)
Expand source code Browse git
def endifblock(self):
    self.opstack.push('End If')
    self.indentlevel = self.indentlevel - 1
def endimmediate(self, *args)
Expand source code Browse git
def endimmediate(self, *args):
    raise Pcode2codeException('not implemented endimmediate')
def endprop(self)

command handling the end of a property example: End Property gives: #EndProp

Expand source code Browse git
def endprop(self):
    """
    command handling the end of a property
    example: End Property
    gives: 
         #EndProp
    """
    self.opstack.push('End Property')
    self.indentlevel = self.indentlevel -1
def endselect(self)

command defining a stmt of "End Select", closing a select case. example: End Select gives: # EndSelect

Expand source code Browse git
def endselect(self):
    """
    command defining a stmt of "End Select", closing a select case.
    example: End Select
    gives: 
         # EndSelect
    """
    self.opstack.push('End Select')
    self.indentlevel = self.indentlevel - 1
def endsub(self)
Expand source code Browse git
def endsub(self):
    self.opstack.push('End Sub')
    self.indentlevel = self.indentlevel - 1
def endtype(self)

command to end a new type definition example: End Type gives: #EndType

Expand source code Browse git
def endtype(self):
    """
    command to end a new type definition
    example: End Type
    gives:
         #EndType
    """
    self.opstack.push('End Type')
    self.indentlevel = self.indentlevel - 1
def endwith(self)

command to end a new with definition example: End With gives: #EndWith

Expand source code Browse git
def endwith(self):
    """
    command to end a new with definition
    example: End With
    gives: #EndWith
    """
    self.opstack.push('End With')
    self.indentlevel = self.indentlevel - 1
def erase(self, nb_params)

command for Erase function keyword example: Erase threeDimArray, twoDimArray gives: # Ld threeDimArray # Ld twoDimArray # Erase 0x0002

Expand source code Browse git
def erase(self, nb_params):
    """
    command for Erase function keyword
    example: Erase threeDimArray, twoDimArray
    gives:
         # Ld threeDimArray
         # Ld twoDimArray
         # Erase 0x0002
    """
    nb_args = int(nb_params, 16)
    val = ''
    params = []
    for i in range(nb_args):
        params.append(self.opstack.pop())
        params = params[::-1]
    val = params[0]
        
    if nb_args > 1:
        for param in params[1:]:
            val = val + ', ' + param

    self.opstack.push('Erase ' + val)
def error(self)

command used for Error keyword example: Error 11 gives: # LitDI2 0x000B # Error

Expand source code Browse git
def error(self):
    """
    command used for Error keyword
    example: Error 11
    gives:
         # LitDI2 0x000B
         # Error
    """
    self.opstack.push('Error ' + self.opstack.pop())
def eventdecl(self, *args)

command for declaring a new event in VBA example: Event LogonCompleted(UserName As String) gives : # EventDecl (Sub LogonCompleted(UserName As String))

Expand source code Browse git
def eventdecl(self, *args):
    """
    command for declaring a new event in VBA
    example: Event LogonCompleted(UserName As String)
    gives : 
       # EventDecl (Sub LogonCompleted(UserName As String))
    """
    val = args[1]
    for arg in args[2:-1]: #strip parenthesis
        val += ' ' + arg
    self.opstack.push('Event ' + val + ' ' + args[-1][:-1])
def raiseevent(self, evt_name, nb_params)

command when RaiseEvent is used example: RaiseEvent LogonCompleted("AntoineJean") gives: # LitStr 0x000A "AntoineJan" # RaiseEvent LogonCompleted 0x0001

Expand source code Browse git
def raiseevent(self, evt_name, nb_params):
    """
    command when RaiseEvent is used
    example: RaiseEvent LogonCompleted("AntoineJean")
    gives:
         # LitStr 0x000A "AntoineJan"
         # RaiseEvent LogonCompleted 0x0001
    """
    nb_args = int(nb_params, 16)
    val = ''
    params = []
    if nb_args > 0:
        for i in range(nb_args):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = '('+ params[0]
        
        if nb_args > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'
                
    self.opstack.push('RaiseEvent ' + evt_name + val)
def argsmemraiseevent(self, var, numparams)

command used when a raiseevent is called on a property of an object example: RaiseEvent myobj.LogonCompleted("AntoineJan") gives: # LitStr 0x000A "AntoineJan" # Ld myobj # ArgsMemRaiseEvent LogonCompleted 0x0001

Expand source code Browse git
def argsmemraiseevent(self, var, numparams):
    """
    command used when a raiseevent is called on a property of an object
    example: RaiseEvent myobj.LogonCompleted("AntoineJan")
    gives:
         # LitStr 0x000A "AntoineJan"
         # Ld myobj
         # ArgsMemRaiseEvent LogonCompleted 0x0001
    """
    nb_args = int(numparams, 16)
    val = 'RaiseEvent ' + self.opstack.pop() + '.' + var + '('
    params = []
    if nb_args > 0:
        for i in range(nb_args):
            params.append(self.opstack.pop())
        params = params[::-1]
        val += params[0]
        
        if nb_args > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'
    self.opstack.push(val)
def argsmemraiseeventwith(self, var, numparams)

command used when a raiseevent is called on a property of an object within a with block example: with myobj … RaiseEvent .LogonCompleted("AntoineJan") … end with gives: # LitStr 0x000A "AntoineJan" # ArgsMemRaiseEventWith LogonCompleted 0x0001

Expand source code Browse git
def argsmemraiseeventwith(self, var, numparams):
    """
    command used when a raiseevent is called on a property of an object within a with block
    example: with myobj ... RaiseEvent .LogonCompleted("AntoineJan") ... end with
    gives:
         # LitStr 0x000A "AntoineJan"
         # ArgsMemRaiseEventWith LogonCompleted 0x0001
    """
    nb_args = int(numparams, 16)
    val = 'RaiseEvent .' + var + '('
    params = []
    if nb_args > 0:
        for i in range(nb_args):
            params.append(self.opstack.pop())
        params = params[::-1]
        val += params[0]
        
        if nb_args > 1:
            for param in params[1:]:
                val = val + ', ' + param
        val += ')'
    self.opstack.push(val)
def exitdo(self)
Expand source code Browse git
def exitdo(self):
    #TODO: comment
    self.opstack.push('Exit Do')
def exitfor(self)
Expand source code Browse git
def exitfor(self):
    #TODO: comment
    self.opstack.push('Exit For')
def exitfunc(self)
Expand source code Browse git
def exitfunc(self):
    #TODO: comment
    self.opstack.push('Exit Function')
def exitprop(self)
Expand source code Browse git
def exitprop(self):
    #TODO: comment
    self.opstack.push('Exit Property')
def exitsub(self)
Expand source code Browse git
def exitsub(self):
    #TODO: comment
    self.opstack.push('Exit Sub')
def fncurdir(self, *args)
Expand source code Browse git
def fncurdir(self, *args):
    #val = 'CurDir(' + self.opstack.pop() + ')'
    #self.opstack.push(val)
    raise Pcode2codeException('not implemented fncurdir')
def fndir(self, *args)
Expand source code Browse git
def fndir(self, *args):
    raise Pcode2codeException('not implemented fndir')
def empty0(self, *args)
Expand source code Browse git
def empty0(self, *args):
    raise Pcode2codeException('not implemented empty0')
def empty1(self, *args)
Expand source code Browse git
def empty1(self, *args):
    raise Pcode2codeException('not implemented empty1')
def fnerror(self, *args)
Expand source code Browse git
def fnerror(self, *args):
    raise Pcode2codeException('not implemented fnerror')
def fnformat(self, *args)
Expand source code Browse git
def fnformat(self, *args):
    raise Pcode2codeException('not implemented format')
def fnfreefile(self, *args)
Expand source code Browse git
def fnfreefile(self, *args):
    raise Pcode2codeException('not implemented fnfreefile')
def fninstr(self)

command used when calling Instr function with 2 arguments example: MyPos = InStr(SearchString, SearchChar) gives: # Ld SearchString # Ld SearchChar # FnInStr # St MyPos

Expand source code Browse git
def fninstr(self):
    """
    command used when calling Instr function with 2 arguments
    example: MyPos = InStr(SearchString, SearchChar)
    gives:
         # Ld SearchString
         # Ld SearchChar
         # FnInStr
         # St MyPos
    """
    arg2 = self.opstack.pop()
    self.opstack.push('Instr(' + self.opstack.pop() + ', ' + arg2 + ')')
def fninstr3(self)

command used when calling Instr function with 3 arguments example: MyPos = InStr(1, SearchString, "W") gives: # LitDI2 0x0001 # Ld SearchString # LitStr 0x0001 "W" # FnInStr3 # St MyPos

Expand source code Browse git
def fninstr3(self):
    """
    command used when calling Instr function with 3 arguments
    example: MyPos = InStr(1, SearchString, "W")
    gives:
         # LitDI2 0x0001
         # Ld SearchString
         # LitStr 0x0001 "W"
         # FnInStr3
         # St MyPos
    """
    arg3 = self.opstack.pop()
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')
def fninstr4(self)

command used when calling Instr function with 4 arguments example: MyPos = InStr(4, SearchString, SearchChar, 1) gives: # LitDI2 0x0004 # Ld SearchString # Ld SearchChar # LitDI2 0x0001 # FnInStr4 # St MyPos

Expand source code Browse git
def fninstr4(self):
    """
    command used when calling Instr function with 4 arguments
    example: MyPos = InStr(4, SearchString, SearchChar, 1)
    gives:
         # LitDI2 0x0004
         # Ld SearchString
         # Ld SearchChar
         # LitDI2 0x0001
         # FnInStr4
         # St MyPos
    """
    arg4 = self.opstack.pop()
    arg3 = self.opstack.pop()
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
def fninstrb(self)

command used when calling InstrB function with 2 arguments example: TODO: make sure here gives:

Expand source code Browse git
def fninstrb(self):
    """
    command used when calling InstrB function with 2 arguments
    example: TODO: make sure here
    gives:
    """
    arg2 = self.opstack.pop()
    self.opstack.push('InstrB(' + self.opstack.pop() + ', ' + arg2 + ')')
def fninstrb3(self)

command used when calling InstrB function with 3 arguments example: TODO: make sure here gives:

Expand source code Browse git
def fninstrb3(self):
    """
    command used when calling InstrB function with 3 arguments
    example: TODO: make sure here
    gives:

    """
    arg3 = self.opstack.pop()
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    self.opstack.push('InstrB(' + arg1 + ', ' + arg2 + ', ' + arg3 + ')')
def fninstrb4(self)

command used when calling InstrB function with 4 arguments example: TODO: make sure here gives:

Expand source code Browse git
def fninstrb4(self):
    """
    command used when calling InstrB function with 4 arguments
    example: TODO: make sure here
    gives:

    """
    arg4 = self.opstack.pop()
    arg3 = self.opstack.pop()
    arg2 = self.opstack.pop()
    arg1 = self.opstack.pop()
    self.opstack.push('Instr(' + arg1 + ', ' + arg2 + ', ' + arg3 + ', ' + arg4 + ')')
def fnlbound(self, arg)

command indicating the use of the LBound function strangely enough, there is an indication of the number of arguments to be popped out of the stack but this number is not good. example: Lower = LBound(TwoDArray, 2) gives: # Ld TwoDArray # LitDI2 0x0002 # FnLBound 0x0001 # St Lower

Expand source code Browse git
def fnlbound(self, arg):
    """
    command indicating the use of the LBound function
    strangely enough, there is an indication of the number of arguments to be popped out of the stack
    but this number is not good.
    example: Lower = LBound(TwoDArray, 2)
    gives: 
         # Ld TwoDArray
         # LitDI2 0x0002
         # FnLBound 0x0001
         # St Lower
    """
    nb_parameters = int(arg,16) + 1
    params = []
    val = '('
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    val = 'LBound' + val
    self.opstack.push(val)
def fnmid(self)
Expand source code Browse git
def fnmid(self):
    val = 'Mid(' + self.opstack.pop() + ')'
    self.opstack.push(val)
def fnmidb(self)
Expand source code Browse git
def fnmidb(self):
    val = 'MidB(' + self.opstack.pop() + ')'
    self.opstack.push(val)
def fnstrcomp(self)

command used when strcomp function with 2 arguments is called example: MyComp = StrComp(MyStr2, MyStr1) gives: # Ld MyStr2 # Ld MyStr1 # FnStrComp # St MyComp

Expand source code Browse git
def fnstrcomp(self):
    """
    command used when strcomp function with 2 arguments is called
    example: MyComp = StrComp(MyStr2, MyStr1)
    gives:
         # Ld MyStr2
         # Ld MyStr1
         # FnStrComp
         # St MyComp
    """
    str2 = self.opstack.pop()
    str1 = self.opstack.pop()
    self.opstack.push('StrComp(' + str1 + ', ' + str2 + ')')
def fnstrcomp3(self)

command used when strcomp function with 3 arguments is called example: MyComp = StrComp(MyStr1, MyStr2, 0) gives: # Ld MyStr1 # Ld MyStr2 # LitDI2 0x0000 # FnStrComp3 # St MyComp

Expand source code Browse git
def fnstrcomp3(self):
    """
    command used when strcomp function with 3 arguments is called
    example: MyComp = StrComp(MyStr1, MyStr2, 0)
    gives:
         # Ld MyStr1
         # Ld MyStr2
         # LitDI2 0x0000
         # FnStrComp3
         # St MyComp
    """
    third_arg = self.opstack.pop()
    str2 = self.opstack.pop()
    str1 = self.opstack.pop()
    self.opstack.push('StrComp(' + str1 + ', ' + str2 + ', ' + third_arg + ')')
def fnstringvar(self, *args)
Expand source code Browse git
def fnstringvar(self, *args):
    raise Pcode2codeException('not implemented fnstringvar')
def fnstringstr(self, *args)
Expand source code Browse git
def fnstringstr(self, *args):
    raise Pcode2codeException('not implemented fnstringstr')
def fnubound(self, arg)

command used when calling Ubound function example: uL = UBound(sb_) gives:
# Ld sb_ # FnUBound 0x0000 # St uL

Expand source code Browse git
def fnubound(self, arg):
    """
    command used when calling Ubound function
    example: uL = UBound(sb_)
    gives:     
         # Ld sb_ 
         # FnUBound 0x0000 
         # St uL
    """
    nb_parameters = int(arg,16) + 1
    params = []
    val = '('
    if nb_parameters > 0:
        for i in range(nb_parameters):
            params.append(self.opstack.pop())
        params = params[::-1]
        val = val + params[0]
        
        if nb_parameters > 1:
            for param in params[1:]:
                val = val + ', ' + param
    val += ')'
    val = 'UBound' + val
    self.opstack.push(val)
def for_(self)
Expand source code Browse git
def for_(self):
    maxvar = self.opstack.pop()
    minvar = self.opstack.pop()
    loopvar = self.opstack.pop()
    val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar
    self.opstack.push(val)
    self.indentincrease_future = True
def foreach(self)

command defining a new for each loop definition example: For Each MyObject In MyClasses gives: # StartForVariable # Ld MyObject # EndForVariable # Ld MyClasses # ForEach

Expand source code Browse git
def foreach(self):
    """
    command defining a new for each loop definition
    example: For Each MyObject In MyClasses
    gives:
         # StartForVariable
         # Ld MyObject
         # EndForVariable
         # Ld MyClasses
         # ForEach
    """
    collect = self.opstack.pop()
    loopvar = self.opstack.pop()
    val = 'For Each ' + loopvar + ' In ' + collect
    self.opstack.push(val)
    self.indentincrease_future = True
def foreachas(self, *args)
Expand source code Browse git
def foreachas(self, *args):
    raise Pcode2codeException('not implemented foreachas')
def forstep(self)
Expand source code Browse git
def forstep(self):
    step = self.opstack.pop()
    maxvar = self.opstack.pop()
    minvar = self.opstack.pop()
    loopvar = self.opstack.pop()
    val = 'For ' + loopvar + ' = ' + minvar + ' To ' + maxvar + ' Step ' + step
    self.opstack.push(val)
    self.indentincrease_future = True
def funcdefn(self, *args)
Expand source code Browse git
def funcdefn(self, *args: str):
    val = args[0]
    for arg in args[1:]:
        val += ' ' + arg
    val = val[1:-1]
    self.opstack.push(val)
    if not val.startswith('Declare'):
        self.indentincrease_future = True
def funcdefnsave(self, *args)
Expand source code Browse git
def funcdefnsave(self, *args):
    raise Pcode2codeException('not implemented funcdefnsave')
def getrec(self)

command to Get from a channel with a record: get channel, record, var example: Get #1, RecordNumber, MyRecord gives: # LitDI2 0x0001 # Sharp # Ld RecordNumber # Ld MyRecord # GetRec

Expand source code Browse git
def getrec(self):
    """
    command to Get from a channel with a record: get channel, record, var
    example: Get #1, RecordNumber, MyRecord
    gives:
         # LitDI2 0x0001
         # Sharp
         # Ld RecordNumber
         # Ld MyRecord
         # GetRec
    """
    record = self.opstack.pop()
    record_num = self.opstack.pop()
    chan = self.opstack.pop()
    if chan is not None:
        self.opstack.push('Get ' + chan + ', ' + record_num + ', ' + record)
    else:
        self.opstack.push('Get ' + record_num + ', , ' + record) # kindly ugly
def gosub(self, var)

command used when gosub is used example: If Num > 0 Then GoSub MyRoutine gives: # Ld Num # LitDI2 0x0000 # Gt # If # BoSImplicit # GoSub MyRoutine # EndIf

Expand source code Browse git
def gosub(self, var):
    """
    command used when gosub is used
    example: If Num > 0 Then GoSub MyRoutine 
    gives:
         # Ld Num
         # LitDI2 0x0000
         # Gt
         # If
         # BoSImplicit
         # GoSub MyRoutine
         # EndIf
    """
    self.opstack.push('GoSub ' + var)
def goto(self, var)

command used when a goto

Expand source code Browse git
def goto(self, var):
    """
    command used when a goto <label> is defined
    example: GoTo label1
    gives: # GoTo label1
    """
    self.opstack.push('GoTo ' + var)
def if_(self, *args)
Expand source code Browse git
def if_(self, *args):
    val = 'If ' + self.opstack.pop() + ' Then'
    self.onelineif = True
    self.opstack.push(val)
def ifblock(self)
Expand source code Browse git
def ifblock(self):
    val = 'If ' + self.opstack.pop() + ' Then'
    self.opstack.push(val)
    self.indentincrease_future = True
def typeof(self, *args)

command used when TypeOf function is used TODO: associated type is obscure for now

Expand source code Browse git
def typeof(self, *args):
    """
    command used when TypeOf function is used
    TODO: associated type is obscure for now
    """
    raise Pcode2codeException('not implemented typeof')
def iftypeblock(self, *args)
Expand source code Browse git
def iftypeblock(self, *args):
    raise Pcode2codeException('not implemented iftypeblock')
def implements(self, *args)

command used when Implements instruction is used TODO: associated type is obscure for now

Expand source code Browse git
def implements(self, *args):
    """
    command used when Implements instruction is used
    TODO: associated type is obscure for now        
    """
    raise Pcode2codeException('not implemented implements')
def input_(self)

command used when Input function is called example : Input #1, MyString, MyNumber gives: # LitDI2 0x0001 # Sharp # Input # Ld MyString # InputItem # Ld MyNumber # InputItem # InputDone

Expand source code Browse git
def input_(self):
    """
    command used when Input function is called
    example : Input #1, MyString, MyNumber
    gives: 
         # LitDI2 0x0001
         # Sharp
         # Input
         # Ld MyString
         # InputItem
         # Ld MyNumber
         # InputItem
         # InputDone        
    """
    self.opstack.push('Input ' + self.opstack.pop())
def inputdone(self)

command used when Input function is called example : Input #1, MyString, MyNumber gives: # LitDI2 0x0001 # Sharp # Input # Ld MyString # InputItem # Ld MyNumber # InputItem # InputDone

Expand source code Browse git
def inputdone(self):
    """
    command used when Input function is called
    example : Input #1, MyString, MyNumber
    gives: 
         # LitDI2 0x0001
         # Sharp
         # Input
         # Ld MyString
         # InputItem
         # Ld MyNumber
         # InputItem
         # InputDone        
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        val += elmt
    self.opstack.push(val)
def inputItem(self)

command used when Input function is called example : Input #1, MyString, MyNumber gives: # LitDI2 0x0001 # Sharp # Input # Ld MyString # InputItem # Ld MyNumber # InputItem # InputDone

Expand source code Browse git
def inputItem(self):
    """
    command used when Input function is called
    example : Input #1, MyString, MyNumber
    gives: 
         # LitDI2 0x0001
         # Sharp
         # Input
         # Ld MyString
         # InputItem
         # Ld MyNumber
         # InputItem
         # InputDone        
    """
    self.opstack.push(', ' + self.opstack.pop())
def label(self, arg)

command defining a new label example: MyString: gives: # Label MyString

Expand source code Browse git
def label(self, arg):
    """
    command defining a new label
    example: MyString:
    gives:
         # Label MyString
    """
    self.opstack.push(arg+':')
def let(self, *args)

command used when let keywork is used example: Let MyStr = "Hello World" gives: # Let # LitStr 0x000B "Hello World" # St MyStr

Expand source code Browse git
def let(self, *args):
    """
    command used when let keywork is used
    example: Let MyStr  = "Hello World"
    gives:
         # Let
         # LitStr 0x000B "Hello World"
         # St MyStr
    """
    self.opstack.push('Let')
    self.has_bos = True #we use this hackish way to print it even if not in stack top
def line(self, *args)
Expand source code Browse git
def line(self, *args):
    raise Pcode2codeException('not implemented line')
def linecont(self, *args)
Expand source code Browse git
def linecont(self, *args):
    #pass on purpose
    pass
def lineInput(self)

command used when Line Input instruction is used (to read one line at a time a file) example: Line Input #1, TextLine gives: # LitDI2 0x0001 # Ld TextLine # LineInput

Expand source code Browse git
def lineInput(self):
    """
    command used when Line Input instruction is used (to read one line at a time a file)
    example: Line Input #1, TextLine
    gives:
         # LitDI2 0x0001
         # Ld TextLine
         # LineInput
    """
    var = self.opstack.pop()
    num_file = self.opstack.pop()
    self.opstack.push('Line Input #' + num_file + ', ' + var)
def linenum(self, *args)
Expand source code Browse git
def linenum(self, *args):
    # ignoring this seems to work fine.
    return
def litcy(self, *args)
Expand source code Browse git
def litcy(self, *args):
    raise Pcode2codeException('not implemented litcy')
def litdate(self, *args)

command to define a date literal TODO: but wtf how to get date? example1: MyDate = #2/12/1969# gives: LitDate 0x0000 0x0000 0xA780 0x40D8 example2: MyDate = #2/12/1970# gives: LitDate 0x0000 0x0000 0x02C0 0x40D9 example3: MyDate = #2/12/1971# gives: LitDate 0x0000 0x0000 0x5E00 0x40D9 example4: MyDate = #2/11/1969# gives: LitDate 0x0000 0x0000 0xA740 0x40D8 example5: MyDate = #2/10/1969# gives: LitDate 0x0000 0x0000 0xA700 0x40D8 example6: MyDate = #3/12/1969# gives: LitDate 0x0000 0x0000 0xAE80 0x40D8 example7: MyDate = #4/12/1969# gives: LitDate 0x0000 0x0000 0xB640 0x40D8

1 year = 23360 (0x5b40) si on fait last2bytes.first2bytes 1 month = 64 (0x40) sur second octet 1 day =

Expand source code Browse git
def litdate(self, *args):
    """
    command to define a date literal
    TODO: but wtf how to get date?
    example1: MyDate = #2/12/1969#
    gives: LitDate 0x0000 0x0000 0xA780 0x40D8
    example2: MyDate = #2/12/1970#
    gives: LitDate 0x0000 0x0000 0x02C0 0x40D9
    example3: MyDate = #2/12/1971#
    gives: LitDate 0x0000 0x0000 0x5E00 0x40D9
    example4: MyDate = #2/11/1969#
    gives: LitDate 0x0000 0x0000 0xA740 0x40D8
    example5: MyDate = #2/10/1969#
    gives: LitDate 0x0000 0x0000 0xA700 0x40D8
    example6: MyDate = #3/12/1969#
    gives: LitDate 0x0000 0x0000 0xAE80 0x40D8
    example7: MyDate = #4/12/1969#
    gives: LitDate 0x0000 0x0000 0xB640 0x40D8


    1 year = 23360 (0x5b40) si on fait last2bytes.first2bytes
    1 month = 64 (0x40) sur second octet
    1 day = 
    """
    raise Pcode2codeException('a date is defined here, but it cannot be reconstructed')
def litdefault(self)

appears to be useless example: Open "TESTFILE" For Output As #1 gives: # LitStr 0x0008 "TESTFILE" # LitDI2 0x0001 # Sharp # LitDefault # Open (For Output) example2: Lock #1, RecordNumber gives: # LitDI2 0x0001 # Sharp # Ld RecordNumber # LitDefault # Lock example3: same for unlock

Expand source code Browse git
def litdefault(self):
    """
    appears to be useless
    example: Open "TESTFILE" For Output As #1 
    gives:
         # LitStr 0x0008 "TESTFILE"
         # LitDI2 0x0001
         # Sharp
         # LitDefault
         # Open (For Output)
    example2: Lock #1, RecordNumber
    gives:
         # LitDI2 0x0001
         # Sharp
         # Ld RecordNumber
         # LitDefault
         # Lock
    example3: same for unlock
    """
    #pass on purpose
    pass
def litdi2(self, value)
Expand source code Browse git
def litdi2(self, value):
    self.opstack.push(str(int(value,16)))
def litdi4(self, byte1, byte2)
Expand source code Browse git
def litdi4(self, byte1, byte2):
    val = int(byte2+byte1[2:], 16)
    self.opstack.push(str(val))
def litdi8(self, *args)
Expand source code Browse git
def litdi8(self, *args):
    raise Pcode2codeException('not implemented litdi8')
def lithi2(self, byte)
Expand source code Browse git
def lithi2(self, byte):
    val = byte[2:]
    while val.startswith('0') and len(val) > 1:
        val = val[1:]
    val = '&H' + val
    self.opstack.push(val)
def lithi4(self, byte1, byte2)
Expand source code Browse git
def lithi4(self, byte1, byte2):
    val = byte2[2:]+byte1[2:]
    while val.startswith('0') and len(val) > 1:
        val = val[1:]
    val = '&H' + val
    self.opstack.push(val)
def lithi8(self, *args)
Expand source code Browse git
def lithi8(self, *args):
    raise Pcode2codeException('not implemented lithi8')
def litnothing(self)

command defining the "Nothing" variable example: Set Inst = Nothing gives: # SetStmt # LitNothing # Set Inst

Expand source code Browse git
def litnothing(self):
    """
    command defining the "Nothing" variable
    example: Set Inst = Nothing
    gives:
         # SetStmt
         # LitNothing
         # Set Inst
    """
    self.opstack.push('Nothing')
def litoi2(self, value)

command used when an octal is defined on a two bytes byte array example: B = &O1 gives: # LitOI2 0x0001 # St B

Expand source code Browse git
def litoi2(self, value):
    """
    command used when an octal is defined on a two bytes byte array
    example: B = &O1
    gives:
         # LitOI2 0x0001
         # St B
    """
    var = int(value,16)
    var2 = str(oct(var))[2:]
    self.opstack.push('&O' + var2)
def litoi4(self, byte1, byte2)

command used when an octal is defined on a two bytes byte array example: B = &O12345644444 gives: # LitOI4 0x4924 0x5397 # St B

Expand source code Browse git
def litoi4(self, byte1, byte2):
    """
    command used when an octal is defined on a two bytes byte array
    example: B = &O12345644444
    gives:
         # LitOI4 0x4924 0x5397
         # St B
    """        
    val = byte2[2:]+byte1[2:]
    var = int(val,16)
    var2 = str(oct(var))[2:]
    self.opstack.push('&O' + var2)
def litoi8(self, *args)
Expand source code Browse git
def litoi8(self, *args):
    raise Pcode2codeException('not implemented litoi8')
def litr4(self, byte1, byte2)

command used when a floating point on 32 bit is declared

Expand source code Browse git
def litr4(self, byte1, byte2):
    """
    command used when a floating point on 32 bit is declared
    """
    val = byte2[2:]+byte1[2:]
    self.opstack.push(str(struct.unpack("!f", bytes.fromhex(val))[0]))
def litr8(self, byte1, byte2, byte3, byte4)

command used when a floating point on 64 bit is declared

Expand source code Browse git
def litr8(self, byte1, byte2, byte3, byte4):
    """
    command used when a floating point on 64 bit is declared
    """
    val = byte4[2:]+byte3[2:]+byte2[2:]+byte1[2:]
    self.opstack.push(str(struct.unpack("!d", bytes.fromhex(val))[0]))
def litsmalli2(self, *args)
Expand source code Browse git
def litsmalli2(self, *args):
    raise Pcode2codeException('not implemented malli2')
def litstr(self, mylen, *args)
Expand source code Browse git
def litstr(self, mylen, *args):
    val = args[0]
    for arg in args[1:]:
        val += ' ' + arg
    if len(val)>=2:
        #assert(val[0]=='"' and val[-1]=='"')
        val = val[1:-1]
        val = val.replace('"', '""')
        val = '"' + val + '"'

    self.opstack.push(val)
def litvarspecial(self, var)
Expand source code Browse git
def litvarspecial(self, var):
    self.opstack.push(var[1:-1])
def lock(self)

command to lock a record example: Lock #1, RecordNumber gives: # LitDI2 0x0001 # Sharp # Ld RecordNumber # LitDefault # Lock

Expand source code Browse git
def lock(self):
    """
    command to lock a record
    example: Lock #1, RecordNumber
    gives:
         # LitDI2 0x0001
         # Sharp
         # Ld RecordNumber
         # LitDefault
         # Lock
    """
    if self.opstack.size() == 3:
        last_record = self.opstack.pop()
        first_record = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push('Lock ' + chan + ', ' + first_record + ' To ' + last_record)
    elif self.opstack.size() == 2:
        record = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push('Lock ' + chan + ', ' + record)
    elif self.opstack.size() == 1:
        chan = self.opstack.pop()
        self.opstack.push('Lock ' + chan)
def loop(self)
Expand source code Browse git
def loop(self):
    self.opstack.push('Loop')
    self.indentlevel = self.indentlevel - 1
def loopuntil(self)

command defining a loop until statement for "do" example: Loop Until TheName = "" gives: # Ld TheName # LitStr 0x0000 "" # Eq # LoopUntil

Expand source code Browse git
def loopuntil(self):
    """
    command defining a loop until statement for "do"
    example: Loop Until TheName = ""
    gives:
         # Ld TheName
         # LitStr 0x0000 ""
         # Eq
         # LoopUntil
    """
    self.opstack.push('Loop Until ' + self.opstack.pop())
    self.indentlevel = self.indentlevel - 1
def loopwhile(self)

command handling " while" definitions example: Loop While Reponse = 5 gives: # Ld Response # LitDI2 0x0005 # Eq # LoopWhile

Expand source code Browse git
def loopwhile(self):
    """
    command handling " while" definitions
    example: Loop While Reponse = 5
    gives:
         # Ld Response
         # LitDI2  0x0005
         # Eq
         # LoopWhile
    """
    self.opstack.push('Loop While ' + self.opstack.pop())
    self.indentlevel = self.indentlevel - 1
def lset(self)

command for RSet keyword example: LSet MyString = "Right->" gives: # LitStr 0x0007 "Right->" # Ld MyString # RSet

Expand source code Browse git
def lset(self):
    """
    command for RSet keyword
    example: LSet MyString = "Right->"
    gives:
         # LitStr 0x0007 "Right->"
         # Ld MyString
         # RSet
    """
    var = self.opstack.pop()
    val = self.opstack.pop()
    self.opstack.push('LSet ' + var + ' = ' + val)
def me(self, *args)
Expand source code Browse git
def me(self, *args):
    raise Pcode2codeException('not implemented me')
def meimplicit(self, *args)

command used when the object is the current form example: Print gives: # MeImplicit # PrintObj # PrintNL

Expand source code Browse git
def meimplicit(self, *args):
    """
    command used when the object is the current form
    example: Print 
    gives:
         # MeImplicit
         # PrintObj
         # PrintNL
    """
    self.opstack.push('MeImplicit') #just pushing a specific marker to change treatment later
def memredim(self, *args)

command used when a property of an object is redim example: ReDim myobj.foo(30) gives: # OptionBase # LitDI2 0x001E # Ld myobj # MemRedim foo 0x0001 (As Variant)

Expand source code Browse git
def memredim(self, *args):
    """
    command used when a property of an object is redim
    example: ReDim myobj.foo(30)
    gives:
         # OptionBase
         # LitDI2 0x001E
         # Ld myobj
         # MemRedim foo 0x0001 (As Variant)
    """
    val = self.opstack.pop()
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + val + '.' + args[0] + '('
    else:
        val2 = 'ReDim '
        if preserve:
            val2 += 'Preserve '
        val2 += val + '.' + args[0] + '('
        val = val2

    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'
    self.opstack.push(val)
def memredimwith(self, *args)

command used when a property of an object is redim within a with example: with myobj … ReDim .foo(30) .. end with gives: # OptionBase # LitDI2 0x001E # MemRedimWith foo 0x0001 (As Variant)

Expand source code Browse git
def memredimwith(self, *args):
    """
    command used when a property of an object is redim within a with
    example: with myobj ... ReDim .foo(30) .. end with
    gives:
         # OptionBase
         # LitDI2 0x001E
         # MemRedimWith foo 0x0001 (As Variant)
    """
    val = ''
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + '.' + args[0] + '('
    else:
        val += 'ReDim '
        if preserve:
            val += 'Preserve '
        val += '.' + args[0] + '('

    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'
    self.opstack.push(val)
def memredimas(self, *args)

command used when a redim is defined on a property of an object with a As in the end example: ReDim myobj.mytab(50) As Double gives: # OptionBase # LitDI2 0x003C # Ld myobj # MemRedimAs Tab 0x0001 (As Double)

Expand source code Browse git
def memredimas(self, *args):
    """
    command used when a redim is defined on a property of an object with a As in the end
    example: ReDim myobj.mytab(50) As Double
    gives:
         # OptionBase
         # LitDI2 0x003C
         # Ld myobj
         # MemRedimAs Tab 0x0001 (As Double)
    """
    val = self.opstack.pop()
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + val + '.' + args[0] + '('
    else:
        val2 = 'ReDim '
        if preserve:
            val2 += 'Preserve '
        val2 += val + '.' + args[0] + '('
        val = val2
        
    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'

    args.pop(0) #remove var
    args.pop(0) # remove nb_params
    if len(args)> 0: # do we have smthng like "(As <type>)"
        if args[-1] != 'Variant)':
            val += ' ' + args[0][1:] + ' ' + args[1][:-1]
    self.opstack.push(val)
def memredimaswith(self, *args)

command used when a redim is defined on a property of an object with a As in the end, within a with block example: With myobj … ReDim .mytab(70) As Integer … End With gives: # OptionBase # LitDI2 0x0046 # MemRedimAsWith Tab 0x0001 (As Integer)

Expand source code Browse git
def memredimaswith(self, *args):
    """
    command used when a redim is defined on a property of an object with a As in the end, within a with block
    example: With myobj ... ReDim .mytab(70) As Integer ... End With 
    gives:
         # OptionBase
         # LitDI2 0x0046
         # MemRedimAsWith Tab 0x0001 (As Integer)
    """
    val = ''
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + '.' + args[0] + '('
    else:
        val += 'ReDim '
        if preserve:
            val += 'Preserve '
        val += '.' + args[0] + '('
        
    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'

    args.pop(0) #remove var
    args.pop(0) # remove nb_params
    if len(args)> 0: # do we have smthng like "(As <type>)"
        if args[-1] != 'Variant)':
            val += ' ' + args[0][1:] + ' ' + args[1][:-1]
    self.opstack.push(val)
def mid(self)

command used when Mid funtion is used to set a sub string part, e.g. as an instruction example: Mid(MyString, 5, 3) = "fox" gives: # LitStr 0x0003 "fox" # Ld MyString # LitDI2 0x0005 # LitDI2 0x0003 # Mid

Expand source code Browse git
def mid(self):
    """
    command used when Mid funtion is used to set a sub string part, e.g. as an instruction
    example: Mid(MyString, 5, 3) = "fox"
    gives:
         # LitStr 0x0003 "fox"
         # Ld MyString
         # LitDI2 0x0005
         # LitDI2 0x0003
         # Mid
    """
    if self.opstack.size() > 3:
        length = self.opstack.pop()
        start = self.opstack.pop()
        obj = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('Mid(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
    else:
        start = self.opstack.pop()
        obj = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('Mid(' + obj + ', ' + start + ') = ' + str1)            
def midb(self)

command used when Mid funtion is used to set a sub string part, e.g as an instruction example: MidB(MyString, 5, 3) = "fox" gives: # LitStr 0x0003 "fox" # Ld MyString # LitDI2 0x0005 # LitDI2 0x0003 # MidB

Expand source code Browse git
def midb(self):
    """
    command used when Mid funtion is used to set a sub string part, e.g as an instruction
    example: MidB(MyString, 5, 3) = "fox"
    gives:
         # LitStr 0x0003 "fox"
         # Ld MyString
         # LitDI2 0x0005
         # LitDI2 0x0003
         # MidB
    """
    if self.opstack.size() > 3:
        length = self.opstack.pop()
        start = self.opstack.pop()
        obj = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('MidB(' + obj + ', ' + start + ', ' + length + ') = ' + str1)
    else:
        start = self.opstack.pop()
        obj = self.opstack.pop()
        str1 = self.opstack.pop()
        self.opstack.push('MidB(' + obj + ', ' + start + ') = ' + str1)            
def name(self)

command for the name keyword, permitting to rename variables example: Name OldName As NewName gives: # Ld OldName # Ld NewName # Name

Expand source code Browse git
def name(self):
    """
    command for the name keyword, permitting to rename variables
    example: Name OldName As NewName
    gives:
         # Ld OldName
         # Ld NewName
         # Name
    """
    newname = self.opstack.pop()
    oldname = self.opstack.pop()
    self.opstack.push('Name ' + oldname + ' As ' + newname) 
def new(self, var)
Expand source code Browse git
def new(self, var):
    self.opstack.push('New ' + var)
def next_(self)
Expand source code Browse git
def next_(self):
    self.opstack.push('Next')
    self.indentlevel = self.indentlevel - 1
    self.indentincrease_future = False
def nextvar(self)
Expand source code Browse git
def nextvar(self):
    self.opstack.push('Next ' + self.opstack.pop())
    self.indentlevel = self.indentlevel - 1
def onerror(self, *args)

command defining "on error" statements example1: On Error GoTo ErrorHandler gives: # OnError ErrorHandler example2: On Error GoTo 0 gives: # OnError (GoTo 0) example3: On Error Resume Next gives: # OnError (Resume Next)

Expand source code Browse git
def onerror(self, *args):
    """
    command defining "on error" statements
    example1: On Error GoTo ErrorHandler
    gives:
         # OnError ErrorHandler
    example2: On Error GoTo 0
    gives: 
         # OnError (GoTo 0)
    example3: On Error Resume Next
    gives: 
         # OnError (Resume Next)
    """
    if args[0] == '(Resume':
        self.opstack.push('On Error Resume Next')
    elif args[0] == '(GoTo':
        self.opstack.push('On Error GoTo 0')
    else:
        #TODO: to check
        self.opstack.push('On Error GoTo ' + args[0])
def ongosub(self, nb, *args)

command used for gosub on a variable example: On Number GoSub Sub1, Sub2 gives: # Ld Number # OnGoSub 0x0004 Sub1, Sub2

Expand source code Browse git
def ongosub(self, nb, *args):
    """
    command used for gosub on a variable
    example: On Number GoSub Sub1, Sub2
    gives:
         # Ld Number
         # OnGoSub 0x0004 Sub1, Sub2
    """
    val = 'On ' + self.opstack.pop() + ' GoSub '
    val2 = args[0]
    for arg in args[1:]:
        val2 += ' ' + arg
    self.opstack.push(val + val2)
def ongoto(self, nb, *args)

command used for goto on a variable example: On Number GoTo Line1, Line2 gives: # Ld Number # OnGoto 0x0004 Line1, Line2

Expand source code Browse git
def ongoto(self, nb, *args):
    """
    command used for goto on a variable
    example: On Number GoTo Line1, Line2
    gives:
         # Ld Number
         # OnGoto 0x0004 Line1, Line2
    """
    val = 'On ' + self.opstack.pop() + ' GoTo '
    val2 = args[0]
    for arg in args[1:]:
        val2 += ' ' + arg
    self.opstack.push(val + val2)
def open_(self, *args)

command used for Open function example: Open "TESTFILE" For Output As #1 gives: # LitStr 0x0008 "TESTFILE" # LitDI2 0x0001 # Sharp # LitDefault # Open (For Output) example2: Open "TESTFILE" For Binary Access Write Lock Write As #1 gives: # LitStr 0x0008 "TESTFILE" # LitDI2 0x0001 # Sharp # LitDefault # Open (For Binary Access Write Lock Write)

Expand source code Browse git
def open_(self, *args):
    """
    command used for Open function
    example: Open "TESTFILE" For Output As #1
    gives:
         # LitStr 0x0008 "TESTFILE"
         # LitDI2 0x0001
         # Sharp
         # LitDefault
         # Open (For Output)
    example2: Open "TESTFILE" For Binary Access Write Lock Write As #1
    gives:
         # LitStr 0x0008 "TESTFILE"
         # LitDI2 0x0001
         # Sharp
         # LitDefault
         # Open (For Binary Access Write Lock Write)
    """
    chan = self.opstack.pop()
    val = args[0][1:] # avoid parenthesis
    for arg in args[1:]:
        val += ' ' + arg
    val = val[:-1] #avoid parenthesis
    self.opstack.push('Open ' + self.opstack.pop() + ' ' + val + ' As ' + chan)
def option(self, *args)

command for option keyword example: Option Explicit gives : # Option (Explicit) example2: Option Compare Binary gives : # Option (Compare Binary)

Expand source code Browse git
def option(self, *args):
    """
    command for option keyword
    example: Option Explicit
    gives : 
       # Option (Explicit)
    example2: Option Compare Binary
    gives :
       # Option (Compare Binary)
    """
    val = args[0][1:]
    if len(args)>1:
        for arg in args[1:]: #strip parenthesis
            val += ' ' + arg
    self.opstack.push('Option ' + val[:-1])
def optionbase(self)

used in the following case: when a table dimension is not declared from base to end, but only size; to treat it, we will push a magic value on stack like for dim and dimimplicit, and vardef will treat it directly example1: Dim MyArray(20) gives: # Dim # OptionBase # LitDI2 0x0014 # VarDefn MyArray

Expand source code Browse git
def optionbase(self):
    """
    used in the following case: when a table dimension is not declared from base to end, but only size;
    to treat it, we will push a magic value on stack like for dim and dimimplicit, and vardef will treat it directly
    example1: Dim MyArray(20)
    gives: 
         # Dim
         # OptionBase
         # LitDI2 0x0014
         # VarDefn MyArray
    """
    self.opstack.push('OptionBase')
def parambyval(self)

command used when Byval keyword is used example: a ByVal b gives: # Ld B # ParamByVal # ArgsCall a 0x0001

Expand source code Browse git
def parambyval(self):
    """
    command used when Byval keyword is used
    example: a ByVal b
    gives:
         # Ld B
         # ParamByVal
         # ArgsCall a 0x0001
    """
    self.opstack.push('ByVal ' + self.opstack.pop())
def paramomitted(self)

command used when a parameter is left blank in a function call example: MsgBox Msg, , "Deferred Error Test" gives: # Ld Msg # ParamOmitted # LitStr 0x0013 "Deferred Error Test" # ArgsCall MsgBox 0x0003

Expand source code Browse git
def paramomitted(self):
    """
    command used when a parameter is left blank in a function call
    example: MsgBox Msg, , "Deferred Error Test"
    gives:
         # Ld Msg
         # ParamOmitted
         # LitStr 0x0013 "Deferred Error Test"
         # ArgsCall MsgBox 0x0003
    """
    self.opstack.push('')
def paramnamed(self, var)

command used when a call is made with named parameters example: MyClasses.Add Item:=Inst, Key:=CStr(Num) gives: # Ld Inst # ParamNamed Item # Ld Num # Coerce (Str) # ParamNamed Key # Ld MyClasses # ArgsMemCall Add 0x0002

Expand source code Browse git
def paramnamed(self, var):
    """
    command used when a call is made with named parameters
    example: MyClasses.Add Item:=Inst, Key:=CStr(Num)
    gives:
         # Ld Inst
         # ParamNamed Item
         # Ld Num
         # Coerce (Str)
         # ParamNamed Key
         # Ld MyClasses
         # ArgsMemCall Add 0x0002
    """
    self.opstack.push(var + ':=' + self.opstack.pop())
def printchan(self)

command defining "print" to a channel example: Print #1, MyBool; " is a Boolean value" gives: # LitDI2 0x0001 # Sharp # PrintChan # Ld MyBool # PrintItemSemi # LitStr 0x0013 " is a Boolean value" # PrintItemNL

Expand source code Browse git
def printchan(self):
    """
    command defining "print" to a channel
    example: Print #1, MyBool; " is a Boolean value"
    gives:
         # LitDI2 0x0001
         # Sharp
         # PrintChan
         # Ld MyBool
         # PrintItemSemi
         # LitStr 0x0013 " is a Boolean value"
         # PrintItemNL
    """
    self.opstack.push('Print ' +self.opstack.pop() + ',')
def printcomma(self, *args)

command used when a colon is used in Print example: Debug.Print Spc(30), "Thirty spaces later… gives: # Debug # PrintObj # LitDI2 0x001E # PrintSpc # PrintComma # LitStr 0x0016 "Thirty spaces later…" # PrintItemNL

Expand source code Browse git
def printcomma(self, *args):
    """
    command used when a colon is used in Print
    example: Debug.Print Spc(30), "Thirty spaces later...
    gives:
         # Debug
         # PrintObj
         # LitDI2 0x001E
         # PrintSpc
         # PrintComma
         # LitStr 0x0016 "Thirty spaces later..."
         # PrintItemNL
    """
    self.opstack.push(',')
def printeos(self)

used at the end of some print when there is nothing, instead of printitemnl

Expand source code Browse git
def printeos(self):
    """
    used at the end of some print when there is nothing, instead of printitemnl
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
            val+= elmt
        else:
            val += ' ' + elmt
    self.opstack.push(val)
def printitemcomma(self)

command defining ",", used for example when writing example: Write #1, "Hello World", 234 gives: # LitDI2 0x0001 # Sharp # WriteChan # LitStr 0x000B "Hello World" # PrintItemComma # LitDI2 0x00EA # PrintItemNL # QuoteRem 0x0020 0x001C " Write comma-delimited data."

Expand source code Browse git
def printitemcomma(self):
    """
    command defining ",", used for example when writing 
    example: Write #1, "Hello World", 234
    gives:
         # LitDI2 0x0001
         # Sharp
         # WriteChan
         # LitStr 0x000B "Hello World"
         # PrintItemComma
         # LitDI2 0x00EA
         # PrintItemNL
         # QuoteRem 0x0020 0x001C " Write comma-delimited data."
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        val += ' ' + elmt
    self.opstack.push(val + ',')
def printitemnl(self)

TODO: not sure what's it is used for example1: Write #1, MyBool; " is a Boolean value" gives: # LitDI2 0x0001 # Sharp # WriteChan # Ld MyBool # PrintItemSemi # LitStr 0x0013 " is a Boolean value" # PrintItemNL example2: Debug.Print i gives: # Debug # PrintObj # Ld i # PrintItemNL

Expand source code Browse git
def printitemnl(self):
    """
    TODO: not sure what's it is used for
    example1: Write #1, MyBool; " is a Boolean value"
    gives:
         # LitDI2 0x0001
         # Sharp
         # WriteChan
         # Ld MyBool
         # PrintItemSemi
         # LitStr 0x0013 " is a Boolean value"
         # PrintItemNL
    example2:  Debug.Print i
    gives:
         # Debug
         # PrintObj
         # Ld i
         # PrintItemNL
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        if ((elmt == ';') or (elmt == ',')) and (elmts.index(elmt) != 1):
            val+= elmt
        else:
            val += ' ' + elmt
    self.opstack.push(val)
def printitemsemi(self)

command defining ";", used for example when writing example: Write #1, MyBool; " is a Boolean value" gives: # LitDI2 0x0001 # Sharp # WriteChan # Ld MyBool # PrintItemSemi # LitStr 0x0013 " is a Boolean value" # PrintItemNL

Expand source code Browse git
def printitemsemi(self):
    """
    command defining ";", used for example when writing 
    example: Write #1, MyBool; " is a Boolean value"
    gives:
         # LitDI2 0x0001
         # Sharp
         # WriteChan
         # Ld MyBool
         # PrintItemSemi
         # LitStr 0x0013 " is a Boolean value"
         # PrintItemNL
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        val += ' ' + elmt
    self.opstack.push(val + ';')
def printnl(self)

really not sure about this one example: Write #1,
gives: # LitDI2 0x0001 # Sharp # WriteChan # PrintNL

Expand source code Browse git
def printnl(self):
    """
    really not sure about this one
    example: Write #1,     
    gives:
         # LitDI2 0x0001
         # Sharp
         # WriteChan
         # PrintNL
    """
    elmts = []
    while self.opstack.size() >= 1:
        elmts.append(self.opstack.pop())
    elmts = elmts[::-1]
    val = elmts[0]
    for elmt in elmts[1:]:
        val += ' ' + elmt
    self.opstack.push(val)
def printobj(self)

appears to call the print method of an object example: Debug.Print i gives: # Debug # PrintObj # Ld i # PrintItemNL

Expand source code Browse git
def printobj(self):
    """
    appears to call the print method of an object
    example:  Debug.Print i
    gives:
         # Debug
         # PrintObj
         # Ld i
         # PrintItemNL
    """
    if self.opstack.top() == 'MeImplicit':
        self.opstack.pop()
        self.opstack.push('Print')
    else:
        self.opstack.push(self.opstack.pop() + '.Print')
def printsemi(self, *args)

command used when a semicolon is used in Print example: Debug.Print Spc(30); "Thirty spaces later… gives: # Debug # PrintObj # LitDI2 0x001E # PrintSpc # PrintSemi # LitStr 0x0016 "Thirty spaces later…" # PrintItemNL

Expand source code Browse git
def printsemi(self, *args):
    """
    command used when a semicolon is used in Print
    example: Debug.Print Spc(30); "Thirty spaces later...
    gives:
         # Debug
         # PrintObj
         # LitDI2 0x001E
         # PrintSpc
         # PrintSemi
         # LitStr 0x0016 "Thirty spaces later..."
         # PrintItemNL
    """
    self.opstack.push(';')
def printspc(self)

command used when SPC(n) is used in Print example: Debug.Print Spc(30); "Thirty spaces later… gives: # Debug # PrintObj # LitDI2 0x001E # PrintSpc # PrintSemi # LitStr 0x0016 "Thirty spaces later…" # PrintItemNL

Expand source code Browse git
def printspc(self):
    """
    command used when SPC(n) is used in Print
    example: Debug.Print Spc(30); "Thirty spaces later...
    gives:
         # Debug
         # PrintObj
         # LitDI2 0x001E
         # PrintSpc
         # PrintSemi
         # LitStr 0x0016 "Thirty spaces later..."
         # PrintItemNL
    """
    self.opstack.push('Spc(' + self.opstack.pop() + ')')
def printtab(self, *args)

command used when Tab(n) is used in Print example: Debug.Print Tab(30); "Thirty spaces later… gives: # Debug # PrintObj # LitDI2 0x001E # PrintTab # PrintSemi # LitStr 0x0016 "Thirty spaces later…" # PrintItemNL

Expand source code Browse git
def printtab(self, *args):
    """
    command used when Tab(n) is used in Print
    example: Debug.Print Tab(30); "Thirty spaces later...
    gives:
         # Debug
         # PrintObj
         # LitDI2 0x001E
         # PrintTab
         # PrintSemi
         # LitStr 0x0016 "Thirty spaces later..."
         # PrintItemNL
    """
    self.opstack.push('Tab(' + self.opstack.pop() + ')')
def printtabcomma(self)

command used when Tab with no arg is used in Print example: Debug.Print Tab, "Thirty spaces later… gives: # Debug # PrintObj # PrintTabComma # PrintComma # LitStr 0x0016 "Thirty spaces later…" # PrintItemNL

Expand source code Browse git
def printtabcomma(self):
    """
    command used when Tab with no arg is used in Print
    example: Debug.Print Tab, "Thirty spaces later...
    gives:
         # Debug
         # PrintObj
         # PrintTabComma
         # PrintComma
         # LitStr 0x0016 "Thirty spaces later..."
         # PrintItemNL
    """
    self.opstack.push('Tab')
def pset(self, numparams)

command used when the pset method of an object is called example: Me.PSet (intI, sngMidPt) gives: # Ld intI # Ld sngMidPt # LitDI2 0x0000 # Ld id_FFFF # PSet 0x0002

Expand source code Browse git
def pset(self, numparams):
    """
    command used when the pset method of an object is called
    example: Me.PSet (intI, sngMidPt)
    gives:
         # Ld intI
         # Ld sngMidPt
         # LitDI2 0x0000
         # Ld id_FFFF
         # PSet 0x0002
    """
    val = self.opstack.pop() + '.PSet('
    first_arg = self.opstack.pop()
    if first_arg != '0':
        val += first_arg + ', '
        
    nb_args = int(numparams, 16)
    params = []
    if nb_args > 0:
        for i in range(nb_args):
            params.append(self.opstack.pop())
        params = params[::-1]

        val += params[0]
        for param in params[1:]:
            val = val + ', ' + param
    val +=')'
    self.opstack.push(val)
def putrec(self)

command to Put to a channel with a record: Put channel, record, var example: Put #1, RecordNumber, MyRecord gives: # LitDI2 0x0001 # Sharp # Ld RecordNumber # Ld MyRecord # PutRec

Expand source code Browse git
def putrec(self):
    """
    command to Put to a channel with a record: Put channel, record, var
    example: Put #1, RecordNumber, MyRecord
    gives:
         # LitDI2 0x0001
         # Sharp
         # Ld RecordNumber
         # Ld MyRecord
         # PutRec
    """
    record = self.opstack.pop()
    record_num = self.opstack.pop()
    chan = self.opstack.pop()
    self.opstack.push(F'Put {chan}, {record_num}, {record}')
def quoterem(self, val1, lenvar, *args)

command handling comments definition with ' multiple cases: example : MsgBox "toto" 'a message to send gives: # LitStr 0x0004 "toto" # ArgsCall MsgBox 0x0001 # QuoteRem 0x000F 0x11

example : TODO macaroni gives: TODO macaroni

Expand source code Browse git
def quoterem(self, val1, lenvar, *args):
    """
    command handling comments definition with '
    multiple cases:
    example : MsgBox "toto" 'a message to send
    gives:
         # LitStr 0x0004 "toto"
         # ArgsCall MsgBox 0x0001
         # QuoteRem 0x000F 0x11

    example : TODO macaroni
    gives: TODO macaroni
    """
    val = "'" + args[0][1:]
    for arg in args[1:] :
        val += ' ' + arg
    val = val[:-1]
    if self.opstack.size() != 0:
        val = self.opstack.pop() + ' ' + val
    self.opstack.push(val)
def redim(self, *args)

command used when redim function is used example : ReDim temp(4) gives: # OptionBase # LitDI2 0x0004 # Redim temp 0x0001 (As Variant)

Expand source code Browse git
def redim(self, *args):
    """
    command used when redim function is used
    example : ReDim temp(4)
    gives:
         # OptionBase
         # LitDI2 0x0004
         # Redim temp 0x0001 (As Variant)
    """
    val = ''
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + args[0] + '('
    else:
        val += 'ReDim '
        if preserve:
            val += 'Preserve '
        val += args[0] + '('
        
    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'
    self.opstack.push(val)
def redimas(self, *args)

command used when a redim is defined with a As in the end example: ReDim mytab(50) As Double gives: # OptionBase # LitDI2 0x0032 # RedimAs mytab 0x0001 (As Double)

Expand source code Browse git
def redimas(self, *args):
    """
    command used when a redim is defined with a As in the end
    example: ReDim mytab(50) As Double
    gives:
         # OptionBase
         # LitDI2 0x0032
         # RedimAs mytab 0x0001 (As Double)
    """
    val = ''
    args = list(args)
    preserve = False
    if args[0] == '(Preserve)':
        args.pop(0)
        preserve = True

    nb_params = int(args[1], 16)

    values = []
    # gather all stack
    while self.opstack.size() > 0:
        values.append(self.opstack.pop())
    values = values[::-1]

    if values[0].startswith('ReDim'): # in case redim of multiple variables
        val = values.pop(0) + ', ' + args[0] + '('
    else:
        val += 'ReDim '
        if preserve:
            val += 'Preserve '
        val += args[0] + '('
        
    curr_val1 = values.pop(0)
    curr_val2 = values.pop(0)
    if curr_val1 == 'OptionBase':
        val += curr_val2 
    else:
        val += curr_val1 + ' To ' + curr_val2 

    while len(values) > 0:
        val += ', '
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

    val += ')'

    args.pop(0) #remove var
    args.pop(0) # remove nb_params
    if len(args)> 0: # do we have smthng like "(As <type>)"
        if args[-1] != 'Variant)':
            val += ' ' + args[0][1:] + ' ' + args[1][:-1]
    self.opstack.push(val)
def reparse(self, *args)

opcode used when a non valid statement is employed

Expand source code Browse git
def reparse(self, *args):
    """
    opcode used when a non valid statement is employed
    """
    val = args[1][1:]
    for arg in args[2:]:
        val += ' ' + arg
    val = val[:-1] # avoid double quotes
    self.opstack.push(val)
def rem(self, *args)

command for Rem keyword example: Rem This entire line is a comment gives: # Rem 0x001F " This entire line is a comment."

Expand source code Browse git
def rem(self, *args):
    """
    command for Rem keyword
    example: Rem This entire line is a comment
    gives:  # Rem 0x001F " This entire line is a comment."
    """
    val = args[2] # avoid space+double quote
    for arg in args[3:]:
        val += ' ' + arg
    val = val[:-1] #avoid double quote
    self.opstack.push('Rem ' + val)
def resume(self, *args)

command used when resume keyword is used example1: Resume gives: # Resume example2: Resume Next gives: # Resume (Next) example3: Resume titi gives: # Resume titi

Expand source code Browse git
def resume(self, *args):
    """
    command used when resume keyword is used 
    example1: Resume
    gives: # Resume
    example2: Resume Next
    gives: # Resume (Next)
    example3: Resume titi
    gives: # Resume titi
    """
    if args == ():
        self.opstack.push('Resume')
    else:
        if args[0] == '(Next)':
            self.opstack.push('Resume Next')
        else:
            self.opstack.push('Resume ' + args[0])
def return_(self)
Expand source code Browse git
def return_(self):
    #TODO: comment
    self.opstack.push('Return')
def rset(self)

command for RSet keyword example: RSet MyString = "Right->" gives: # LitStr 0x0007 "Right->" # Ld MyString # RSet

Expand source code Browse git
def rset(self):
    """
    command for RSet keyword
    example: RSet MyString = "Right->"
    gives:
         # LitStr 0x0007 "Right->"
         # Ld MyString
         # RSet
    """
    var = self.opstack.pop()
    val = self.opstack.pop()
    self.opstack.push('RSet ' + var + ' = ' + val)
def scale(self, *args)

command used when an object scale method is used example: Me.Scale gives: # LitDI2 0x0000 # LitDI2 0x0000 # Ld sngNewH # Ld sngNewV # Ld id_FFFF # Scale 0x0000 TODO: what to do with this command?

Expand source code Browse git
def scale(self, *args):
    """
    command used when an object scale method is used
    example: Me.Scale 
    gives:
         # LitDI2 0x0000
         # LitDI2 0x0000
         # Ld sngNewH
         # Ld sngNewV
         # Ld id_FFFF
         # Scale 0x0000
    TODO: what to do with this command?
    """
    raise Pcode2codeException('not implemented scale')
def seek(self)

opcode used when seek is used to search in a file example: Seek #1, 2 gives: # LitDI2 0x0001 # Sharp # LitDI2 0x0002 # Seek

Expand source code Browse git
def seek(self):
    """
    opcode used when seek is used to search in a file
    example: Seek #1, 2
    gives:
         # LitDI2 0x0001
         # Sharp
         # LitDI2 0x0002
         # Seek
    """
    data = self.opstack.pop()
    self.opstack.push('Seek ' + self.opstack.pop() + ', ' + data)
def selectcase(self)

command handling a "select case" definition against a variable example : Select Case x gives: # Ld x # SelectCase

Expand source code Browse git
def selectcase(self):
    """
    command handling a "select case" definition against a variable
    example : Select Case x
    gives:
         # Ld x
         # SelectCase
    """
    self.opstack.push('Select Case ' + self.opstack.pop())
    self.indentincrease_future = True
def selectis(self, *args)
Expand source code Browse git
def selectis(self, *args):
    raise Pcode2codeException('not implemented selectis')
def selecttype(self, *args)
Expand source code Browse git
def selecttype(self, *args):
    raise Pcode2codeException('not implemented selecttype')
def setstmt(self)
Expand source code Browse git
def setstmt(self):
    # TODO: comment
    #pass on purpose
    pass
def stack(self, *args)
Expand source code Browse git
def stack(self, *args):
    raise Pcode2codeException('not implemented stack')
def stop(self)
Expand source code Browse git
def stop(self):
    #TODO: comment
    self.opstack.push('Stop')
def type_(self, *args)

command for Type keyword, #TODO: beware because it's also used for enum keyword example: Type EmployeeRecord gives : # Type EmployeeRecord

Expand source code Browse git
def type_(self, *args):
    """
    command for Type keyword, #TODO: beware because it's also used for enum keyword
    example: Type EmployeeRecord
    gives : 
       # Type EmployeeRecord
    """
    if args[0] == '(Private)':
        self.opstack.push('Private Type ' + args[1])
    elif args[0] == '(Public)':
        self.opstack.push('Public Type ' + args[1])
    else:
        self.opstack.push('Type ' + args[0])
    self.indentincrease_future = True
def unlock(self)

command to unlock a record example: Unlock #1, RecordNumber gives: # LitDI2 0x0001 # Sharp # Ld RecordNumber # LitDefault # Unlock

Expand source code Browse git
def unlock(self):
    """
    command to unlock a record
    example: Unlock #1, RecordNumber
    gives:
         # LitDI2 0x0001
         # Sharp
         # Ld RecordNumber
         # LitDefault
         # Unlock
    """
    if self.opstack.size() == 3:
        last_record = self.opstack.pop()
        first_record = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push('Unlock ' + chan + ', ' + first_record + ' To ' + last_record)
    elif self.opstack.size() == 2:
        record = self.opstack.pop()
        chan = self.opstack.pop()
        self.opstack.push('Unlock ' + chan + ', ' + record)
    elif self.opstack.size() == 1:
        chan = self.opstack.pop()
        self.opstack.push('Unlock ' + chan)
def vardefn(self, *args)
Expand source code Browse git
def vardefn(self, *args):      
    ending =''
    args = list(args) #quite ugly, but fu...
    if args[0] == '(WithEvents)':
        var = args.pop(0)[1:-1] + ' ' + args.pop(0)
    else:
        var = args.pop(0)

    spaces = 1
    if len(args) > 0:
        if args[-1].startswith('0x'):
            spaces = int(args.pop(-1),16) #TODO: treat spaces there
        ending = args[0]
        for arg in args[1:]:
            ending += ' ' + arg
        ending = ' ' + ending[1:-1]
        

    # first we check if this is only one literal definition
    # in this case, we get Dim definitions and we are all set up
    stacktop = self.opstack.pop()

    if stacktop == 'DimImplicit': #case where dim is implicit, 
        val = var + ending  # we have pushed in this case 'DimImplicit' on stack
        self.opstack.push(val)
        return

    # in this case we have a single variable declaration
    decls = ['Dim', 'Private', 'Public', 'Protected', 'Friend', 'Protected Friend', 'Shared', 'Shadows', 'Static', 'ReadOnly']
    if stacktop in decls:
        val = stacktop + ' ' + var + ending
        self.opstack.push(val)
        return

    else:
        # in this case, our variable is either a table, or there is also some const declarations
        # if so, walk the stack and check for declaration
        self.opstack.push(stacktop)
        values = []

        # gather all stack
        while self.opstack.size() > 0:
            values.append(self.opstack.pop())
        values = values[::-1]

        # if we have multiple vardefn with dim, then we are here
        # because all previous vardef should have been pushed correctly on stack
        if len(values) == 1 :
            for decl in decls:
                if values[0].startswith(decl):
                    val = values[0] +', ' + var + ending
                    self.opstack.push(val)
                    return
                
        # if const is used for declaration, then a value is attributed to variable
        # appears somehow not possible to declare a table as const, so far so good, no need to check this case
        if 'Const' in values[0]:
            val = values.pop(0)
            end_val = ' = ' + values.pop(0)
            if len(values) > 0:
                # how to say what is dimensions to what is attribution
                #val = 'Undefined variable declaration'
                raise Pcode2codeException('undefined variable declaration')
            else:
                val = val + ' ' + var + ending + end_val
            self.opstack.push(val)
            return
        
        #so here we have a table
        val = ''
        if values[0] in decls: #first we check if this is the first definition
            val += values.pop(0) + ' ' + var + '('
        elif values[0] == 'DimImplicit': #not sure about this one
            values.pop(0)
            val += var + '('
        else:
            #next we check for a previous declaration
            prev_decl = False
            for decl in decls:
                if values[0].startswith(decl):
                    val += values.pop(0) +', ' + var + '('
                    prev_decl = True
            if prev_decl is False: #in this case, nothing before
                val+= var + '('

        #first occurence
        curr_val1 = values.pop(0)
        curr_val2 = values.pop(0)
        if curr_val1 == 'OptionBase':
            val += curr_val2 
        else:
            val += curr_val1 + ' To ' + curr_val2 

        #other occurences
        while len(values) > 0:
            val += ', '
            curr_val1 = values.pop(0)
            curr_val2 = values.pop(0)
            if curr_val1 == 'OptionBase':
                val += curr_val2 
            else:
                val += curr_val1 + ' To ' + curr_val2 

        #closing
        val += ')' + ending
        self.opstack.push(val)
def wend(self)

command handling end of while loop "Wend" example: Wend gives : # Wend

Expand source code Browse git
def wend(self):
    """
    command handling end of while loop "Wend"
    example: Wend
    gives : 
          # Wend
    """
    self.opstack.push('Wend')
    self.indentlevel = self.indentlevel - 1
def while_(self)

command handling "while" loops definitions example: While numero <= 12 gives: # Ld numero # LitDI2 0x000C # Le # While

Expand source code Browse git
def while_(self):
    """
    command handling "while" loops definitions
    example: While numero <= 12
    gives:
         # Ld numero
         # LitDI2 0x000C
         # Le
         # While
    """
    self.opstack.push('While ' + self.opstack.pop())
    self.indentincrease_future = True
def with_(self)

command handling "with" definitions example: with theWindow gives: # StartWithExpr # Ld theWindow # With

Expand source code Browse git
def with_(self):
    """
    command handling "with" definitions
    example: with theWindow 
    gives:
         # StartWithExpr
         # Ld theWindow
         # With
    """
    self.opstack.push('With ' + self.opstack.pop())
    self.indentincrease_future = True
def writechan(self)

command defining "write" to a channel example: Write #1, MyBool; " is a Boolean value" gives: # LitDI2 0x0001 # Sharp # WriteChan # Ld MyBool # PrintItemSemi # LitStr 0x0013 " is a Boolean value" # PrintItemNL

Expand source code Browse git
def writechan(self):
    """
    command defining "write" to a channel
    example: Write #1, MyBool; " is a Boolean value"
    gives:
         # LitDI2 0x0001
         # Sharp
         # WriteChan
         # Ld MyBool
         # PrintItemSemi
         # LitStr 0x0013 " is a Boolean value"
         # PrintItemNL
    """
    self.opstack.push('Write ' +self.opstack.pop() + ',')
def constfuncexpr(self, *args)
Expand source code Browse git
def constfuncexpr(self, *args):
    raise Pcode2codeException('not implemented constfuncexpr')
def lbconst(self, var)

opcode used when #Const is used example: #Const x = y gives: # LbMark # Ld B # LbConst a

Expand source code Browse git
def lbconst(self, var):
    """
    opcode used when #Const is used
    example: #Const x = y
    gives:
         # LbMark
         # Ld B
         # LbConst a
    """
    self.opstack.push('#Const ' + var + ' = ' + self.opstack.pop())
def lbif(self)

opcode used when #If is used example: #If a = b Then gives: # LbMark # Ld a # Ld B # Eq # LbIf

Expand source code Browse git
def lbif(self):
    """
    opcode used when #If is used
    example: #If a = b Then
    gives:
         # LbMark
         # Ld a
         # Ld B
         # Eq
         # LbIf
    """
    self.opstack.push('#If ' + self.opstack.pop() + ' Then')
    self.indentincrease_future = True
def lbelse(self)

opcode used when #Else is used example: #Else gives: lbElse

Expand source code Browse git
def lbelse(self):
    """
    opcode used when #Else is used
    example: #Else 
    gives: lbElse
    """
    self.opstack.push('#Else')
    self.indentlevel = self.indentlevel - 1
    self.indentincrease_future = True
def lbelseif(self)

opcode used when #Elseif is used example: #ElseIf a = c Then gives: # LbMark # Ld a # Ld c # Eq # LbElseIf

Expand source code Browse git
def lbelseif(self):
    """
    opcode used when #Elseif is used
    example: #ElseIf a = c Then
    gives:
         # LbMark
         # Ld a
         # Ld c
         # Eq
         # LbElseIf
    """
    self.opstack.push('#ElseIf ' + self.opstack.pop() + ' Then')
    self.indentlevel = self.indentlevel - 1
    self.indentincrease_future = True
def lbendif(self)

opcode used when "#End If" is used example: #End If gives: #LbEndIf

Expand source code Browse git
def lbendif(self):
    """
    opcode used when "#End If" is used
    example: #End If
    gives: #LbEndIf
    """
    self.opstack.push('#End If')
    self.indentlevel = self.indentlevel - 1
def lbmark(self)

appears to be used to indicate the start of a lb statement, appears quite useless

Expand source code Browse git
def lbmark(self):
    """
    appears to be used to indicate the start of a lb statement, appears quite useless
    """
    pass #pass on purposes
def endforvariable(self)

This command ends out a for loop variable definition. Gives nothing interesting in fact example: TODO macaroni gives: TODO macaroni

Expand source code Browse git
def endforvariable(self):
    """
    This command ends out a for loop variable definition. Gives nothing interesting in fact
    example: TODO macaroni
    gives: TODO macaroni
    """
    #pass on purposes
    pass
def startforvariable(self)

This command starts out a for loop variable definition. Gives nothing interesting in fact example: TODO macaroni gives: TODO macaroni

Expand source code Browse git
def startforvariable(self):
    """
    This command starts out a for loop variable definition. Gives nothing interesting in fact
    example: TODO macaroni
    gives: TODO macaroni
    """
    #pass on purposes
    pass
def newredim(self, *args)
Expand source code Browse git
def newredim(self, *args):
    raise Pcode2codeException('not implemented newredim')
def startwithexpr(self)

used like startforvariable, eg, simply an indicator of when a with variable is declared. pretty useless for us. example: With theWindow gives: # StartWithExpr # Ld theWindow # With

Expand source code Browse git
def startwithexpr(self):
    """
    used like startforvariable, eg, simply an indicator of when a with variable is declared.
    pretty useless for us.
    example: With theWindow
    gives:
         # StartWithExpr
         # Ld theWindow
         # With
    """
    #pass on purposes
    pass
def setorst(self, *args)
Expand source code Browse git
def setorst(self, *args):
    raise Pcode2codeException('not implemented setorst')
def endenum(self)

command to end an enum example: End Enum gives: #EndEnum

Expand source code Browse git
def endenum(self):
    """
    command to end an enum
    example: End Enum
    gives:
         #EndEnum
    """
    self.opstack.push('End Enum')
    self.indentlevel = self.indentlevel - 1
def illegal(self, *args)
Expand source code Browse git
def illegal(self, *args):
    raise Pcode2codeException('not implemented illegal')
def newline(self)

defines a blank line. Used for internal processing, for blank streams and lines

Expand source code Browse git
def newline(self):
    """
    defines a blank line. Used for internal processing, for blank streams and lines
    """
    self.opstack.push('')
def clearstack(self)
Expand source code Browse git
def clearstack(self):
    self.opstack.clearstack()
def getstacktop(self)
Expand source code Browse git
def getstacktop(self):
    return self.opstack.top()
def getstackpop(self)
Expand source code Browse git
def getstackpop(self):
    return self.opstack.pop()
def getstacksize(self)
Expand source code Browse git
def getstacksize(self):
    return self.opstack.size()
def increaseindentlevel_future(self)

when we increase the indent level, we need to first print out the line, and then to increase the indent level. to do so, when a line has been printed, this function checks if the indent level need to be increased and do so.

Expand source code Browse git
def increaseindentlevel_future(self):
    """
    when we increase the indent level, we need to first print out the line, and then to increase the indent level. 
    to do so, when a line has been printed, this function checks if the indent level need to be increased and do so.
    """
    if self.unindented > 0:
        self.unindented -= 1
    elif self.indentincrease_future:
        self.indentlevel = self.indentlevel + 1
    self.indentincrease_future = False
def getindentlevel(self)

function retrieving the class indentlevel parameter, used to print out code with correct indent

Expand source code Browse git
def getindentlevel(self):
    """
     function retrieving the class indentlevel parameter, used to print out code with correct indent
    """
    return self.indentlevel
def hasbos(self)
Expand source code Browse git
def hasbos(self):
    return self.has_bos
def resethasbos(self)
Expand source code Browse git
def resethasbos(self):
    self.has_bos = False
class Parser (myinput)
Expand source code Browse git
class Parser:

    def __init__(self, myinput):
        self.myinput = myinput  # input to be processed, is always a dump of pcodedmp module there
        self.opstack = Stack()  # vba bytecode is somewhat stack based, so we declare a new one 
        self.operations = Operations(self.opstack) # all operations that can be found in vba bytecode
        self.output = ''        # the output of global processing
        self.output_queue = []
        self.unindented = 0

    def queueLineOutput(self, line, linenum, print_linenum=False, has_end=True):
        self.output_queue.append((line, linenum, print_linenum, has_end))

    def addlineOutput(self, line, linenum, print_linenum=False, has_end=True, _checking_queue=False):
        """
            Because we can choose what is the output for our module, this function somehow bufferize the
            output before it's printed in the latter.
        """
        if not line.strip():
            return
        while not _checking_queue and self.output_queue:
            self.addlineOutput(*self.output_queue.pop(), True)
        if print_linenum:
            self.output += str(linenum) + ': '           
        if not has_end:
            self.output += line
            return
        self.output += line + '\n' 

    def getOutput(self):
        """
        simply a getter to output, used in the end of global processing
        """
        return self.output

    def parseInput(self):
        """
            Function parsing pcodedmp dump to create a dictionary of all lines of the input with the operation lines associated.
            Basically, to explain, a pcodedmp dump would look like so:
               ' Line #7:
               '   Dim 
               '   VarDefn hiz7dgus (As String)
            Here the first line gives out the line number, and the rest are operation lines.
        """
        splittedInput = self.myinput.splitlines()
        lines = {}
        i = 0
        started = False
        streams = {}
        laststream = None
        opelinesblock = []
        # we parse each lines, and cut them by line blocks, to put them in "lines"
        #TODO: simplify
        for inputLine in splittedInput:
            inputLine = inputLine.strip()

            if 'VBA/' in inputLine and inputLine.endswith('bytes'): # here we have a new stream in the document
                if laststream is None: #eg first occurence
                    laststream = inputLine
                else:
                    if opelinesblock == []:
                        opelinesblock = ['NewLine']
                    lines[i] = opelinesblock
                    streams[laststream] = lines
                    opelinesblock = []
                    i = 0
                    lines = {}
                    started = False
                    laststream = inputLine
            if inputLine.startswith('Line #'): # here is our new line block
                started = True
                if not inputLine.startswith('Line #0'):
                    
                    if opelinesblock == []:             # when line is blank, it still appears in dump
                        opelinesblock = ['NewLine']     # so we treat it with a special new operation
                                                        # saying line is blank
                    lines[i] = opelinesblock
                    i+=1
                opelinesblock = []
            else:
                if started:
                    opelinesblock.append(inputLine)

        if opelinesblock == []:
            opelinesblock = ['NewLine']
            
        lines[i] = opelinesblock
        streams[laststream] = lines

        self.myinput = streams


    def parseOpLine(self, inputLine):
        """
            function to parse an operation line.
            to avoid using costly regexp, we split each operation line. The first element is always the operation
            to do, and the rest is potential args. In case there are args, they will be reconstructed by the underlying operation.
        """
        linelist = inputLine.split()
        ope = linelist[0]
        args = linelist[1:]
        func = self.operations.ops[ope]
        func(*args)

    def processInput(self, print_linenum):
        """
            When the input has been <<parsed>>, this function process it to disassemble the input, by calling parseOpLine for each line. 
            It is basically only a printing function.
            args: 
              - print_linenum: boolean indicating if line numbers should be printed in the output or not. Please refer to function named "process"
        """
        for stream in self.myinput.keys():
            if stream:
                self.queueLineOutput('# DECOMPILED STREAM : ' + stream, 0)
            unindented = 0
            for linenum, oplines in self.myinput[stream].items():
                for line in oplines:
                    if line.startswith('FuncDefn'):
                        unindented += 1
                    if line.startswith('EndFunc') or line.startswith('EndSub'):
                        unindented -= 1
            self.operations.unindented = unindented
            for linenum in self.myinput[stream]:
                try:
                    self.operations.clearstack()
                    for opline in self.myinput[stream][linenum]:
                        self.parseOpLine(opline)
                    if self.operations.hasbos():
                        output_parts = []
                        while self.operations.getstacksize() > 0:
                            output_parts.append(self.operations.getstackpop())
                        output_parts = output_parts[::-1]
                        self.addlineOutput(self.operations.getindentlevel() * '  ', linenum, print_linenum, False)
                        for part in output_parts[:-1]:
                            self.addlineOutput(part + ' ', linenum, has_end=False)
                        self.addlineOutput(output_parts[-1], linenum)
                        self.operations.resethasbos()
                    else:
                        self.addlineOutput(self.operations.getindentlevel() * '  ' + self.operations.getstacktop(), linenum, print_linenum)
                except Pcode2codeException as e:
                    self.addlineOutput("' pcode2code, cannot process line "+ str(linenum) + ' : ' + str(e), linenum, print_linenum)
                    for opline in self.myinput[stream][linenum]:
                        self.addlineOutput("'\t# " + opline, linenum)
                except Exception as e:
                    self.addlineOutput("' a generic exception occured at line " + str(linenum) + ": " + str(e), linenum, print_linenum)
                    for opline in self.myinput[stream][linenum]:
                        self.addlineOutput("'\t# " + opline, linenum)
                self.operations.increaseindentlevel_future()
            self.output_queue.clear()

Methods

def queueLineOutput(self, line, linenum, print_linenum=False, has_end=True)
Expand source code Browse git
def queueLineOutput(self, line, linenum, print_linenum=False, has_end=True):
    self.output_queue.append((line, linenum, print_linenum, has_end))
def addlineOutput(self, line, linenum, print_linenum=False, has_end=True)

Because we can choose what is the output for our module, this function somehow bufferize the output before it's printed in the latter.

Expand source code Browse git
def addlineOutput(self, line, linenum, print_linenum=False, has_end=True, _checking_queue=False):
    """
        Because we can choose what is the output for our module, this function somehow bufferize the
        output before it's printed in the latter.
    """
    if not line.strip():
        return
    while not _checking_queue and self.output_queue:
        self.addlineOutput(*self.output_queue.pop(), True)
    if print_linenum:
        self.output += str(linenum) + ': '           
    if not has_end:
        self.output += line
        return
    self.output += line + '\n' 
def getOutput(self)

simply a getter to output, used in the end of global processing

Expand source code Browse git
def getOutput(self):
    """
    simply a getter to output, used in the end of global processing
    """
    return self.output
def parseInput(self)

Function parsing pcodedmp dump to create a dictionary of all lines of the input with the operation lines associated. Basically, to explain, a pcodedmp dump would look like so: ' Line #7: ' Dim ' VarDefn hiz7dgus (As String) Here the first line gives out the line number, and the rest are operation lines.

Expand source code Browse git
def parseInput(self):
    """
        Function parsing pcodedmp dump to create a dictionary of all lines of the input with the operation lines associated.
        Basically, to explain, a pcodedmp dump would look like so:
           ' Line #7:
           '   Dim 
           '   VarDefn hiz7dgus (As String)
        Here the first line gives out the line number, and the rest are operation lines.
    """
    splittedInput = self.myinput.splitlines()
    lines = {}
    i = 0
    started = False
    streams = {}
    laststream = None
    opelinesblock = []
    # we parse each lines, and cut them by line blocks, to put them in "lines"
    #TODO: simplify
    for inputLine in splittedInput:
        inputLine = inputLine.strip()

        if 'VBA/' in inputLine and inputLine.endswith('bytes'): # here we have a new stream in the document
            if laststream is None: #eg first occurence
                laststream = inputLine
            else:
                if opelinesblock == []:
                    opelinesblock = ['NewLine']
                lines[i] = opelinesblock
                streams[laststream] = lines
                opelinesblock = []
                i = 0
                lines = {}
                started = False
                laststream = inputLine
        if inputLine.startswith('Line #'): # here is our new line block
            started = True
            if not inputLine.startswith('Line #0'):
                
                if opelinesblock == []:             # when line is blank, it still appears in dump
                    opelinesblock = ['NewLine']     # so we treat it with a special new operation
                                                    # saying line is blank
                lines[i] = opelinesblock
                i+=1
            opelinesblock = []
        else:
            if started:
                opelinesblock.append(inputLine)

    if opelinesblock == []:
        opelinesblock = ['NewLine']
        
    lines[i] = opelinesblock
    streams[laststream] = lines

    self.myinput = streams
def parseOpLine(self, inputLine)

function to parse an operation line. to avoid using costly regexp, we split each operation line. The first element is always the operation to do, and the rest is potential args. In case there are args, they will be reconstructed by the underlying operation.

Expand source code Browse git
def parseOpLine(self, inputLine):
    """
        function to parse an operation line.
        to avoid using costly regexp, we split each operation line. The first element is always the operation
        to do, and the rest is potential args. In case there are args, they will be reconstructed by the underlying operation.
    """
    linelist = inputLine.split()
    ope = linelist[0]
    args = linelist[1:]
    func = self.operations.ops[ope]
    func(*args)
def processInput(self, print_linenum)

When the input has been <>, this function process it to disassemble the input, by calling parseOpLine for each line. It is basically only a printing function. args: - print_linenum: boolean indicating if line numbers should be printed in the output or not. Please refer to function named "process"

Expand source code Browse git
def processInput(self, print_linenum):
    """
        When the input has been <<parsed>>, this function process it to disassemble the input, by calling parseOpLine for each line. 
        It is basically only a printing function.
        args: 
          - print_linenum: boolean indicating if line numbers should be printed in the output or not. Please refer to function named "process"
    """
    for stream in self.myinput.keys():
        if stream:
            self.queueLineOutput('# DECOMPILED STREAM : ' + stream, 0)
        unindented = 0
        for linenum, oplines in self.myinput[stream].items():
            for line in oplines:
                if line.startswith('FuncDefn'):
                    unindented += 1
                if line.startswith('EndFunc') or line.startswith('EndSub'):
                    unindented -= 1
        self.operations.unindented = unindented
        for linenum in self.myinput[stream]:
            try:
                self.operations.clearstack()
                for opline in self.myinput[stream][linenum]:
                    self.parseOpLine(opline)
                if self.operations.hasbos():
                    output_parts = []
                    while self.operations.getstacksize() > 0:
                        output_parts.append(self.operations.getstackpop())
                    output_parts = output_parts[::-1]
                    self.addlineOutput(self.operations.getindentlevel() * '  ', linenum, print_linenum, False)
                    for part in output_parts[:-1]:
                        self.addlineOutput(part + ' ', linenum, has_end=False)
                    self.addlineOutput(output_parts[-1], linenum)
                    self.operations.resethasbos()
                else:
                    self.addlineOutput(self.operations.getindentlevel() * '  ' + self.operations.getstacktop(), linenum, print_linenum)
            except Pcode2codeException as e:
                self.addlineOutput("' pcode2code, cannot process line "+ str(linenum) + ' : ' + str(e), linenum, print_linenum)
                for opline in self.myinput[stream][linenum]:
                    self.addlineOutput("'\t# " + opline, linenum)
            except Exception as e:
                self.addlineOutput("' a generic exception occured at line " + str(linenum) + ": " + str(e), linenum, print_linenum)
                for opline in self.myinput[stream][linenum]:
                    self.addlineOutput("'\t# " + opline, linenum)
            self.operations.increaseindentlevel_future()
        self.output_queue.clear()