当前位置: 首页>>代码示例>>C++>>正文


C++ qstr_str函数代码示例

本文整理汇总了C++中qstr_str函数的典型用法代码示例。如果您正苦于以下问题:C++ qstr_str函数的具体用法?C++ qstr_str怎么用?C++ qstr_str使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了qstr_str函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: mp_obj_print_exception

// helper function to print an exception with traceback
void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc) {
    if (mp_obj_is_exception_instance(exc)) {
        mp_uint_t n, *values;
        mp_obj_exception_get_traceback(exc, &n, &values);
        if (n > 0) {
            assert(n % 3 == 0);
            print(env, "Traceback (most recent call last):\n");
            for (int i = n - 3; i >= 0; i -= 3) {
#if MICROPY_ENABLE_SOURCE_LINE
                print(env, "  File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
#else
                print(env, "  File \"%s\"", qstr_str(values[i]));
#endif
                // the block name can be NULL if it's unknown
                qstr block = values[i + 2];
                if (block == MP_QSTR_NULL) {
                    print(env, "\n");
                } else {
                    print(env, ", in %s\n", qstr_str(block));
                }
            }
        }
    }
    mp_obj_print_helper(print, env, exc, PRINT_EXC);
    print(env, "\n");
}
开发者ID:Lothilius,项目名称:micropython,代码行数:27,代码来源:obj.c

示例2: mp_parse_node_show

void mp_parse_node_show(mp_parse_node_t pn, int indent) {
    for (int i = 0; i < indent; i++) {
        printf(" ");
    }
    if (MP_PARSE_NODE_IS_NULL(pn)) {
        printf("NULL\n");
    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
        int arg = MP_PARSE_NODE_LEAF_ARG(pn);
        switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
            case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_SMALL_INT: printf("int(%d)\n", arg); break;
            case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_TOKEN: printf("tok(%d)\n", arg); break;
            default: assert(0);
        }
    } else {
        mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pn;
        int n = pns2->kind_num_nodes >> 8;
#ifdef USE_RULE_NAME
        printf("%s(%d) (n=%d)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns2)]->rule_name, MP_PARSE_NODE_STRUCT_KIND(pns2), n);
#else
        printf("rule(%u) (n=%d)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns2), n);
#endif
        for (int i = 0; i < n; i++) {
            mp_parse_node_show(pns2->nodes[i], indent + 2);
        }
    }
}
开发者ID:brooksman,项目名称:micropython,代码行数:31,代码来源:parse.c

示例3: pin_print

/// \method __str__()
/// Return a string describing the pin object.
STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
    pin_obj_t *self = self_in;

    // pin name
    print(env, "Pin(Pin.cpu.%s, mode=Pin.", qstr_str(self->name));

    uint32_t mode = pin_get_mode(self);

    if (mode == GPIO_MODE_ANALOG) {
        // analog
        print(env, "ANALOG)");

    } else {
        // IO mode
        bool af = false;
        qstr mode_qst;
        if (mode == GPIO_MODE_INPUT) {
            mode_qst = MP_QSTR_IN;
        } else if (mode == GPIO_MODE_OUTPUT_PP) {
            mode_qst = MP_QSTR_OUT_PP;
        } else if (mode == GPIO_MODE_OUTPUT_OD) {
            mode_qst = MP_QSTR_OUT_OD;
        } else {
            af = true;
            if (mode == GPIO_MODE_AF_PP) {
                mode_qst = MP_QSTR_AF_PP;
            } else {
                mode_qst = MP_QSTR_AF_OD;
            }
        }
        print(env, qstr_str(mode_qst)); // safe because mode_qst has no formating chars

        // pull mode
        qstr pull_qst = MP_QSTR_NULL;
        uint32_t pull = pin_get_pull(self);
        if (pull == GPIO_PULLUP) {
            pull_qst = MP_QSTR_PULL_UP;
        } else if (pull == GPIO_PULLDOWN) {
            pull_qst = MP_QSTR_PULL_DOWN;
        }
        if (pull_qst != MP_QSTR_NULL) {
            print(env, ", pull=Pin.%s", qstr_str(pull_qst));
        }

        // AF mode
        if (af) {
            mp_uint_t af_idx = pin_get_af(self);
            const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx);
            if (af_obj == NULL) {
                print(env, ", af=%d)", af_idx);
            } else {
                print(env, ", af=Pin.%s)", qstr_str(af_obj->name));
            }
        } else {
            print(env, ")");
        }
    }
}
开发者ID:gradoj,项目名称:micropython,代码行数:60,代码来源:pin.c

示例4: exception_print

void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
    mp_obj_exception_t *o = o_in;
    if (o->msg != 0) {
        print(env, "%s: %s", qstr_str(o->id), qstr_str(o->msg));
    } else {
        print(env, "%s", qstr_str(o->id));
        tuple_print(print, env, &o->args);
    }
}
开发者ID:brooksman,项目名称:micropython,代码行数:9,代码来源:objexcept.c

示例5: get_arg_i

STATIC int get_arg_i(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
    if (!MP_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
        printf("SyntaxError: '%s' expects an integer in position %d\n", qstr_str(op), wanted_arg_num);
        return 0;
    }
    int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn_args[wanted_arg_num]);
    if ((i & (~fit_mask)) != 0) {
        printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", qstr_str(op), i, fit_mask);
        return 0;
    }
    return i;
}
开发者ID:UNIVERSAL-IT-SYSTEMS,项目名称:micropython,代码行数:12,代码来源:emitinlinethumb.c

示例6: get_arg_rlo

STATIC uint get_arg_rlo(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) {
    if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
        printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
        return 0;
    }
    qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
    const char *reg_str = qstr_str(reg_qstr);
    if (!(strlen(reg_str) == 2 && reg_str[0] == 'r' && ('0' <= reg_str[1] && reg_str[1] <= '7'))) {
        printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
        return 0;
    }
    return reg_str[1] - '0';
}
开发者ID:UNIVERSAL-IT-SYSTEMS,项目名称:micropython,代码行数:13,代码来源:emitinlinethumb.c

示例7: m_renew

id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) {
    for (int i = 0; i < scope->id_info_len; i++) {
        if (scope->id_info[i].qstr == qstr) {
            *added = false;
            return &scope->id_info[i];
        }
    }

    // make sure we have enough memory
    if (scope->id_info_len >= scope->id_info_alloc) {
        scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc * 2);
        scope->id_info_alloc *= 2;
    }

    id_info_t *id_info;

    {
    /*
    // just pick next slot in array
    id_info = &scope->id_info[scope->id_info_len++];
    */
    }

    if (0) {
        // sort insert into id_info array, so we are equivalent to CPython (no other reason to do it)
        // actually, seems that this is not what CPython does...
        scope->id_info_len += 1;
        for (int i = scope->id_info_len - 1;; i--) {
            if (i == 0 || strcmp(qstr_str(scope->id_info[i - 1].qstr), qstr_str(qstr)) < 0) {
                id_info = &scope->id_info[i];
                break;
            } else {
                scope->id_info[i] = scope->id_info[i - 1];
            }
        }
    } else {
        // just add new id to end of array of all ids; this seems to match CPython
        // important thing is that function arguments are first, but that is
        // handled by the compiler because it adds arguments before compiling the body
        id_info = &scope->id_info[scope->id_info_len++];
    }

    id_info->param = false;
    id_info->kind = 0;
    id_info->qstr = qstr;
    id_info->local_num = 0;
    *added = true;
    return id_info;
}
开发者ID:BlastarIndia,项目名称:micropython,代码行数:49,代码来源:scope.c

示例8: mp_parse_node_print

void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
    if (MP_PARSE_NODE_IS_STRUCT(pn)) {
        printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
    } else {
        printf("       ");
    }
    for (size_t i = 0; i < indent; i++) {
        printf(" ");
    }
    if (MP_PARSE_NODE_IS_NULL(pn)) {
        printf("NULL\n");
    } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
        mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
        printf("int(" INT_FMT ")\n", arg);
    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
        uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
        switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
            case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
            case MP_PARSE_NODE_TOKEN: printf("tok(%u)\n", (uint)arg); break;
            default: assert(0);
        }
    } else {
        // node must be a mp_parse_node_struct_t
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
            printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
            printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
            #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
            printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
            #else
            printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
            #endif
        } else {
            size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
#ifdef USE_RULE_NAME
            printf("%s(%u) (n=%u)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
#else
            printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n);
#endif
            for (size_t i = 0; i < n; i++) {
                mp_parse_node_print(pns->nodes[i], indent + 2);
            }
        }
    }
}
开发者ID:19emtuck,项目名称:micropython,代码行数:49,代码来源:parse.c

示例9: mp_obj_exception_print

STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
    mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in);
    mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
    bool is_subclass = kind & PRINT_EXC_SUBCLASS;
    if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {
        mp_print_str(print, qstr_str(o->base.type->name));
    }

    if (k == PRINT_EXC) {
        mp_print_str(print, ": ");
    }

    if (k == PRINT_STR || k == PRINT_EXC) {
        if (o->args == NULL || o->args->len == 0) {
            mp_print_str(print, "");
            return;
        } else if (o->args->len == 1) {
            #if MICROPY_PY_UERRNO
            // try to provide a nice OSError error message
            if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
                qstr qst = mp_errno_to_str(o->args->items[0]);
                if (qst != MP_QSTR_NULL) {
                    mp_printf(print, "[Errno %d] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);
                    return;
                }
            }
            #endif
            mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
            return;
        }
    }
    mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind);
}
开发者ID:cav71,项目名称:micropython,代码行数:33,代码来源:objexcept.c

示例10: jobject_attr

STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) {
    if (dest[0] == MP_OBJ_NULL) {
        // load attribute
        mp_obj_jobject_t *self = self_in;

        const char *attr = qstr_str(attr_in);
        jclass obj_class = JJ(GetObjectClass, self->obj);
        jstring field_name = JJ(NewStringUTF, attr);
        jobject field = JJ(CallObjectMethod, obj_class, Class_getField_mid, field_name);
        JJ(DeleteLocalRef, field_name);
        JJ(DeleteLocalRef, obj_class);
        if (!JJ1(ExceptionCheck)) {
            jfieldID field_id = JJ(FromReflectedField, field);
            JJ(DeleteLocalRef, field);
            jobject obj = JJ(GetObjectField, self->obj, field_id);
            dest[0] = new_jobject(obj);
            return;
        }
        //JJ1(ExceptionDescribe);
        JJ1(ExceptionClear);

        mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t);
        o->base.type = &jmethod_type;
        o->name = attr_in;
        o->meth = NULL;
        o->obj = self->obj;
        o->is_static = false;
        dest[0] = o;
    }
}
开发者ID:raccoonjr,项目名称:micropython,代码行数:30,代码来源:modjni.c

示例11: convert_obj_for_inline_asm

// convert a Micro Python object to a sensible value for inline asm
machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
    // TODO for byte_array, pass pointer to the array
    if (MP_OBJ_IS_SMALL_INT(obj)) {
        return MP_OBJ_SMALL_INT_VALUE(obj);
    } else if (obj == mp_const_none) {
        return 0;
    } else if (obj == mp_const_false) {
        return 0;
    } else if (obj == mp_const_true) {
        return 1;
    } else if (MP_OBJ_IS_TYPE(obj, &str_type)) {
        // pointer to the string (it's probably constant though!)
        return (machine_uint_t)qstr_str(mp_obj_str_get(obj));
#if MICROPY_ENABLE_FLOAT
    } else if (MP_OBJ_IS_TYPE(obj, &float_type)) {
        // convert float to int (could also pass in float registers)
        return (machine_int_t)mp_obj_float_get(obj);
#endif
    } else if (MP_OBJ_IS_TYPE(obj, &tuple_type)) {
        // pointer to start of tuple (could pass length, but then could use len(x) for that)
        uint len;
        mp_obj_t *items;
        mp_obj_tuple_get(obj, &len, &items);
        return (machine_uint_t)items;
    } else if (MP_OBJ_IS_TYPE(obj, &list_type)) {
        // pointer to start of list (could pass length, but then could use len(x) for that)
        uint len;
        mp_obj_t *items;
        mp_obj_list_get(obj, &len, &items);
        return (machine_uint_t)items;
    } else {
        // just pass along a pointer to the object
        return (machine_uint_t)obj;
    }
}
开发者ID:FurKan7,项目名称:micropython,代码行数:36,代码来源:objfun.c

示例12: mp_emit_glue_assign_byte_code

void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, uint n_pos_args, uint n_kwonly_args, qstr *arg_names, uint scope_flags) {
    rc->kind = MP_CODE_BYTE;
    rc->scope_flags = scope_flags;
    rc->n_pos_args = n_pos_args;
    rc->n_kwonly_args = n_kwonly_args;
    rc->arg_names = arg_names;
    rc->u_byte.code = code;
    rc->u_byte.len = len;

#ifdef DEBUG_PRINT
    DEBUG_printf("assign byte code: code=%p len=%u n_pos_args=%d n_kwonly_args=%d flags=%x\n", code, len, n_pos_args, n_kwonly_args, scope_flags);
    DEBUG_printf("  arg names:");
    for (int i = 0; i < n_pos_args + n_kwonly_args; i++) {
        DEBUG_printf(" %s", qstr_str(arg_names[i]));
    }
    DEBUG_printf("\n");
    for (int i = 0; i < 128 && i < len; i++) {
        if (i > 0 && i % 16 == 0) {
            DEBUG_printf("\n");
        }
        DEBUG_printf(" %02x", code[i]);
    }
    DEBUG_printf("\n");
#if MICROPY_DEBUG_PRINTERS
    mp_byte_code_print(code, len);
#endif
#endif
}
开发者ID:CarterTsai,项目名称:micropython,代码行数:28,代码来源:emitglue.c

示例13: mp_bytecode_print

void mp_bytecode_print(const void *descr, const byte *ip, int len) {
    const byte *ip_start = ip;

    // get code info size
    machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
    const byte *code_info = ip;
    ip += code_info_size;

    qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
    qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
    printf("File %s, code block '%s' (descriptor: %p, bytecode @%p %d bytes)\n",
        qstr_str(source_file), qstr_str(block_name), descr, code_info, len);

    // bytecode prelude: state size and exception stack size; 16 bit uints
    {
        uint n_state = ip[0] | (ip[1] << 8);
        uint n_exc_stack = ip[2] | (ip[3] << 8);
        ip += 4;
        printf("(N_STATE %u)\n", n_state);
        printf("(N_EXC_STACK %u)\n", n_exc_stack);
    }

    // bytecode prelude: initialise closed over variables
    {
        uint n_local = *ip++;
        printf("(NUM_LOCAL %u)\n", n_local);
        for (; n_local > 0; n_local--) {
            uint local_num = *ip++;
            printf("(INIT_CELL %u)\n", local_num);
        }
        len -= ip - ip_start;
        ip_start = ip;
    }

    // print out line number info
    {
        machine_int_t bc = (code_info + code_info_size) - ip;
        machine_uint_t source_line = 1;
        printf("  bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
        for (const byte* ci = code_info + 12; *ci; ci++) {
            bc += *ci & 31;
            source_line += *ci >> 5;
            printf("  bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
        }
    }
    mp_bytecode_print2(ip, len - 0);
}
开发者ID:HackDads,项目名称:micropython,代码行数:47,代码来源:showbc.c

示例14: mp_arg_parse_all

void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_uint_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {
    mp_uint_t pos_found = 0, kws_found = 0;
    for (mp_uint_t i = 0; i < n_allowed; i++) {
        mp_obj_t given_arg;
        if (i < n_pos) {
            if (allowed[i].flags & MP_ARG_KW_ONLY) {
                goto extra_positional;
            }
            pos_found++;
            given_arg = pos[i];
        } else {
            mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qst), MP_MAP_LOOKUP);
            if (kw == NULL) {
                if (allowed[i].flags & MP_ARG_REQUIRED) {
                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                        mp_arg_error_terse_mismatch();
                    } else {
                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                            "'%s' argument required",
                            qstr_str(allowed[i].qst)));
                    }
                }
                out_vals[i] = allowed[i].defval;
                continue;
            } else {
                kws_found++;
                given_arg = kw->value;
            }
        }
        if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_BOOL) {
            out_vals[i].u_bool = mp_obj_is_true(given_arg);
        } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) {
            out_vals[i].u_int = mp_obj_get_int(given_arg);
        } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ) {
            out_vals[i].u_obj = given_arg;
        } else {
            assert(0);
        }
    }
    if (pos_found < n_pos) {
        extra_positional:
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            mp_arg_error_terse_mismatch();
        } else {
            // TODO better error message
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "extra positional arguments given"));
        }
    }
    if (kws_found < kws->used) {
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            mp_arg_error_terse_mismatch();
        } else {
            // TODO better error message
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "extra keyword arguments given"));
        }
    }
}
开发者ID:Dreamapple,项目名称:micropython,代码行数:59,代码来源:argcheck.c

示例15: vstr_new

mp_lexer_t *mp_import_open_file(qstr mod_name) {
    vstr_t *vstr = vstr_new();
    if (import_base_dir != NULL) {
        vstr_printf(vstr, "%s/", import_base_dir);
    }
    vstr_printf(vstr, "%s.py", qstr_str(mod_name));
    return mp_lexer_new_from_file(vstr_str(vstr)); // TODO does lexer need to copy the string? can we free it here?
}
开发者ID:anpage,项目名称:micropython,代码行数:8,代码来源:lexerunix.c


注:本文中的qstr_str函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。