/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_object_json_reader_func_null(tb_object_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t null = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // append character if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("null: %s", tb_static_string_cstr(&data)); // null? if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_object_null_init(); } while (0); // exit data tb_static_string_exit(&data); // ok? return null; }
tb_bool_t vm86_parser_get_number_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value) { // check tb_assert(pp && e && value); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // check tb_check_break(p < e && (tb_isdigit16(*p) || *p == '-')); // is sign? tb_bool_t is_sign = tb_false; if (*p == '-') { is_sign = tb_true; p++; } // save the base tb_char_t const* b = p; // skip the value while (p < e && tb_isdigit16(*p)) p++; // is hex? tb_bool_t is_hex = tb_false; if (p < e && *p == 'h') { is_hex = tb_true; p++; } // check end, exclude variable name tb_check_break(!tb_isalpha(*p) && *p != '_'); // save value *value = is_hex? tb_s16tou32(b) : tb_s10tou32(b); if (is_sign) *value = (tb_uint32_t)(((tb_sint32_t)*value) * -1); // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
static tb_void_t tb_check_is() { tb_int_t i = 0; for (i = 0; i < 256; i++) { if ((tb_isspace(i)? 1 : 0) != (isspace(i)? 1 : 0)) tb_printf("[e] isspace: 0x%02x\n", i); if ((tb_isalpha(i)? 1 : 0) != (isalpha(i)? 1 : 0)) tb_printf("[e] isalpha: 0x%02x\n", i); if ((tb_isdigit(i)? 1 : 0) != (isdigit(i)? 1 : 0)) tb_printf("[e] isdigit: 0x%02x\n", i); if ((tb_isupper(i)? 1 : 0) != (isupper(i)? 1 : 0)) tb_printf("[e] isupper: 0x%02x\n", i); if ((tb_islower(i)? 1 : 0) != (islower(i)? 1 : 0)) tb_printf("[e] islower: 0x%02x\n", i); if ((tb_isascii(i)? 1 : 0) != (isascii(i)? 1 : 0)) tb_printf("[e] isascii: 0x%02x\n", i); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t vm86_parser_get_variable_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn) { // check tb_assert(pp && e && name && maxn); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // check tb_check_break(p < e && (tb_isalpha(*p) || *p == '_')); p++; // get name while (p < e && (tb_isalpha(*p) || *p == '_' || tb_isdigit(*p))) p++; tb_check_break(p <= e && p - b < maxn); tb_memcpy(name, b, p - b); // end name[p - b] = '\0'; // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
tb_bool_t tb_path_is_absolute(tb_char_t const* path) { // check tb_assert_and_check_return_val(path, tb_false); // is absolute? #ifdef TB_CONFIG_OS_WINDOWS return ( path[0] == '~' || (tb_isalpha(path[0]) && path[1] == ':' && tb_path_is_separator(path[2]))); #else return ( path[0] == '/' || path[0] == '\\' || path[0] == '~' || !tb_strnicmp(path, "file:", 5)); #endif }
tb_bool_t vm86_parser_get_instruction_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn) { // check tb_assert(pp && e && name && maxn); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // skip name while (p < e && tb_isalpha(*p)) p++; tb_check_break(p <= e && p - b < maxn); // not instruction name? if (p < e && !tb_isspace(*p)) break; // save name tb_memcpy(name, b, p - b); // end name[p - b] = '\0'; // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_path_translate(tb_char_t* path, tb_size_t size, tb_size_t maxn) { // check tb_assert_and_check_return_val(path, 0); // file://? tb_char_t* p = path; if (!tb_strnicmp(p, "file:", 5)) p += 5; // is user directory? else if (path[0] == '~') { // get the home directory tb_char_t home[TB_PATH_MAXN]; tb_size_t home_size = tb_directory_home(home, sizeof(home) - 1); tb_assert_and_check_return_val(home_size, 0); // check the path space tb_size_t path_size = size? size : tb_strlen(path); tb_assert_and_check_return_val(home_size + path_size - 1 < maxn, 0); // move the path and ensure the enough space for the home directory tb_memmov(path + home_size, path + 1, path_size - 1); // copy the home directory tb_memcpy(path, home, home_size); path[home_size + path_size - 1] = '\0'; } // remove repeat separator tb_char_t* q = path; tb_size_t repeat = 0; for (; *p; p++) { if (tb_path_is_separator(*p)) { // save the separator if not exists if (!repeat) *q++ = TB_PATH_SEPARATOR; // repeat it repeat++; } else { // save character *q++ = *p; // clear repeat repeat = 0; } } // remove the tail separator and not root: '/' if (q > path + 1 && *(q - 1) == TB_PATH_SEPARATOR) q--; // end *q = '\0'; // is windows path? if (q > path + 1 && tb_isalpha(path[0]) && path[1] == ':') { // get the upper drive prefix path[0] = tb_toupper(path[0]); // append the drive separator if not exists if (q - path == 2) { *q++ = TB_PATH_SEPARATOR; *q = '\0'; } } // trace tb_trace_d("translate: %s", path); // ok return q - path; }
tb_char_t const* tb_path_absolute_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn) { // check tb_assert_and_check_return_val(path && data && maxn, tb_null); // trace tb_trace_d("path: %s", path); // the path is absolute? if (tb_path_is_absolute(path)) { // copy it tb_strlcpy(data, path, maxn); // translate it return tb_path_translate(data, 0, maxn)? data : tb_null; } // get the root directory tb_size_t size = 0; if (root) { // copy it size = tb_strlcpy(data, root, maxn); tb_assert_and_check_return_val(size < maxn, tb_null); } else { // get the current directory if (!(size = tb_directory_current(data, maxn))) return tb_null; } // translate the root directory size = tb_path_translate(data, size, maxn); // trace tb_trace_d("root: %s, size: %lu", data, size); // is windows path? skip the drive prefix tb_char_t* absolute = data; if (size > 2 && tb_isalpha(absolute[0]) && absolute[1] == ':' && absolute[2] == TB_PATH_SEPARATOR) { // skip it absolute += 2; size -= 2; } // path => data tb_char_t const* p = path; tb_char_t const* t = p; tb_char_t* q = absolute + size; tb_char_t const* e = absolute + maxn - 1; while (1) { if (tb_path_is_separator(*p) || !*p) { // the item size tb_size_t n = p - t; // ..? remove item if (n == 2 && t[0] == '.' && t[1] == '.') { // find the last separator for (; q > absolute && *q != TB_PATH_SEPARATOR; q--) ; // strip it *q = '\0'; } // .? continue it else if (n == 1 && t[0] == '.') ; // append item else if (n && q + 1 + n < e) { *q++ = TB_PATH_SEPARATOR; tb_strncpy(q, t, n); q += n; } // empty item? remove repeat else if (!n) ; // too small? else { // trace tb_trace_e("the data path is too small for %s", path); return tb_null; } // break tb_check_break(*p); // next t = p + 1; } // next p++; } // end if (q > absolute) *q = '\0'; // root? else { *q++ = TB_PATH_SEPARATOR; *q = '\0'; } // trace tb_trace_d("absolute: %s", data); // ok? return data; }
tb_void_t tb_option_help(tb_option_ref_t option) { // check tb_option_impl_t* impl = (tb_option_impl_t*)option; tb_assert_and_check_return(impl && impl->opts); // dump usage head tb_printf("======================================================================\n"); tb_printf("[usage]: %s", impl->name); // dump usage item tb_bool_t bopt = tb_false; tb_option_item_t const* item = impl->opts; while (item) { // dump options if (bopt && item->mode != TB_OPTION_MODE_KEY && item->mode != TB_OPTION_MODE_KEY_VAL) { tb_printf(" [options]"); bopt = tb_false; } // dump item switch (item->mode) { case TB_OPTION_MODE_KEY: case TB_OPTION_MODE_KEY_VAL: { bopt = tb_true; item++; } break; case TB_OPTION_MODE_VAL: { tb_printf(" %s", item->lname); item++; } break; case TB_OPTION_MODE_MORE: tb_printf(" ..."); case TB_OPTION_MODE_END: default: item = tb_null; break; } } // dump usage tail tb_printf("\n\n"); // dump help if (tb_string_size(&impl->help)) tb_printf("[help]: %s\n\n", tb_string_cstr(&impl->help)); // dump options head tb_printf("[options]: \n"); for (item = impl->opts; item; ) { // dump item tb_size_t spaces = 32; switch (item->mode) { case TB_OPTION_MODE_KEY: case TB_OPTION_MODE_KEY_VAL: { // dump spaces tb_printf(" "); spaces -= 3; // has short name? if (tb_isalpha(item->sname)) { // dump short name tb_printf("-%c", item->sname); spaces -= 2; // dump long name if (item->lname) { tb_printf(", --%s", item->lname); spaces -= 4; if (tb_strlen(item->lname) <= spaces) spaces -= tb_strlen(item->lname); } } // dump long name else if (item->lname) { tb_printf(" --%s", item->lname); spaces -= 6; if (tb_strlen(item->lname) <= spaces) spaces -= tb_strlen(item->lname); } // dump value if (item->mode == TB_OPTION_MODE_KEY_VAL) { switch (item->type) { case TB_OPTION_TYPE_BOOL: tb_printf("=BOOL"); spaces -= 5; break; case TB_OPTION_TYPE_CSTR: tb_printf("=STRING"); spaces -= 7; break; case TB_OPTION_TYPE_INTEGER: tb_printf("=INTEGER"); spaces -= 8; break; case TB_OPTION_TYPE_FLOAT: tb_printf("=FLOAT"); spaces -= 6; break; default: break; } } // dump help if (item->help) { tb_char_t line[8192] = {0}; tb_char_t const* pb = item->help; tb_char_t* qb = line; tb_char_t* qe = line + 8192; while (qb < qe) { if (*pb != '\n' && *pb) *qb++ = *pb++; else { // strip line and next *qb = '\0'; qb = line; // dump spaces while (spaces--) tb_printf(" "); // dump help line tb_printf("%s", line); // reset spaces spaces = 32; // next or end? if (*pb) { // dump new line tb_printf("\n"); pb++; } else break; } } } // dump newline tb_printf("\n"); // next item++; } break; case TB_OPTION_MODE_VAL: item++; break; case TB_OPTION_MODE_MORE: case TB_OPTION_MODE_END: default: item = tb_null; break; } } // dump options tail tb_printf("\n\n"); // dump values head tb_printf("[values]: \n"); for (item = impl->opts; item; ) { // dump item tb_size_t spaces = 32; switch (item->mode) { case TB_OPTION_MODE_KEY: case TB_OPTION_MODE_KEY_VAL: item++; break; case TB_OPTION_MODE_VAL: { // dump spaces tb_printf(" "); spaces -= 3; // dump long name if (item->lname) { tb_printf("%s", item->lname); if (tb_strlen(item->lname) <= spaces) spaces -= tb_strlen(item->lname); } // dump help if (item->help) { tb_char_t line[8192] = {0}; tb_char_t const* pb = item->help; tb_char_t* qb = line; tb_char_t* qe = line + 8192; while (qb < qe) { if (*pb != '\n' && *pb) *qb++ = *pb++; else { // strip line and next *qb = '\0'; qb = line; // dump spaces while (spaces--) tb_printf(" "); // dump help line tb_printf("%s", line); // reset spaces spaces = 32; // next or end? if (*pb) { // dump new line tb_printf("\n"); pb++; } else break; } } } // dump newline tb_printf("\n"); // next item++; } break; case TB_OPTION_MODE_MORE: tb_printf(" ...\n"); case TB_OPTION_MODE_END: default: item = tb_null; break; } } // dump values tail tb_printf("\n"); }
tb_bool_t tb_option_done(tb_option_ref_t option, tb_size_t argc, tb_char_t** argv) { // check tb_option_impl_t* impl = (tb_option_impl_t*)option; tb_assert_and_check_return_val(impl && impl->list && impl->opts, tb_false); // walk arguments tb_size_t i = 0; tb_size_t more = 0; tb_option_item_t const* item = impl->opts; tb_option_item_t const* last = tb_null; for (i = 0; i < argc; i++) { // the argument tb_char_t* p = argv[i]; tb_char_t* e = p + tb_strlen(p); tb_assert_and_check_return_val(p && p < e, tb_false); // is long key? if (p + 2 < e && p[0] == '-' && p[1] == '-' && tb_isalpha(p[2])) { // the key tb_char_t key[512] = {0}; { tb_char_t* k = key; tb_char_t* e = key + 511; for (p += 2; *p && *p != '=' && k < e; p++, k++) *k = *p; } // the val tb_char_t* val = (*p == '=')? (p + 1) : tb_null; // trace tb_trace_d("[lname]: %s => %s", key, val); // find the item tb_option_item_t const* find = tb_option_item_find(impl->opts, key, '\0'); if (find) { // check key & val if (!val == !(find->mode == TB_OPTION_MODE_KEY_VAL)) { // has value? tb_object_ref_t object = tb_null; if (val) { // init the value object switch (find->type) { case TB_OPTION_TYPE_CSTR: object = tb_oc_string_init_from_cstr(val); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(val), tb_false); object = tb_oc_number_init_from_sint64(tb_atoll(val)); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(val), tb_false); object = tb_oc_boolean_init(!tb_stricmp(val, "y")? tb_true : tb_false); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(val), tb_false); object = tb_oc_number_init_from_double(tb_atof(val)); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } } else { // check tb_assert_and_check_return_val(find->type == TB_OPTION_TYPE_BOOL, tb_false); // key => true object = tb_oc_boolean_init(tb_true); } // add the value object if (object) { tb_oc_dictionary_insert(impl->list, key, object); if (tb_isalpha(find->sname)) { tb_char_t ch[2] = {0}; ch[0] = find->sname; tb_oc_dictionary_insert(impl->list, ch, object); tb_object_retain(object); } } } else if (val) { // print tb_trace_e("%s: unrecognized option value '--%s=%s'", impl->name, key, val); // next continue ; } else { // print tb_trace_e("%s: no option value '--%s='", impl->name, key); // next continue ; } } else { // print tb_trace_e("%s: unrecognized option '--%s'", impl->name, key); // next continue ; } } // is short key? else if (p + 1 < e && p[0] == '-' && tb_isalpha(p[1])) { // the key tb_char_t key[512] = {0}; { tb_char_t* k = key; tb_char_t* e = key + 511; for (p += 1; *p && *p != '=' && k < e; p++, k++) *k = *p; } // the val tb_char_t const* val = (*p == '=')? (p + 1) : tb_null; // trace tb_trace_d("[sname]: %s => %s", key, val); // is short name? if (tb_strlen(key) != 1) { // print tb_trace_e("%s: unrecognized option '-%s'", impl->name, key); // next continue ; } // find the item tb_option_item_t const* find = tb_option_item_find(impl->opts, tb_null, key[0]); if (find) { // check key & val if (!val == !(find->mode == TB_OPTION_MODE_KEY_VAL)) { // has value? tb_object_ref_t object = tb_null; if (val) { // add value switch (find->type) { case TB_OPTION_TYPE_CSTR: object = tb_oc_string_init_from_cstr(val); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(val), tb_false); object = tb_oc_number_init_from_sint64(tb_atoll(val)); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(val), tb_false); object = tb_oc_boolean_init(!tb_stricmp(val, "y")? tb_true : tb_false); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(val), tb_false); object = tb_oc_number_init_from_double(tb_atof(val)); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } } else { // check tb_assert_and_check_return_val(find->type == TB_OPTION_TYPE_BOOL, tb_false); // key => true object = tb_oc_boolean_init(tb_true); } // add the value object if (object) { tb_oc_dictionary_insert(impl->list, key, object); if (find->lname) { tb_oc_dictionary_insert(impl->list, find->lname, object); tb_object_retain(object); } } } else if (val) { // print tb_trace_e("%s: unrecognized option value '--%s=%s'", impl->name, key, val); // next continue ; } else { // print tb_trace_e("%s: no option value '--%s='", impl->name, key); // next continue ; } } else { // print tb_trace_e("%s: unrecognized option '-%s'", impl->name, key); // next continue ; } } // is value? else { // trace tb_trace_d("[val]: %s", p); // find the value item while (item && item->mode != TB_OPTION_MODE_VAL && item->mode != TB_OPTION_MODE_END && item->mode != TB_OPTION_MODE_MORE) item++; // has value item? if (item->mode == TB_OPTION_MODE_VAL) { // check tb_assert_and_check_return_val(item->lname, tb_false); // add value switch (item->type) { case TB_OPTION_TYPE_CSTR: tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_string_init_from_cstr(p)); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_number_init_from_sint64(tb_atoll(p))); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_boolean_init(!tb_stricmp(p, "y")? tb_true : tb_false)); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_number_init_from_double(tb_atof(p))); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } // save last last = item; // next item item++; } // has more item? else if (item->mode == TB_OPTION_MODE_MORE && last) { // the more name tb_char_t name[64] = {0}; tb_snprintf(name, 63, "more%lu", more); // add value switch (last->type) { case TB_OPTION_TYPE_CSTR: tb_oc_dictionary_insert(impl->list, name, tb_oc_string_init_from_cstr(p)); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_number_init_from_sint64(tb_atoll(p))); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_boolean_init(!tb_stricmp(p, "y")? tb_true : tb_false)); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_number_init_from_double(tb_atof(p))); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } // next more more++; } } } // ok return tb_true;//tb_option_check(impl); }
tb_bool_t vm86_parser_get_register(tb_char_t const** pp, tb_char_t const* e, tb_uint16_t* r) { // check tb_assert(pp && e && r); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // get instruction name tb_char_t name[64] = {0}; while (p < e && tb_isalpha(*p)) p++; tb_check_break(p <= e && p - b < sizeof(name)); tb_memcpy(name, b, p - b); // skip the space while (p < e && tb_isspace(*p)) p++; // the register entry type typedef struct __vm86_register_entry_t { // the register name tb_char_t const* name; // the register index tb_uint8_t index; }vm86_register_entry_t, *vm86_register_entry_ref_t; // the registers static vm86_register_entry_t s_registers[] = { { "ah", VM86_REGISTER_EAX | VM86_REGISTER_AH } , { "al", VM86_REGISTER_EAX | VM86_REGISTER_AL } , { "ax", VM86_REGISTER_EAX | VM86_REGISTER_AX } , { "bh", VM86_REGISTER_EBX | VM86_REGISTER_BH } , { "bl", VM86_REGISTER_EBX | VM86_REGISTER_BL } , { "bx", VM86_REGISTER_EBX | VM86_REGISTER_BX } , { "ch", VM86_REGISTER_ECX | VM86_REGISTER_CH } , { "cl", VM86_REGISTER_ECX | VM86_REGISTER_CL } , { "cx", VM86_REGISTER_ECX | VM86_REGISTER_CX } , { "dh", VM86_REGISTER_EDX | VM86_REGISTER_DH } , { "dl", VM86_REGISTER_EDX | VM86_REGISTER_DL } , { "dx", VM86_REGISTER_EDX | VM86_REGISTER_DX } , { "eax", VM86_REGISTER_EAX } , { "ebp", VM86_REGISTER_EBP } , { "ebx", VM86_REGISTER_EBX } , { "ecx", VM86_REGISTER_ECX } , { "edi", VM86_REGISTER_EDI } , { "edx", VM86_REGISTER_EDX } , { "esi", VM86_REGISTER_ESI } , { "esp", VM86_REGISTER_ESP } }; // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, s_registers, tb_arrayn(s_registers), sizeof(vm86_register_entry_t)); // find register by the binary search tb_size_t itor = tb_binary_find_all_if(iterator, vm86_parser_comp_register, name); tb_check_break(itor != tb_iterator_tail(iterator)); // get the register vm86_register_entry_ref_t entry = (vm86_register_entry_ref_t)tb_iterator_item(iterator, itor); tb_assert_and_check_break(entry && (entry->index & VM86_REGISTER_MASK) < VM86_REGISTER_MAXN); // save register *r = entry->index; // trace tb_trace_d("register: %s: %x", name, entry->index); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }