Changeset 10334c2e in mainline
- Timestamp:
- 2012-07-30T01:40:55Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 20ac1a4
- Parents:
- d1e580a
- Location:
- uspace/app/bithenge
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/expression.c
rd1e580a r10334c2e 417 417 } 418 418 419 typedef struct { 420 bithenge_transform_t base; 421 bithenge_expression_t *expr; 422 bithenge_transform_t *true_xform, *false_xform; 423 } if_transform_t; 424 425 static inline bithenge_transform_t *if_as_transform(if_transform_t *self) 426 { 427 return &self->base; 428 } 429 430 static inline if_transform_t *transform_as_if(bithenge_transform_t *base) 431 { 432 return (if_transform_t *)base; 433 } 434 435 static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope, 436 bool *out) 437 { 438 bithenge_node_t *cond_node; 439 int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node); 440 if (rc != EOK) 441 return rc; 442 if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) { 443 bithenge_node_dec_ref(cond_node); 444 return EINVAL; 445 } 446 *out = bithenge_boolean_node_value(cond_node); 447 bithenge_node_dec_ref(cond_node); 448 return EOK; 449 } 450 451 static int if_transform_apply(bithenge_transform_t *base, 452 bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out) 453 { 454 if_transform_t *self = transform_as_if(base); 455 bool cond; 456 int rc = if_transform_choose(self, scope, &cond); 457 if (rc != EOK) 458 return rc; 459 return bithenge_transform_apply( 460 cond ? self->true_xform : self->false_xform, scope, in, out); 461 } 462 463 static int if_transform_prefix_length(bithenge_transform_t *base, 464 bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out) 465 { 466 if_transform_t *self = transform_as_if(base); 467 bool cond; 468 int rc = if_transform_choose(self, scope, &cond); 469 if (rc != EOK) 470 return rc; 471 return bithenge_transform_prefix_length( 472 cond ? self->true_xform : self->false_xform, scope, in, out); 473 } 474 475 static void if_transform_destroy(bithenge_transform_t *base) 476 { 477 if_transform_t *self = transform_as_if(base); 478 bithenge_expression_dec_ref(self->expr); 479 bithenge_transform_dec_ref(self->true_xform); 480 bithenge_transform_dec_ref(self->false_xform); 481 free(self); 482 } 483 484 static const bithenge_transform_ops_t if_transform_ops = { 485 .apply = if_transform_apply, 486 .prefix_length = if_transform_prefix_length, 487 .destroy = if_transform_destroy, 488 }; 489 490 /** Create a transform that applies either of two transforms depending on a 491 * boolean expression. Takes references to @a expr, @a true_xform, and 492 * @a false_xform. 493 * @param[out] out Holds the new transform. 494 * @param expr The boolean expression to evaluate. 495 * @param true_xform The transform to apply if the expression is true. 496 * @param false_xform The transform to apply if the expression is false. */ 497 int bithenge_if_transform(bithenge_transform_t **out, 498 bithenge_expression_t *expr, bithenge_transform_t *true_xform, 499 bithenge_transform_t *false_xform) 500 { 501 int rc; 502 if_transform_t *self = malloc(sizeof(*self)); 503 if (!self) { 504 rc = ENOMEM; 505 goto error; 506 } 507 508 rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops, 509 0); 510 if (rc != EOK) 511 goto error; 512 513 self->expr = expr; 514 self->true_xform = true_xform; 515 self->false_xform = false_xform; 516 *out = if_as_transform(self); 517 return EOK; 518 519 error: 520 free(self); 521 bithenge_expression_dec_ref(expr); 522 bithenge_transform_dec_ref(true_xform); 523 bithenge_transform_dec_ref(false_xform); 524 return rc; 525 } 526 419 527 /** @} 420 528 */ -
uspace/app/bithenge/expression.h
rd1e580a r10334c2e 100 100 int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *, 101 101 bithenge_expression_t **); 102 int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *, 103 bithenge_transform_t *, bithenge_transform_t *); 102 104 103 105 #endif -
uspace/app/bithenge/script.c
rd1e580a r10334c2e 58 58 59 59 /* Keywords */ 60 TOKEN_ELSE, 61 TOKEN_FALSE, 62 TOKEN_IF, 60 63 TOKEN_STRUCT, 61 64 TOKEN_TRANSFORM, 65 TOKEN_TRUE, 62 66 } token_type_t; 63 67 … … 204 208 if (!value) { 205 209 error_errno(state, ENOMEM); 210 } else if (!str_cmp(value, "else")) { 211 state->token = TOKEN_ELSE; 212 free(value); 213 } else if (!str_cmp(value, "false")) { 214 state->token = TOKEN_FALSE; 215 free(value); 216 } else if (!str_cmp(value, "if")) { 217 state->token = TOKEN_IF; 218 free(value); 206 219 } else if (!str_cmp(value, "struct")) { 207 220 state->token = TOKEN_STRUCT; … … 209 222 } else if (!str_cmp(value, "transform")) { 210 223 state->token = TOKEN_TRANSFORM; 224 free(value); 225 } else if (!str_cmp(value, "true")) { 226 state->token = TOKEN_TRUE; 211 227 free(value); 212 228 } else { … … 329 345 static bithenge_expression_t *parse_expression(state_t *state) 330 346 { 331 if (state->token == TOKEN_INTEGER) { 347 if (state->token == TOKEN_TRUE || state->token == TOKEN_FALSE) { 348 bool val = state->token == TOKEN_TRUE; 349 next_token(state); 350 bithenge_node_t *node; 351 int rc = bithenge_new_boolean_node(&node, val); 352 if (rc != EOK) { 353 error_errno(state, rc); 354 return NULL; 355 } 356 357 bithenge_expression_t *expr; 358 rc = bithenge_const_expression(&expr, node); 359 if (rc != EOK) { 360 error_errno(state, rc); 361 return NULL; 362 } 363 364 return expr; 365 } else if (state->token == TOKEN_INTEGER) { 332 366 bithenge_int_t val = state->token_int; 333 367 next_token(state); … … 454 488 455 489 return result; 490 } 491 492 static bithenge_transform_t *parse_if(state_t *state) 493 { 494 expect(state, TOKEN_IF); 495 expect(state, '('); 496 bithenge_expression_t *expr = parse_expression(state); 497 expect(state, ')'); 498 expect(state, '{'); 499 bithenge_transform_t *true_xform = parse_transform(state); 500 expect(state, '}'); 501 expect(state, TOKEN_ELSE); 502 expect(state, '{'); 503 bithenge_transform_t *false_xform = parse_transform(state); 504 expect(state, '}'); 505 if (state->error != EOK) { 506 bithenge_expression_dec_ref(expr); 507 bithenge_transform_dec_ref(true_xform); 508 bithenge_transform_dec_ref(false_xform); 509 return NULL; 510 } 511 bithenge_transform_t *if_xform; 512 int rc = bithenge_if_transform(&if_xform, expr, true_xform, 513 false_xform); 514 if (rc != EOK) { 515 error_errno(state, rc); 516 return NULL; 517 } 518 return if_xform; 456 519 } 457 520 … … 507 570 if (state->token == TOKEN_IDENTIFIER) { 508 571 return parse_invocation(state); 572 } else if (state->token == TOKEN_IF) { 573 return parse_if(state); 509 574 } else if (state->token == TOKEN_STRUCT) { 510 575 return parse_struct(state); -
uspace/app/bithenge/tree.c
rd1e580a r10334c2e 126 126 } 127 127 128 /** Initialize an internal node. 129 * @memberof bithenge_node_t 130 * @param[out] self The node. 131 * @param[in] ops The operations provided. 132 * @return EOK on success or an error code from errno.h. */ 133 int bithenge_init_internal_node(bithenge_node_t *self, 134 const bithenge_internal_node_ops_t *ops) 135 { 136 self->type = BITHENGE_NODE_INTERNAL; 137 self->refs = 1; 138 self->internal_ops = ops; 139 return EOK; 140 } 141 142 static void internal_node_indestructible(bithenge_node_t *self) 143 { 144 assert(false); 145 } 146 147 static int empty_internal_node_for_each(bithenge_node_t *base, 148 bithenge_for_each_func_t func, void *data) 149 { 150 return EOK; 151 } 152 153 static int empty_internal_node_get(bithenge_node_t *self, bithenge_node_t *key, 154 bithenge_node_t **out) 155 { 156 return ENOENT; 157 } 158 159 static const bithenge_internal_node_ops_t empty_internal_node_ops = { 160 .for_each = empty_internal_node_for_each, 161 .get = empty_internal_node_get, 162 .destroy = internal_node_indestructible, 163 }; 164 165 static bithenge_node_t empty_internal_node = { 166 BITHENGE_NODE_INTERNAL, 167 1, 168 { .internal_ops = &empty_internal_node_ops }, 169 }; 170 171 /** Create an empty internal node. 172 * @param[out] out Holds the created node. 173 * @return EOK on success or an error code from errno.h. */ 174 int bithenge_new_empty_internal_node(bithenge_node_t **out) 175 { 176 bithenge_node_inc_ref(&empty_internal_node); 177 *out = &empty_internal_node; 178 return EOK; 179 } 180 128 181 typedef struct 129 182 { … … 173 226 .destroy = simple_internal_node_destroy, 174 227 }; 175 176 /** Initialize an internal node.177 * @memberof bithenge_node_t178 * @param[out] self The node.179 * @param[in] ops The operations provided.180 * @return EOK on success or an error code from errno.h. */181 int bithenge_init_internal_node(bithenge_node_t *self,182 const bithenge_internal_node_ops_t *ops)183 {184 self->type = BITHENGE_NODE_INTERNAL;185 self->refs = 1;186 self->internal_ops = ops;187 return EOK;188 }189 228 190 229 /** Create an internal node from a set of keys and values. This function takes -
uspace/app/bithenge/tree.h
rd1e580a r10334c2e 161 161 int bithenge_init_internal_node(bithenge_node_t *, 162 162 const bithenge_internal_node_ops_t *); 163 int bithenge_new_empty_internal_node(bithenge_node_t **); 163 164 int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **, 164 165 bithenge_int_t, bool needs_free);
Note:
See TracChangeset
for help on using the changeset viewer.