Index: uspace/app/bithenge/helenos/os.h
===================================================================
--- uspace/app/bithenge/helenos/os.h	(revision 4056ad0489ea8411e60723494ce05bf411223d7d)
+++ uspace/app/bithenge/helenos/os.h	(revision 32eb01b859a99ad60bf61e20d715ef6f837bd618)
@@ -82,5 +82,11 @@
 static inline int bithenge_parse_int(const char *start, bithenge_int_t *result)
 {
-	return str_uint64_t(start, NULL, 10, false, result);
+	const char *real_start = *start == '-' ? start + 1 : start;
+	uint64_t val;
+	int rc = str_uint64_t(real_start, NULL, 10, false, &val);
+	*result = val;
+	if (*start == '-')
+		*result = -*result;
+	return rc;
 }
 
Index: uspace/app/bithenge/script.c
===================================================================
--- uspace/app/bithenge/script.c	(revision 4056ad0489ea8411e60723494ce05bf411223d7d)
+++ uspace/app/bithenge/script.c	(revision 32eb01b859a99ad60bf61e20d715ef6f837bd618)
@@ -74,6 +74,8 @@
 	 * to indicate whether an error has occurred. */
 	int error;
+
 	/** The list of named transforms. */
 	transform_list_t *transform_list;
+
 	/** The name of the script file. */
 	const char *filename;
@@ -91,4 +93,5 @@
 	/** Added to a buffer position to find the column number. */
 	int line_offset;
+
 	/** The type of the current token. */
 	token_type_t token;
@@ -100,4 +103,9 @@
 		bithenge_int_t token_int;
 	};
+
+	/** The names of the current transform's parameters. */
+	char **parameter_names;
+	/** The number of parameters. */
+	int num_params;
 } state_t;
 
@@ -340,4 +348,26 @@
 
 		return expr;
+	} else if (state->token == TOKEN_IDENTIFIER) {
+		int i;
+		for (i = 0; i < state->num_params; i++)
+			if (!str_cmp(state->parameter_names[i],
+			    state->token_string))
+				break;
+
+		if (i == state->num_params) {
+			syntax_error(state, "unknown identifier");
+			return NULL;
+		}
+
+		bithenge_expression_t *expr;
+		int rc = bithenge_param_expression(&expr, i);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		next_token(state);
+
+		return expr;
 	} else {
 		syntax_error(state, "expression expected");
@@ -494,8 +524,41 @@
 	expect(state, TOKEN_TRANSFORM);
 	char *name = expect_identifier(state);
+
+	if (state->token == '(') {
+		next_token(state);
+		while (state->error == EOK && state->token != ')') {
+			if (state->num_params)
+				expect(state, ',');
+			state->parameter_names = state_realloc(state,
+			    state->parameter_names,
+			    (state->num_params + 1)*sizeof(*state->parameter_names));
+			if (state->error != EOK)
+				break;
+			state->parameter_names[state->num_params++] =
+			    expect_identifier(state);
+		}
+		expect(state, ')');
+	}
+
 	expect(state, '=');
 	bithenge_transform_t *xform = parse_transform(state);
 	expect(state, ';');
+
+	if (state->error == EOK && state->num_params) {
+		int rc = bithenge_new_param_transform(&xform, xform,
+		    state->num_params);
+		if (rc != EOK) {
+			xform = NULL;
+			error_errno(state, rc);
+		}
+	}
+
 	add_named_transform(state, xform, name);
+
+	for (int i = 0; i < state->num_params; i++)
+		free(state->parameter_names[i]);
+	free(state->parameter_names);
+	state->parameter_names = NULL;
+	state->num_params = 0;
 }
 
@@ -505,4 +568,6 @@
 	state->error = EOK;
 	state->transform_list = NULL;
+	state->parameter_names = NULL;
+	state->num_params = 0;
 	state->token = TOKEN_ERROR;
 	state->old_buffer_pos = state->buffer_pos = BUFFER_SIZE - 1;
@@ -532,4 +597,7 @@
 		entry = next;
 	}
+	for (int i = 0; i < state->num_params; i++)
+		free(state->parameter_names[i]);
+	free(state->parameter_names);
 }
 
Index: uspace/app/bithenge/transform.c
===================================================================
--- uspace/app/bithenge/transform.c	(revision 4056ad0489ea8411e60723494ce05bf411223d7d)
+++ uspace/app/bithenge/transform.c	(revision 32eb01b859a99ad60bf61e20d715ef6f837bd618)
@@ -385,5 +385,5 @@
 	bithenge_node_t base;
 	struct struct_transform *transform;
-	bithenge_scope_t *scope;
+	bithenge_scope_t scope;
 	bithenge_blob_t *blob;
 } struct_node_t;
@@ -491,5 +491,5 @@
 	for (size_t i = 0; subxforms[i].transform; i++) {
 		rc = struct_node_for_one(subxforms[i].name,
-		    subxforms[i].transform, struct_node->scope, &blob, func,
+		    subxforms[i].transform, &struct_node->scope, &blob, func,
 		    data);
 		if (rc != EOK)
@@ -516,4 +516,5 @@
 	bithenge_transform_dec_ref(struct_as_transform(node->transform));
 	bithenge_blob_dec_ref(node->blob);
+	bithenge_scope_destroy(&node->scope);
 	free(node);
 }
@@ -533,7 +534,14 @@
 	if (!node)
 		return ENOMEM;
-	int rc = bithenge_init_internal_node(struct_as_node(node),
+	bithenge_scope_init(&node->scope);
+	int rc = bithenge_scope_copy(&node->scope, scope);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+	rc = bithenge_init_internal_node(struct_as_node(node),
 	    &struct_node_ops);
 	if (rc != EOK) {
+		bithenge_scope_destroy(&node->scope);
 		free(node);
 		return rc;
@@ -542,5 +550,4 @@
 	node->transform = self;
 	bithenge_node_inc_ref(in);
-	node->scope = scope;
 	node->blob = bithenge_node_as_blob(in);
 	*out = struct_as_node(node);
Index: uspace/app/bithenge/transform.h
===================================================================
--- uspace/app/bithenge/transform.h	(revision 4056ad0489ea8411e60723494ce05bf411223d7d)
+++ uspace/app/bithenge/transform.h	(revision 32eb01b859a99ad60bf61e20d715ef6f837bd618)
@@ -88,4 +88,23 @@
 }
 
+/** Copy a scope.
+ * @param[out] out The scope to fill in; must have been initialized with @a
+ * bithenge_scope_init.
+ * @param scope The scope to copy.
+ * @return EOK on success or an error code from errno.h. */
+static inline int bithenge_scope_copy(bithenge_scope_t *out,
+    bithenge_scope_t *scope)
+{
+	out->params = malloc(sizeof(*out->params) * scope->num_params);
+	if (!out->params)
+		return ENOMEM;
+	memcpy(out->params, scope->params, sizeof(*out->params) *
+	    scope->num_params);
+	out->num_params = scope->num_params;
+	for (int i = 0; i < out->num_params; i++)
+		bithenge_node_inc_ref(out->params[i]);
+	return EOK;
+}
+
 /** Allocate parameters. The parameters must then be set with @a
  * bithenge_scope_set_param.
