+uint32_t code_genstring(const char *str)
+{
+ uint32_t off = code_chars_elements;
+ while (*str) {
+ code_chars_add(*str);
+ ++str;
+ }
+ code_chars_add(0);
+ return off;
+}
+
+uint32_t code_cachedstring(const char *str)
+{
+ size_t s = 0;
+ /* We could implement knuth-morris-pratt or something
+ * and also take substrings, but I'm uncomfortable with
+ * pointing to subparts of strings for the sake of clarity...
+ */
+ while (s < code_chars_elements) {
+ if (!strcmp(str, code_chars_data + s))
+ return s;
+ while (code_chars_data[s]) ++s;
+ ++s;
+ }
+ return code_genstring(str);
+}
+
+void code_test() {
+ prog_section_def d1 = { TYPE_VOID, 28, 1 };
+ prog_section_def d2 = { TYPE_FUNCTION, 29, 8 };
+ prog_section_def d3 = { TYPE_STRING, 30, 14};
+ prog_section_function f1 = { 1, 0, 0, 0, 1, 0,0, {0}};
+ prog_section_function f2 = {-4, 0, 0, 0, 8, 0,0, {0}};
+ prog_section_function f3 = { 0, 0, 0, 0, 14+13, 0,0, {0}};
+ prog_section_function f4 = { 0, 0, 0, 0, 14+13+10, 0,0, {0}};
+ prog_section_function f5 = { 0, 0, 0, 0, 14+13+10+7, 0,0, {0}};
+ prog_section_function f6 = { 0, 0, 0, 0, 14+13+10+7+9, 0,0, {0}};
+ prog_section_statement s1 = { INSTR_STORE_F, {30}, {OFS_PARM0}, {0}};
+ prog_section_statement s2 = { INSTR_CALL1, {29}, {0}, {0}};
+ prog_section_statement s3 = { INSTR_RETURN, {0}, {0}, {0}};
+
+ code_chars_put("m_init", 0x6);
+ code_chars_put("print", 0x5);
+ code_chars_put("hello world\n", 0xC);
+ code_chars_put("m_keydown", 0x9);
+ code_chars_put("m_draw", 0x6);
+ code_chars_put("m_toggle", 0x8);
+ code_chars_put("m_shutdown", 0xA);
+