NAME=rawptr
FILE=bins/dectest32
EXPECT=<<EOF

uint sym.get_global_array_entry(void)

{
    return *0x804c034;
}

--

uint sym.get_global_array_entry(void)

{
    return uRam0804c034;
}

EOF
CMDS=<<EOF
s sym.get_global_array_entry
af
e r2ghidra.rawptr=1
pdg
?e --
e r2ghidra.rawptr=0
pdg
EOF
RUN

NAME=global flag
FILE=bins/dectest32
EXPECT=<<EOF

uint sym.get_global_var(void)

{
    return _obj.global_var;
}

--

//WARNING: Globals starting with '_' overlap smaller symbols at the same address

uint sym.get_global_var(void)

{
    return _obj.global_var;
}

EOF
CMDS=<<EOF
s sym.get_global_var
af
e r2ghidra.rawptr=1
pdg
?e --
e r2ghidra.rawptr=0
pdg
EOF
RUN

NAME=function variable annotations
FILE=bins/dectest64
EXPECT=<<EOF
{
  "code": "\nulong main(int argc,char **argv)\n\n{\n    ulong uVar1;\n    int64_t in_FS_OFFSET;\n    int64_t var_30h;\n    int32_t var_24h;\n    int64_t var_20h;\n    int64_t var_8h;\n    \n    var_8h = *(in_FS_OFFSET + 0x28);\n    sym.Aeropause(&var_20h,argc,argv);\n    uVar1 = 0;\n    if (var_8h != *(in_FS_OFFSET + 0x28)) {\n        uVar1 = sym.imp.__stack_chk_fail();\n    }\n    return uVar1;\n}\n\n",
  "annotations": [
    {
      "start": 1,
      "end": 6,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 7,
      "end": 11,
      "type": "function_name",
      "name": "main",
      "offset": 4198782
    },
    {
      "start": 7,
      "end": 11,
      "type": "offset",
      "offset": 4198782
    },
    {
      "start": 7,
      "end": 11,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 12,
      "end": 15,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 16,
      "end": 20,
      "type": "function_parameter",
      "name": "argc"
    },
    {
      "start": 16,
      "end": 20,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 21,
      "end": 25,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 28,
      "end": 32,
      "type": "function_parameter",
      "name": "argv"
    },
    {
      "start": 28,
      "end": 32,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 41,
      "end": 46,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 47,
      "end": 52,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 47,
      "end": 52,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 58,
      "end": 65,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 66,
      "end": 78,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 66,
      "end": 78,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 84,
      "end": 91,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 92,
      "end": 99,
      "type": "local_variable",
      "name": "var_30h"
    },
    {
      "start": 92,
      "end": 99,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 105,
      "end": 112,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 113,
      "end": 120,
      "type": "local_variable",
      "name": "var_24h"
    },
    {
      "start": 113,
      "end": 120,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 126,
      "end": 133,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 134,
      "end": 141,
      "type": "local_variable",
      "name": "var_20h"
    },
    {
      "start": 134,
      "end": 141,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 147,
      "end": 154,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 155,
      "end": 161,
      "type": "local_variable",
      "name": "var_8h"
    },
    {
      "start": 155,
      "end": 161,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 172,
      "end": 178,
      "type": "local_variable",
      "name": "var_8h"
    },
    {
      "start": 172,
      "end": 178,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 179,
      "end": 180,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 181,
      "end": 182,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 183,
      "end": 195,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 183,
      "end": 195,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 196,
      "end": 197,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 198,
      "end": 202,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 172,
      "end": 203,
      "type": "offset",
      "offset": 4198797
    },
    {
      "start": 209,
      "end": 222,
      "type": "function_name",
      "name": "sym.Aeropause",
      "offset": 4199038
    },
    {
      "start": 209,
      "end": 222,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 223,
      "end": 224,
      "type": "offset",
      "offset": 4198819
    },
    {
      "start": 224,
      "end": 231,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 231,
      "end": 232,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 232,
      "end": 236,
      "type": "function_parameter",
      "name": "argc"
    },
    {
      "start": 232,
      "end": 236,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 236,
      "end": 237,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 237,
      "end": 241,
      "type": "function_parameter",
      "name": "argv"
    },
    {
      "start": 237,
      "end": 241,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 209,
      "end": 242,
      "type": "offset",
      "offset": 4198828
    },
    {
      "start": 248,
      "end": 253,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 248,
      "end": 253,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 254,
      "end": 255,
      "type": "offset",
      "offset": 4198833
    },
    {
      "start": 256,
      "end": 257,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 248,
      "end": 257,
      "type": "offset",
      "offset": 4198833
    },
    {
      "start": 263,
      "end": 265,
      "type": "offset",
      "offset": 4198851
    },
    {
      "start": 263,
      "end": 265,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 267,
      "end": 273,
      "type": "local_variable",
      "name": "var_8h"
    },
    {
      "start": 267,
      "end": 273,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 274,
      "end": 276,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 277,
      "end": 278,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 279,
      "end": 291,
      "type": "local_variable",
      "name": "in_FS_OFFSET"
    },
    {
      "start": 279,
      "end": 291,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 292,
      "end": 293,
      "type": "offset",
      "offset": 4198842
    },
    {
      "start": 294,
      "end": 298,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 311,
      "end": 316,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 311,
      "end": 316,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 317,
      "end": 318,
      "type": "offset",
      "offset": 4198853
    },
    {
      "start": 319,
      "end": 343,
      "type": "function_name",
      "name": "sym.imp.__stack_chk_fail",
      "offset": 4198464
    },
    {
      "start": 319,
      "end": 343,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 311,
      "end": 345,
      "type": "offset",
      "offset": 4198853
    },
    {
      "start": 357,
      "end": 363,
      "type": "offset",
      "offset": 4198859
    },
    {
      "start": 357,
      "end": 363,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 364,
      "end": 369,
      "type": "local_variable",
      "name": "uVar1"
    },
    {
      "start": 364,
      "end": 369,
      "type": "syntax_highlight",
      "syntax_highlight": "local_variable"
    },
    {
      "start": 357,
      "end": 369,
      "type": "offset",
      "offset": 4198859
    }
  ]
}
EOF
CMDS=<<EOF
s main
af
pdgj~{}
EOF
RUN

NAME=global variable annotation
FILE=bins/dectest32
EXPECT=<<EOF
{
  "code": "\nuint sym.get_global_array_entry(void)\n\n{\n    return *0x804c034;\n}\n\n",
  "annotations": [
    {
      "start": 1,
      "end": 5,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 6,
      "end": 32,
      "type": "function_name",
      "name": "sym.get_global_array_entry",
      "offset": 134517184
    },
    {
      "start": 6,
      "end": 32,
      "type": "offset",
      "offset": 134517184
    },
    {
      "start": 6,
      "end": 32,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 33,
      "end": 37,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 46,
      "end": 52,
      "type": "offset",
      "offset": 134517193
    },
    {
      "start": 46,
      "end": 52,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 53,
      "end": 54,
      "type": "offset",
      "offset": 134517187
    },
    {
      "start": 54,
      "end": 63,
      "type": "global_variable",
      "offset": 134529076
    },
    {
      "start": 54,
      "end": 63,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 46,
      "end": 63,
      "type": "offset",
      "offset": 134517193
    }
  ]
}
EOF
CMDS=<<EOF
s sym.get_global_array_entry
af
pdgj~{}
EOF
RUN

NAME=constant variable annotation
FILE=bins/dectest32
EXPECT=<<EOF
{
  "code": "\nvoid sym.PrintAmbassador(int32_t arg_8h)\n\n{\n    sym.imp.printf(\"Ambassador value: \");\n    if (arg_8h < 5) {\n        if (arg_8h < 5) {\n            switch(*(arg_8h * 4 + 0x804a048)) {\n            case 0x8049261:\n                sym.imp.printf(\"pure\");\n                break;\n            case 0x8049273:\n                sym.imp.printf(\"reason\");\n                break;\n            case 0x8049285:\n                sym.imp.printf(\"revolution\");\n                break;\n            case 0x8049297:\n                sym.imp.printf(\"echoes\");\n                break;\n            case 0x80492a9:\n                sym.imp.printf(\"wall\");\n            }\n        }\n    }\n    else if (arg_8h == 1000000) {\n        sym.imp.printf(\"million\");\n    }\n    sym.imp.putchar(10);\n    return;\n}\n\n",
  "annotations": [
    {
      "start": 1,
      "end": 5,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 6,
      "end": 25,
      "type": "function_name",
      "name": "sym.PrintAmbassador",
      "offset": 134517281
    },
    {
      "start": 6,
      "end": 25,
      "type": "offset",
      "offset": 134517281
    },
    {
      "start": 6,
      "end": 25,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 26,
      "end": 33,
      "type": "syntax_highlight",
      "syntax_highlight": "datatype"
    },
    {
      "start": 34,
      "end": 40,
      "type": "function_parameter",
      "name": "arg_8h"
    },
    {
      "start": 34,
      "end": 40,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 49,
      "end": 63,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 49,
      "end": 63,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 64,
      "end": 84,
      "type": "constant_variable",
      "offset": 134520840
    },
    {
      "start": 64,
      "end": 84,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 49,
      "end": 85,
      "type": "offset",
      "offset": 134517295
    },
    {
      "start": 91,
      "end": 93,
      "type": "offset",
      "offset": 134517307
    },
    {
      "start": 91,
      "end": 93,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 95,
      "end": 101,
      "type": "function_parameter",
      "name": "arg_8h"
    },
    {
      "start": 95,
      "end": 101,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 102,
      "end": 103,
      "type": "offset",
      "offset": 134517307
    },
    {
      "start": 104,
      "end": 105,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 117,
      "end": 119,
      "type": "offset",
      "offset": 134517313
    },
    {
      "start": 117,
      "end": 119,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 121,
      "end": 127,
      "type": "function_parameter",
      "name": "arg_8h"
    },
    {
      "start": 121,
      "end": 127,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 128,
      "end": 129,
      "type": "offset",
      "offset": 134517313
    },
    {
      "start": 130,
      "end": 131,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 147,
      "end": 153,
      "type": "offset",
      "offset": 134517332
    },
    {
      "start": 147,
      "end": 153,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 154,
      "end": 155,
      "type": "offset",
      "offset": 134517330
    },
    {
      "start": 156,
      "end": 162,
      "type": "function_parameter",
      "name": "arg_8h"
    },
    {
      "start": 156,
      "end": 162,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 163,
      "end": 164,
      "type": "offset",
      "offset": 134517322
    },
    {
      "start": 165,
      "end": 166,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 167,
      "end": 168,
      "type": "offset",
      "offset": 134517325
    },
    {
      "start": 169,
      "end": 178,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 195,
      "end": 199,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 227,
      "end": 241,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 227,
      "end": 241,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 242,
      "end": 248,
      "type": "constant_variable",
      "offset": 134520859
    },
    {
      "start": 242,
      "end": 248,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 227,
      "end": 249,
      "type": "offset",
      "offset": 134517353
    },
    {
      "start": 267,
      "end": 272,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 267,
      "end": 273,
      "type": "offset",
      "offset": 134517361
    },
    {
      "start": 286,
      "end": 290,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 318,
      "end": 332,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 318,
      "end": 332,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 333,
      "end": 341,
      "type": "constant_variable",
      "offset": 134520864
    },
    {
      "start": 333,
      "end": 341,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 318,
      "end": 342,
      "type": "offset",
      "offset": 134517371
    },
    {
      "start": 360,
      "end": 365,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 360,
      "end": 366,
      "type": "offset",
      "offset": 134517379
    },
    {
      "start": 379,
      "end": 383,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 411,
      "end": 425,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 411,
      "end": 425,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 426,
      "end": 438,
      "type": "constant_variable",
      "offset": 134520871
    },
    {
      "start": 426,
      "end": 438,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 411,
      "end": 439,
      "type": "offset",
      "offset": 134517389
    },
    {
      "start": 457,
      "end": 462,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 457,
      "end": 463,
      "type": "offset",
      "offset": 134517397
    },
    {
      "start": 476,
      "end": 480,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 508,
      "end": 522,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 508,
      "end": 522,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 523,
      "end": 531,
      "type": "constant_variable",
      "offset": 134520882
    },
    {
      "start": 523,
      "end": 531,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 508,
      "end": 532,
      "type": "offset",
      "offset": 134517407
    },
    {
      "start": 550,
      "end": 555,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 550,
      "end": 556,
      "type": "offset",
      "offset": 134517415
    },
    {
      "start": 569,
      "end": 573,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 601,
      "end": 615,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 601,
      "end": 615,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 616,
      "end": 622,
      "type": "constant_variable",
      "offset": 134520889
    },
    {
      "start": 616,
      "end": 622,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 601,
      "end": 623,
      "type": "offset",
      "offset": 134517425
    },
    {
      "start": 659,
      "end": 663,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 664,
      "end": 666,
      "type": "offset",
      "offset": 134517341
    },
    {
      "start": 664,
      "end": 666,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 668,
      "end": 674,
      "type": "function_parameter",
      "name": "arg_8h"
    },
    {
      "start": 668,
      "end": 674,
      "type": "syntax_highlight",
      "syntax_highlight": "function_parameter"
    },
    {
      "start": 675,
      "end": 677,
      "type": "offset",
      "offset": 134517334
    },
    {
      "start": 678,
      "end": 685,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 697,
      "end": 711,
      "type": "function_name",
      "name": "sym.imp.printf",
      "offset": 134516816
    },
    {
      "start": 697,
      "end": 711,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 712,
      "end": 721,
      "type": "constant_variable",
      "offset": 134520894
    },
    {
      "start": 712,
      "end": 721,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 697,
      "end": 722,
      "type": "offset",
      "offset": 134517443
    },
    {
      "start": 734,
      "end": 749,
      "type": "function_name",
      "name": "sym.imp.putchar",
      "offset": 134516880
    },
    {
      "start": 734,
      "end": 749,
      "type": "syntax_highlight",
      "syntax_highlight": "function_name"
    },
    {
      "start": 750,
      "end": 752,
      "type": "syntax_highlight",
      "syntax_highlight": "constant_variable"
    },
    {
      "start": 734,
      "end": 753,
      "type": "offset",
      "offset": 134517459
    },
    {
      "start": 759,
      "end": 765,
      "type": "offset",
      "offset": 134517469
    },
    {
      "start": 759,
      "end": 765,
      "type": "syntax_highlight",
      "syntax_highlight": "keyword"
    },
    {
      "start": 759,
      "end": 765,
      "type": "offset",
      "offset": 134517469
    }
  ]
}
EOF
CMDS=<<EOF
s sym.PrintAmbassador
af
pdgj~{}
EOF
RUN

NAME=aeropause32 (many features combined)
FILE=bins/dectest32
EXPECT=<<EOF

void sym.Aeropause(Bright *bright,int32_t argc,char **argv)

{
    Ambassador AVar1;
    Morning *pMVar2;
    int iVar3;
    
    pMVar2 = sym.imp.malloc(8);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    }
    else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar3 = sym.imp.strcmp((bright->window).sunlight,0x804a05c);
        if (iVar3 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        }
        else {
            iVar3 = sym.imp.strcmp((bright->window).sunlight,"dark");
            if (iVar3 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            }
            else {
                iVar3 = sym.imp.strcmp((bright->window).sunlight,"third");
                if (iVar3 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                }
                else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    AVar1 = bright->ambassador;
    if (AVar1 < (AMBASSADOR_WALL|AMBASSADOR_REASON)) {
    //switch table (5 cases) at 0x804a070
        switch(AVar1) {
        case AMBASSADOR_PURE:
            sym.imp.printf("pure");
            break;
        case AMBASSADOR_REASON:
            sym.imp.printf("reason");
            break;
        case AMBASSADOR_REVOLUTION:
            sym.imp.printf("revolution");
            break;
        case AMBASSADOR_ECHOES:
            sym.imp.printf("echoes");
            break;
        case AMBASSADOR_WALL:
            sym.imp.printf("wall");
        }
    }
    else if (AVar1 == AMBASSADOR_MILLION) {
        sym.imp.printf("million");
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}

EOF
CMDS=<<EOF
aaa
to bins/types.h
s sym.Aeropause
afvb 8 bright Bright *
afvb 12 argc int32_t
afvb 16 argv const char **
pdg
EOF
RUN

NAME=aeropause64 (many features combined)
FILE=bins/dectest64
EXPECT=<<EOF

void sym.Aeropause(Bright *bright,int32_t argc,char **argv)

{
    uint uVar1;
    int iVar2;
    Morning *pMVar3;
    int64_t var_18h;
    int32_t var_ch;
    void **var_8h;
    
    pMVar3 = sym.imp.malloc(0x10);
    bright->morning = pMVar3;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        *&bright->ambassador = AMBASSADOR_PURE;
    }
    else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar2 = sym.imp.strcmp((bright->window).sunlight,"the  ");
        if (iVar2 == 0) {
            *&bright->ambassador = AMBASSADOR_REASON;
        }
        else {
            iVar2 = sym.imp.strcmp((bright->window).sunlight,"dark");
            if (iVar2 == 0) {
                *&bright->ambassador = AMBASSADOR_REVOLUTION;
            }
            else {
                iVar2 = sym.imp.strcmp((bright->window).sunlight,"third");
                if (iVar2 == 0) {
                    *&bright->ambassador = AMBASSADOR_ECHOES;
                }
                else {
                    *&bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    uVar1 = bright->ambassador;
    if (uVar1 < (AMBASSADOR_WALL|AMBASSADOR_REASON)) {
    //switch table (5 cases) at 0x402088
        switch(uVar1) {
        case 0:
            sym.imp.printf("pure");
            break;
        case 1:
            sym.imp.printf("reason");
            break;
        case 2:
            sym.imp.printf("revolution");
            break;
        case 3:
            sym.imp.printf("echoes");
            break;
        case 4:
            sym.imp.printf("wall");
        }
    }
    else if (uVar1 == AMBASSADOR_MILLION) {
        sym.imp.printf("million");
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}

EOF
CMDS=<<EOF
aaa
to bins/types.h

s sym.Aeropause
pdg
EOF
RUN

NAME=typedef
FILE=bins/dectest32
EXPECT=<<EOF

void sym.Aeropause(Bright *bright,int32_t argc,char **argv)

{
    Ambassador AVar1;
    Morning *pMVar2;
    int iVar3;
    
    pMVar2 = sym.imp.malloc(8);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    }
    else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar3 = sym.imp.strcmp((bright->window).sunlight,0x804a05c);
        if (iVar3 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        }
        else {
            iVar3 = sym.imp.strcmp((bright->window).sunlight,"dark");
            if (iVar3 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            }
            else {
                iVar3 = sym.imp.strcmp((bright->window).sunlight,"third");
                if (iVar3 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                }
                else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    AVar1 = bright->ambassador;
    if (AVar1 < (AMBASSADOR_WALL|AMBASSADOR_REASON)) {
    //switch table (5 cases) at 0x804a070
        switch(AVar1) {
        case AMBASSADOR_PURE:
            sym.imp.printf("pure");
            break;
        case AMBASSADOR_REASON:
            sym.imp.printf("reason");
            break;
        case AMBASSADOR_REVOLUTION:
            sym.imp.printf("revolution");
            break;
        case AMBASSADOR_ECHOES:
            sym.imp.printf("echoes");
            break;
        case AMBASSADOR_WALL:
            sym.imp.printf("wall");
        }
    }
    else if (AVar1 == AMBASSADOR_MILLION) {
        sym.imp.printf("million");
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}

--

void sym.Aeropause(Bright *bright,int32_t argc,char **argv)

{
    Ambassador AVar1;
    Morning *pMVar2;
    int iVar3;
    
    pMVar2 = sym.imp.malloc(8);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    }
    else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar3 = sym.imp.strcmp((bright->window).sunlight,0x804a05c);
        if (iVar3 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        }
        else {
            iVar3 = sym.imp.strcmp((bright->window).sunlight,"dark");
            if (iVar3 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            }
            else {
                iVar3 = sym.imp.strcmp((bright->window).sunlight,"third");
                if (iVar3 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                }
                else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    AVar1 = bright->ambassador;
    if (AVar1 < (AMBASSADOR_WALL|AMBASSADOR_REASON)) {
    //switch table (5 cases) at 0x804a070
        switch(AVar1) {
        case AMBASSADOR_PURE:
            sym.imp.printf("pure");
            break;
        case AMBASSADOR_REASON:
            sym.imp.printf("reason");
            break;
        case AMBASSADOR_REVOLUTION:
            sym.imp.printf("revolution");
            break;
        case AMBASSADOR_ECHOES:
            sym.imp.printf("echoes");
            break;
        case AMBASSADOR_WALL:
            sym.imp.printf("wall");
        }
    }
    else if (AVar1 == AMBASSADOR_MILLION) {
        sym.imp.printf("million");
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}

--

void sym.Aeropause(Bright *bright,int32_t argc,char **argv)

{
    Ambassador AVar1;
    Morning *pMVar2;
    int iVar3;
    
    pMVar2 = sym.imp.malloc(8);
    bright->morning = pMVar2;
    bright->morning->saved_argc = argc;
    bright->morning->saved_argv = argv;
    if (bright->morning->saved_argc < 2) {
        bright->ambassador = AMBASSADOR_PURE;
    }
    else {
        (bright->window).sunlight = bright->morning->saved_argv[1];
        iVar3 = sym.imp.strcmp((bright->window).sunlight,0x804a05c);
        if (iVar3 == 0) {
            bright->ambassador = AMBASSADOR_REASON;
        }
        else {
            iVar3 = sym.imp.strcmp((bright->window).sunlight,"dark");
            if (iVar3 == 0) {
                bright->ambassador = AMBASSADOR_REVOLUTION;
            }
            else {
                iVar3 = sym.imp.strcmp((bright->window).sunlight,"third");
                if (iVar3 == 0) {
                    bright->ambassador = AMBASSADOR_ECHOES;
                }
                else {
                    bright->ambassador = AMBASSADOR_MILLION;
                }
            }
        }
    }
    AVar1 = bright->ambassador;
    if (AVar1 < (AMBASSADOR_WALL|AMBASSADOR_REASON)) {
    //switch table (5 cases) at 0x804a070
        switch(AVar1) {
        case AMBASSADOR_PURE:
            sym.imp.printf("pure");
            break;
        case AMBASSADOR_REASON:
            sym.imp.printf("reason");
            break;
        case AMBASSADOR_REVOLUTION:
            sym.imp.printf("revolution");
            break;
        case AMBASSADOR_ECHOES:
            sym.imp.printf("echoes");
            break;
        case AMBASSADOR_WALL:
            sym.imp.printf("wall");
        }
    }
    else if (AVar1 == AMBASSADOR_MILLION) {
        sym.imp.printf("million");
    }
    sym.PrintAmbassador(bright->ambassador);
    return;
}

EOF
CMDS=<<EOF
aaa
to bins/types.h
s sym.Aeropause
afvb 8 bright BrightPtr
afvb 12 argc Bright *
afvb 16 argv const char **
pdg
?e --
afvb 8 bright BrightTypedefd *
afvb 12 argc int32_t
afvb 16 argv const char **
pdg
?e --
afvb 8 bright BrightTypedefdPtr
pdg
EOF
RUN

NAME=recursive type
FILE=bins/rec
CMDS=<<EOF
to bins/types_rec.h
aaa
s sym.KillList
afvt arg1 LL
afvt ptr LL
pdg
EOF
EXPECT=<<EOF

void sym.KillList(LL arg1)

{
    LL pLVar1;
    LL ptr;
    int64_t var_8h;
    
    ptr = arg1;
    while (ptr != NULL) {
        pLVar1 = *&ptr->next;
        sym.imp.free(ptr);
        ptr = pLVar1;
    }
    return;
}

EOF
RUN

NAME=ppc64 variadic prototype recovers call-site register args under pdg
FILE=bins/elf/ppc64v1-vararg
CMDS=<<EOF
aa
"td int vfmt(const char *tag, ...);"
pdg @ sym.caller~vfmt
EOF
EXPECT=<<EOF
    iVar1 = sym.vfmt(0x100001c8,arg1,arg2);
EOF
RUN

NAME=string literals render inline instead of as flag symbols
FILE=bins/elf/crackme0x05
CMDS=<<EOF
aaa
pdg @ main~printf
EOF
EXPECT=<<EOF
    sym.imp.printf("IOLI Crackme Level 0x05\n");
    sym.imp.printf("Password: ");
EOF
RUN

NAME=return type from r2 prototype is preserved
FILE=bins/elf/crackme0x05
EXPECT=<<EOF
int mycheck(int code)
EOF
CMDS=<<EOF
s sym.check
af
afn mycheck
afc cdecl
'afs int mycheck(int code)
pdg~mycheck(
EOF
RUN

NAME=return type preserved for argument-less prototype
FILE=bins/elf/crackme0x05
EXPECT=<<EOF
int mycheck(void)
EOF
CMDS=<<EOF
s sym.check
af
afn mycheck
afc cdecl
'afs int mycheck(void)
pdg~mycheck(
EOF
RUN

NAME=ppc64 noreturn void callee gets no phantom canary arg under pdg
FILE=bins/elf/ppc64-noreturn-arg.so
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF2
aaa
pdg @ sym.withbuf~stack_chk_fail
EOF2
EXPECT=<<EOF2
    sub.__stack_chk_fail();
EOF2
RUN

NAME=ppc64 noreturn callee that takes an argument keeps it under pdg
FILE=bins/elf/ppc64-noreturn-arg.so
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF2
aaa
pdg @ sym.doexit~0x2a
EOF2
EXPECT=<<EOF2
        entry0(0x2a);
EOF2
RUN

NAME=pdg survives an unparseable var type string instead of recursing
FILE=bins/dectest64
CMDS=<<EOF
s sym.Aeropause
af
afvt arg1 int (*)(int)
pdg~Aeropause(
EOF
EXPECT=<<EOF
void sym.Aeropause(int arg1,int64_t arg2,int64_t arg3)
EOF
RUN

NAME=afvt pointer type on a register arg applies under pdg
FILE=bins/dectest64
CMDS=<<EOF
s sym.Aeropause
af
"afvt arg1 char *"
pdg~Aeropause(
EOF
EXPECT=<<EOF
void sym.Aeropause(char *arg1,int64_t arg2,int64_t arg3)
EOF
RUN

NAME=pdgw writes the recovered register-arg type and signature
FILE=bins/dectest64
ARGS=-e log.level=0
CMDS=<<EOF
s sym.Aeropause
af
e r2ghidra.vars=false
e log.level=2
pdgw
afv
afs
EOF
EXPECT=<<EOF
arg int64_t * arg1 @ rdi
arg int64_t arg2 @ rsi
arg int64_t arg3 @ rdx
var int64_t var_8h @ rbp-0x8
var int32_t var_ch @ rbp-0xc
var int64_t var_18h @ rbp-0x18
void sym.Aeropause (int64_t arg1, int64_t arg2, int64_t arg3);
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: wrote 1 types, 0 names
EOF
RUN

NAME=pdgw run twice makes no further changes
FILE=bins/dectest64
ARGS=-e log.level=0
CMDS=<<EOF
s sym.Aeropause
af
e r2ghidra.vars=false
e log.level=2
pdgw
pdgw
afv
EOF
EXPECT=<<EOF
arg int64_t * arg1 @ rdi
arg int64_t arg2 @ rsi
arg int64_t arg3 @ rdx
var int64_t var_8h @ rbp-0x8
var int32_t var_ch @ rbp-0xc
var int64_t var_18h @ rbp-0x18
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: wrote 1 types, 0 names
INFO: pdgw: no changes
EOF
RUN

NAME=pdg output improves after pdgw writes types
FILE=bins/dectest64
CMDS=<<EOF
s sym.Aeropause
af
pdg~Aeropause(
e r2ghidra.vars=false
pdgw
e r2ghidra.vars=true
pdg~Aeropause(
EOF
EXPECT=<<EOF
void sym.Aeropause(int64_t arg1,int64_t arg2,int64_t arg3)
void sym.Aeropause(int64_t *arg1,int64_t arg2,int64_t arg3)
EOF
RUN

NAME=pdgw with write gates disabled changes nothing
FILE=bins/dectest64
ARGS=-e log.level=0
CMDS=<<EOF
s sym.Aeropause
af
e r2ghidra.vars=false
e r2ghidra.write.vars=false
e r2ghidra.write.sig=false
e log.level=2
pdgw
afv~arg1
EOF
EXPECT=<<EOF
arg int64_t arg1 @ rdi
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw writes the recovered signature on big endian ppc64
FILE=bins/elf/ppc64v1-crc32_generic.ko
ARGS=-e bin.relocs.apply=true -e log.level=0
CMDS=<<EOF
aaa
s sym..crc32_init
e log.level=2
pdgw
afs
pdgw
EOF
EXPECT=<<EOF
void sym..crc32_init (int64_t arg1);
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: wrote 0 types, 0 names, signature
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw preserves an existing explicit prototype
FILE=bins/elf/hello_world
ARGS=-e log.level=0
CMDS=<<EOF
aaa
s main
"afs int main(int argc, char **argv)"
e log.level=2
pdgw
afs
EOF
EXPECT=<<EOF
int main (int argc, char **argv);
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw writes the recovered signature on arm64
FILE=bins/elf/arm64-varargs.so
ARGS=-e log.level=0
CMDS=<<EOF
aaa
s sym.p_snprintf
e log.level=2
pdgw
afs
pdgw
EOF
EXPECT=<<EOF
int sym.p_snprintf (int64_t arg1, int64_t arg2);
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: wrote 0 types, 0 names, signature
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw is stable on 32-bit x86 stack arguments
FILE=bins/elf/crackme0x05
ARGS=-e log.level=0
CMDS=<<EOF
s sym.check
af
e r2ghidra.vars=false
e log.level=2
pdgw
pdgw
afv
EOF
EXPECT=<<EOF
arg int32_t arg_8h @ ebp+0x8
var int32_t var_8h @ ebp-0x8
var int32_t var_ch @ ebp-0xc
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: no changes
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw does not import auto-generated ghidra variable names
FILE=bins/dectest64
ARGS=-e log.level=0
CMDS=<<EOF
s main
af
e r2ghidra.vars=false
e log.level=2
pdgw
afv
EOF
EXPECT=<<EOF
arg int argc @ rdi
arg char ** argv @ rsi
var int64_t var_8h @ rbp-0x8
var int64_t var_20h @ rbp-0x20
var int32_t var_24h @ rbp-0x24
var int64_t var_30h @ rbp-0x30
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: no changes
EOF
RUN

NAME=pdgw converges when a ghidra local shares storage with a parameter
FILE=bins/elf/arm64-varargs.so
ARGS=-e log.level=0
CMDS=<<EOF
aaa
s sym.p_snprintf
e r2ghidra.varargs=true
e log.level=2
pdgw
pdgw
afv~arg1
EOF
EXPECT=<<EOF
arg int64_t arg1 @ x0
EOF
EXPECT_ERR=<<EOF
INFO: pdgw: wrote 0 types, 0 names, signature
INFO: pdgw: no changes
EOF
RUN

NAME=typed HFA parameter decodes join-space storage under pdg
FILE=bins/elf/join-hfa-arm64
CMDS=<<EOF
s sym.sum2
af
'td struct V2 { float x; float y; };
'afs float sum2(V2 v)
pdg~v.x
EOF
EXPECT=<<EOF
    return v.x + v.y;
EOF
RUN

NAME=scalar float parameter keeps regular storage under pdg
FILE=bins/elf/join-hfa-arm64
CMDS=<<EOF
s sym.scale1
af
'afs float scale1(float a)
pdg~return
EOF
EXPECT=<<EOF
    return a + a;
EOF
RUN

NAME=typed function pointer struct field is stored as a pointer
FILE=bins/elf/function-pointer-field-arm64
CMDS=<<EOF
to bins/function-pointer-field-arm64.h
s sym.call_short_slot
af
'afs float call_short_slot(ShortSlot* slot, Receiver* receiver)
pdg~methodPtr
EOF
EXPECT=<<EOF
    fVar1 = (*slot->methodPtr)(receiver,slot->method);
EOF
RUN

NAME=typed function pointer field preserves return type with a long owner name
FILE=bins/elf/function-pointer-field-arm64
CMDS=<<EOF
to bins/function-pointer-field-arm64.h
s sym.call_long_slot
af
'afs float call_long_slot(VeryLongConcreteGenericOwnerName_VTableSlot* slot, Receiver* receiver)
pdg~methodPtr
EOF
EXPECT=<<EOF
    fVar1 = (*slot->methodPtr)(receiver,slot->method);
EOF
RUN

# radare2 stores union member metadata in sdb only after the 6.1.8 release
NAME=typed function pointer union member is stored as a pointer
BROKEN=1
FILE=bins/elf/function-pointer-field-arm64.o
CMDS=<<EOF
to bins/function-pointer-union-arm64.h
s sym.call_short_slot
af
'afs float call_short_slot(UnionSlot* slot, Receiver* receiver)
pdg~cb
EOF
EXPECT=<<EOF
    fVar1 = (*(slot->cb).fn)(receiver,slot->method);
EOF
RUN
