Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/sbi/src/run_expr.c

    rc5cb943d r051b3db8  
    11/*
    2  * Copyright (c) 2010 Jiri Svoboda
     2 * Copyright (c) 2011 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    113113static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
    114114static void run_call_args(run_t *run, list_t *args, list_t *arg_vals);
     115static void run_destroy_arg_vals(list_t *arg_vals);
    115116
    116117static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
     
    200201        rdata_address_t *address;
    201202        rdata_addr_var_t *addr_var;
     203        rdata_addr_prop_t *addr_prop;
     204        rdata_aprop_named_t *aprop_named;
     205        rdata_deleg_t *deleg_p;
    202206        rdata_value_t *value;
    203207        rdata_var_t *var;
     
    334338                break;
    335339        case sc_var:
    336 #ifdef DEBUG_RUN_TRACE
    337                 printf("Referencing member variable.\n");
    338 #endif
    339                 /* There should be no global variables. */
     340        case sc_prop:
     341#ifdef DEBUG_RUN_TRACE
     342                if (sym->sc == sc_var)
     343                        printf("Referencing member variable.\n");
     344                else
     345                        printf("Referencing unqualified property.\n");
     346#endif
     347                /* There should be no global variables or properties. */
    340348                assert(csi != NULL);
    341349
    342350                if (symbol_search_csi(run->program, csi, nameref->name)
    343351                    == NULL && !stree_symbol_is_static(sym)) {
    344                         /* Variable is not in the current object. */
     352                        /* Symbol is not in the current object. */
    345353                        printf("Error: Cannot access non-static member "
    346354                            "variable '");
     
    352360                }
    353361
     362                /*
     363                 * Determine object in which the symbol resides
     364                 */
    354365                if (stree_symbol_is_static(sym)) {
    355366                        /*
     367                         * Class object
    356368                         * XXX This is too slow!
    357369                         *
     
    365377                        aobj = sobj->u.object_v;
    366378                } else {
    367                         aobj = obj;
     379                        /*
     380                         * Instance object. Currently we don't support
     381                         * true inner classes, thus we know the symbol is
     382                         * in the active object (there is no dynamic parent).
     383                         */
     384                        sobj = proc_ar->obj;
     385                        aobj = sobj->u.object_v;;
    368386                }
    369387
    370                 /* Find member variable in object. */
    371                 member_var = intmap_get(&aobj->fields, nameref->name->sid);
    372                 assert(member_var != NULL);
    373 
    374                 /* Return address of the variable. */
    375                 item = rdata_item_new(ic_address);
    376                 address = rdata_address_new(ac_var);
    377                 addr_var = rdata_addr_var_new();
    378 
    379                 item->u.address = address;
    380                 address->u.var_a = addr_var;
    381                 addr_var->vref = member_var;
    382 
    383                 *res = item;
    384                 break;
    385         case sc_prop:
    386                 /* XXX TODO */
    387                 printf("Unimplemented: Property name reference.\n");
    388                 abort();
     388                if (sym->sc == sc_var) {
     389                        /* Find member variable in object. */
     390                        member_var = intmap_get(&aobj->fields,
     391                            nameref->name->sid);
     392                        assert(member_var != NULL);
     393
     394                        /* Return address of the variable. */
     395                        item = rdata_item_new(ic_address);
     396                        address = rdata_address_new(ac_var);
     397                        addr_var = rdata_addr_var_new();
     398
     399                        item->u.address = address;
     400                        address->u.var_a = addr_var;
     401                        addr_var->vref = member_var;
     402
     403                        *res = item;
     404                } else {
     405                        /* Construct named property address. */
     406                        item = rdata_item_new(ic_address);
     407                        address = rdata_address_new(ac_prop);
     408                        addr_prop = rdata_addr_prop_new(apc_named);
     409                        aprop_named = rdata_aprop_named_new();
     410                        item->u.address = address;
     411                        address->u.prop_a = addr_prop;
     412                        addr_prop->u.named = aprop_named;
     413
     414                        deleg_p = rdata_deleg_new();
     415                        deleg_p->obj = sobj;
     416                        deleg_p->sym = sym;
     417                        addr_prop->u.named->prop_d = deleg_p;
     418
     419                        *res = item;
     420                }
    389421                break;
    390422        }
     
    611643        rdata_value_t *v1, *v2;
    612644
     645        rarg1_i = NULL;
     646        rarg2_i = NULL;
     647        rarg1_vi = NULL;
     648        rarg2_vi = NULL;
     649
    613650#ifdef DEBUG_RUN_TRACE
    614651        printf("Run binary operation.\n");
     
    616653        run_expr(run, binop->arg1, &rarg1_i);
    617654        if (run_is_bo(run)) {
    618                 *res = NULL;
    619                 return;
     655                *res = run_recovery_item(run);
     656                goto cleanup;
     657        }
     658
     659#ifdef DEBUG_RUN_TRACE
     660        printf("Check binop argument result.\n");
     661#endif
     662        run_cvt_value_item(run, rarg1_i, &rarg1_vi);
     663        if (run_is_bo(run)) {
     664                *res = run_recovery_item(run);
     665                goto cleanup;
    620666        }
    621667
    622668        run_expr(run, binop->arg2, &rarg2_i);
    623669        if (run_is_bo(run)) {
    624                 *res = NULL;
    625                 return;
    626         }
    627 
    628 #ifdef DEBUG_RUN_TRACE
    629         printf("Check binop argument results.\n");
    630 #endif
    631 
    632         run_cvt_value_item(run, rarg1_i, &rarg1_vi);
     670                *res = run_recovery_item(run);
     671                goto cleanup;
     672        }
     673
     674#ifdef DEBUG_RUN_TRACE
     675        printf("Check binop argument result.\n");
     676#endif
    633677        run_cvt_value_item(run, rarg2_i, &rarg2_vi);
     678        if (run_is_bo(run)) {
     679                *res = run_recovery_item(run);
     680                goto cleanup;
     681        }
    634682
    635683        v1 = rarg1_vi->u.value;
     
    668716                assert(b_false);
    669717        }
     718
     719cleanup:
     720        if (rarg1_i != NULL)
     721                rdata_item_destroy(rarg1_i);
     722        if (rarg2_i != NULL)
     723                rdata_item_destroy(rarg2_i);
     724        if (rarg1_vi != NULL)
     725                rdata_item_destroy(rarg1_vi);
     726        if (rarg2_vi != NULL)
     727                rdata_item_destroy(rarg2_vi);
    670728}
    671729
     
    10541112        rdata_bool_t *bool_v;
    10551113
    1056         rdata_var_t *ref1, *ref2;
     1114        stree_embr_t *e1, *e2;
    10571115
    10581116        (void) run;
     
    10671125        var->u.bool_v = bool_v;
    10681126
    1069         ref1 = v1->var->u.ref_v->vref;
    1070         ref2 = v2->var->u.ref_v->vref;
     1127        e1 = v1->var->u.enum_v->value;
     1128        e2 = v2->var->u.enum_v->value;
    10711129
    10721130        switch (binop->bc) {
    10731131        case bo_equal:
    1074                 bool_v->value = (ref1 == ref2);
     1132                bool_v->value = (e1 == e2);
    10751133                break;
    10761134        case bo_notequal:
    1077                 bool_v->value = (ref1 != ref2);
     1135                bool_v->value = (e1 != e2);
    10781136                break;
    10791137        default:
     
    11001158        printf("Run unary operation.\n");
    11011159#endif
     1160        rarg_i = NULL;
     1161        rarg_vi = NULL;
     1162
    11021163        run_expr(run, unop->arg, &rarg_i);
    11031164        if (run_is_bo(run)) {
    1104                 *res = NULL;
    1105                 return;
     1165                *res = run_recovery_item(run);
     1166                goto cleanup;
    11061167        }
    11071168
     
    11101171#endif
    11111172        run_cvt_value_item(run, rarg_i, &rarg_vi);
     1173        if (run_is_bo(run)) {
     1174                *res = run_recovery_item(run);
     1175                goto cleanup;
     1176        }
    11121177
    11131178        val = rarg_vi->u.value;
     
    11241189                    "type %d.\n", val->var->vc);
    11251190                run_raise_error(run);
    1126                 *res = NULL;
    1127                 break;
    1128         }
     1191                *res = run_recovery_item(run);
     1192                break;
     1193        }
     1194cleanup:
     1195        if (rarg_i != NULL)
     1196                rdata_item_destroy(rarg_i);
     1197        if (rarg_vi != NULL)
     1198                rdata_item_destroy(rarg_vi);
    11291199}
    11301200
     
    12081278        *res = item;
    12091279}
     1280
     1281/** Run equality comparison of two values
     1282 *
     1283 * This should be equivalent to equality ('==') binary operation.
     1284 * XXX Duplicating code of run_binop_xxx().
     1285 *
     1286 * @param run           Runner object
     1287 * @param v1            Value of first argument
     1288 * @param v2            Value of second argument
     1289 * @param res           Place to store result (plain boolean value)
     1290 */
     1291void run_equal(run_t *run, rdata_value_t *v1, rdata_value_t *v2, bool_t *res)
     1292{
     1293        bool_t b1, b2;
     1294        bigint_t *c1, *c2;
     1295        bigint_t *i1, *i2;
     1296        bigint_t diff;
     1297        const char *s1, *s2;
     1298        rdata_var_t *ref1, *ref2;
     1299        stree_embr_t *e1, *e2;
     1300
     1301        (void) run;
     1302        assert(v1->var->vc == v2->var->vc);
     1303
     1304        switch (v1->var->vc) {
     1305        case vc_bool:
     1306                b1 = v1->var->u.bool_v->value;
     1307                b2 = v2->var->u.bool_v->value;
     1308
     1309                *res = (b1 == b2);
     1310                break;
     1311        case vc_char:
     1312                c1 = &v1->var->u.char_v->value;
     1313                c2 = &v2->var->u.char_v->value;
     1314
     1315                bigint_sub(c1, c2, &diff);
     1316                *res = bigint_is_zero(&diff);
     1317                break;
     1318        case vc_int:
     1319                i1 = &v1->var->u.int_v->value;
     1320                i2 = &v2->var->u.int_v->value;
     1321
     1322                bigint_sub(i1, i2, &diff);
     1323                *res = bigint_is_zero(&diff);
     1324                break;
     1325        case vc_string:
     1326                s1 = v1->var->u.string_v->value;
     1327                s2 = v2->var->u.string_v->value;
     1328
     1329                *res = os_str_cmp(s1, s2) == 0;
     1330                break;
     1331        case vc_ref:
     1332                ref1 = v1->var->u.ref_v->vref;
     1333                ref2 = v2->var->u.ref_v->vref;
     1334
     1335                *res = (ref1 == ref2);
     1336                break;
     1337        case vc_enum:
     1338                e1 = v1->var->u.enum_v->value;
     1339                e2 = v2->var->u.enum_v->value;
     1340
     1341                *res = (e1 == e2);
     1342                break;
     1343
     1344        case vc_deleg:
     1345        case vc_array:
     1346        case vc_object:
     1347        case vc_resource:
     1348        case vc_symbol:
     1349                assert(b_false);
     1350        }
     1351}
     1352
    12101353
    12111354/** Evaluate @c new operation.
     
    12971440                run_expr(run, expr, &rexpr);
    12981441                if (run_is_bo(run)) {
    1299                         *res = NULL;
     1442                        *res = run_recovery_item(run);
    13001443                        return;
    13011444                }
    13021445
    13031446                run_cvt_value_item(run, rexpr, &rexpr_vi);
     1447                if (run_is_bo(run)) {
     1448                        *res = run_recovery_item(run);
     1449                        return;
     1450                }
     1451
    13041452                assert(rexpr_vi->ic == ic_value);
    13051453                rexpr_var = rexpr_vi->u.value->var;
     
    13751523        run_call_args(run, &new_op->ctor_args, &arg_vals);
    13761524        if (run_is_bo(run)) {
    1377                 *res = NULL;
     1525                *res = run_recovery_item(run);
    13781526                return;
    13791527        }
     
    13871535        assert(obj_i->u.address->ac == ac_var);
    13881536        run_object_ctor(run, obj_i->u.address->u.var_a->vref, &arg_vals);
     1537        rdata_item_destroy(obj_i);
     1538
     1539        /* Destroy argument values */
     1540        run_destroy_arg_vals(&arg_vals);
    13891541}
    13901542
     
    14041556        printf("Run access operation.\n");
    14051557#endif
     1558        rarg = NULL;
     1559
    14061560        run_expr(run, access->arg, &rarg);
    14071561        if (run_is_bo(run)) {
    1408                 *res = NULL;
    1409                 return;
     1562                *res = run_recovery_item(run);
     1563                goto cleanup;
    14101564        }
    14111565
     
    14161570
    14171571        run_access_item(run, access, rarg, res);
     1572cleanup:
     1573        if (rarg != NULL)
     1574                rdata_item_destroy(rarg);
    14181575}
    14191576
     
    14841641        /* Try again. */
    14851642        run_access_item(run, access, darg, res);
     1643
     1644        /* Destroy temporary */
     1645        rdata_item_destroy(darg);
    14861646}
    14871647
     
    17901950#endif
    17911951        run_cvt_value_item(run, arg, &arg_vi);
     1952        if (run_is_bo(run)) {
     1953                *res = run_recovery_item(run);
     1954                return;
     1955        }
     1956
    17921957        arg_val = arg_vi->u.value;
    17931958        assert(arg_val->var->vc == vc_symbol);
     
    18001965        embr = stree_enum_find_mbr(symbol_v->sym->u.enum_d,
    18011966            access->member_name);
     1967
     1968        rdata_item_destroy(arg_vi);
    18021969
    18031970        /* Member existence should be ensured by static type checking. */
     
    18412008        printf("Run call operation.\n");
    18422009#endif
     2010        rdeleg = NULL;
     2011        rdeleg_vi = NULL;
     2012
    18432013        run_expr(run, call->fun, &rdeleg);
    18442014        if (run_is_bo(run)) {
    1845                 *res = NULL;
    1846                 return;
    1847         }
    1848 
    1849         if (run->thread_ar->bo_mode != bm_none) {
    18502015                *res = run_recovery_item(run);
    1851                 return;
     2016                goto cleanup;
    18522017        }
    18532018
    18542019        run_cvt_value_item(run, rdeleg, &rdeleg_vi);
     2020        if (run_is_bo(run)) {
     2021                *res = run_recovery_item(run);
     2022                goto cleanup;
     2023        }
     2024
    18552025        assert(rdeleg_vi->ic == ic_value);
    18562026
     
    18772047        run_call_args(run, &call->args, &arg_vals);
    18782048        if (run_is_bo(run)) {
    1879                 *res = NULL;
    1880                 return;
     2049                *res = run_recovery_item(run);
     2050                goto cleanup;
    18812051        }
    18822052
     
    18892059        /* Fill in argument values. */
    18902060        run_proc_ar_set_args(run, proc_ar, &arg_vals);
     2061
     2062        /* Destroy arg_vals, they are no longer needed. */
     2063        run_destroy_arg_vals(&arg_vals);
    18912064
    18922065        /* Run the function. */
     
    19002073        }
    19012074
     2075        /* Destroy procedure activation record. */
     2076        run_proc_ar_destroy(run, proc_ar);
     2077
     2078cleanup:
     2079        if (rdeleg != NULL)
     2080                rdata_item_destroy(rdeleg);
     2081        if (rdeleg_vi != NULL)
     2082                rdata_item_destroy(rdeleg_vi);
     2083
    19022084#ifdef DEBUG_RUN_TRACE
    19032085        printf("Returned from function call.\n");
     
    19282110                run_expr(run, arg, &rarg_i);
    19292111                if (run_is_bo(run))
    1930                         return;
     2112                        goto error;
    19312113
    19322114                run_cvt_value_item(run, rarg_i, &rarg_vi);
     2115                rdata_item_destroy(rarg_i);
     2116                if (run_is_bo(run))
     2117                        goto error;
    19332118
    19342119                list_append(arg_vals, rarg_vi);
    19352120                arg_n = list_next(args, arg_n);
    19362121        }
     2122        return;
     2123
     2124error:
     2125        /*
     2126         * An exception or error occured while evaluating one of the
     2127         * arguments. Destroy already obtained argument values and
     2128         * dismantle the list.
     2129         */
     2130        run_destroy_arg_vals(arg_vals);
     2131}
     2132
     2133/** Destroy list of evaluated arguments.
     2134 *
     2135 * Provided a list of evaluated arguments, destroy them, removing them
     2136 * from the list and fini the list itself.
     2137 *
     2138 * @param arg_vals      List of evaluated arguments (value items,
     2139 *                      rdata_item_t).
     2140 */
     2141static void run_destroy_arg_vals(list_t *arg_vals)
     2142{
     2143        list_node_t *val_n;
     2144        rdata_item_t *val_i;
     2145
     2146        /*
     2147         * An exception or error occured while evaluating one of the
     2148         * arguments. Destroy already obtained argument values and
     2149         * dismantle the list.
     2150         */
     2151        while (!list_is_empty(arg_vals)) {
     2152                val_n = list_first(arg_vals);
     2153                val_i = list_node_data(val_n, rdata_item_t *);
     2154
     2155                rdata_item_destroy(val_i);
     2156                list_remove(arg_vals, val_n);
     2157        }
     2158        list_fini(arg_vals);
    19372159}
    19382160
     
    19542176        var_class_t vc;
    19552177        list_t arg_vals;
     2178        list_node_t *val_n;
     2179        rdata_item_t *val_i;
    19562180
    19572181#ifdef DEBUG_RUN_TRACE
     
    19602184        run_expr(run, index->base, &rbase);
    19612185        if (run_is_bo(run)) {
    1962                 *res = NULL;
     2186                *res = run_recovery_item(run);
    19632187                return;
    19642188        }
     
    19692193        if (vc == vc_ref) {
    19702194                run_dereference(run, rbase, index->base->cspan, &base_i);
     2195                rdata_item_destroy(rbase);
    19712196                if (run_is_bo(run)) {
    1972                         *res = NULL;
     2197                        *res = run_recovery_item(run);
    19732198                        return;
    19742199                }
     
    19872212                run_expr(run, arg, &rarg_i);
    19882213                if (run_is_bo(run)) {
    1989                         *res = NULL;
    1990                         return;
     2214                        *res = run_recovery_item(run);
     2215                        goto cleanup;
    19912216                }
    19922217
    19932218                run_cvt_value_item(run, rarg_i, &rarg_vi);
     2219                rdata_item_destroy(rarg_i);
     2220                if (run_is_bo(run)) {
     2221                        *res = run_recovery_item(run);
     2222                        goto cleanup;
     2223                }
    19942224
    19952225                list_append(&arg_vals, rarg_vi);
     
    20122242                exit(1);
    20132243        }
     2244
     2245        /* Destroy the indexing base temporary */
     2246        rdata_item_destroy(base_i);
     2247cleanup:
     2248        /*
     2249         * An exception or error occured while evaluating one of the
     2250         * arguments. Destroy already obtained argument values and
     2251         * dismantle the list.
     2252         */
     2253        while (!list_is_empty(&arg_vals)) {
     2254                val_n = list_first(&arg_vals);
     2255                val_i = list_node_data(val_n, rdata_item_t *);
     2256
     2257                rdata_item_destroy(val_i);
     2258                list_remove(&arg_vals, val_n);
     2259        }
     2260
     2261        list_fini(&arg_vals);
    20142262}
    20152263
     
    21362384
    21372385        list_node_t *node;
    2138         rdata_item_t *arg;
     2386        rdata_item_t *arg, *arg_copy;
    21392387
    21402388#ifdef DEBUG_RUN_TRACE
     
    21862434        while (node != NULL) {
    21872435                arg = list_node_data(node, rdata_item_t *);
    2188                 list_append(&aprop_indexed->args, arg);
     2436
     2437                /*
     2438                 * Clone argument so that original can
     2439                 * be freed.
     2440                 */
     2441                assert(arg->ic == ic_value);
     2442                arg_copy = rdata_item_new(ic_value);
     2443                rdata_value_copy(arg->u.value, &arg_copy->u.value);
     2444
     2445                list_append(&aprop_indexed->args, arg_copy);
    21892446                node = list_next(args, node);
    21902447        }
     
    22252482
    22262483        run_cvt_value_item(run, base, &base_vi);
     2484        if (run_is_bo(run)) {
     2485                *res = run_recovery_item(run);
     2486                return;
     2487        }
     2488
    22272489        assert(base_vi->u.value->var->vc == vc_string);
    22282490        string = base_vi->u.value->var->u.string_v;
     
    22772539                    index->expr->cspan);
    22782540                *res = run_recovery_item(run);
    2279                 return;
     2541                goto cleanup;
    22802542        }
    22812543
     
    22912553
    22922554        *res = ritem;
     2555cleanup:
     2556        rdata_item_destroy(base_vi);
    22932557}
    22942558
     
    23102574        printf("Run assign operation.\n");
    23112575#endif
     2576        rdest_i = NULL;
     2577        rsrc_i = NULL;
     2578        rsrc_vi = NULL;
     2579
    23122580        run_expr(run, assign->dest, &rdest_i);
    23132581        if (run_is_bo(run)) {
    2314                 *res = NULL;
    2315                 return;
     2582                *res = run_recovery_item(run);
     2583                goto cleanup;
    23162584        }
    23172585
    23182586        run_expr(run, assign->src, &rsrc_i);
    23192587        if (run_is_bo(run)) {
    2320                 *res = NULL;
    2321                 return;
     2588                *res = run_recovery_item(run);
     2589                goto cleanup;
    23222590        }
    23232591
    23242592        run_cvt_value_item(run, rsrc_i, &rsrc_vi);
     2593        if (run_is_bo(run)) {
     2594                *res = run_recovery_item(run);
     2595                goto cleanup;
     2596        }
     2597
    23252598        assert(rsrc_vi->ic == ic_value);
    23262599
     
    23342607
    23352608        *res = NULL;
     2609cleanup:
     2610        if (rdest_i != NULL)
     2611                rdata_item_destroy(rdest_i);
     2612        if (rsrc_i != NULL)
     2613                rdata_item_destroy(rsrc_i);
     2614        if (rsrc_vi != NULL)
     2615                rdata_item_destroy(rsrc_vi);
    23362616}
    23372617
     
    23592639        run_expr(run, as_op->arg, &rarg_i);
    23602640        if (run_is_bo(run)) {
    2361                 *res = NULL;
     2641                *res = run_recovery_item(run);
    23622642                return;
    23632643        }
     
    23692649        assert(run_item_get_vc(run, rarg_i) == vc_ref);
    23702650        run_cvt_value_item(run, rarg_i, &rarg_vi);
     2651        rdata_item_destroy(rarg_i);
     2652
     2653        if (run_is_bo(run)) {
     2654                *res = run_recovery_item(run);
     2655                return;
     2656        }
     2657
    23712658        assert(rarg_vi->ic == ic_value);
    23722659
     
    24052692        }
    24062693
     2694        /* The dereferenced item is not used anymore. */
     2695        rdata_item_destroy(rarg_di);
     2696
    24072697        *res = rarg_vi;
    24082698}
     
    24352725        run_expr(run, box->arg, &rarg_i);
    24362726        if (run_is_bo(run)) {
    2437                 *res = NULL;
     2727                *res = run_recovery_item(run);
    24382728                return;
    24392729        }
    24402730
    24412731        run_cvt_value_item(run, rarg_i, &rarg_vi);
     2732        rdata_item_destroy(rarg_i);
     2733        if (run_is_bo(run)) {
     2734                *res = run_recovery_item(run);
     2735                return;
     2736        }
     2737
    24422738        assert(rarg_vi->ic == ic_value);
    24432739
     
    24822778
    24832779        rdata_var_write(mbr_var, rarg_vi->u.value);
     2780        rdata_item_destroy(rarg_vi);
    24842781}
    24852782
     
    26572954        assert(res == NULL);
    26582955
     2956        /* Destroy procedure activation record. */
     2957        run_proc_ar_destroy(run, proc_ar);
     2958
    26592959#ifdef DEBUG_RUN_TRACE
    26602960        printf("Returned from constructor..\n");
     
    26752975        rdata_item_t *vitem;
    26762976        rdata_var_t *var;
     2977        bool_t res;
    26772978
    26782979        (void) run;
    26792980        run_cvt_value_item(run, item, &vitem);
     2981        if (run_is_bo(run))
     2982                return b_true;
    26802983
    26812984        assert(vitem->ic == ic_value);
     
    26832986
    26842987        assert(var->vc == vc_bool);
    2685         return var->u.bool_v->value;
    2686 }
     2988        res = var->u.bool_v->value;
     2989
     2990        /* Free value item */
     2991        rdata_item_destroy(vitem);
     2992        return res;
     2993}
Note: See TracChangeset for help on using the changeset viewer.