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

Changeset c3437d9 in mainline


Ignore:
Timestamp:
2012-08-04T03:51:15Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
0ce0103
Parents:
e3f2765
Message:

Bithenge: add do{}while() transforms

Location:
uspace
Files:
7 edited

Legend:

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

    re3f2765 rc3437d9  
    5959
    6060        /* Keywords */
     61        TOKEN_DO,
    6162        TOKEN_ELSE,
    6263        TOKEN_FALSE,
     
    6768        TOKEN_TRANSFORM,
    6869        TOKEN_TRUE,
     70        TOKEN_WHILE,
    6971} token_type_t;
    7072
     
    211213                if (!value) {
    212214                        error_errno(state, ENOMEM);
     215                } else if (!str_cmp(value, "do")) {
     216                        state->token = TOKEN_DO;
     217                        free(value);
    213218                } else if (!str_cmp(value, "else")) {
    214219                        state->token = TOKEN_ELSE;
     
    234239                } else if (!str_cmp(value, "true")) {
    235240                        state->token = TOKEN_TRUE;
     241                        free(value);
     242                } else if (!str_cmp(value, "while")) {
     243                        state->token = TOKEN_WHILE;
    236244                        free(value);
    237245                } else {
     
    686694}
    687695
     696static bithenge_transform_t *parse_do_while(state_t *state)
     697{
     698        expect(state, TOKEN_DO);
     699        expect(state, '{');
     700        bithenge_transform_t *xform = parse_transform(state);
     701        expect(state, '}');
     702        expect(state, TOKEN_WHILE);
     703        expect(state, '(');
     704        bithenge_expression_t *expr = parse_expression(state);
     705        expect(state, ')');
     706
     707        if (state->error != EOK) {
     708                bithenge_expression_dec_ref(expr);
     709                bithenge_transform_dec_ref(xform);
     710                return NULL;
     711        }
     712
     713        bithenge_transform_t *do_while_xform;
     714        int rc = bithenge_do_while_transform(&do_while_xform, xform, expr);
     715        if (rc != EOK) {
     716                error_errno(state, rc);
     717                return NULL;
     718        }
     719        return do_while_xform;
     720}
     721
    688722/* The TOKEN_STRUCT and '{' must already have been skipped. */
    689723static bithenge_transform_t *parse_struct(state_t *state)
     
    740774static bithenge_transform_t *parse_transform_no_compose(state_t *state)
    741775{
    742         if (state->token == TOKEN_IDENTIFIER) {
     776        if (state->token == TOKEN_DO) {
     777                return parse_do_while(state);
     778        } else if (state->token == TOKEN_IDENTIFIER) {
    743779                return parse_invocation(state);
    744780        } else if (state->token == TOKEN_IF) {
  • uspace/app/bithenge/sequence.c

    re3f2765 rc3437d9  
    4444
    4545
     46/***************** seq_node                                  *****************/
     47
    4648typedef struct {
    4749        bithenge_node_t base;
     
    236238        bithenge_blob_dec_ref(self->blob);
    237239        free(self->ends);
     240}
     241
     242static void seq_node_set_num_xforms(seq_node_t *self,
     243    bithenge_int_t num_xforms)
     244{
     245        self->num_xforms = num_xforms;
    238246}
    239247
     
    270278
    271279
     280/***************** bithenge_new_struct                       *****************/
     281
    272282typedef struct {
    273283        bithenge_transform_t base;
     
    581591
    582592
     593/***************** bithenge_repeat_transform                 *****************/
     594
    583595typedef struct {
    584596        bithenge_transform_t base;
     
    636648                rc = seq_node_subtransform(repeat_as_seq(self),
    637649                    &subxform_result, i);
    638                 if (rc != EOK && self->count == -1) {
     650                if ((rc == EINVAL || rc == ENOENT) && self->count == -1) {
     651                        self->count = i;
     652                        seq_node_set_num_xforms(repeat_as_seq(self),
     653                            self->count);
    639654                        rc = EOK;
    640655                        break;
     
    845860}
    846861
     862
     863
     864/***************** bithenge_do_while_transform               *****************/
     865
     866typedef struct {
     867        bithenge_transform_t base;
     868        bithenge_expression_t *expr;
     869        bithenge_transform_t *xform;
     870} do_while_transform_t;
     871
     872static inline bithenge_transform_t *do_while_as_transform(
     873    do_while_transform_t *self)
     874{
     875        return &self->base;
     876}
     877
     878static inline do_while_transform_t *transform_as_do_while(
     879    bithenge_transform_t *base)
     880{
     881        return (do_while_transform_t *)base;
     882}
     883
     884typedef struct {
     885        seq_node_t base;
     886        bool prefix;
     887        bithenge_expression_t *expr;
     888        bithenge_transform_t *xform;
     889        bithenge_int_t count;
     890} do_while_node_t;
     891
     892static seq_node_t *do_while_as_seq(do_while_node_t *self)
     893{
     894        return &self->base;
     895}
     896
     897static do_while_node_t *seq_as_do_while(seq_node_t *base)
     898{
     899        return (do_while_node_t *)base;
     900}
     901
     902static bithenge_node_t *do_while_as_node(do_while_node_t *self)
     903{
     904        return seq_as_node(do_while_as_seq(self));
     905}
     906
     907static do_while_node_t *node_as_do_while(bithenge_node_t *base)
     908{
     909        return seq_as_do_while(node_as_seq(base));
     910}
     911
     912static int do_while_node_for_each(bithenge_node_t *base,
     913    bithenge_for_each_func_t func, void *data)
     914{
     915        int rc = EOK;
     916        do_while_node_t *self = node_as_do_while(base);
     917
     918        for (bithenge_int_t i = 0; ; i++) {
     919                bithenge_node_t *subxform_result;
     920                rc = seq_node_subtransform(do_while_as_seq(self),
     921                    &subxform_result, i);
     922                if (rc != EOK)
     923                        return rc;
     924
     925                bithenge_node_t *key_node;
     926                rc = bithenge_new_integer_node(&key_node, i);
     927                if (rc != EOK) {
     928                        bithenge_node_dec_ref(subxform_result);
     929                        return rc;
     930                }
     931                bithenge_node_inc_ref(subxform_result);
     932                rc = func(key_node, subxform_result, data);
     933                if (rc != EOK) {
     934                        bithenge_node_dec_ref(subxform_result);
     935                        return rc;
     936                }
     937
     938                bithenge_scope_t scope;
     939                bithenge_scope_init(&scope);
     940                rc = bithenge_scope_copy(&scope,
     941                    seq_node_scope(do_while_as_seq(self)));
     942                bithenge_scope_set_current_node(&scope, subxform_result);
     943                if (rc != EOK) {
     944                        bithenge_scope_destroy(&scope);
     945                        return rc;
     946                }
     947                bithenge_node_t *expr_result;
     948                rc = bithenge_expression_evaluate(self->expr, &scope,
     949                    &expr_result);
     950                bithenge_scope_destroy(&scope);
     951                if (rc != EOK)
     952                        return rc;
     953                if (bithenge_node_type(expr_result) != BITHENGE_NODE_BOOLEAN) {
     954                        bithenge_node_dec_ref(expr_result);
     955                        return EINVAL;
     956                }
     957                bool cond = bithenge_boolean_node_value(expr_result);
     958                bithenge_node_dec_ref(expr_result);
     959                if (!cond) {
     960                        self->count = i + 1;
     961                        seq_node_set_num_xforms(do_while_as_seq(self),
     962                            self->count);
     963                        break;
     964                }
     965        }
     966
     967        if (!self->prefix) {
     968                bool complete;
     969                rc = seq_node_complete(do_while_as_seq(self), &complete);
     970                if (rc != EOK)
     971                        return rc;
     972                if (!complete)
     973                        return EINVAL;
     974        }
     975
     976        return rc;
     977}
     978
     979static void do_while_node_destroy(bithenge_node_t *base)
     980{
     981        do_while_node_t *self = node_as_do_while(base);
     982        seq_node_destroy(do_while_as_seq(self));
     983        bithenge_expression_dec_ref(self->expr);
     984        bithenge_transform_dec_ref(self->xform);
     985        free(self);
     986}
     987
     988static const bithenge_internal_node_ops_t do_while_node_ops = {
     989        .for_each = do_while_node_for_each,
     990        .destroy = do_while_node_destroy,
     991};
     992
     993static int do_while_node_get_transform(seq_node_t *base,
     994    bithenge_transform_t **out, bithenge_int_t index)
     995{
     996        do_while_node_t *self = seq_as_do_while(base);
     997        *out = self->xform;
     998        bithenge_transform_inc_ref(*out);
     999        return EOK;
     1000}
     1001
     1002static const seq_node_ops_t do_while_node_seq_ops = {
     1003        .get_transform = do_while_node_get_transform,
     1004};
     1005
     1006static int do_while_transform_make_node(do_while_transform_t *self,
     1007    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
     1008    bool prefix)
     1009{
     1010        do_while_node_t *node = malloc(sizeof(*node));
     1011        if (!node)
     1012                return ENOMEM;
     1013
     1014        int rc = bithenge_init_internal_node(do_while_as_node(node),
     1015            &do_while_node_ops);
     1016        if (rc != EOK) {
     1017                free(node);
     1018                return rc;
     1019        }
     1020
     1021        rc = seq_node_init(do_while_as_seq(node), &do_while_node_seq_ops,
     1022            scope, blob, -1, false);
     1023        if (rc != EOK) {
     1024                free(node);
     1025                return rc;
     1026        }
     1027
     1028        bithenge_transform_inc_ref(self->xform);
     1029        node->xform = self->xform;
     1030        bithenge_expression_inc_ref(self->expr);
     1031        node->expr = self->expr;
     1032        node->prefix = prefix;
     1033        node->count = -1;
     1034        *out = do_while_as_node(node);
     1035        return EOK;
     1036}
     1037
     1038static int do_while_transform_apply(bithenge_transform_t *base,
     1039    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     1040{
     1041        do_while_transform_t *self = transform_as_do_while(base);
     1042        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     1043                return EINVAL;
     1044        return do_while_transform_make_node(self, out, scope,
     1045            bithenge_node_as_blob(in), false);
     1046}
     1047
     1048static int for_each_noop(bithenge_node_t *key, bithenge_node_t *value,
     1049    void *data)
     1050{
     1051        bithenge_node_dec_ref(key);
     1052        bithenge_node_dec_ref(value);
     1053        return EOK;
     1054}
     1055
     1056static int do_while_transform_prefix_apply(bithenge_transform_t *base,
     1057    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
     1058    aoff64_t *out_size)
     1059{
     1060        do_while_transform_t *self = transform_as_do_while(base);
     1061        int rc = do_while_transform_make_node(self, out_node, scope, blob,
     1062            true);
     1063        if (rc != EOK)
     1064                return rc;
     1065
     1066        rc = bithenge_node_for_each(*out_node, for_each_noop, NULL);
     1067        if (rc != EOK) {
     1068                bithenge_node_dec_ref(*out_node);
     1069                return rc;
     1070        }
     1071
     1072        rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
     1073            node_as_do_while(*out_node)->count);
     1074        if (rc != EOK) {
     1075                bithenge_node_dec_ref(*out_node);
     1076                return rc;
     1077        }
     1078
     1079        return EOK;
     1080}
     1081
     1082static void do_while_transform_destroy(bithenge_transform_t *base)
     1083{
     1084        do_while_transform_t *self = transform_as_do_while(base);
     1085        bithenge_transform_dec_ref(self->xform);
     1086        bithenge_expression_dec_ref(self->expr);
     1087        free(self);
     1088}
     1089
     1090static const bithenge_transform_ops_t do_while_transform_ops = {
     1091        .apply = do_while_transform_apply,
     1092        .prefix_apply = do_while_transform_prefix_apply,
     1093        .destroy = do_while_transform_destroy,
     1094};
     1095
     1096/** Create a transform that applies its subtransform while an expression on the
     1097 * result returns true. Takes a reference to @a xform and @a expr.
     1098 * @param[out] out Holds the new transform.
     1099 * @param xform The subtransform to apply repeatedly.
     1100 * @param expr Applied in the result of each application of @a xform to
     1101 * determine whether there will be more.
     1102 * @return EOK on success or an error code from errno.h. */
     1103int bithenge_do_while_transform(bithenge_transform_t **out,
     1104    bithenge_transform_t *xform, bithenge_expression_t *expr)
     1105{
     1106        int rc;
     1107        do_while_transform_t *self = malloc(sizeof(*self));
     1108        if (!self) {
     1109                rc = ENOMEM;
     1110                goto error;
     1111        }
     1112
     1113        rc = bithenge_init_transform(do_while_as_transform(self),
     1114            &do_while_transform_ops, 0);
     1115        if (rc != EOK)
     1116                goto error;
     1117
     1118        self->expr = expr;
     1119        self->xform = xform;
     1120        *out = do_while_as_transform(self);
     1121        return EOK;
     1122
     1123error:
     1124        free(self);
     1125        bithenge_expression_dec_ref(expr);
     1126        bithenge_transform_dec_ref(xform);
     1127        return rc;
     1128}
     1129
    8471130/** @}
    8481131 */
  • uspace/app/bithenge/sequence.h

    re3f2765 rc3437d9  
    4444int bithenge_repeat_transform(bithenge_transform_t **, bithenge_transform_t *,
    4545    bithenge_expression_t *);
     46int bithenge_do_while_transform(bithenge_transform_t **,
     47    bithenge_transform_t *, bithenge_expression_t *);
    4648
    4749#endif
  • uspace/app/bithenge/transform.c

    re3f2765 rc3437d9  
    201201        for (int i = 0; i < out->num_params; i++)
    202202                bithenge_node_inc_ref(out->params[i]);
     203        bithenge_node_dec_ref(out->current_node);
    203204        out->current_node = scope->current_node;
    204205        if (out->current_node)
     
    474475bithenge_transform_t bithenge_known_length_transform = {
    475476        &known_length_ops, 1, 1
     477};
     478
     479static int nonzero_boolean_apply(bithenge_transform_t *self,
     480    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     481{
     482        if (bithenge_node_type(in) != BITHENGE_NODE_INTEGER)
     483                return EINVAL;
     484        bool value = bithenge_integer_node_value(in) != 0;
     485        return bithenge_new_boolean_node(out, value);
     486}
     487
     488static const bithenge_transform_ops_t nonzero_boolean_ops = {
     489        .apply = nonzero_boolean_apply,
     490        .destroy = transform_indestructible,
     491};
     492
     493/** A transform that converts integers to booleans, true if nonzero. */
     494bithenge_transform_t bithenge_nonzero_boolean_transform = {
     495        &nonzero_boolean_ops, 1, 0
    476496};
    477497
     
    602622        {"ascii", &bithenge_ascii_transform},
    603623        {"known_length", &bithenge_known_length_transform},
     624        {"nonzero_boolean", &bithenge_nonzero_boolean_transform},
    604625        {"uint8", &bithenge_uint8_transform},
    605626        {"uint16le", &bithenge_uint16le_transform},
  • uspace/app/bithenge/transform.h

    re3f2765 rc3437d9  
    112112
    113113extern bithenge_transform_t bithenge_ascii_transform;
     114extern bithenge_transform_t bithenge_invalid_transform;
    114115extern bithenge_transform_t bithenge_known_length_transform;
    115 extern bithenge_transform_t bithenge_invalid_transform;
     116extern bithenge_transform_t bithenge_nonzero_boolean_transform;
    116117extern bithenge_transform_t bithenge_uint8_transform;
    117118extern bithenge_transform_t bithenge_uint16le_transform;
  • uspace/dist/src/bithenge/test-repeat.bh

    re3f2765 rc3437d9  
    77
    88transform without_count = struct {
    9         .error <- repeat { uint8 <- zero_terminated };
    10         .end <- repeat { uint8 };
     9        .until_error <- repeat { uint8 <- zero_terminated };
     10        .until_end <- repeat { uint8 };
    1111};
     12
     13transform do_while = do {
     14        struct {
     15                .valid <- nonzero_boolean <- uint8;
     16                .val <- uint8;
     17        }
     18} while (.valid);
    1219
    1320transform main = struct {
    1421        .with_count <- with_count;
    15         .without_count <- without_count;
     22        .without_count <- without_count <- known_length(9);
     23        .do_while <- do_while;
    1624};
Note: See TracChangeset for help on using the changeset viewer.