Index: uspace/app/bithenge/expression.c
===================================================================
--- uspace/app/bithenge/expression.c	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/app/bithenge/expression.c	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -63,4 +63,8 @@
 }
 
+
+
+/***************** binary_expression                         *****************/
+
 typedef struct {
 	bithenge_expression_t base;
@@ -185,4 +189,43 @@
 }
 
+
+
+/***************** in_node_expression                        *****************/
+
+static int in_node_evaluate(bithenge_expression_t *self,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	for (; scope && !bithenge_scope_is_barrier(scope);
+	    scope = bithenge_scope_outer(scope)) {
+		*out = bithenge_scope_in_node(scope);
+		if (*out)
+			return EOK;
+	}
+	return EINVAL;
+}
+
+static const bithenge_expression_ops_t in_node_ops = {
+	.evaluate = in_node_evaluate,
+	.destroy = expression_indestructible,
+};
+
+static bithenge_expression_t in_node_expression = {
+	&in_node_ops, 1
+};
+
+/** Create an expression that gets the current input node.
+ * @param[out] out Holds the new expression.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_in_node_expression(bithenge_expression_t **out)
+{
+	bithenge_expression_inc_ref(&in_node_expression);
+	*out = &in_node_expression;
+	return EOK;
+}
+
+
+
+/***************** current_node_expression                   *****************/
+
 static int current_node_evaluate(bithenge_expression_t *self,
     bithenge_scope_t *scope, bithenge_node_t **out)
@@ -212,4 +255,8 @@
 	return EOK;
 }
+
+
+
+/***************** param_expression                          *****************/
 
 typedef struct {
@@ -270,4 +317,8 @@
 	return EOK;
 }
+
+
+
+/***************** const_expression                          *****************/
 
 typedef struct {
@@ -651,4 +702,9 @@
 }
 
+
+
+/***************** expression_transform           *****************/
+
+/* Also used by inputless_transform. */
 typedef struct {
 	bithenge_transform_t base;
@@ -672,22 +728,15 @@
 {
 	expression_transform_t *self = transform_as_expression(base);
-	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
-		return EINVAL;
-	aoff64_t len;
-	int rc = bithenge_blob_size(bithenge_node_as_blob(in), &len);
-	if (rc != EOK)
-		return rc;
-	if (len != 0)
-		return EINVAL;
-	return bithenge_expression_evaluate(self->expr, scope, out);
-}
-
-static int expression_transform_prefix_length(bithenge_transform_t *base,
-    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
-{
-	*out = 0;
-	return EOK;
-}
-
+	bithenge_scope_t *inner;
+	int rc = bithenge_scope_new(&inner, scope);
+	if (rc != EOK)
+		return rc;
+	bithenge_scope_set_in_node(inner, in);
+	rc = bithenge_expression_evaluate(self->expr, inner, out);
+	bithenge_scope_dec_ref(inner);
+	return rc;
+}
+
+/* Also used by inputless_transform. */
 static void expression_transform_destroy(bithenge_transform_t *base)
 {
@@ -699,5 +748,60 @@
 static const bithenge_transform_ops_t expression_transform_ops = {
 	.apply = expression_transform_apply,
-	.prefix_length = expression_transform_prefix_length,
+	.destroy = expression_transform_destroy,
+};
+
+/** Create a transform that evaluates an expression on the input node. Takes a
+ * reference to the expression.
+ * @param[out] out Holds the new transform.
+ * @param expr The expression to evaluate.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_expression_transform(bithenge_transform_t ** out,
+    bithenge_expression_t *expr)
+{
+	int rc;
+	expression_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(expression_as_transform(self),
+	    &expression_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	*out = expression_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	return rc;
+}
+
+
+
+/***************** inputless_transform            *****************/
+
+static int inputless_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	*out = 0;
+	return EOK;
+}
+
+static int inputless_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	*out_size = 0;
+	return bithenge_expression_evaluate(self->expr, scope, out_node);
+}
+
+static const bithenge_transform_ops_t inputless_transform_ops = {
+	.prefix_length = inputless_transform_prefix_length,
+	.prefix_apply = inputless_transform_prefix_apply,
 	.destroy = expression_transform_destroy,
 };
@@ -708,5 +812,5 @@
  * @param expr The expression to evaluate.
  * @return EOK on success or an error code from errno.h. */
-int bithenge_expression_transform(bithenge_transform_t ** out,
+int bithenge_inputless_transform(bithenge_transform_t ** out,
     bithenge_expression_t *expr)
 {
@@ -719,5 +823,5 @@
 
 	rc = bithenge_init_transform(expression_as_transform(self),
-	    &expression_transform_ops, 0);
+	    &inputless_transform_ops, 0);
 	if (rc != EOK)
 		goto error;
@@ -732,4 +836,8 @@
 	return rc;
 }
+
+
+
+/***************** if_transform                              *****************/
 
 typedef struct {
Index: uspace/app/bithenge/expression.h
===================================================================
--- uspace/app/bithenge/expression.h	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/app/bithenge/expression.h	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -103,4 +103,5 @@
 int bithenge_binary_expression(bithenge_expression_t **, bithenge_binary_op_t,
     bithenge_expression_t *, bithenge_expression_t *);
+int bithenge_in_node_expression(bithenge_expression_t **);
 int bithenge_current_node_expression(bithenge_expression_t **);
 int bithenge_param_expression(bithenge_expression_t **, int);
@@ -114,4 +115,6 @@
 int bithenge_expression_transform(bithenge_transform_t **,
     bithenge_expression_t *);
+int bithenge_inputless_transform(bithenge_transform_t **,
+    bithenge_expression_t *);
 int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *,
     bithenge_transform_t *, bithenge_transform_t *);
Index: uspace/app/bithenge/script.c
===================================================================
--- uspace/app/bithenge/script.c	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/app/bithenge/script.c	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -64,4 +64,5 @@
 	TOKEN_FALSE,
 	TOKEN_IF,
+	TOKEN_IN,
 	TOKEN_REPEAT,
 	TOKEN_STRUCT,
@@ -225,4 +226,7 @@
 		} else if (!str_cmp(value, "if")) {
 			state->token = TOKEN_IF;
+			free(value);
+		} else if (!str_cmp(value, "in")) {
+			state->token = TOKEN_IN;
 			free(value);
 		} else if (!str_cmp(value, "repeat")) {
@@ -434,4 +438,13 @@
 
 		return expr;
+	} else if (state->token == TOKEN_IN) {
+		next_token(state);
+		bithenge_expression_t *expr;
+		rc = bithenge_in_node_expression(&expr);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+		return expr;
 	} else if (state->token == TOKEN_INTEGER) {
 		bithenge_int_t val = state->token_int;
@@ -621,5 +634,5 @@
 
 	bithenge_transform_t *xform;
-	rc = bithenge_expression_transform(&xform, expr);
+	rc = bithenge_inputless_transform(&xform, expr);
 	if (rc != EOK) {
 		error_errno(state, rc);
@@ -867,5 +880,21 @@
 static bithenge_transform_t *parse_transform_no_compose(state_t *state)
 {
-	if (state->token == TOKEN_DO) {
+	if (state->token == '(') {
+		next_token(state);
+		bithenge_expression_t *expr = parse_expression(state);
+		expect(state, ')');
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(expr);
+			return NULL;
+		}
+
+		bithenge_transform_t *xform;
+		int rc = bithenge_expression_transform(&xform, expr);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+		return xform;
+	} else if (state->token == TOKEN_DO) {
 		return parse_do_while(state);
 	} else if (state->token == TOKEN_IDENTIFIER) {
Index: uspace/app/bithenge/transform.c
===================================================================
--- uspace/app/bithenge/transform.c	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/app/bithenge/transform.c	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -183,4 +183,5 @@
 	self->params = NULL;
 	self->current_node = NULL;
+	self->in_node = NULL;
 	*out = self;
 	return EOK;
@@ -211,8 +212,17 @@
 }
 
+/** Get the current node being created, which may be NULL.
+ * @param scope The scope to get the current node from.
+ * @return The node being created, or NULL. */
+bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *scope)
+{
+	if (scope->current_node)
+		bithenge_node_inc_ref(scope->current_node);
+	return scope->current_node;
+}
+
 /** Set the current node being created. Takes a reference to @a node.
  * @param scope The scope to set the current node in.
- * @param node The current node being created, or NULL.
- * @return EOK on success or an error code from errno.h. */
+ * @param node The current node being created, or NULL. */
 void bithenge_scope_set_current_node(bithenge_scope_t *scope,
     bithenge_node_t *node)
@@ -220,4 +230,23 @@
 	bithenge_node_dec_ref(scope->current_node);
 	scope->current_node = node;
+}
+
+/** Get the current input node, which may be NULL.
+ * @param scope The scope to get the current input node from.
+ * @return The input node, or NULL. */
+bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *scope)
+{
+	if (scope->in_node)
+		bithenge_node_inc_ref(scope->in_node);
+	return scope->in_node;
+}
+
+/** Set the current input node. Takes a reference to @a node.
+ * @param scope The scope to set the input node in.
+ * @param node The input node, or NULL. */
+void bithenge_scope_set_in_node(bithenge_scope_t *scope, bithenge_node_t *node)
+{
+	bithenge_node_dec_ref(scope->in_node);
+	scope->in_node = node;
 }
 
@@ -236,14 +265,4 @@
 {
 	return self->barrier;
-}
-
-/** Get the current node being created, which may be NULL.
- * @param scope The scope to get the current node from.
- * @return The node being created, or NULL. */
-bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *scope)
-{
-	if (scope->current_node)
-		bithenge_node_inc_ref(scope->current_node);
-	return scope->current_node;
 }
 
Index: uspace/app/bithenge/transform.h
===================================================================
--- uspace/app/bithenge/transform.h	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/app/bithenge/transform.h	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -58,4 +58,5 @@
 	bithenge_node_t **params;
 	bithenge_node_t *current_node;
+	bithenge_node_t *in_node;
 } bithenge_scope_t;
 
@@ -153,8 +154,10 @@
 void bithenge_scope_dec_ref(bithenge_scope_t *);
 bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *);
+bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *);
 void bithenge_scope_set_current_node(bithenge_scope_t *, bithenge_node_t *);
+bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *);
+void bithenge_scope_set_in_node(bithenge_scope_t *, bithenge_node_t *);
 void bithenge_scope_set_barrier(bithenge_scope_t *);
 bool bithenge_scope_is_barrier(bithenge_scope_t *);
-bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *);
 int bithenge_scope_alloc_params(bithenge_scope_t *, int);
 int bithenge_scope_set_param(bithenge_scope_t *, int, bithenge_node_t *);
Index: uspace/dist/src/bithenge/test.bh
===================================================================
--- uspace/dist/src/bithenge/test.bh	(revision ad5c8a48df08e34725b61fbf9df8a163eec40df4)
+++ uspace/dist/src/bithenge/test.bh	(revision a66ea217be2cd83836475a91052425e6ac64aa0f)
@@ -16,11 +16,11 @@
 
 transform item(little_endian, len) = struct {
-	.type <- u32(little_endian);
+	.type <- (3*in+1) <- u32(little_endian);
 	.name <- pascal_string;
 	switch (.type) {
-		3: {
+		10: {
 			.val <- u32(little_endian);
 		};
-		14: {
+		11: {
 			.text <- ascii <- known_length(len);
 		};
