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

Changeset 4056ad0 in mainline


Ignore:
Timestamp:
2012-07-28T01:57:31Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
32eb01b
Parents:
03cad47
Message:

Bithenge: basic parameter passing (integer literals only)

Location:
uspace/app/bithenge
Files:
7 edited

Legend:

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

    r03cad47 r4056ad0  
    231231
    232232error:
    233         bithenge_node_dec_ref(in);
    234233        bithenge_scope_destroy(&inner);
    235234        return rc;
    236235}
    237 
    238236
    239237static int param_wrapper_prefix_length(bithenge_transform_t *base,
     
    252250
    253251error:
    254         bithenge_blob_dec_ref(in);
    255252        bithenge_scope_destroy(&inner);
    256253        return rc;
    257254}
     255
    258256static void param_wrapper_destroy(bithenge_transform_t *base)
    259257{
  • uspace/app/bithenge/helenos/os.h

    r03cad47 r4056ad0  
    3333#include <byteorder.h>
    3434#include <errno.h>
     35#include <inttypes.h>
    3536#include <macros.h>
    3637#include <mem.h>
     
    3839#include <str.h>
    3940#include <str_error.h>
     41
     42typedef int64_t bithenge_int_t;
     43#define BITHENGE_PRId PRId64
    4044
    4145typedef struct {
     
    7680}
    7781
     82static inline int bithenge_parse_int(const char *start, bithenge_int_t *result)
     83{
     84        return str_uint64_t(start, NULL, 10, false, result);
     85}
     86
    7887#endif
  • uspace/app/bithenge/linux/os.h

    r03cad47 r4056ad0  
    3232#include <endian.h>
    3333#include <errno.h>
     34#include <inttypes.h>
    3435#include <memory.h>
    3536#include <stdbool.h>
    36 #include <stdint.h>
     37#include <stdlib.h>
    3738#include <string.h>
    3839#include <wchar.h>
     
    4445#define ELIMIT EINVAL
    4546
     47typedef intmax_t bithenge_int_t;
     48#define BITHENGE_PRId PRIdMAX
    4649typedef uint64_t aoff64_t;
    47 
    4850typedef const char *string_iterator_t;
    4951
     
    130132}
    131133
     134static inline int bithenge_parse_int(const char *start, bithenge_int_t *result)
     135{
     136        errno = 0;
     137        *result = strtoll(start, NULL, 10);
     138        return errno;
     139}
     140
    132141#endif
  • uspace/app/bithenge/script.c

    r03cad47 r4056ad0  
    3838#include <stdio.h>
    3939#include <stdlib.h>
     40#include "expression.h"
    4041#include "os.h"
    4142#include "script.h"
     
    5354        TOKEN_EOF,
    5455        TOKEN_IDENTIFIER,
     56        TOKEN_INTEGER,
    5557        TOKEN_LEFT_ARROW,
    5658
     
    9597                 * NULL, it will be freed when the next token is read. */
    9698                char *token_string;
     99                /** The value of a TOKEN_INTEGER token. */
     100                bithenge_int_t token_int;
    97101        };
    98102} state_t;
     
    202206                        state->token_string = value;
    203207                }
     208        } else if (isdigit(ch)) {
     209                while (isdigit(state->buffer[state->buffer_pos]))
     210                        state->buffer_pos++;
     211                state->token = TOKEN_INTEGER;
     212                int rc = bithenge_parse_int(state->buffer +
     213                    state->old_buffer_pos, &state->token_int);
     214                if (rc != EOK)
     215                        error_errno(state, rc);
    204216        } else if (ch == '<') {
    205217                state->token = ch;
     
    307319
    308320static bithenge_transform_t *parse_transform(state_t *state);
     321
     322static bithenge_expression_t *parse_expression(state_t *state)
     323{
     324        if (state->token == TOKEN_INTEGER) {
     325                bithenge_int_t val = state->token_int;
     326                next_token(state);
     327                bithenge_node_t *node;
     328                int rc = bithenge_new_integer_node(&node, val);
     329                if (rc != EOK) {
     330                        error_errno(state, rc);
     331                        return NULL;
     332                }
     333
     334                bithenge_expression_t *expr;
     335                rc = bithenge_const_expression(&expr, node);
     336                if (rc != EOK) {
     337                        error_errno(state, rc);
     338                        return NULL;
     339                }
     340
     341                return expr;
     342        } else {
     343                syntax_error(state, "expression expected");
     344                return NULL;
     345        }
     346}
     347
     348// state->token must be TOKEN_IDENTIFIER when this is called
     349static bithenge_transform_t *parse_invocation(state_t *state)
     350{
     351        bithenge_transform_t *result = get_named_transform(state,
     352            state->token_string);
     353        if (!result)
     354                syntax_error(state, "transform not found");
     355        next_token(state);
     356
     357        bithenge_expression_t **params = NULL;
     358        int num_params = 0;
     359        if (state->token == '(') {
     360                next_token(state);
     361                while (state->error == EOK && state->token != ')') {
     362                        if (num_params)
     363                                expect(state, ',');
     364                        params = state_realloc(state, params,
     365                            (num_params + 1)*sizeof(*params));
     366                        if (state->error != EOK)
     367                                break;
     368                        params[num_params] = parse_expression(state);
     369                        num_params++;
     370                }
     371                expect(state, ')');
     372        }
     373
     374        /* TODO: show correct error position */
     375        if (state->error == EOK
     376            && bithenge_transform_num_params(result) != num_params)
     377                syntax_error(state, "incorrect number of parameters before");
     378
     379        if (state->error != EOK) {
     380                while (num_params--)
     381                        bithenge_expression_dec_ref(params[num_params]);
     382                free(params);
     383                bithenge_transform_dec_ref(result);
     384                return NULL;
     385        }
     386
     387        if (num_params) {
     388                int rc = bithenge_param_wrapper(&result, result, params);
     389                if (rc != EOK) {
     390                        error_errno(state, rc);
     391                        result = NULL;
     392                }
     393        }
     394
     395        return result;
     396}
    309397
    310398static bithenge_transform_t *parse_struct(state_t *state)
     
    358446{
    359447        if (state->token == TOKEN_IDENTIFIER) {
    360                 bithenge_transform_t *result = get_named_transform(state,
    361                     state->token_string);
    362                 if (!result)
    363                         syntax_error(state, "transform not found");
    364                 next_token(state);
    365                 return result;
     448                return parse_invocation(state);
    366449        } else if (state->token == TOKEN_STRUCT) {
    367450                return parse_struct(state);
  • uspace/app/bithenge/transform.c

    r03cad47 r4056ad0  
    4747 * transform will get its own context with parameters, probably provided by a
    4848 * param_wrapper. If this is zero, the existing outer context will be used with
    49  * whatever parameters it has.
     49 * whatever parameters it has, so they can be passed to any param_wrappers
     50 * within.
    5051 * @return EOK or an error code from errno.h. */
    5152int bithenge_init_transform(bithenge_transform_t *self,
     
    6465{
    6566        assert(false);
     67}
     68
     69typedef struct {
     70        bithenge_transform_t base;
     71        bithenge_transform_t *transform;
     72} param_transform_t;
     73
     74static inline param_transform_t *transform_as_param(
     75    bithenge_transform_t *base)
     76{
     77        return (param_transform_t *)base;
     78}
     79
     80static inline bithenge_transform_t *param_as_transform(
     81    param_transform_t *self)
     82{
     83        return &self->base;
     84}
     85
     86static int param_transform_apply(bithenge_transform_t *base,
     87    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     88{
     89        param_transform_t *self = transform_as_param(base);
     90        return bithenge_transform_apply(self->transform, scope, in, out);
     91}
     92
     93static int param_transform_prefix_length(bithenge_transform_t *base,
     94    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
     95{
     96        param_transform_t *self = transform_as_param(base);
     97        return bithenge_transform_prefix_length(self->transform, scope, in,
     98            out);
     99}
     100
     101static void param_transform_destroy(bithenge_transform_t *base)
     102{
     103        param_transform_t *self = transform_as_param(base);
     104        bithenge_transform_dec_ref(self->transform);
     105        free(self);
     106}
     107
     108static const bithenge_transform_ops_t param_transform_ops = {
     109        .apply = param_transform_apply,
     110        .prefix_length = param_transform_prefix_length,
     111        .destroy = param_transform_destroy,
     112};
     113
     114/** Create a wrapper transform with a different number of parameters. Takes a
     115 * reference to @a transform, which it will use for all operations.
     116 * @param[out] out Holds the created transform.
     117 * @param transform The transform to wrap.
     118 * @param num_params The number of parameters to require.
     119 * @return EOK on success or an error code from errno.h. */
     120int bithenge_new_param_transform(bithenge_transform_t **out,
     121    bithenge_transform_t *transform, int num_params)
     122{
     123        assert(transform);
     124        assert(bithenge_transform_num_params(transform) == 0);
     125        assert(num_params != 0);
     126
     127        int rc;
     128        param_transform_t *self = malloc(sizeof(*self));
     129        if (!self) {
     130                rc = ENOMEM;
     131                goto error;
     132        }
     133        rc = bithenge_init_transform(param_as_transform(self),
     134            &param_transform_ops, num_params);
     135        if (rc != EOK)
     136                goto error;
     137        self->transform = transform;
     138        *out = param_as_transform(self);
     139        return EOK;
     140error:
     141        bithenge_transform_dec_ref(transform);
     142        free(self);
     143        return rc;
    66144}
    67145
     
    105183bithenge_transform_t bithenge_ascii_transform = {
    106184        &ascii_ops, 1, 0
     185};
     186
     187static int known_length_apply(bithenge_transform_t *self,
     188    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     189{
     190        bithenge_node_t *length_node;
     191        int rc = bithenge_scope_get_param(scope, 0, &length_node);
     192        if (rc != EOK)
     193                return rc;
     194        if (bithenge_node_type(length_node) != BITHENGE_NODE_INTEGER) {
     195                bithenge_node_dec_ref(length_node);
     196                return EINVAL;
     197        }
     198        bithenge_int_t length = bithenge_integer_node_value(length_node);
     199        bithenge_node_dec_ref(length_node);
     200
     201        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     202                return EINVAL;
     203        aoff64_t size;
     204        rc = bithenge_blob_size(bithenge_node_as_blob(in), &size);
     205        if (rc != EOK)
     206                return rc;
     207        if (length != (bithenge_int_t)size)
     208                return EINVAL;
     209
     210        bithenge_node_inc_ref(in);
     211        *out = in;
     212        return EOK;
     213}
     214
     215static int known_length_prefix_length(bithenge_transform_t *self,
     216    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
     217{
     218        bithenge_node_t *length_node;
     219        int rc = bithenge_scope_get_param(scope, 0, &length_node);
     220        if (rc != EOK)
     221                return rc;
     222        if (bithenge_node_type(length_node) != BITHENGE_NODE_INTEGER) {
     223                bithenge_node_dec_ref(length_node);
     224                return EINVAL;
     225        }
     226        bithenge_int_t length = bithenge_integer_node_value(length_node);
     227        bithenge_node_dec_ref(length_node);
     228
     229        *out = (aoff64_t)length;
     230        return EOK;
     231}
     232
     233static const bithenge_transform_ops_t known_length_ops = {
     234        .apply = known_length_apply,
     235        .prefix_length = known_length_prefix_length,
     236        .destroy = transform_indestructible,
     237};
     238
     239/** Pass through a blob, but require its length to equal the first argument. */
     240bithenge_transform_t bithenge_known_length_transform = {
     241        &known_length_ops, 1, 1
    107242};
    108243
     
    232367static bithenge_named_transform_t primitive_transforms[] = {
    233368        {"ascii", &bithenge_ascii_transform},
     369        {"known_length", &bithenge_known_length_transform},
    234370        {"uint8", &bithenge_uint8_transform},
    235371        {"uint16le", &bithenge_uint16le_transform},
  • uspace/app/bithenge/transform.h

    r03cad47 r4056ad0  
    207207
    208208extern bithenge_transform_t bithenge_ascii_transform;
     209extern bithenge_transform_t bithenge_known_length_transform;
    209210extern bithenge_transform_t bithenge_uint8_transform;
    210211extern bithenge_transform_t bithenge_uint16le_transform;
     
    217218extern bithenge_named_transform_t *bithenge_primitive_transforms;
    218219
    219 int bithenge_init_transform(bithenge_transform_t *self,
    220     const bithenge_transform_ops_t *ops, int num_params);
    221 int bithenge_new_struct(bithenge_transform_t **out,
    222     bithenge_named_transform_t *subtransforms);
     220int bithenge_init_transform(bithenge_transform_t *,
     221    const bithenge_transform_ops_t *, int);
     222int bithenge_new_param_transform(bithenge_transform_t **,
     223    bithenge_transform_t *, int);
     224int bithenge_new_struct(bithenge_transform_t **,
     225    bithenge_named_transform_t *);
    223226int bithenge_new_composed_transform(bithenge_transform_t **,
    224227    bithenge_transform_t **, size_t);
  • uspace/app/bithenge/tree.h

    r03cad47 r4056ad0  
    3939
    4040#include <assert.h>
    41 #include <inttypes.h>
    4241#include <sys/types.h>
    4342#include "os.h"
    44 
    45 #ifdef INTMAX_MAX
    46 typedef intmax_t bithenge_int_t;
    47 #define BITHENGE_PRId PRIdMAX
    48 #else
    49 typedef int64_t bithenge_int_t;
    50 #define BITHENGE_PRId PRId64
    51 #endif
    5243
    5344/** Indicates the type of a tree node. */
Note: See TracChangeset for help on using the changeset viewer.