Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 0b60d2d in mainline


Ignore:
Timestamp:
2012-08-09T04:46:44Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
3c70376
Parents:
d8bd2ec
Message:

Bithenge: add subblob expressions

Location:
uspace/app/bithenge
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/expression.c

    rd8bd2ec r0b60d2d  
    545545
    546546
     547/***************** subblob_expression                        *****************/
     548
     549typedef struct {
     550        bithenge_expression_t base;
     551        bithenge_expression_t *blob, *start, *limit;
     552        bool absolute_limit;
     553} subblob_expression_t;
     554
     555static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base)
     556{
     557        return (subblob_expression_t *)base;
     558}
     559
     560static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr)
     561{
     562        return &expr->base;
     563}
     564
     565static int subblob_expression_evaluate(bithenge_expression_t *base,
     566    bithenge_scope_t *scope, bithenge_node_t **out)
     567{
     568        subblob_expression_t *self = expression_as_subblob(base);
     569        bithenge_node_t *start_node;
     570        int rc = bithenge_expression_evaluate(self->start, scope, &start_node);
     571        if (rc != EOK)
     572                return rc;
     573        if (bithenge_node_type(start_node) != BITHENGE_NODE_INTEGER) {
     574                bithenge_node_dec_ref(start_node);
     575                return EINVAL;
     576        }
     577        bithenge_int_t start = bithenge_integer_node_value(start_node);
     578        bithenge_node_dec_ref(start_node);
     579
     580        bithenge_int_t limit = -1;
     581        if (self->limit) {
     582                bithenge_node_t *limit_node;
     583                rc = bithenge_expression_evaluate(self->limit, scope,
     584                    &limit_node);
     585                if (rc != EOK)
     586                        return rc;
     587                if (bithenge_node_type(limit_node) != BITHENGE_NODE_INTEGER) {
     588                        bithenge_node_dec_ref(limit_node);
     589                        return EINVAL;
     590                }
     591                limit = bithenge_integer_node_value(limit_node);
     592                bithenge_node_dec_ref(limit_node);
     593                if (self->absolute_limit)
     594                        limit -= start;
     595        }
     596
     597        if (start < 0 || (self->limit && limit < 0))
     598                return EINVAL;
     599
     600        bithenge_node_t *blob;
     601        rc = bithenge_expression_evaluate(self->blob, scope, &blob);
     602        if (rc != EOK)
     603                return rc;
     604        if (bithenge_node_type(blob) != BITHENGE_NODE_BLOB) {
     605                bithenge_node_dec_ref(blob);
     606                return EINVAL;
     607        }
     608
     609        if (self->limit)
     610                return bithenge_new_subblob(out, bithenge_node_as_blob(blob),
     611                    start, limit);
     612        else
     613                return bithenge_new_offset_blob(out,
     614                    bithenge_node_as_blob(blob), start);
     615}
     616
     617static void subblob_expression_destroy(bithenge_expression_t *base)
     618{
     619        subblob_expression_t *self = expression_as_subblob(base);
     620        bithenge_expression_dec_ref(self->start);
     621        bithenge_expression_dec_ref(self->limit);
     622        free(self);
     623}
     624
     625static const bithenge_expression_ops_t subblob_expression_ops = {
     626        .evaluate = subblob_expression_evaluate,
     627        .destroy = subblob_expression_destroy,
     628};
     629
     630/** Create an expression that gets a subblob. Takes references to @a blob,
     631 * @a start, and @a limit.
     632 * @param[out] out Holds the new expression.
     633 * @param blob Calculates the blob.
     634 * @param start Calculates the start offset within the blob.
     635 * @param limit Calculates the limit. Can be NULL, in which case an offset blob
     636 * is returned.
     637 * @param absolute_limit If true, the limit is an absolute offset; otherwise,
     638 * it is relative to the start.
     639 * @return EOK on success or an error code from errno.h. */
     640int bithenge_subblob_expression(bithenge_expression_t **out,
     641    bithenge_expression_t *blob, bithenge_expression_t *start,
     642    bithenge_expression_t *limit, bool absolute_limit)
     643{
     644        int rc;
     645        subblob_expression_t *self = malloc(sizeof(*self));
     646        if (!self) {
     647                rc = ENOMEM;
     648                goto error;
     649        }
     650
     651        rc = bithenge_init_expression(subblob_as_expression(self),
     652            &subblob_expression_ops);
     653        if (rc != EOK)
     654                goto error;
     655
     656        self->blob = blob;
     657        self->start = start;
     658        self->limit = limit;
     659        self->absolute_limit = absolute_limit;
     660        *out = subblob_as_expression(self);
     661        return EOK;
     662
     663error:
     664        bithenge_expression_dec_ref(blob);
     665        bithenge_expression_dec_ref(start);
     666        bithenge_expression_dec_ref(limit);
     667        free(self);
     668        return rc;
     669}
     670
    547671/***************** param_wrapper                             *****************/
    548672
  • uspace/app/bithenge/expression.h

    rd8bd2ec r0b60d2d  
    111111int bithenge_scope_member_expression(bithenge_expression_t **,
    112112    bithenge_node_t *);
     113int bithenge_subblob_expression(bithenge_expression_t **,
     114    bithenge_expression_t *, bithenge_expression_t *, bithenge_expression_t *,
     115    bool);
    113116int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
    114117    bithenge_expression_t **);
  • uspace/app/bithenge/script.c

    rd8bd2ec r0b60d2d  
    530530}
    531531
     532static bithenge_expression_t *parse_postfix_expression(state_t *state)
     533{
     534        bithenge_expression_t *expr = parse_term(state);
     535        while (state->error == EOK) {
     536                if (state->token == '[') {
     537                        next_token(state);
     538                        bithenge_expression_t *start = parse_expression(state);
     539                        bool absolute_limit;
     540                        if (state->token == ',') {
     541                                absolute_limit = false;
     542                                next_token(state);
     543                        } else if (state->token == ':') {
     544                                absolute_limit = true;
     545                                next_token(state);
     546                        } else {
     547                                syntax_error(state, "expected ',' or ':'");
     548                        }
     549                        bithenge_expression_t *limit = NULL;
     550                        if (!(state->token == ']' && absolute_limit))
     551                                limit = parse_expression(state);
     552                        expect(state, ']');
     553
     554                        if (state->error != EOK) {
     555                                bithenge_expression_dec_ref(expr);
     556                                bithenge_expression_dec_ref(start);
     557                                bithenge_expression_dec_ref(limit);
     558                                return NULL;
     559                        }
     560                        int rc = bithenge_subblob_expression(&expr, expr,
     561                            start, limit, absolute_limit);
     562                        if (rc != EOK) {
     563                                error_errno(state, rc);
     564                                return NULL;
     565                        }
     566                } else {
     567                        break;
     568                }
     569        }
     570        return expr;
     571}
     572
    532573static bithenge_expression_t *parse_expression_precedence(state_t *state,
    533574    precedence_t prev_precedence)
    534575{
    535         bithenge_expression_t *expr = parse_term(state);
     576        bithenge_expression_t *expr = parse_postfix_expression(state);
    536577        while (state->error == EOK) {
    537578                bithenge_binary_op_t op =
     
    544585                next_token(state);
    545586
    546                 bithenge_expression_t *expr2 = parse_term(state);
     587                bithenge_expression_t *expr2 = parse_postfix_expression(state);
    547588                if (state->error != EOK) {
    548589                        bithenge_expression_dec_ref(expr2);
Note: See TracChangeset for help on using the changeset viewer.