diff options
author | Ben Longbons <b.r.longbons@gmail.com> | 2014-11-08 17:53:18 -0800 |
---|---|---|
committer | Ben Longbons <b.r.longbons@gmail.com> | 2014-11-09 19:58:42 -0800 |
commit | 3cf55f763ef8c75e8e8c11fca3c3e564668aee52 (patch) | |
tree | 703a5744c4ee1cb807e59ca49df283d52250f613 /src | |
parent | a7333d7e59515db8a5f95f43a3b26793505b2aae (diff) | |
download | tmwa-3cf55f763ef8c75e8e8c11fca3c3e564668aee52.tar.gz tmwa-3cf55f763ef8c75e8e8c11fca3c3e564668aee52.tar.bz2 tmwa-3cf55f763ef8c75e8e8c11fca3c3e564668aee52.tar.xz tmwa-3cf55f763ef8c75e8e8c11fca3c3e564668aee52.zip |
Make it easier to debug scripts, especially from coredumps
Diffstat (limited to 'src')
-rw-r--r-- | src/io/fd.cpp | 5 | ||||
-rw-r--r-- | src/map/fwd.hpp | 1 | ||||
-rw-r--r-- | src/map/itemdb.cpp | 4 | ||||
-rw-r--r-- | src/map/magic-v2.cpp | 2 | ||||
-rw-r--r-- | src/map/npc-parse.cpp | 8 | ||||
-rw-r--r-- | src/map/script-call.cpp | 130 | ||||
-rw-r--r-- | src/map/script-call.hpp | 2 | ||||
-rw-r--r-- | src/map/script-parse.cpp | 9 | ||||
-rw-r--r-- | src/map/script-parse.hpp | 4 | ||||
-rw-r--r-- | src/map/script-parse.py | 553 | ||||
-rw-r--r-- | src/map/script-persist.hpp | 2 | ||||
-rw-r--r-- | src/strings/rstring.py | 5 |
12 files changed, 584 insertions, 141 deletions
diff --git a/src/io/fd.cpp b/src/io/fd.cpp index c0b44e8..bb0bbd5 100644 --- a/src/io/fd.cpp +++ b/src/io/fd.cpp @@ -102,6 +102,11 @@ namespace io int FD::close() { + if (fd == -1) + { + errno = EBADF; + return -1; + } return ::close(fd); } int FD::shutdown(int how) diff --git a/src/map/fwd.hpp b/src/map/fwd.hpp index 3e4f221..0ab6128 100644 --- a/src/map/fwd.hpp +++ b/src/map/fwd.hpp @@ -57,7 +57,6 @@ struct item_data; enum class SP : uint16_t; -struct ScriptBuffer; struct ScriptState; namespace magic diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 2ce03ea..2f7ed30 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -200,8 +200,8 @@ bool itemdb_readdb(ZString filename) idv.elv = item.elv.data; idv.look = item.view.data; - idv.use_script = compile_script(item.use_script, true); - idv.equip_script = compile_script(item.equip_script, true); + idv.use_script = compile_script(STRPRINTF("use script %d"_fmt, idv.nameid), item.use_script, true); + idv.equip_script = compile_script(STRPRINTF("equip script %d"_fmt, idv.nameid), item.equip_script, true); Borrowed<struct item_data> id = itemdb_search(idv.nameid); *id = std::move(idv); diff --git a/src/map/magic-v2.cpp b/src/map/magic-v2.cpp index 26c1a19..204c774 100644 --- a/src/map/magic-v2.cpp +++ b/src/map/magic-v2.cpp @@ -800,7 +800,7 @@ namespace magic_v2 } auto code = TRY_UNWRAP(code_res.get_success(), return fail(s._list[1], "script does not compile"_s)); - std::unique_ptr<const ScriptBuffer> script = compile_script(code, true); + std::unique_ptr<const ScriptBuffer> script = compile_script(STRPRINTF("script magic %s:%d"_fmt, begin.filename, begin.line), code, true); if (!script) return fail(s._list[1], "script does not compile"_s); EffectScript e; diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index 22c3ce3..2bd801d 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -422,7 +422,7 @@ void npc_convertlabel_db(ScriptLabel lname, int pos, dumb_ptr<npc_data_script> n static bool npc_load_script_function(ast::script::ScriptBody& body, ast::npc::ScriptFunction& script_function) { - std::unique_ptr<const ScriptBuffer> script = compile_script(body, false); + std::unique_ptr<const ScriptBuffer> script = compile_script(STRPRINTF("script function \"%s\""_fmt, script_function.name.data), body, false); if (script == nullptr) return false; @@ -434,7 +434,7 @@ bool npc_load_script_function(ast::script::ScriptBody& body, ast::npc::ScriptFun static bool npc_load_script_none(ast::script::ScriptBody& body, ast::npc::ScriptNone& script_none) { - std::unique_ptr<const ScriptBuffer> script = compile_script(body, false); + std::unique_ptr<const ScriptBuffer> script = compile_script(STRPRINTF("script npc \"%s\""_fmt, script_none.name.data), body, false); if (script == nullptr) return false; @@ -529,7 +529,7 @@ bool npc_load_script_map_none(ast::script::ScriptBody& body, ast::npc::ScriptMap return false; }); - std::unique_ptr<const ScriptBuffer> script = compile_script(body, false); + std::unique_ptr<const ScriptBuffer> script = compile_script(STRPRINTF("script npc \"%s\""_fmt, script_map_none.name.data), body, false); if (script == nullptr) return false; @@ -638,7 +638,7 @@ bool npc_load_script_map(ast::script::ScriptBody& body, ast::npc::ScriptMap& scr return false; }); - std::unique_ptr<const ScriptBuffer> script = compile_script(body, false); + std::unique_ptr<const ScriptBuffer> script = compile_script(STRPRINTF("script npc \"%s\""_fmt, script_map.name.data), body, false); if (script == nullptr) return false; diff --git a/src/map/script-call.cpp b/src/map/script-call.cpp index 8af5099..212e0e3 100644 --- a/src/map/script-call.cpp +++ b/src/map/script-call.cpp @@ -669,136 +669,6 @@ void run_func(ScriptState *st) } } -// pretend it's external so this can be called in the debugger -void dump_script(Borrowed<const ScriptBuffer> script); -void dump_script(Borrowed<const ScriptBuffer> script) -{ - ScriptPointer scriptp(script, 0); - while (scriptp.pos < reinterpret_cast<const std::vector<ByteCode> *>(&*script)->size()) - { - PRINTF("%6zu: "_fmt, scriptp.pos); - switch (ByteCode c = get_com(&scriptp)) - { - case ByteCode::EOL: - PRINTF("EOL\n"_fmt); // extra newline between functions - break; - case ByteCode::INT: - // synthesized! - PRINTF("INT %d"_fmt, get_num(&scriptp)); - break; - - case ByteCode::POS: - case ByteCode::VARIABLE: - case ByteCode::FUNC_REF: - case ByteCode::PARAM: - { - int arg = 0; - arg |= static_cast<uint8_t>(scriptp.pop()) << 0; - arg |= static_cast<uint8_t>(scriptp.pop()) << 8; - arg |= static_cast<uint8_t>(scriptp.pop()) << 16; - switch(c) - { - case ByteCode::POS: - PRINTF("POS %d"_fmt, arg); - break; - case ByteCode::VARIABLE: - PRINTF("VARIABLE %s"_fmt, variable_names.outtern(arg)); - break; - case ByteCode::FUNC_REF: - PRINTF("FUNC_REF %s"_fmt, builtin_functions[arg].name); - break; - case ByteCode::PARAM: - PRINTF("PARAM SP::#%d (sorry)"_fmt, arg); - break; - } - } - break; - case ByteCode::ARG: - PRINTF("ARG"_fmt); - break; - case ByteCode::STR: - PRINTF("STR \"%s\""_fmt, scriptp.pops()); - break; - case ByteCode::FUNC: - PRINTF("FUNC"_fmt); - break; - - case ByteCode::ADD: - PRINTF("ADD"_fmt); - break; - case ByteCode::SUB: - PRINTF("SUB"_fmt); - break; - case ByteCode::MUL: - PRINTF("MUL"_fmt); - break; - case ByteCode::DIV: - PRINTF("DIV"_fmt); - break; - case ByteCode::MOD: - PRINTF("MOD"_fmt); - break; - case ByteCode::EQ: - PRINTF("EQ"_fmt); - break; - case ByteCode::NE: - PRINTF("NE"_fmt); - break; - case ByteCode::GT: - PRINTF("GT"_fmt); - break; - case ByteCode::GE: - PRINTF("GE"_fmt); - break; - case ByteCode::LT: - PRINTF("LT"_fmt); - break; - case ByteCode::LE: - PRINTF("LE"_fmt); - break; - case ByteCode::AND: - PRINTF("AND"_fmt); - break; - case ByteCode::OR: - PRINTF("OR"_fmt); - break; - case ByteCode::XOR: - PRINTF("XOR"_fmt); - break; - case ByteCode::LAND: - PRINTF("LAND"_fmt); - break; - case ByteCode::LOR: - PRINTF("LOR"_fmt); - break; - case ByteCode::R_SHIFT: - PRINTF("R_SHIFT"_fmt); - break; - case ByteCode::L_SHIFT: - PRINTF("L_SHIFT"_fmt); - break; - case ByteCode::NEG: - PRINTF("NEG"_fmt); - break; - case ByteCode::NOT: - PRINTF("NOT"_fmt); - break; - case ByteCode::LNOT: - PRINTF("LNOT"_fmt); - break; - - case ByteCode::NOP: - PRINTF("NOP"_fmt); - break; - - default: - PRINTF("??? %d"_fmt, c); - break; - } - PRINTF("\n"_fmt); - } -} - /*========================================== * スクリプトの実行メイン部分 *------------------------------------------ diff --git a/src/map/script-call.hpp b/src/map/script-call.hpp index 1a405b2..0819ddd 100644 --- a/src/map/script-call.hpp +++ b/src/map/script-call.hpp @@ -26,6 +26,8 @@ #include "../compat/borrow.hpp" +#include "script-buffer.hpp" + namespace tmwa { diff --git a/src/map/script-parse.cpp b/src/map/script-parse.cpp index 85e29a5..6fb94de 100644 --- a/src/map/script-parse.cpp +++ b/src/map/script-parse.cpp @@ -52,7 +52,11 @@ class ScriptBuffer typedef ZString::iterator ZSit; std::vector<ByteCode> script_buf; + RString debug_name; + std::vector<std::pair<ScriptLabel, size_t>> debug_labels; public: + ScriptBuffer(RString name) : debug_name(std::move(name)) {} + // construction methods void add_scriptc(ByteCode a); void add_scriptb(uint8_t a); @@ -694,9 +698,9 @@ void add_builtin_functions(void) } } -std::unique_ptr<const ScriptBuffer> compile_script(const ast::script::ScriptBody& body, bool implicit_end) +std::unique_ptr<const ScriptBuffer> compile_script(RString debug_name, const ast::script::ScriptBody& body, bool implicit_end) { - auto script_buf = make_unique<ScriptBuffer>(); + auto script_buf = make_unique<ScriptBuffer>(std::move(debug_name)); script_buf->parse_script(body.braced_body, body.span.begin.line, implicit_end); return std::move(script_buf); } @@ -769,6 +773,7 @@ void ScriptBuffer::parse_script(ZString src, int line, bool implicit_end) } set_label(ld, script_buf.size()); scriptlabel_db.insert(stringish<ScriptLabel>(str), script_buf.size()); + debug_labels.push_back(std::make_pair(stringish<ScriptLabel>(str), script_buf.size())); p = tmpp + 1; continue; } diff --git a/src/map/script-parse.hpp b/src/map/script-parse.hpp index b8b5012..360711e 100644 --- a/src/map/script-parse.hpp +++ b/src/map/script-parse.hpp @@ -24,10 +24,12 @@ #include <memory> +#include "script-buffer.hpp" + namespace tmwa { -std::unique_ptr<const ScriptBuffer> compile_script(const ast::script::ScriptBody& body, bool implicit_end); +std::unique_ptr<const ScriptBuffer> compile_script(RString debug_name, const ast::script::ScriptBody& body, bool implicit_end); extern Map<ScriptLabel, int> scriptlabel_db; diff --git a/src/map/script-parse.py b/src/map/script-parse.py new file mode 100644 index 0000000..de27d57 --- /dev/null +++ b/src/map/script-parse.py @@ -0,0 +1,553 @@ +class ScriptBuffer(object): + __slots__ = ('_value') + name = 'tmwa::ScriptBuffer' + enabled = True + + def __init__(self, value): + self._value = value + + def to_string(self): + return self._value['debug_name'] + + def get_com(self, b, i, r, labels_dict): + # see script-parse-internal.hpp:ByteCode and script-call.cpp:get_com + ops = ''' + NOP, POS, INT, PARAM, FUNC, STR, ARG, + VARIABLE, EOL, + LOR, LAND, LE, LT, GE, GT, EQ, NE, + XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, + NEG, LNOT, NOT, R_SHIFT, L_SHIFT, + FUNC_REF, + '''.replace(',', '').split() + ci = int(b[i]) + if ci >= 0x80: + rv = 0 + sh = 0 + # Because of how the python iterator up a frame consumed the i already, + # have to manually unroll the first iteration of the C loop. + # TODO itertools.chain([i], r) or something? + if True: + if True: + rv += (ci & 0x7f) << sh + sh += 6 + if ci >= 0xc0: + while True: + i = next(r) + ci = int(b[i]) + + rv += (ci & 0x7f) << sh + sh += 6 + if not (ci >= 0xc0): + break + return 'INT %d' % rv + + cs = ops[ci] + if cs in {'POS', 'VARIABLE', 'FUNC_REF', 'PARAM'}: + ai = 0 + ai |= (int(b[next(r)]) << 0) + ai |= (int(b[next(r)]) << 8) + ai |= (int(b[next(r)]) << 16) + if cs == 'POS': + ln = labels_dict.get(ai) + if ln is not None: + return 'POS %d %s' % (ai, ln[0]) + elif cs == 'VARIABLE': + global rstring_disable_children + rstring_disable_children = True + try: + rv = 'VARIABLE %s' % gdb.parse_and_eval('tmwa::variable_names.names._M_impl._M_start[{ai}]'.format(ai=ai)) + finally: + rstring_disable_children = False + return rv + elif cs == 'FUNC_REF': + return 'FUNC_REF %s' % gdb.parse_and_eval('tmwa::builtin_functions[{ai}].name'.format(ai=ai)) + elif cs == 'PARAM': + # https://sourceware.org/bugzilla/show_bug.cgi?id=17568 + try: + # this should work + SP = gdb.lookup_type('tmwa::SP') + except gdb.error: + # this should not work + SP = gdb.parse_and_eval('tmwa::SP').type + return 'PARAM %s' % gdb.Value(ai).cast(SP) + else: + assert False + return '%s %d' % (cs, ai) + elif cs == 'STR': + buf = bytearray() + while True: + i = next(r) + ci = int(b[i]) + if ci == 0: + break + buf.append(ci) + return 'STR "%s"' % str(buf).replace('\\', '\\\\').replace('"', '\\"') + elif cs == 'EOL': + return cs + '\n' + return cs + + def children(self): + labels = self._value['debug_labels'] + labels_begin = labels['_M_impl']['_M_start'] + labels_end = labels['_M_impl']['_M_finish'] + labels_size = int(labels_end - labels_begin) + labels_list = [labels_begin[i] for i in range(labels_size)] + labels_dict = {} + char_ptr = gdb.lookup_type('char').pointer() + for e in labels_list: + offset = int(e['second']) + label_name = str(e['first'].address.cast(char_ptr)) + labels_dict.setdefault(offset, []).append(label_name) + code = self._value['script_buf'] + code_begin = code['_M_impl']['_M_start'] + code_end = code['_M_impl']['_M_finish'] + code_size = int(code_end - code_begin) + r = iter(range(code_size)) + for i in r: + buf = [] + for label in labels_dict.get(i, []): + if label.startswith('On'): + yield 'blah', 'event %s:' % label + else: + yield 'blah', 'label %s:' % label + c = self.get_com(code_begin, i, r, labels_dict) + yield 'blah', '%6d: %s' % (i, c) + + + def display_hint(self): + return 'array' + + src = ''' + { + end; + S_Sub: + return; + OnFoo: + callsub S_Sub; + setarray @a, + -1, 0, 1, + 0x0, 0x1, 0x2, + 0x1, 0x2, 0x3, + 0x3, 0x4, 0x5, + 0x7, 0x8, 0x9, + 0xf, 0x10, 0x11, + 0x1f, 0x20, 0x21, + 0x3f, 0x40, 0x41, + 0x7f, 0x80, 0x81, + 0xff, 0x100, 0x101, + 0x1ff, 0x200, 0x201, + 0x3ff, 0x400, 0x401, + 0x7ff, 0x800, 0x801, + 0xfff, 0x1000, 0x1001, + 0x1fff, 0x2000, 0x2001, + 0x3fff, 0x4000, 0x4001, + 0x7fff, 0x8000, 0x8001, + 0xffff, 0x10000, 0x10001, + 0x1ffff, 0x20000, 0x20001, + 0x3ffff, 0x40000, 0x40001, + 0x7ffff, 0x80000, 0x80001, + 0xfffff, 0x100000, 0x100001, + 0x1fffff, 0x200000, 0x200001, + 0x3fffff, 0x400000, 0x400001, + 0x7fffff, 0x800000, 0x800001, + 0xffffff, 0x1000000, 0x1000001, + 0x1ffffff, 0x2000000, 0x2000001, + 0x3ffffff, 0x4000000, 0x4000001, + 0x7ffffff, 0x8000000, 0x8000001, + 0xfffffff, 0x10000000, 0x10000001, + 0x1fffffff, 0x20000000, 0x20000001, + 0x3fffffff, 0x40000000, 0x40000001, + 0x7fffffff, 0x80000000, 0x80000001, + 0xffffffff; + set TEST_FAKE_PARAM_BASELEVEL, TEST_FAKE_CONSTANT; + set @s$, "hello"; + set @i, a || b; + set @i, a && b; + set @i, a <= b; + set @i, a < b; + set @i, a >= b; + set @i, a > b; + set @i, a == b; + set @i, a != b; + set @i, a ^ b; + set @i, a | b; + set @i, a & b; + set @i, a + b; + set @i, a - b; + set @i, a * b; + set @i, a / b; + set @i, a % b; + set @i, - b; + set @i, ! b; + set @i, ~ b; + set @i, a >> b; + set @i, a << b; + } + '''.replace('\n', ' ') + + asm = ''\ + +''' 0: FUNC_REF "end", + 4: ARG, + 5: FUNC, + 6: EOL + , + label "S_Sub":, + 7: FUNC_REF "return", + 11: ARG, + 12: FUNC, + 13: EOL + , + label "OnFoo":, + 14: FUNC_REF "callsub", + 18: ARG, + 19: POS 7 "S_Sub", + 23: FUNC, + 24: EOL + , + 25: FUNC_REF "setarray", + 29: ARG, + 30: VARIABLE "@a", + 34: INT 1, + 35: NEG, + 36: INT 0, + 37: INT 1, + 38: INT 0, + 39: INT 1, + 40: INT 2, + 41: INT 1, + 42: INT 2, + 43: INT 3, + 44: INT 3, + 45: INT 4, + 46: INT 5, + 47: INT 7, + 48: INT 8, + 49: INT 9, + 50: INT 15, + 51: INT 16, + 52: INT 17, + 53: INT 31, + 54: INT 32, + 55: INT 33, + 56: INT 63, + 57: INT 64, + 59: INT 65, + 61: INT 127, + 63: INT 128, + 65: INT 129, + 67: INT 255, + 69: INT 256, + 71: INT 257, + 73: INT 511, + 75: INT 512, + 77: INT 513, + 79: INT 1023, + 81: INT 1024, + 83: INT 1025, + 85: INT 2047, + 87: INT 2048, + 89: INT 2049, + 91: INT 4095, + 93: INT 4096, + 95: INT 4097, + 97: INT 8191, + 100: INT 8192, + 103: INT 8193, + 106: INT 16383, + 109: INT 16384, + 112: INT 16385, + 115: INT 32767, + 118: INT 32768, + 121: INT 32769, + 124: INT 65535, + 127: INT 65536, + 130: INT 65537, + 133: INT 131071, + 136: INT 131072, + 139: INT 131073, + 142: INT 262143, + 145: INT 262144, + 148: INT 262145, + 151: INT 524287, + 155: INT 524288, + 159: INT 524289, + 163: INT 1048575, + 167: INT 1048576, + 171: INT 1048577, + 175: INT 2097151, + 179: INT 2097152, + 183: INT 2097153, + 187: INT 4194303, + 191: INT 4194304, + 195: INT 4194305, + 199: INT 8388607, + 203: INT 8388608, + 207: INT 8388609, + 211: INT 16777215, + 215: INT 16777216, + 219: INT 16777217, + 223: INT 33554431, + 228: INT 33554432, + 233: INT 33554433, + 238: INT 67108863, + 243: INT 67108864, + 248: INT 67108865, + 253: INT 134217727, + 258: INT 134217728, + 263: INT 134217729, + 268: INT 268435455, + 273: INT 268435456, + 278: INT 268435457, + 283: INT 536870911, + 288: INT 536870912, + 293: INT 536870913, + 298: INT 1073741823, + 303: INT 1073741824, + 308: INT 1073741825, + 313: INT 2147483647, + 319: INT 2147483648, + 325: INT 2147483649, + 331: INT 4294967295, + 337: FUNC, + 338: EOL + , + 339: FUNC_REF "set", + 343: ARG, + 344: PARAM tmwa::SP::BASELEVEL, + 348: INT 42, + 349: FUNC, + 350: EOL + , + 351: FUNC_REF "set", + 355: ARG, + 356: VARIABLE "@s$", + 360: STR "hello", + 367: FUNC, + 368: EOL + , + 369: FUNC_REF "set", + 373: ARG, + 374: VARIABLE "@i", + 378: VARIABLE "a", + 382: VARIABLE "b", + 386: LOR, + 387: FUNC, + 388: EOL + , + 389: FUNC_REF "set", + 393: ARG, + 394: VARIABLE "@i", + 398: VARIABLE "a", + 402: VARIABLE "b", + 406: LAND, + 407: FUNC, + 408: EOL + , + 409: FUNC_REF "set", + 413: ARG, + 414: VARIABLE "@i", + 418: VARIABLE "a", + 422: VARIABLE "b", + 426: LE, + 427: FUNC, + 428: EOL + , + 429: FUNC_REF "set", + 433: ARG, + 434: VARIABLE "@i", + 438: VARIABLE "a", + 442: VARIABLE "b", + 446: LT, + 447: FUNC, + 448: EOL + , + 449: FUNC_REF "set", + 453: ARG, + 454: VARIABLE "@i", + 458: VARIABLE "a", + 462: VARIABLE "b", + 466: GE, + 467: FUNC, + 468: EOL + , + 469: FUNC_REF "set", + 473: ARG, + 474: VARIABLE "@i", + 478: VARIABLE "a", + 482: VARIABLE "b", + 486: GT, + 487: FUNC, + 488: EOL + , + 489: FUNC_REF "set", + 493: ARG, + 494: VARIABLE "@i", + 498: VARIABLE "a", + 502: VARIABLE "b", + 506: EQ, + 507: FUNC, + 508: EOL + , + 509: FUNC_REF "set", + 513: ARG, + 514: VARIABLE "@i", + 518: VARIABLE "a", + 522: VARIABLE "b", + 526: NE, + 527: FUNC, + 528: EOL + , + 529: FUNC_REF "set", + 533: ARG, + 534: VARIABLE "@i", + 538: VARIABLE "a", + 542: VARIABLE "b", + 546: XOR, + 547: FUNC, + 548: EOL + , + 549: FUNC_REF "set", + 553: ARG, + 554: VARIABLE "@i", + 558: VARIABLE "a", + 562: VARIABLE "b", + 566: OR, + 567: FUNC, + 568: EOL + , + 569: FUNC_REF "set", + 573: ARG, + 574: VARIABLE "@i", + 578: VARIABLE "a", + 582: VARIABLE "b", + 586: AND, + 587: FUNC, + 588: EOL + , + 589: FUNC_REF "set", + 593: ARG, + 594: VARIABLE "@i", + 598: VARIABLE "a", + 602: VARIABLE "b", + 606: ADD, + 607: FUNC, + 608: EOL + , + 609: FUNC_REF "set", + 613: ARG, + 614: VARIABLE "@i", + 618: VARIABLE "a", + 622: VARIABLE "b", + 626: SUB, + 627: FUNC, + 628: EOL + , + 629: FUNC_REF "set", + 633: ARG, + 634: VARIABLE "@i", + 638: VARIABLE "a", + 642: VARIABLE "b", + 646: MUL, + 647: FUNC, + 648: EOL + , + 649: FUNC_REF "set", + 653: ARG, + 654: VARIABLE "@i", + 658: VARIABLE "a", + 662: VARIABLE "b", + 666: DIV, + 667: FUNC, + 668: EOL + , + 669: FUNC_REF "set", + 673: ARG, + 674: VARIABLE "@i", + 678: VARIABLE "a", + 682: VARIABLE "b", + 686: MOD, + 687: FUNC, + 688: EOL + , + 689: FUNC_REF "set", + 693: ARG, + 694: VARIABLE "@i", + 698: VARIABLE "b", + 702: NEG, + 703: FUNC, + 704: EOL + , + 705: FUNC_REF "set", + 709: ARG, + 710: VARIABLE "@i", + 714: VARIABLE "b", + 718: LNOT, + 719: FUNC, + 720: EOL + , + 721: FUNC_REF "set", + 725: ARG, + 726: VARIABLE "@i", + 730: VARIABLE "b", + 734: NOT, + 735: FUNC, + 736: EOL + , + 737: FUNC_REF "set", + 741: ARG, + 742: VARIABLE "@i", + 746: VARIABLE "a", + 750: VARIABLE "b", + 754: R_SHIFT, + 755: FUNC, + 756: EOL + , + 757: FUNC_REF "set", + 761: ARG, + 762: VARIABLE "@i", + 766: VARIABLE "a", + 770: VARIABLE "b", + 774: L_SHIFT, + 775: FUNC, + 776: EOL + , + 777: NOP'''.replace(''' + ''', '\n') + + test_extra = (''' + #include "../compat/borrow.hpp" + #include "../io/line.hpp" + #include "../mmo/clif.t.hpp" + #include "../ast/script.hpp" + #include "../map/script-parse-internal.hpp" + + using tmwa::operator "" _s; + + static + const tmwa::ScriptBuffer& test_script_buffer(tmwa::LString source) + { + auto p = tmwa::add_strp("TEST_FAKE_PARAM_BASELEVEL"_s); + p->type = tmwa::StringCode::PARAM; + p->val = static_cast<uint16_t>(tmwa::SP::BASELEVEL); + p = tmwa::add_strp("TEST_FAKE_CONSTANT"_s); + p->type = tmwa::StringCode::INT; + p->val = 42; + + tmwa::io::LineCharReader lr(tmwa::io::from_string, "<script debug print test>"_s, source); + tmwa::ast::script::ScriptOptions opt; + opt.implicit_start = true; + opt.implicit_end = true; + auto code_res = tmwa::ast::script::parse_script_body(lr, opt); + auto code = TRY_UNWRAP(code_res.get_success(), abort()); + auto ups = tmwa::compile_script("script debug print test"_s, code, opt.implicit_end); + assert(ups); + return *ups.release(); + } + ''') + + # the pretty-printer is designed to be run with 'set print array on' + # but the testsuite runs with all settings default, in this case off. + tests = [ + ('test_script_buffer("' + src.replace('\\', '\\\\').replace('"', '\\"') + '"_s)', + '"script debug print test" = {' + asm.replace('\n', ' ').replace('EOL ,', 'EOL\n,') + '}'), + ] diff --git a/src/map/script-persist.hpp b/src/map/script-persist.hpp index 3d9f22b..044c567 100644 --- a/src/map/script-persist.hpp +++ b/src/map/script-persist.hpp @@ -28,6 +28,8 @@ #include "../sexpr/variant.hpp" +#include "script-buffer.hpp" + namespace tmwa { diff --git a/src/strings/rstring.py b/src/strings/rstring.py index 27e9ff2..75fe2db 100644 --- a/src/strings/rstring.py +++ b/src/strings/rstring.py @@ -1,3 +1,6 @@ +# used by other pretty-printers +rstring_disable_children = False + class RString(object): __slots__ = ('_value') name = 'tmwa::strings::RString' @@ -21,6 +24,8 @@ class RString(object): return b.lazy_string(length=d) def children(self): + if rstring_disable_children: + return v = self._value if v['maybe_end']: pass |