Index: uspace/app/sbi/src/bigint.c
===================================================================
--- uspace/app/sbi/src/bigint.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
+++ uspace/app/sbi/src/bigint.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Big integers.
+ *
+ * Sysel type @c int should accomodate large numbers. This implementation
+ * is limited by the available memory and range of the @c size_t type used
+ * to index digits.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "debug.h"
+#include "mytypes.h"
+
+#include "bigint.h"
+
+static void bigint_sign_comb(bool_t srf_a, bigint_t *a, bool_t srf_b,
+    bigint_t *b, bigint_t *dest);
+static void bigint_add_abs(bigint_t *a, bigint_t *b, bigint_t *dest);
+static void bigint_sub_abs(bigint_t *a, bigint_t *b, bigint_t *dest);
+static void bigint_shift_mul_dig(bigint_t *a, bigint_word_t b, size_t shift,
+    bigint_t *dest);
+
+static void bigint_alloc(bigint_t *bigint, size_t length);
+static void bigint_refine_len(bigint_t *bigint);
+
+/** Initialize bigint with value from small integer.
+ *
+ * Initializes a bigint structure with the provided small value.
+ *
+ * @param value		Initial value (small int).
+ */
+void bigint_init(bigint_t *bigint, int value)
+{
+	size_t length;
+	size_t idx;
+	int t;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Initialize bigint with int value %d.\n", value);
+#endif
+
+	if (value < 0) {
+		bigint->negative = b_true;
+		value = -value;
+	} else {
+		bigint->negative = b_false;
+	}
+
+	/* Determine length. */
+	length = 0;
+	t = value;
+	while (t > 0) {
+		length += 1;
+		t = t / BIGINT_BASE;
+	}
+
+	/* Allocate digit array. */
+	bigint_alloc(bigint, length);
+
+	/* Compute digits. */
+	t = value;
+	for (idx = 0; idx < length; ++idx) {
+		bigint->digit[idx] = t % BIGINT_BASE;
+		t = t / BIGINT_BASE;
+	}
+}
+
+/** Shallow copy of integer.
+ *
+ * @param src		Source.
+ * @param dest		Destination.
+ */
+void bigint_shallow_copy(bigint_t *src, bigint_t *dest)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Shallow copy of bigint.\n");
+#endif
+	dest->negative = src->negative;
+	dest->digit = src->digit;
+	dest->length = src->length;
+}
+/** Clone big integer.
+ *
+ * @param src		Source.
+ * @param dest		Destination.
+ */
+void bigint_clone(bigint_t *src, bigint_t *dest)
+{
+	size_t idx;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Clone bigint.\n");
+#endif
+	/* Copy sign. */
+	dest->negative = src->negative;
+
+	/* Allocate dest digit array. */
+	bigint_alloc(dest, src->length);
+
+	/* Copy digits. */
+	for (idx = 0; idx < dest->length; ++idx)
+		dest->digit[idx] = src->digit[idx];
+}
+
+/** Compute big integer with reversed sign.
+ *
+ * @param src		Source.
+ * @param dest		Destination.
+ */
+void bigint_reverse_sign(bigint_t *src, bigint_t *dest)
+{
+	size_t idx;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Reverse-sign copy of bigint.\n");
+#endif
+	/* Copy reversed sign. */
+	dest->negative = !src->negative;
+
+	/* Allocate dest digit array. */
+	bigint_alloc(dest, src->length);
+
+	/* Copy digits. */
+	for (idx = 0; idx < dest->length; ++idx)
+		dest->digit[idx] = src->digit[idx];
+}
+
+/** Destroy big integer.
+ *
+ * Any bigint that is initialized via bigint_init() or any other bigint
+ * function that constructs a new bigint value should be destroyed with
+ * this function to free memory associated with the bigint. It should
+ * also be used to destroy a bigint before it is reused.
+ *
+ * @param bigint	The bigint to destroy.
+ */
+void bigint_destroy(bigint_t *bigint)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Destroy bigint.\n");
+#endif
+	bigint->negative = b_false;
+
+	bigint->length = 0;
+
+	free(bigint->digit);
+	bigint->digit = NULL;
+}
+
+/** Get value of big integer.
+ *
+ * Allows to obtain the value of big integer, provided that it fits
+ * into a small integer.
+ *
+ * @param bigint	Bigint to obtain value from.
+ * @param dval		Place to store value.
+ * @return		EOK on success, ELIMIT if bigint is too big to fit
+ *			to @a dval.
+ */
+int bigint_get_value_int(bigint_t *bigint, int *dval)
+{
+	bigint_t vval, diff;
+	size_t idx;
+	int val;
+	bool_t zf;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Get int value of bigint.\n");
+#endif
+	val = 0;
+	for (idx = 0; idx < bigint->length; ++idx) {
+		val = val * BIGINT_BASE + bigint->digit[idx];
+	}
+
+	if (bigint->negative)
+		val = - val;
+
+	/* If the value did not fit @c val now contains garbage. Verify. */
+	bigint_init(&vval, val);
+
+	bigint_sub(bigint, &vval, &diff);
+	zf = bigint_is_zero(&diff);
+
+	bigint_destroy(&vval);
+	bigint_destroy(&diff);
+
+	/* If the difference is not zero, the verification failed. */
+	if (zf != b_true)
+		return EINVAL;
+
+	*dval = val;
+	return EOK;
+}
+
+/** Determine if bigint is zero.
+ *
+ * @param bigint	Big integer.
+ * @return		b_true if @a bigint is zero, b_false otherwise.
+ */
+bool_t bigint_is_zero(bigint_t *bigint)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Determine if bigint is zero.\n");
+#endif
+	return (bigint->length == 0);
+}
+
+/** Determine if bigint is negative.
+ *
+ * @param bigint	Big integer.
+ * @return		b_true if @a bigint is negative, b_false otherwise.
+ */
+bool_t bigint_is_negative(bigint_t *bigint)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Determine if bigint is negative\n");
+#endif
+	/* Verify that we did not accidentaly introduce a negative zero. */
+	assert(bigint->negative == b_false || bigint->length > 0);
+
+	return bigint->negative;
+}
+
+/** Divide bigint by (unsigned) digit.
+ *
+ * @param a		Bigint dividend.
+ * @param b		Divisor digit.
+ * @param quot		Output bigint quotient.
+ * @param rem		Output remainder digit.
+ */
+void bigint_div_digit(bigint_t *a, bigint_word_t b, bigint_t *quot,
+    bigint_word_t *rem)
+{
+	size_t lbound;
+	size_t idx;
+	bigint_dword_t da, db;
+	bigint_dword_t q, r;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Divide bigint by digit.\n");
+#endif
+	lbound = a->length;
+	bigint_alloc(quot, lbound);
+
+	quot->negative = a->negative;
+
+	r = 0;
+	idx = lbound;
+	while (idx > 0) {
+		--idx;
+
+		da = a->digit[idx] + r * BIGINT_BASE;
+		db = b;
+
+		q = da / db;
+		r = da % db;
+
+		quot->digit[idx] = q;
+	}
+
+	bigint_refine_len(quot);
+	*rem = r;
+}
+
+/** Add two big integers.
+ *
+ * The big integers @a a and @a b are added and the result is stored in
+ * @a dest.
+ *
+ * @param a		First addend.
+ * @param b		Second addend.
+ * @param dest		Destination bigint.
+ */
+void bigint_add(bigint_t *a, bigint_t *b, bigint_t *dest)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Add bigints.\n");
+#endif
+	bigint_sign_comb(b_false, a, b_false, b, dest);
+}
+
+/** Subtract two big integers.
+ *
+ * The big integers @a a and @a b are subtracted and the result is stored in
+ * @a dest.
+ *
+ * @param a		Minuend.
+ * @param b		Subtrahend.
+ * @param dest		Destination bigint.
+ */
+void bigint_sub(bigint_t *a, bigint_t *b, bigint_t *dest)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Subtract bigints.\n");
+#endif
+	bigint_sign_comb(b_false, a, b_true, b, dest);
+}
+
+/** Multiply two big integers.
+ *
+ * The big integers @a a and @a b are multiplied and the result is stored in
+ * @a dest.
+ *
+ * @param a		First factor.
+ * @param b		Second factor.
+ * @param dest		Destination bigint.
+ */
+void bigint_mul(bigint_t *a, bigint_t *b, bigint_t *dest)
+{
+	size_t idx;
+	bigint_t dprod;
+	bigint_t sum;
+	bigint_t tmp;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Multiply bigints.\n");
+#endif
+	bigint_init(&sum, 0);
+	for (idx = 0; idx < b->length; ++idx) {
+		bigint_shift_mul_dig(a, b->digit[idx], idx, &dprod);
+		bigint_add(&dprod, &sum, &tmp);
+		bigint_destroy(&dprod);
+
+		bigint_destroy(&sum);
+		bigint_shallow_copy(&tmp, &sum);
+	}
+
+	if (b->negative)
+		sum.negative = !sum.negative;
+
+	bigint_shallow_copy(&sum, dest);
+}
+
+/** Print bigint to standard output. */
+void bigint_print(bigint_t *bigint)
+{
+	bigint_t val, tmp;
+	bigint_word_t rem;
+	size_t ndigits;
+	int *digits;
+	size_t idx;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Print bigint.\n");
+#endif
+	assert(BIGINT_BASE >= 10);
+
+	if (bigint_is_zero(bigint)) {
+		putchar('0');
+		return;
+	}
+
+	if (bigint->negative)
+		putchar('-');
+
+	/* Compute number of digits. */
+	ndigits = 0;
+	bigint_clone(bigint, &val);
+	while (bigint_is_zero(&val) != b_true) {
+		bigint_div_digit(&val, 10, &tmp, &rem);
+		bigint_destroy(&val);
+		bigint_shallow_copy(&tmp, &val);
+
+		ndigits += 1;
+	}
+	bigint_destroy(&val);
+
+	/* Store digits to array. */
+
+	digits = malloc(ndigits * sizeof(int));
+	if (digits == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	idx = 0;
+	bigint_clone(bigint, &val);
+	while (bigint_is_zero(&val) != b_true) {
+		bigint_div_digit(&val, 10, &tmp, &rem);
+		bigint_destroy(&val);
+		bigint_shallow_copy(&tmp, &val);
+
+		digits[idx++] = (int) rem;
+	}
+	bigint_destroy(&val);
+
+	for (idx = 0; idx < ndigits; ++idx)
+		printf("%u", digits[ndigits - 1 - idx]);
+
+	free(digits);
+}
+
+/** Compute sign combination of two big integers.
+ *
+ * Of the big integers @a a and @a b each is optionally sign-reversed and then
+ * they are added and the result is stored in @a dest.
+ *
+ * @param srf_a		First sign reversal flag.
+ * @param a		First bigint.
+ * @param srf_b		Second sign reversal flag.
+ * @param b		Second bigint.
+ * @param dest		Destination bigint.
+ */
+static void bigint_sign_comb(bool_t srf_a, bigint_t *a, bool_t srf_b,
+    bigint_t *b, bigint_t *dest)
+{
+	bool_t neg_a, neg_b;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Signed combination of two bigints.\n");
+#endif
+	/* Compute resulting signs of combination elements. */
+	neg_a = (srf_a != a->negative);
+	neg_b = (srf_b != b->negative);
+
+	if (neg_a == neg_b) {
+		bigint_add_abs(a, b, dest);
+		dest->negative = neg_a;
+	} else {
+		bigint_sub_abs(a, b, dest);
+		dest->negative = (neg_a != dest->negative);
+	}
+}
+
+/** Add absolute values of two big integers.
+ *
+ * The absolute values of big integers @a a and @a b are added and the result
+ * is stored in @a dest.
+ *
+ * @param a		First addend.
+ * @param b		Second addend.
+ * @param dest		Destination bigint.
+ */
+static void bigint_add_abs(bigint_t *a, bigint_t *b, bigint_t *dest)
+{
+	size_t lbound;
+	size_t idx;
+	bigint_dword_t da, db;
+	bigint_dword_t tmp;
+	bigint_word_t res, carry;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Add absolute values of bigints.\n");
+#endif
+	/* max(a->length, b->length) + 1 */
+	lbound = (a->length > b->length ? a->length : b->length) + 1;
+	dest->negative = b_false;
+
+	bigint_alloc(dest, lbound);
+	carry = 0;
+
+	for (idx = 0; idx < lbound; ++idx) {
+		da = idx < a->length ? a->digit[idx] : 0;
+		db = idx < b->length ? b->digit[idx] : 0;
+
+		tmp = da + db + (bigint_word_t) carry;
+
+		carry = (bigint_word_t) (tmp / BIGINT_BASE);
+		res = (bigint_word_t) (tmp % BIGINT_BASE);
+
+		dest->digit[idx] = res;
+	}
+
+	/* If our lbound is correct, carry must be zero. */
+	assert(carry == 0);
+
+	bigint_refine_len(dest);
+}
+
+/** Subtract absolute values of two big integers.
+ *
+ * The absolute values of big integers @a a and @a b are subtracted and the
+ * result is stored in @a dest.
+ *
+ * @param a		Minuend.
+ * @param b		Subtrahend.
+ * @param dest		Destination bigint.
+ */
+static void bigint_sub_abs(bigint_t *a, bigint_t *b, bigint_t *dest)
+{
+	size_t lbound;
+	size_t idx;
+	bigint_dword_t da, db;
+	bigint_dword_t tmp;
+	bigint_word_t res, borrow;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Subtract absolute values of bigints.\n");
+#endif
+	/* max(a->length, b->length) */
+	lbound = a->length > b->length ? a->length : b->length;
+
+	bigint_alloc(dest, lbound);
+	borrow = 0;
+
+	for (idx = 0; idx < lbound; ++idx) {
+		da = idx < a->length ? a->digit[idx] : 0;
+		db = idx < b->length ? b->digit[idx] : 0;
+
+		if (da > db + borrow) {
+			tmp = da - db - borrow;
+			borrow = 0;
+		} else {
+			tmp = da + BIGINT_BASE - db - borrow;
+			borrow = 1;
+		}
+
+		res = (bigint_word_t) tmp;
+		dest->digit[idx] = res;
+	}
+
+	if (borrow != 0) {
+		/* We subtracted the greater number from the smaller. */
+		dest->negative = b_true;
+
+		/*
+		 * Now we must complement the number to get the correct
+		 * absolute value. We do this by subtracting from 10..0
+		 * (0 repeated lbound-times).
+		 */
+		borrow = 0;
+
+		for (idx = 0; idx < lbound; ++idx) {
+			da = 0;
+			db = dest->digit[idx];
+
+			if (da > db + borrow) {
+				tmp = da - db - borrow;
+				borrow = 0;
+			} else {
+				tmp = da + BIGINT_BASE - db - borrow;
+				borrow = 1;
+			}
+
+			res = (bigint_word_t) tmp;
+			dest->digit[idx] = res;
+		}
+
+		/* The last step is the '1'. */
+		assert(borrow == 1);
+	} else {
+		dest->negative = b_false;
+	}
+
+	bigint_refine_len(dest);
+}
+
+/** Multiply big integer by digit.
+ *
+ * @param a		Bigint factor.
+ * @param b		Digit factor.
+ * @param dest		Destination bigint.
+ */
+static void bigint_shift_mul_dig(bigint_t *a, bigint_word_t b, size_t shift,
+    bigint_t *dest)
+{
+	size_t lbound;
+	size_t idx;
+
+	bigint_dword_t da, db;
+	bigint_dword_t tmp;
+	bigint_word_t res, carry;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Multiply bigint by digit.\n");
+#endif
+	/* Compute length bound and allocate. */
+	lbound = a->length + shift + 1;
+	bigint_alloc(dest, lbound);
+
+	/* Copy sign. */
+	dest->negative = a->negative;
+
+	for (idx = 0; idx < shift; ++idx)
+		dest->digit[idx] = 0;
+
+	carry = 0;
+	for (idx = 0; idx < lbound - shift; ++idx) {
+		da = idx < a->length ? a->digit[idx] : 0;
+		db = b;
+
+		tmp = (da * db) + (bigint_word_t) carry;
+
+		carry = (bigint_word_t) (tmp / BIGINT_BASE);
+		res = (bigint_word_t) (tmp % BIGINT_BASE);
+
+		dest->digit[shift + idx] = res;
+	}
+
+	/* If our lbound is correct, carry must be zero. */
+	assert(carry == 0);
+
+	bigint_refine_len(dest);
+}
+
+
+/** Allocate bigint of the given length.
+ *
+ * @param bigint	Bigint whose digit array should be allocated.
+ * @param length	Length of array (also set as bigint length).
+ */
+static void bigint_alloc(bigint_t *bigint, size_t length)
+{
+	size_t a_length;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Allocate bigint digit array.\n");
+#endif
+	/* malloc() sometimes cannot allocate blocks of zero size. */
+	if (length == 0)
+		a_length = 1;
+	else
+		a_length = length;
+
+	bigint->digit = malloc(a_length * sizeof(bigint_word_t));
+	if (bigint->digit == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	bigint->length = length;
+}
+
+/** Adjust length field of bigint to be exact.
+ *
+ * When bigint is allocated with bigint_alloc() its length can be
+ * imprecise (higher than actually number of non-zero digits).
+ * Then this function is used to lower @c length to the exact value.
+ */
+static void bigint_refine_len(bigint_t *bigint)
+{
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Refine bigint length.\n");
+#endif
+	while (bigint->length > 0 && bigint->digit[bigint->length - 1] == 0)
+		bigint->length -= 1;
+
+	if (bigint->length == 0)
+		bigint->negative = b_false;
+}
Index: uspace/app/sbi/src/bigint.h
===================================================================
--- uspace/app/sbi/src/bigint.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
+++ uspace/app/sbi/src/bigint.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_H_
+#define BIGINT_H_
+
+#include "mytypes.h"
+
+void bigint_init(bigint_t *bigint, int value);
+void bigint_shallow_copy(bigint_t *src, bigint_t *dest);
+void bigint_clone(bigint_t *src, bigint_t *dest);
+void bigint_reverse_sign(bigint_t *src, bigint_t *dest);
+void bigint_destroy(bigint_t *bigint);
+
+int bigint_get_value_int(bigint_t *bigint, int *dval);
+bool_t bigint_is_zero(bigint_t *bigint);
+bool_t bigint_is_negative(bigint_t *bigint);
+
+void bigint_div_digit(bigint_t *a, bigint_word_t b, bigint_t *quot,
+    bigint_word_t *rem);
+
+void bigint_add(bigint_t *a, bigint_t *b, bigint_t *dest);
+void bigint_sub(bigint_t *a, bigint_t *b, bigint_t *dest);
+void bigint_mul(bigint_t *a, bigint_t *b, bigint_t *dest);
+void bigint_print(bigint_t *bigint);
+
+#endif
Index: uspace/app/sbi/src/bigint_t.h
===================================================================
--- uspace/app/sbi/src/bigint_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
+++ uspace/app/sbi/src/bigint_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BIGINT_T_H_
+#define BIGINT_T_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+typedef uint8_t bigint_word_t;
+typedef uint16_t bigint_dword_t;
+
+#define BIGINT_BASE ((bigint_dword_t) 256UL)
+
+/** Big integer.
+ *
+ * Used to implement Sysel @c int type.
+ */
+typedef struct bigint {
+	/** Number of non-zero digits in the @c digit array. */
+	size_t length;
+
+	/** Sign. */
+	bool_t negative;
+
+	/** Digits starting from the least significant. */
+	bigint_word_t *digit;
+} bigint_t;
+
+#endif
Index: uspace/app/sbi/src/builtin.c
===================================================================
--- uspace/app/sbi/src/builtin.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/builtin.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -41,4 +41,5 @@
 #include <assert.h>
 #include "ancr.h"
+#include "builtin/bi_error.h"
 #include "builtin/bi_fun.h"
 #include "builtin/bi_textfile.h"
@@ -86,4 +87,5 @@
 	 */
 
+	bi_error_declare(bi);
 	bi_fun_declare(bi);
 	bi_textfile_declare(bi);
@@ -92,4 +94,5 @@
 	ancr_module_process(program, program->module);
 
+	bi_error_bind(bi);
 	bi_fun_bind(bi);
 	bi_textfile_bind(bi);
Index: uspace/app/sbi/src/builtin/bi_error.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_error.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
+++ uspace/app/sbi/src/builtin/bi_error.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Error classes (used with exception handling). */
+
+#include <assert.h>
+#include "../builtin.h"
+#include "../mytypes.h"
+#include "../symbol.h"
+
+#include "bi_error.h"
+
+/** Declare error class hierarchy. */
+void bi_error_declare(builtin_t *bi)
+{
+	/*
+	 * Declare class Error and its subclasses.
+	 * Here, class Error supplants a package or namespace.
+	 */
+
+	builtin_code_snippet(bi,
+		"class Error is\n"
+			/* Common ancestor of all error classes */
+			"class Base is\n"
+			"end\n"
+			/* Accessing nil reference */
+			"class NilReference : Base is\n"
+			"end\n"
+			/* Array index out of bounds */
+			"class OutOfBounds : Base is\n"
+			"end\n"
+		"end\n");}
+
+/** Bind error class hierarchy. */
+void bi_error_bind(builtin_t *bi)
+{
+	stree_symbol_t *sym;
+
+	/* Declare class Error and its subclasses. */
+
+	sym = builtin_find_lvl1(bi, "Error", "OutOfBounds");
+	bi->error_outofbounds = symbol_to_csi(sym);
+	assert(bi->error_outofbounds != NULL);
+
+	sym = builtin_find_lvl1(bi, "Error", "NilReference");
+	bi->error_nilreference = symbol_to_csi(sym);
+	assert(bi->error_nilreference != NULL);
+}
Index: uspace/app/sbi/src/builtin/bi_error.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_error.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
+++ uspace/app/sbi/src/builtin/bi_error.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BI_ERROR_H_
+#define BI_ERROR_H_
+
+#include "../mytypes.h"
+
+void bi_error_declare(builtin_t *bi);
+void bi_error_bind(builtin_t *bi);
+
+#endif
Index: uspace/app/sbi/src/builtin/bi_fun.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_fun.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/builtin/bi_fun.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -32,4 +32,5 @@
 #include <stdlib.h>
 #include <assert.h>
+#include "../bigint.h"
 #include "../builtin.h"
 #include "../list.h"
@@ -107,5 +108,6 @@
 	switch (var->vc) {
 	case vc_int:
-		printf("%d\n", var->u.int_v->value);
+		bigint_print(&var->u.int_v->value);
+		putchar('\n');
 		break;
 	case vc_string:
Index: uspace/app/sbi/src/builtin/bi_textfile.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_textfile.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/builtin/bi_textfile.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -32,4 +32,5 @@
 #include <stdlib.h>
 #include <assert.h>
+#include "../bigint.h"
 #include "../builtin.h"
 #include "../debug.h"
@@ -344,5 +345,5 @@
 	/* Construct return value. */
 	eof_int = rdata_int_new();
-	eof_int->value = eof_flag;
+	bigint_init(&eof_int->value, eof_flag);
 
 	eof_var = rdata_var_new(vc_int);
Index: uspace/app/sbi/src/builtin_t.h
===================================================================
--- uspace/app/sbi/src/builtin_t.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/builtin_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -42,4 +42,10 @@
 	/** Grandfather object */
 	struct stree_symbol *gf_class;
+
+	/** Error class for nil reference access. */
+	struct stree_csi *error_nilreference;
+
+	/** Error class for out-of-bounds array access. */
+	struct stree_csi *error_outofbounds;
 } builtin_t;
 
Index: uspace/app/sbi/src/debug.h
===================================================================
--- uspace/app/sbi/src/debug.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/debug.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -45,3 +45,6 @@
 //#define DEBUG_RUN_TRACE
 
+/** Uncomment this to get verbose debugging messages for bigint computation. */
+//#define DEBUG_BIGINT_TRACE
+
 #endif
Index: uspace/app/sbi/src/imode.c
===================================================================
--- uspace/app/sbi/src/imode.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/imode.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -40,4 +40,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "os/os.h"
 #include "ancr.h"
 #include "assert.h"
@@ -122,4 +123,7 @@
 	list_append(&run.thread_ar->proc_ar, proc_ar);
 
+	printf("SBI interactive mode. ");
+	os_input_disp_help();
+
 	quit_im = b_false;
 	while (quit_im != b_true) {
@@ -152,4 +156,7 @@
 		run_stat(&run, stat, &rexpr);
 
+		/* Check for unhandled exceptions. */
+		run_exc_check_unhandled(&run);
+
 		if (rexpr != NULL) {
 			/* Convert expression result to value item. */
Index: uspace/app/sbi/src/lex.c
===================================================================
--- uspace/app/sbi/src/lex.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/lex.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -34,4 +34,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "bigint.h"
 #include "mytypes.h"
 #include "input.h"
@@ -135,4 +136,6 @@
 	{ lc_assign,	"=" },
 	{ lc_plus,	"+" },
+	{ lc_minus,	"-" },
+	{ lc_mult,	"*" },
 	{ lc_increase,	"+=" },
 
@@ -205,5 +208,7 @@
 		break;
 	case lc_lit_int:
-		printf("(%d)", lem->u.lit_int.value);
+		printf("(");
+		bigint_print(&lem->u.lit_int.value);
+		printf(")");
 		break;
 	case lc_lit_string:
@@ -267,4 +272,6 @@
  *
  * @param lex		Lexer object.
+ * @return		Pointer to current lem. Owned by @a lex and only valid
+ *			until next call to lex_next().
  */
 lem_t *lex_get_current(lex_t *lex)
@@ -376,4 +383,10 @@
 		lex->current.lclass = lc_plus; ++bp; break;
 
+	case '-':
+		lex->current.lclass = lc_minus; ++bp; break;
+
+	case '*':
+		lex->current.lclass = lc_mult; ++bp; break;
+
 	case '<':
 		if (bp[1] == '=') {
@@ -458,18 +471,32 @@
 {
 	char *bp;
-	int value;
+	bigint_t value;
+	bigint_t dgval;
+	bigint_t base;
+	bigint_t tprod;
 
 	bp = lex->ibp;
-	value = 0;
+
+	bigint_init(&value, 0);
+	bigint_init(&base, 10);
 
 	while (is_digit(*bp)) {
-		value = value * 10 + digit_value(*bp);
+		bigint_mul(&value, &base, &tprod);
+		bigint_init(&dgval, digit_value(*bp));
+
+		bigint_destroy(&value);
+		bigint_add(&tprod, &dgval, &value);
+		bigint_destroy(&tprod);
+		bigint_destroy(&dgval);
+
 		++bp;
 	}
 
+	bigint_destroy(&base);
+
 	lex->ibp = bp;
 
 	lex->current.lclass = lc_lit_int;
-	lex->current.u.lit_int.value = value;
+	bigint_shallow_copy(&value, &lex->current.u.lit_int.value);
 }
 
Index: uspace/app/sbi/src/lex_t.h
===================================================================
--- uspace/app/sbi/src/lex_t.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/lex_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -29,4 +29,6 @@
 #ifndef LEX_T_H_
 #define LEX_T_H_
+
+#include "bigint_t.h"
 
 /** Lexical element class */
@@ -95,4 +97,6 @@
 	lc_assign,
 	lc_plus,
+	lc_minus,
+	lc_mult,
 	lc_increase,
 
@@ -112,5 +116,5 @@
 typedef struct {
 	/* Integer value */
-	int value;
+	bigint_t value;
 } lem_lit_int_t;
 
Index: uspace/app/sbi/src/main.c
===================================================================
--- uspace/app/sbi/src/main.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/main.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -94,4 +94,5 @@
 	parse_module(&parse);
 
+	/* Check for parse errors. */
 	if (parse.error)
 		return 1;
@@ -105,4 +106,5 @@
 	stype_module(&stype, program->module);
 
+	/* Check for typing errors. */
 	if (stype.error)
 		return 1;
@@ -111,4 +113,8 @@
 	run_init(&run);
 	run_program(&run, program);
+
+	/* Check for run-time errors. */
+	if (run.thread_ar->error)
+		return 1;
 
 	return 0;
Index: uspace/app/sbi/src/mytypes.h
===================================================================
--- uspace/app/sbi/src/mytypes.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/mytypes.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -47,4 +47,5 @@
 #define EOK 0
 
+#include "bigint_t.h"
 #include "builtin_t.h"
 #include "input_t.h"
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/os/helenos.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -101,4 +101,10 @@
 }
 
+/** Display survival help message. */
+void os_input_disp_help(void)
+{
+	printf("Press Ctrl-Q to quit.\n");
+}
+
 /** Read one line of input from the user. */
 int os_input_line(char **ptr)
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/os/os.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -34,4 +34,5 @@
 char *os_str_dup(const char *str);
 int os_str_get_char(const char *str, int index, int *out_char);
+void os_input_disp_help(void);
 int os_input_line(char **ptr);
 int os_exec(char *const cmd[]);
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/os/posix.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -95,4 +95,10 @@
 static char os_input_buffer[OS_INPUT_BUFFER_SIZE];
 
+/** Display survival help message. */
+void os_input_disp_help(void)
+{
+	printf("Send ^C (SIGINT) to quit.\n");
+}
+
 /** Read one line of input from the user. */
 int os_input_line(char **ptr)
Index: uspace/app/sbi/src/p_expr.c
===================================================================
--- uspace/app/sbi/src/p_expr.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/p_expr.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -31,4 +31,5 @@
 #include <assert.h>
 #include <stdlib.h>
+#include "bigint.h"
 #include "debug.h"
 #include "lex.h"
@@ -44,4 +45,5 @@
 static stree_expr_t *parse_comparative(parse_t *parse);
 static stree_expr_t *parse_additive(parse_t *parse);
+static stree_expr_t *parse_multip(parse_t *parse);
 static stree_expr_t *parse_prefix(parse_t *parse);
 static stree_expr_t *parse_prefix_new(parse_t *parse);
@@ -51,4 +53,5 @@
 static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a);
 static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a);
+static stree_expr_t *parse_paren(parse_t *parse);
 static stree_expr_t *parse_primitive(parse_t *parse);
 static stree_expr_t *parse_nameref(parse_t *parse);
@@ -166,14 +169,21 @@
 	stree_expr_t *a, *b, *tmp;
 	stree_binop_t *binop;
-
-	a = parse_prefix(parse);
-	while (lcur_lc(parse) == lc_plus) {
+	binop_class_t bc;
+
+	a = parse_multip(parse);
+	while (lcur_lc(parse) == lc_plus || lcur_lc(parse) == lc_minus) {
 		if (parse_is_error(parse))
 			break;
 
+		switch (lcur_lc(parse)) {
+		case lc_plus: bc = bo_plus; break;
+		case lc_minus: bc = bo_minus; break;
+		default: assert(b_false);
+		}
+
 		lskip(parse);
-		b = parse_prefix(parse);
-
-		binop = stree_binop_new(bo_plus);
+		b = parse_multip(parse);
+
+		binop = stree_binop_new(bc);
 		binop->arg1 = a;
 		binop->arg2 = b;
@@ -187,4 +197,39 @@
 }
 
+/** Parse multiplicative expression.
+ *
+ * @param parse		Parser object.
+ */
+static stree_expr_t *parse_multip(parse_t *parse)
+{
+	stree_expr_t *a, *b, *tmp;
+	stree_binop_t *binop;
+	binop_class_t bc;
+
+	a = parse_prefix(parse);
+	while (lcur_lc(parse) == lc_mult) {
+		if (parse_is_error(parse))
+			break;
+
+		switch (lcur_lc(parse)) {
+		case lc_mult: bc = bo_mult; break;
+		default: assert(b_false);
+		}
+
+		lskip(parse);
+		b = parse_prefix(parse);
+
+		binop = stree_binop_new(bc);
+		binop->arg1 = a;
+		binop->arg2 = b;
+
+		tmp = stree_expr_new(ec_binop);
+		tmp->u.binop = binop;
+		a = tmp;
+	}
+
+	return a;
+}
+
 /** Parse prefix expression.
  *
@@ -194,10 +239,29 @@
 {
 	stree_expr_t *a;
+	stree_expr_t *tmp;
+	stree_unop_t *unop;
+	unop_class_t uc;
 
 	switch (lcur_lc(parse)) {
 	case lc_plus:
-		printf("Unimplemented: Unary plus.\n");
-		a = parse_recovery_expr(parse);
-		parse_note_error(parse);
+	case lc_minus:
+		if (parse_is_error(parse))
+			return parse_recovery_expr(parse);
+
+		switch (lcur_lc(parse)) {
+		case lc_plus: uc = uo_plus; break;
+		case lc_minus: uc = uo_minus; break;
+		default: assert(b_false);
+		}
+
+		lskip(parse);
+		a = parse_postfix(parse);
+
+		unop = stree_unop_new(uc);
+		unop->arg = a;
+
+		tmp = stree_expr_new(ec_unop);
+		tmp->u.unop = unop;
+		a = tmp;
 		break;
 	case lc_new:
@@ -248,5 +312,5 @@
 	stree_expr_t *tmp;
 
-	a = parse_primitive(parse);
+	a = parse_paren(parse);
 
 	while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen ||
@@ -398,4 +462,24 @@
 }
 
+/** Parse possibly partenthesized expression.
+ *
+ * @param parse		Parser object.
+ */
+static stree_expr_t *parse_paren(parse_t *parse)
+{
+	stree_expr_t *expr;
+
+	if (lcur_lc(parse) == lc_lparen) {
+		lskip(parse);
+		expr = parse_expr(parse);
+		lmatch(parse, lc_rparen);
+	} else {
+		expr = parse_primitive(parse);
+	}
+
+	return expr;
+}
+
+
 /** Parse primitive expression.
  *
@@ -459,5 +543,6 @@
 
 	literal = stree_literal_new(ltc_int);
-	literal->u.lit_int.value = lcur(parse)->u.lit_int.value;
+	bigint_clone(&lcur(parse)->u.lit_int.value,
+	    &literal->u.lit_int.value);
 
 	lskip(parse);
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/parse.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -79,4 +79,15 @@
 static stree_except_t *parse_except(parse_t *parse);
 
+/** Initialize parser object.
+ *
+ * Set up parser @a parse to use lexer @a lex for input and to store
+ * output (i.e. new declarations) to program @a prog. @a prog is not
+ * necessarily empty, the declarations being parsed are simply added
+ * to it.
+ *
+ * @param parse		Parser object.
+ * @param prog		Destination program stree.
+ * @param lex		Input lexer.
+ */
 void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
 {
@@ -91,5 +102,19 @@
 }
 
-/** Parse module. */
+/** Parse module.
+ *
+ * Parse a program module.
+ *
+ * The input is read using the lexer associated with @a parse. The resulting
+ * declarations are added to existing declarations in the program associated
+ * with @a parse.
+ *
+ * If any parse error occurs, parse->error will @c b_true when this function
+ * returns. parse->error_bailout will be @c b_true if the error has not
+ * been recovered yet. Similar holds for other parsing functions in this
+ * module.
+ *
+ * @param parse		Parser object.
+ */
 void parse_module(parse_t *parse)
 {
@@ -117,5 +142,11 @@
 }
 
-/** Parse class, struct or interface declaration. */
+/** Parse class, struct or interface declaration.
+ *
+ * @param parse		Parser object.
+ * @param dclass	What to parse: @c lc_class, @c lc_struct or @c lc_csi.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
     stree_csi_t *outer_csi)
@@ -169,5 +200,10 @@
 }
 
-/** Parse class, struct or interface member. */
+/** Parse class, struct or interface member.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
 {
@@ -211,5 +247,10 @@
 
 
-/** Parse member function. */
+/** Parse member function.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
 {
@@ -297,5 +338,10 @@
 }
 
-/** Parse member variable. */
+/** Parse member variable.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
 {
@@ -318,5 +364,10 @@
 }
 
-/** Parse member property. */
+/** Parse member property.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
 {
@@ -424,5 +475,10 @@
 }
 
-/** Parse symbol attribute. */
+/** Parse symbol attribute.
+ *
+ * @param parse		Parser object.
+ * @param outer_csi	CSI containing this declaration or @c NULL if global.
+ * @return		New syntax tree node.
+ */
 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
 {
@@ -442,5 +498,9 @@
 }
 
-/** Parse formal function argument. */
+/** Parse formal function argument.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
 {
@@ -468,5 +528,9 @@
 }
 
-/** Parse argument attribute. */
+/** Parse argument attribute.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
 {
@@ -486,5 +550,9 @@
 }
 
-/** Parse statement block. */
+/** Parse statement block.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_block_t *parse_block(parse_t *parse)
 {
@@ -509,5 +577,9 @@
 }
 
-/** Parse statement. */
+/** Parse statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 stree_stat_t *parse_stat(parse_t *parse)
 {
@@ -576,5 +648,9 @@
 }
 
-/** Parse variable declaration statement. */
+/** Parse variable declaration statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_vdecl_t *parse_vdecl(parse_t *parse)
 {
@@ -603,5 +679,9 @@
 }
 
-/** Parse @c if statement, */
+/** Parse @c if statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_if_t *parse_if(parse_t *parse)
 {
@@ -629,5 +709,8 @@
 }
 
-/** Parse @c while statement. */
+/** Parse @c while statement.
+ *
+ * @param parse		Parser object.
+ */
 static stree_while_t *parse_while(parse_t *parse)
 {
@@ -648,5 +731,9 @@
 }
 
-/** Parse @c for statement. */
+/** Parse @c for statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_for_t *parse_for(parse_t *parse)
 {
@@ -671,5 +758,8 @@
 }
 
-/** Parse @c raise statement. */
+/** Parse @c raise statement.
+ *
+ * @param parse		Parser object.
+ */
 static stree_raise_t *parse_raise(parse_t *parse)
 {
@@ -687,5 +777,9 @@
 }
 
-/** Parse @c return statement. */
+/** Parse @c return statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_return_t *parse_return(parse_t *parse)
 {
@@ -704,5 +798,9 @@
 }
 
-/* Parse @c with-except-finally statement. */
+/* Parse @c with-except-finally statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_wef_t *parse_wef(parse_t *parse)
 {
@@ -746,5 +844,9 @@
 }
 
-/* Parse expression statement. */
+/* Parse expression statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_exps_t *parse_exps(parse_t *parse)
 {
@@ -764,5 +866,9 @@
 }
 
-/* Parse @c except clause. */
+/* Parse @c except clause.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 static stree_except_t *parse_except(parse_t *parse)
 {
@@ -785,5 +891,9 @@
 }
 
-/** Parse identifier. */
+/** Parse identifier.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
 stree_ident_t *parse_ident(parse_t *parse)
 {
@@ -801,5 +911,8 @@
 }
 
-/** Signal a parse error, start bailing out from parser. */
+/** Signal a parse error, start bailing out from parser. 
+ *
+ * @param parse		Parser object.
+ */
 void parse_raise_error(parse_t *parse)
 {
@@ -808,5 +921,8 @@
 }
 
-/** Note a parse error that has been immediately recovered. */
+/** Note a parse error that has been immediately recovered.
+ *
+ * @param parse		Parser object.
+ */
 void parse_note_error(parse_t *parse)
 {
@@ -814,5 +930,8 @@
 }
 
-/** Check if we are currently bailing out of parser due to a parse error. */
+/** Check if we are currently bailing out of parser due to a parse error.
+ *
+ * @param parse		Parser object.
+ */
 bool_t parse_is_error(parse_t *parse)
 {
@@ -823,4 +942,6 @@
  *
  * Still remember that there was an error, but stop bailing out.
+ *
+ * @param parse		Parser object.
  */
 void parse_recover_error(parse_t *parse)
@@ -832,5 +953,10 @@
 }
 
-/** Return current lem. */
+/** Return current lem.
+ *
+ * @param parse		Parser object.
+ * @return		Pointer to current lem. Only valid until the lexing
+ *			position is advanced.
+ */
 lem_t *lcur(parse_t *parse)
 {
@@ -841,5 +967,9 @@
 }
 
-/** Retturn current lem lclass. */
+/** Return current lem lclass.
+ *
+ * @param parse		Parser object.
+ * @return		Lclass of the current lem.
+ */
 lclass_t lcur_lc(parse_t *parse)
 {
@@ -861,5 +991,8 @@
 }
 
-/** Skip to next lem. */
+/** Skip to next lem.
+ *
+ * @param parse		Parser object.
+ */
 void lskip(parse_t *parse)
 {
@@ -870,5 +1003,12 @@
 }
 
-/** Verify that lclass of current lem is @a lc. */
+/** Verify that lclass of current lem is @a lc.
+ *
+ * If a lem of different lclass is found, a parse error is raised and
+ * a message is printed.
+ *
+ * @param parse		Parser object.
+ * @param lc		Expected lclass.
+ */
 void lcheck(parse_t *parse, lclass_t lc)
 {
@@ -887,5 +1027,12 @@
 }
 
-/** Verify that lclass of current lem is @a lc and go to next lem. */
+/** Verify that lclass of current lem is @a lc and go to next lem.
+ *
+ * If a lem of different lclass is found, a parse error is raised and
+ * a message is printed.
+ *
+ * @param parse		Parser object.
+ * @param lc		Expected lclass.
+ */
 void lmatch(parse_t *parse, lclass_t lc)
 {
@@ -910,5 +1057,8 @@
 }
 
-/** Display generic parsing error. */
+/** Raise and display generic parsing error.
+ *
+ * @param parse		Parser object.
+ */
 void lunexpected_error(parse_t *parse)
 {
@@ -920,5 +1070,11 @@
 }
 
-/** Basically tells us whether @a lclass is in next(block). */
+/** Determine whether @a lclass is in follow(block).
+ *
+ * Tests whether @a lclass belongs to the follow(block) set, i.e. if it is
+ * lclass of a lem that can follow a block in the program.
+ *
+ * @param lclass	Lclass.
+ */
 bool_t terminates_block(lclass_t lclass)
 {
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/rdata.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -27,8 +27,26 @@
  */
 
-/** @file Run-time data representation. */
+/** @file Run-time data representation.
+ *
+ * At run time SBI represents all data as a graph of interconnected @c var
+ * nodes (variable nodes). Any piece of memory addressable by the program
+ * (i.e. all variables) are stored in var nodes. However, var nodes are also
+ * used internally to implement value items. (I.e. values in value items
+ * have exactly the same structure as program variables).
+ *
+ * Unlike byte- or word-oriented memory on a real machine, var nodes provide
+ * structured and typed storage. (This typing is dynamic, however and has
+ * nothing to do with the static type system).
+ *
+ * There are several types of var nodes, one for each primitive type,
+ * reference, delegate, array, and object. A reference var node contains
+ * a pointer to another var node. Delegate var node points to some stree
+ * declaration. Array and object var nodes refer to a collection of child
+ * nodes (fields, elements).
+ */
 
 #include <stdlib.h>
 #include <assert.h>
+#include "bigint.h"
 #include "mytypes.h"
 #include "stree.h"
@@ -50,5 +68,9 @@
 static void rdata_var_print(rdata_var_t *var);
 
-
+/** Allocate new data item.
+ *
+ * @param ic	Item class.
+ * @return	New item.
+ */
 rdata_item_t *rdata_item_new(item_class_t ic)
 {
@@ -65,4 +87,8 @@
 }
 
+/** Allocate new address.
+ *
+ * @return	New address.
+ */
 rdata_addr_var_t *rdata_addr_var_new(void)
 {
@@ -78,4 +104,8 @@
 }
 
+/** Allocate new named property address.
+ *
+ * @return	New named property address.
+ */
 rdata_aprop_named_t *rdata_aprop_named_new(void)
 {
@@ -91,4 +121,8 @@
 }
 
+/** Allocate new indexed property address.
+ *
+ * @return	New indexed property address.
+ */
 rdata_aprop_indexed_t *rdata_aprop_indexed_new(void)
 {
@@ -104,4 +138,9 @@
 }
 
+/** Allocate new property address.
+ *
+ * @param apc	Property address class.
+ * @return	New property address.
+ */
 rdata_addr_prop_t *rdata_addr_prop_new(aprop_class_t apc)
 {
@@ -118,4 +157,9 @@
 }
 
+/** Allocate new address.
+ *
+ * @param ac	Address class.
+ * @return	New address.
+ */
 rdata_address_t *rdata_address_new(address_class_t ac)
 {
@@ -132,4 +176,8 @@
 }
 
+/** Allocate new value.
+ *
+ * @return	New value.
+ */
 rdata_value_t *rdata_value_new(void)
 {
@@ -145,4 +193,9 @@
 }
 
+/** Allocate new var node.
+ *
+ * @param vc	Var node class (varclass).
+ * @return	New var node.
+ */
 rdata_var_t *rdata_var_new(var_class_t vc)
 {
@@ -159,4 +212,8 @@
 }
 
+/** Allocate new reference.
+ *
+ * @return	New reference.
+ */
 rdata_ref_t *rdata_ref_new(void)
 {
@@ -172,4 +229,8 @@
 }
 
+/** Allocate new delegate.
+ *
+ * @return	New delegate.
+ */
 rdata_deleg_t *rdata_deleg_new(void)
 {
@@ -185,4 +246,8 @@
 }
 
+/** Allocate new array.
+ *
+ * @return	New array.
+ */
 rdata_array_t *rdata_array_new(int rank)
 {
@@ -205,4 +270,8 @@
 }
 
+/** Allocate new object.
+ *
+ * @return	New object.
+ */
 rdata_object_t *rdata_object_new(void)
 {
@@ -218,4 +287,8 @@
 }
 
+/** Allocate new integer.
+ *
+ * @return	New integer.
+ */
 rdata_int_t *rdata_int_new(void)
 {
@@ -231,4 +304,8 @@
 }
 
+/** Allocate new string.
+ *
+ * @return	New string.
+ */
 rdata_string_t *rdata_string_new(void)
 {
@@ -244,4 +321,8 @@
 }
 
+/** Allocate new resource.
+ *
+ * @return	New resource.
+ */
 rdata_resource_t *rdata_resource_new(void)
 {
@@ -257,4 +338,10 @@
 }
 
+/** Allocate array elements.
+ *
+ * Allocates var nodes for elements of @a array.
+ *
+ * @param array		Array.
+ */
 void rdata_array_alloc_element(rdata_array_t *array)
 {
@@ -282,4 +369,6 @@
  * Dimension is the total number of elements in an array, in other words,
  * the product of all extents.
+ *
+ * @param array		Array.
  */
 static int rdata_array_get_dim(rdata_array_t *array)
@@ -294,5 +383,12 @@
 }
 
-/** Make copy of a variable. */
+/** Make copy of a variable.
+ *
+ * Creates a new var node that is an exact copy of an existing var node.
+ * This can be thought of as a shallow copy.
+ *
+ * @param src		Source var node.
+ * @param dest		Place to store pointer to new var node.
+ */
 void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest)
 {
@@ -328,10 +424,20 @@
 }
 
+/** Copy integer.
+ *
+ * @param src		Source integer.
+ * @param dest		Place to store pointer to new integer.
+ */
 static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest)
 {
 	*dest = rdata_int_new();
-	(*dest)->value = src->value;
-}
-
+	bigint_clone(&src->value, &(*dest)->value);
+}
+
+/** Copy string.
+ *
+ * @param src		Source string.
+ * @param dest		Place to store pointer to new string.
+ */
 static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest)
 {
@@ -340,4 +446,9 @@
 }
 
+/** Copy reference.
+ *
+ * @param src		Source reference.
+ * @param dest		Place to store pointer to new reference.
+ */
 static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest)
 {
@@ -346,4 +457,9 @@
 }
 
+/** Copy delegate.
+ *
+ * @param src		Source delegate.
+ * @param dest		Place to store pointer to new delegate.
+ */
 static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest)
 {
@@ -353,4 +469,9 @@
 }
 
+/** Copy array.
+ *
+ * @param src		Source array.
+ * @param dest		Place to store pointer to new array.
+ */
 static void rdata_array_copy(rdata_array_t *src, rdata_array_t **dest)
 {
@@ -360,4 +481,9 @@
 }
 
+/** Copy object.
+ *
+ * @param src		Source object.
+ * @param dest		Place to store pointer to new object.
+ */
 static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest)
 {
@@ -367,4 +493,9 @@
 }
 
+/** Copy resource.
+ *
+ * @param src		Source resource.
+ * @param dest		Place to store pointer to new resource.
+ */
 static void rdata_resource_copy(rdata_resource_t *src, rdata_resource_t **dest)
 {
@@ -375,5 +506,12 @@
 /** Read data from a variable.
  *
- * Return value stored in variable @a var.
+ * This copies data from the variable to a value item. Ideally any read access
+ * to a program variable should go through this function. (Keep in mind
+ * that although values are composed of var nodes internally, but are not
+ * variables per se. Therefore this function is not used to read from values)
+ *
+ * @param var		Variable to read from (var node where it is stored).
+ * @param ritem		Place to store pointer to new value item read from
+ *			the variable.
  */
 void rdata_var_read(rdata_var_t *var, rdata_item_t **ritem)
@@ -393,5 +531,11 @@
 /** Write data to a variable.
  *
- * Store @a value to variable @a var.
+ * This copies data to the variable from a value. Ideally any write access
+ * to a program variable should go through this function. (Keep in mind
+ * that even though values are composed of var nodes internally, but are not
+ * variables per se. Therefore this function is not used to write to values)
+ *
+ * @param var		Variable to write to (var node where it is stored).
+ * @param value		The value to write.
  */
 void rdata_var_write(rdata_var_t *var, rdata_value_t *value)
@@ -418,4 +562,8 @@
 }
 
+/** Print data item in human-readable form.
+ *
+ * @param item		Item to print.
+ */
 void rdata_item_print(rdata_item_t *item)
 {
@@ -437,4 +585,13 @@
 }
 
+/** Print address in human-readable form.
+ *
+ * Actually this displays contents of the var node that is being addressed.
+ *
+ * XXX Maybe we should really rather print the address and not the data
+ * it is pointing to?
+ *
+ * @param item		Address to print.
+ */
 static void rdata_address_print(rdata_address_t *address)
 {
@@ -449,4 +606,8 @@
 }
 
+/** Print value in human-readable form.
+ *
+ * @param value		Value to print.
+ */
 void rdata_value_print(rdata_value_t *value)
 {
@@ -454,9 +615,15 @@
 }
 
+/** Print contents of var node in human-readable form.
+ *
+ * @param item		Var node to print.
+ */
 static void rdata_var_print(rdata_var_t *var)
 {
 	switch (var->vc) {
 	case vc_int:
-		printf("int(%d)", var->u.int_v->value);
+		printf("int(");
+		bigint_print(&var->u.int_v->value);
+		printf(")");
 		break;
 	case vc_string:
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/rdata_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -35,11 +35,11 @@
 #include "intmap_t.h"
 
-/** Integer variable */
-typedef struct {
-	/*
-	 * Note: Sysel int type should be able to store arbitrarily large
-	 * numbers. But for now we can live with limited width.
-	 */
-	int value;
+/** Integer variable.
+ *
+ * Sysel int type should be able to store arbitrarily (or at least
+ * very) large numbers.
+ */
+typedef struct {
+	bigint_t value;
 } rdata_int_t;
 
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/run.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -32,4 +32,5 @@
 #include <stdlib.h>
 #include <assert.h>
+#include "bigint.h"
 #include "builtin.h"
 #include "debug.h"
@@ -57,4 +58,6 @@
 
 static bool_t run_exc_match(run_t *run, stree_except_t *except_c);
+static stree_csi_t *run_exc_payload_get_csi(run_t *run);
+
 static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *aprop);
 
@@ -113,10 +116,5 @@
 	run_proc(run, proc_ar, &res);
 
-	/* Check for unhandled exceptions. */
-	if (run->thread_ar->bo_mode != bm_none) {
-		assert(run->thread_ar->bo_mode == bm_exc);
-		printf("Error: Unhandled exception.\n");
-		exit(1);
-	}
+	run_exc_check_unhandled(run);
 }
 
@@ -302,5 +300,5 @@
 
 	var->u.int_v = int_v;
-	int_v->value = 0;
+	bigint_init(&int_v->value, 0);
 
 	block_ar = run_get_current_block_ar(run);
@@ -329,4 +327,6 @@
 #endif
 	run_expr(run, if_s->cond, &rcond);
+	if (run_is_bo(run))
+		return;
 
 	if (run_item_boolean_value(run, rcond) == b_true) {
@@ -357,8 +357,12 @@
 #endif
 	run_expr(run, while_s->cond, &rcond);
+	if (run_is_bo(run))
+		return;
 
 	while (run_item_boolean_value(run, rcond) == b_true) {
 		run_block(run, while_s->body);
 		run_expr(run, while_s->cond, &rcond);
+		if (run_is_bo(run))
+			return;
 
 		if (run->thread_ar->bo_mode != bm_none)
@@ -381,4 +385,7 @@
 #endif
 	run_expr(run, raise_s->expr, &rexpr);
+	if (run_is_bo(run))
+		return;
+
 	run_cvt_value_item(run, rexpr, &rexpr_vi);
 
@@ -401,4 +408,7 @@
 #endif
 	run_expr(run, return_s->expr, &rexpr);
+	if (run_is_bo(run))
+		return;
+
 	run_cvt_value_item(run, rexpr, &rexpr_vi);
 
@@ -477,6 +487,5 @@
  *
  * Checks if the currently active exception in the runner object @c run
- * matches except clause @c except_c. Generates an error if the exception
- * payload has invalid type (i.e. not an object).
+ * matches except clause @c except_c.
  *
  * @param run		Runner object.
@@ -486,8 +495,28 @@
 static bool_t run_exc_match(run_t *run, stree_except_t *except_c)
 {
+	stree_csi_t *exc_csi;
+	tdata_item_t *etype;
+
+	/* Get CSI of active exception. */
+	exc_csi = run_exc_payload_get_csi(run);
+
+	/* Evaluate type expression in except clause. */
+	run_texpr(run->program, run_get_current_csi(run), except_c->etype,
+	    &etype);
+
+	/* Determine if active exc. is derived from type in exc. clause. */
+	return tdata_is_csi_derived_from_ti(exc_csi, etype);
+}
+
+/** Return CSI of the active exception.
+ *
+ * @param run		Runner object.
+ * @return		CSI of the active exception.
+ */
+static stree_csi_t *run_exc_payload_get_csi(run_t *run)
+{
 	rdata_value_t *payload;
 	rdata_var_t *payload_v;
 	rdata_object_t *payload_o;
-	tdata_item_t *etype;
 
 	payload = run->thread_ar->exc_payload;
@@ -495,4 +524,5 @@
 
 	if (payload->var->vc != vc_ref) {
+		/* XXX Prevent this via static type checking. */
 		printf("Error: Exception payload must be an object "
 		    "(found type %d).\n", payload->var->vc);
@@ -502,4 +532,5 @@
 	payload_v = payload->var->u.ref_v->vref;
 	if (payload_v->vc != vc_object) {
+		/* XXX Prevent this via static type checking. */
 		printf("Error: Exception payload must be an object "
 		    "(found type %d).\n", payload_v->vc);
@@ -517,10 +548,30 @@
 	assert(payload_o->class_sym->sc == sc_csi);
 
-	/* Evaluate type expression in except clause. */
-	run_texpr(run->program, run_get_current_csi(run), except_c->etype,
-	    &etype);
-
-	return tdata_is_csi_derived_from_ti(payload_o->class_sym->u.csi,
-	    etype);
+	return payload_o->class_sym->u.csi;
+}
+
+
+/** Check for unhandled exception.
+ *
+ * Checks whether there is an active exception. If so, it prints an
+ * error message and raises a run-time error.
+ *
+ * @param run		Runner object.
+ */
+void run_exc_check_unhandled(run_t *run)
+{
+	stree_csi_t *exc_csi;
+
+	if (run->thread_ar->bo_mode != bm_none) {
+		assert(run->thread_ar->bo_mode == bm_exc);
+
+		exc_csi = run_exc_payload_get_csi(run);
+
+		printf("Error: Unhandled exception '");
+		symbol_print_fqn(csi_to_symbol(exc_csi));
+		printf("'.\n");
+
+		run_raise_error(run);
+	}
 }
 
@@ -620,5 +671,6 @@
 
 		(*var)->u.int_v = int_v;
-		int_v->value = item->u.value->var->u.int_v->value;
+		bigint_clone(&item->u.value->var->u.int_v->value,
+		    &int_v->value);
 		break;
 	case vc_string:
@@ -1171,6 +1223,9 @@
 
 	if (addr_var->vref == NULL) {
+#ifdef DEBUG_RUN_TRACE
 		printf("Error: Accessing null reference.\n");
-		run_raise_error(run);
+#endif
+		/* Raise Error.NilReference */
+		run_raise_exc(run, run->program->builtin->error_nilreference);
 		*ritem = run_recovery_item(run);
 		return;
@@ -1181,4 +1236,33 @@
 #endif
 	*ritem = item;
+}
+
+/** Raise an exception of the given class.
+ *
+ * Used when the interpreter generates an exception due to a run-time
+ * error (not for the @c raise statement).
+ *
+ * @param run		Runner object.
+ * @param csi		Exception class.
+ */
+void run_raise_exc(run_t *run, stree_csi_t *csi)
+{
+	rdata_item_t *exc_vi;
+
+	/* Create exception object. */
+	run_new_csi_inst(run, csi, &exc_vi);
+	assert(exc_vi->ic == ic_value);
+
+	/* Store exception object in thread AR. */
+	run->thread_ar->exc_payload = exc_vi->u.value;
+
+	/* Start exception bailout. */
+	run->thread_ar->bo_mode = bm_exc;
+}
+
+/** Determine if we are bailing out. */
+bool_t run_is_bo(run_t *run)
+{
+	return run->thread_ar->bo_mode != bm_none;
 }
 
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/run.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -39,4 +39,5 @@
 void run_print_fun_bt(run_t *run);
 
+void run_exc_check_unhandled(run_t *run);
 void run_raise_error(run_t *run);
 rdata_item_t *run_recovery_item(run_t *run);
@@ -64,4 +65,7 @@
 void run_dereference(run_t *run, rdata_item_t *ref, rdata_item_t **ritem);
 
+void run_raise_exc(run_t *run, stree_csi_t *csi);
+bool_t run_is_bo(run_t *run);
+
 run_thread_ar_t *run_thread_ar_new(void);
 run_proc_ar_t *run_proc_ar_new(void);
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/run_expr.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -32,4 +32,5 @@
 #include <stdlib.h>
 #include <assert.h>
+#include "bigint.h"
 #include "debug.h"
 #include "intmap.h"
@@ -71,4 +72,7 @@
 
 static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
+static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
+    rdata_item_t **res);
+
 static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
 static void run_new_array(run_t *run, stree_new_t *new_op,
@@ -349,5 +353,5 @@
 	value->var = var;
 	var->u.int_v = int_v;
-	int_v->value = lit_int->value;
+	bigint_clone(&lit_int->value, &int_v->value);
 
 	*res = item;
@@ -436,8 +440,19 @@
 #endif
 	run_expr(run, binop->arg1, &rarg1_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
+
 	run_expr(run, binop->arg2, &rarg2_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
 
 	switch (binop->bc) {
 	case bo_plus:
+	case bo_minus:
+	case bo_mult:
 	case bo_equal:
 	case bo_notequal:
@@ -496,5 +511,8 @@
 	rdata_int_t *int_v;
 
-	int i1, i2;
+	bigint_t *i1, *i2;
+	bigint_t diff;
+	bool_t done;
+	bool_t zf, nf;
 
 	(void) run;
@@ -509,30 +527,54 @@
 	var->u.int_v = int_v;
 
-	i1 = v1->var->u.int_v->value;
-	i2 = v2->var->u.int_v->value;
+	i1 = &v1->var->u.int_v->value;
+	i2 = &v2->var->u.int_v->value;
+
+	done = b_true;
 
 	switch (binop->bc) {
 	case bo_plus:
-		int_v->value = i1 + i2;
-		break;
+		bigint_add(i1, i2, &int_v->value);
+		break;
+	case bo_minus:
+		bigint_sub(i1, i2, &int_v->value);
+		break;
+	case bo_mult:
+		bigint_mul(i1, i2, &int_v->value);
+		break;
+	default:
+		done = b_false;
+		break;
+	}
+
+	if (done) {
+		*res = item;
+		return;
+	}
+
+	/* Relational operation. */
+
+	bigint_sub(i1, i2, &diff);
+	zf = bigint_is_zero(&diff);
+	nf = bigint_is_negative(&diff);
 
 	/* XXX We should have a real boolean type. */
+	switch (binop->bc) {
 	case bo_equal:
-		int_v->value = (i1 == i2) ? 1 : 0;
+		bigint_init(&int_v->value, zf ? 1 : 0);
 		break;
 	case bo_notequal:
-		int_v->value = (i1 != i2) ? 1 : 0;
+		bigint_init(&int_v->value, !zf ? 1 : 0);
 		break;
 	case bo_lt:
-		int_v->value = (i1 < i2) ? 1 : 0;
+		bigint_init(&int_v->value, (!zf && nf) ? 1 : 0);
 		break;
 	case bo_gt:
-		int_v->value = (i1 > i2) ? 1 : 0;
+		bigint_init(&int_v->value, (!zf && !nf) ? 1 : 0);
 		break;
 	case bo_lt_equal:
-		int_v->value = (i1 <= i2) ? 1 : 0;
+		bigint_init(&int_v->value, (zf || nf) ? 1 : 0);
 		break;
 	case bo_gt_equal:
-		int_v->value = (i1 >= i2) ? 1 : 0;
+		bigint_init(&int_v->value, !nf ? 1 : 0);
 		break;
 	default:
@@ -610,8 +652,8 @@
 	/* XXX We should have a real boolean type. */
 	case bo_equal:
-		int_v->value = (ref1 == ref2) ? 1 : 0;
+		bigint_init(&int_v->value, (ref1 == ref2) ? 1 : 0);
 		break;
 	case bo_notequal:
-		int_v->value = (ref1 != ref2) ? 1 : 0;
+		bigint_init(&int_v->value, (ref1 != ref2) ? 1 : 0);
 		break;
 	default:
@@ -628,12 +670,70 @@
 static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
 {
-	rdata_item_t *rarg;
+	rdata_item_t *rarg_i;
+	rdata_item_t *rarg_vi;
+	rdata_value_t *val;
 
 #ifdef DEBUG_RUN_TRACE
 	printf("Run unary operation.\n");
 #endif
-	run_expr(run, unop->arg, &rarg);
-	*res = NULL;
-}
+	run_expr(run, unop->arg, &rarg_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Check unop argument result.\n");
+#endif
+	run_cvt_value_item(run, rarg_i, &rarg_vi);
+
+	val = rarg_vi->u.value;
+
+	switch (val->var->vc) {
+	case vc_int:
+		run_unop_int(run, unop, val, res);
+		break;
+	default:
+		printf("Unimplemented: Unrary operation argument of "
+		    "type %d.\n", val->var->vc);
+		run_raise_error(run);
+		*res = NULL;
+		break;
+	}
+}
+
+/** Evaluate unary operation on int argument. */
+static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_int_t *int_v;
+
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_int);
+	int_v = rdata_int_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.int_v = int_v;
+
+	switch (unop->uc) {
+	case uo_plus:
+	        bigint_clone(&val->var->u.int_v->value, &int_v->value);
+		break;
+	case uo_minus:
+		bigint_reverse_sign(&val->var->u.int_v->value,
+		    &int_v->value);
+		break;
+	}
+
+	*res = item;
+}
+
 
 /** Evaluate @c new operation. */
@@ -680,4 +780,6 @@
 	int length;
 	int i;
+	int rc;
+	int iextent;
 
 #ifdef DEBUG_RUN_TRACE
@@ -708,4 +810,9 @@
 		/* Evaluate extent argument. */
 		run_expr(run, expr, &rexpr);
+		if (run_is_bo(run)) {
+			*res = NULL;
+			return;
+		}
+
 		run_cvt_value_item(run, rexpr, &rexpr_vi);
 		assert(rexpr_vi->ic == ic_value);
@@ -718,7 +825,16 @@
 
 #ifdef DEBUG_RUN_TRACE
-		printf("Array extent: %d.\n", rexpr_var->u.int_v->value);
-#endif
-		array->extent[i] = rexpr_var->u.int_v->value;
+		printf("Array extent: ");
+		bigint_print(&rexpr_var->u.int_v->value);
+		printf(".\n");
+#endif
+		rc = bigint_get_value_int(&rexpr_var->u.int_v->value,
+		    &iextent);
+		if (rc != EOK) {
+			printf("Memory allocation failed (big int used).\n");
+			exit(1);
+		}
+
+		array->extent[i] = iextent;
 		length = length * array->extent[i];
 
@@ -738,5 +854,5 @@
 		elem_var = rdata_var_new(vc_int);
 		elem_var->u.int_v = rdata_int_new();
-		elem_var->u.int_v->value = 0;
+		bigint_init(&elem_var->u.int_v->value, 0);
 
 		array->element[i] = elem_var;
@@ -755,19 +871,9 @@
     tdata_item_t *titem, rdata_item_t **res)
 {
-	rdata_object_t *obj;
-	rdata_var_t *obj_var;
-
-	stree_symbol_t *csi_sym;
 	stree_csi_t *csi;
-	stree_csimbr_t *csimbr;
-
-	rdata_var_t *mbr_var;
-
-	list_node_t *node;
 
 #ifdef DEBUG_RUN_TRACE
 	printf("Create new object.\n");
 #endif
-	(void) run;
 	(void) new_op;
 
@@ -775,33 +881,7 @@
 	assert(titem->tic == tic_tobject);
 	csi = titem->u.tobject->csi;
-	csi_sym = csi_to_symbol(csi);
-
-	/* Create the object. */
-	obj = rdata_object_new();
-	obj->class_sym = csi_sym;
-	intmap_init(&obj->fields);
-
-	obj_var = rdata_var_new(vc_object);
-	obj_var->u.object_v = obj;
-
-	/* Create object fields. */
-	node = list_first(&csi->members);
-	while (node != NULL) {
-		csimbr = list_node_data(node, stree_csimbr_t *);
-		if (csimbr->cc == csimbr_var) {
-			/* XXX Depends on member variable type. */
-			mbr_var = rdata_var_new(vc_int);
-			mbr_var->u.int_v = rdata_int_new();
-			mbr_var->u.int_v->value = 0;
-
-			intmap_set(&obj->fields, csimbr->u.var->name->sid,
-			    mbr_var);
-		}
-
-		node = list_next(&csi->members, node);
-	}
-
-	/* Create reference to the new object. */
-	run_reference(run, obj_var, res);
+
+	/* Create CSI instance. */
+	run_new_csi_inst(run, csi, res);
 }
 
@@ -815,4 +895,9 @@
 #endif
 	run_expr(run, access->arg, &rarg);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+    	}
+
 	if (rarg == NULL) {
 		printf("Error: Sub-expression has no value.\n");
@@ -1028,4 +1113,8 @@
 #endif
 	run_expr(run, call->fun, &rfun);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
 
 	if (run->thread_ar->bo_mode != bm_none) {
@@ -1058,4 +1147,9 @@
 		arg = list_node_data(node, stree_expr_t *);
 		run_expr(run, arg, &rarg_i);
+		if (run_is_bo(run)) {
+			*res = NULL;
+			return;
+		}
+
 		run_cvt_value_item(run, rarg_i, &rarg_vi);
 
@@ -1096,4 +1190,8 @@
 #endif
 	run_expr(run, index->base, &rbase);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
 
 	vc = run_item_get_vc(run, rbase);
@@ -1115,4 +1213,9 @@
 		arg = list_node_data(node, stree_expr_t *);
 		run_expr(run, arg, &rarg_i);
+		if (run_is_bo(run)) {
+			*res = NULL;
+			return;
+		}
+
 		run_cvt_value_item(run, rarg_i, &rarg_vi);
 
@@ -1149,4 +1252,5 @@
 	int elem_index;
 	int arg_val;
+	int rc;
 
 	rdata_item_t *ritem;
@@ -1189,10 +1293,16 @@
 		}
 
-		arg_val = arg->u.value->var->u.int_v->value;
-
-		if (arg_val < 0 || arg_val >= array->extent[i]) {
+		rc = bigint_get_value_int(
+		    &arg->u.value->var->u.int_v->value,
+		    &arg_val);
+
+		if (rc != EOK || arg_val < 0 || arg_val >= array->extent[i]) {
+#ifdef DEBUG_RUN_TRACE
 			printf("Error: Array index (value: %d) is out of range.\n",
 			    arg_val);
-			run_raise_error(run);
+#endif
+			/* Raise Error.OutOfBounds */
+			run_raise_exc(run,
+			    run->program->builtin->error_outofbounds);
 			*res = run_recovery_item(run);
 			return;
@@ -1307,5 +1417,5 @@
 	int elem_index;
 	int arg_val;
-	int rc;
+	int rc1, rc2;
 
 	rdata_value_t *value;
@@ -1322,5 +1432,5 @@
 	run_cvt_value_item(run, base, &base_vi);
 	assert(base_vi->u.value->var->vc == vc_string);
-	string = base->u.value->var->u.string_v;
+	string = base_vi->u.value->var->u.string_v;
 
 	/*
@@ -1346,5 +1456,8 @@
 		}
 
-		arg_val = arg->u.value->var->u.int_v->value;
+		rc1 = bigint_get_value_int(
+		    &arg->u.value->var->u.int_v->value,
+		    &arg_val);
+
 		elem_index = arg_val;
 
@@ -1358,6 +1471,8 @@
 	}
 
-	rc = os_str_get_char(string->value, elem_index, &cval);
-	if (rc != EOK) {
+	if (rc1 == EOK)
+		rc2 = os_str_get_char(string->value, elem_index, &cval);
+
+	if (rc1 != EOK || rc2 != EOK) {
 		printf("Error: String index (value: %d) is out of range.\n",
 		    arg_val);
@@ -1372,5 +1487,5 @@
 	cvar = rdata_var_new(vc_int);
 	cvar->u.int_v = rdata_int_new();
-	cvar->u.int_v->value = cval;
+	bigint_init(&cvar->u.int_v->value, cval);
 	value->var = cvar;
 
@@ -1389,5 +1504,14 @@
 #endif
 	run_expr(run, assign->dest, &rdest_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
+
 	run_expr(run, assign->src, &rsrc_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
 
 	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
@@ -1423,4 +1547,8 @@
 #endif
 	run_expr(run, as_op->arg, &rarg_i);
+	if (run_is_bo(run)) {
+		*res = NULL;
+		return;
+	}
 
 	/*
@@ -1467,4 +1595,54 @@
 
 	*res = rarg_vi;
+}
+
+/** Create new CSI instance. */
+void run_new_csi_inst(run_t *run, stree_csi_t *csi, rdata_item_t **res)
+{
+	rdata_object_t *obj;
+	rdata_var_t *obj_var;
+
+	stree_symbol_t *csi_sym;
+	stree_csimbr_t *csimbr;
+
+	rdata_var_t *mbr_var;
+
+	list_node_t *node;
+
+	csi_sym = csi_to_symbol(csi);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Create new instance of CSI '");
+	symbol_print_fqn(csi_sym);
+	printf("'.\n");
+#endif
+
+	/* Create the object. */
+	obj = rdata_object_new();
+	obj->class_sym = csi_sym;
+	intmap_init(&obj->fields);
+
+	obj_var = rdata_var_new(vc_object);
+	obj_var->u.object_v = obj;
+
+	/* Create object fields. */
+	node = list_first(&csi->members);
+	while (node != NULL) {
+		csimbr = list_node_data(node, stree_csimbr_t *);
+		if (csimbr->cc == csimbr_var) {
+			/* XXX Depends on member variable type. */
+			mbr_var = rdata_var_new(vc_int);
+			mbr_var->u.int_v = rdata_int_new();
+			bigint_init(&mbr_var->u.int_v->value, 0);
+
+			intmap_set(&obj->fields, csimbr->u.var->name->sid,
+			    mbr_var);
+		}
+
+		node = list_next(&csi->members, node);
+	}
+
+	/* Create reference to the new object. */
+	run_reference(run, obj_var, res);
 }
 
@@ -1492,4 +1670,4 @@
 	}
 
-	return (var->u.int_v->value != 0);
-}
+	return !bigint_is_zero(&var->u.int_v->value);
+}
Index: uspace/app/sbi/src/run_expr.h
===================================================================
--- uspace/app/sbi/src/run_expr.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/run_expr.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -34,4 +34,5 @@
 void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res);
 
+void run_new_csi_inst(run_t *run, stree_csi_t *csi, rdata_item_t **res);
 bool_t run_item_boolean_value(run_t *run, rdata_item_t *item);
 
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/stree.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -376,4 +376,18 @@
 }
 
+stree_unop_t *stree_unop_new(unop_class_t uc)
+{
+	stree_unop_t *unop;
+
+	unop = calloc(1, sizeof(stree_unop_t));
+	if (unop == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	unop->uc = uc;
+	return unop;
+}
+
 stree_new_t *stree_new_new(void)
 {
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/stree.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -62,4 +62,5 @@
 stree_assign_t *stree_assign_new(assign_class_t ac);
 stree_binop_t *stree_binop_new(binop_class_t bc);
+stree_unop_t *stree_unop_new(unop_class_t uc);
 stree_new_t *stree_new_new(void);
 stree_access_t *stree_access_new(void);
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/stree_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -30,4 +30,5 @@
 #define STREE_T_H_
 
+#include "bigint_t.h"
 #include "list_t.h"
 #include "builtin_t.h"
@@ -54,5 +55,5 @@
 
 typedef struct {
-	int value;
+	bigint_t value;
 } stree_lit_int_t;
 
@@ -89,10 +90,13 @@
 	bo_lt_equal,
 	bo_gt_equal,
-	bo_plus
+	bo_plus,
+	bo_minus,
+	bo_mult
 } binop_class_t;
 
 /** Unary operation class */
 typedef enum {
-	uo_plus
+	uo_plus,
+	uo_minus,
 } unop_class_t;
 
@@ -109,5 +113,5 @@
 typedef struct {
 	/** Operation class */
-	unop_class_t oc;
+	unop_class_t uc;
 
 	/** Argument */
Index: uspace/app/sbi/src/stype.c
===================================================================
--- uspace/app/sbi/src/stype.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/stype.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -162,5 +162,5 @@
 		    &titem);
 
-		if (titem->tic != tic_tarray) {
+		if (titem->tic != tic_tarray && titem->tic != tic_ignore) {
 			printf("Error: Packed argument is not an array.\n");
 			stype_note_error(stype);
@@ -487,5 +487,5 @@
 	}
 
-	if (dest == NULL || src == NULL)
+	if (dest->tic == tic_ignore || src->tic == tic_ignore)
 		return expr;
 
@@ -680,13 +680,8 @@
 {
 	tdata_item_t *titem;
-	tdata_primitive_t *tprimitive;
 
 	(void) stype;
 
-	titem = tdata_item_new(tic_tprimitive);
-	tprimitive = tdata_primitive_new(tpc_int);
-
-	titem->u.tprimitive = tprimitive;
-
+	titem = tdata_item_new(tic_ignore);
 	return titem;
 }
Index: uspace/app/sbi/src/stype_expr.c
===================================================================
--- uspace/app/sbi/src/stype_expr.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/stype_expr.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -60,4 +60,6 @@
 static void stype_unop(stype_t *stype, stree_unop_t *unop,
     tdata_item_t **rtitem);
+static void stype_unop_tprimitive(stype_t *stype, stree_unop_t *unop,
+    tdata_item_t *ta, tdata_item_t **rtitem);
 static void stype_new(stype_t *stype, stree_new_t *new,
     tdata_item_t **rtitem);
@@ -276,5 +278,5 @@
 {
 	bool_t equal;
-	tdata_item_t *titem;
+	tdata_item_t *titem1, *titem2;
 
 #ifdef DEBUG_TYPE_TRACE
@@ -284,56 +286,46 @@
 	stype_expr(stype, binop->arg2);
 
-	/* XXX This should be checked properly. */
-	assert(binop->arg1->titem != NULL);
-	assert(binop->arg2->titem != NULL);
-
-	if (binop->arg1->titem == NULL) {
-		printf("Error First binary operand has no value.\n");
-		stype_note_error(stype);
-		if (binop->arg2->titem != NULL)
-			*rtitem = binop->arg2->titem;
-		else
-			*rtitem = stype_recovery_titem(stype);
-		return;
-	}
-
-	if (binop->arg2->titem == NULL) {
-		printf("Error: Second binary operand has no value.\n");
-		stype_note_error(stype);
-		*rtitem = binop->arg1->titem;
-		return;
-	}
-
-	equal = tdata_item_equal(binop->arg1->titem, binop->arg2->titem);
+	titem1 = binop->arg1->titem;
+	titem2 = binop->arg2->titem;
+
+	if (titem1 == NULL || titem2 == NULL) {
+		printf("Error: Binary operand has no value.\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	if (titem1->tic == tic_ignore || titem2->tic == tic_ignore) {
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	equal = tdata_item_equal(titem1, titem2);
 	if (equal != b_true) {
 		printf("Error: Binary operation arguments "
 		    "have different types ('");
-		tdata_item_print(binop->arg1->titem);
+		tdata_item_print(titem1);
 		printf("' and '");
-		tdata_item_print(binop->arg2->titem);
+		tdata_item_print(titem2);
 		printf("').\n");
 		stype_note_error(stype);
-		*rtitem = binop->arg1->titem;
-		return;
-	}
-
-	titem = binop->arg1->titem;
-
-	switch (titem->tic) {
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	switch (titem1->tic) {
 	case tic_tprimitive:
-		stype_binop_tprimitive(stype, binop, binop->arg1->titem,
-		    binop->arg2->titem, rtitem);
+		stype_binop_tprimitive(stype, binop, titem1, titem2, rtitem);
 		break;
 	case tic_tobject:
-		stype_binop_tobject(stype, binop, binop->arg1->titem,
-		    binop->arg2->titem, rtitem);
+		stype_binop_tobject(stype, binop, titem1, titem2, rtitem);
 		break;
 	default:
 		printf("Error: Binary operation on value which is not of a "
 		    "supported type (found '");
-		tdata_item_print(titem);
+		tdata_item_print(titem1);
 		printf("').\n");
 		stype_note_error(stype);
-		*rtitem = titem;
+		*rtitem = stype_recovery_titem(stype);
 		break;
 	}
@@ -417,4 +409,6 @@
     tdata_item_t **rtitem)
 {
+	tdata_item_t *titem;
+
 #ifdef DEBUG_TYPE_TRACE
 	printf("Evaluate type of unary operation.\n");
@@ -422,5 +416,54 @@
 	stype_expr(stype, unop->arg);
 
-	*rtitem = NULL;
+	titem = unop->arg->titem;
+
+	if (titem->tic == tic_ignore) {
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	switch (titem->tic) {
+	case tic_tprimitive:
+		stype_unop_tprimitive(stype, unop, titem, rtitem);
+		break;
+	default:
+		printf("Error: Unary operation on value which is not of a "
+		    "supported type (found '");
+		tdata_item_print(titem);
+		printf("').\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		break;
+	}
+}
+
+/** Type a binary operation arguments of primitive type. */
+static void stype_unop_tprimitive(stype_t *stype, stree_unop_t *unop,
+    tdata_item_t *ta, tdata_item_t **rtitem)
+{
+	tprimitive_class_t rtpc;
+	tdata_item_t *res_ti;
+
+	(void) stype;
+	(void) unop;
+
+	assert(ta->tic == tic_tprimitive);
+
+	switch (ta->u.tprimitive->tpc) {
+	case tpc_int:
+		rtpc = tpc_int;
+		break;
+	default:
+		printf("Error: Unary operator applied on unsupported "
+		    "primitive type %d.\n", ta->u.tprimitive->tpc);
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	res_ti = tdata_item_new(tic_tprimitive);
+	res_ti->u.tprimitive = tdata_primitive_new(rtpc);
+
+	*rtitem = res_ti;
 }
 
@@ -474,4 +517,7 @@
 		printf("Error: Using '.' operator on a function.\n");
 		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		break;
+	case tic_ignore:
 		*rtitem = stype_recovery_titem(stype);
 		break;
@@ -613,6 +659,24 @@
 	stype_expr(stype, call->fun);
 
+	/* Check type item class */
+
 	fun_ti = call->fun->titem;
-	assert(fun_ti->tic == tic_tfun);
+	switch (fun_ti->tic) {
+	case tic_tfun:
+		/* The expected case */
+		break;
+	case tic_ignore:
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	default:
+		printf("Error: Calling something which is not a function ");
+		printf("(found '");
+		tdata_item_print(fun_ti);
+		printf("').\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
 	fun = fun_ti->u.tfun->fun;
 	fun_sym = fun_to_symbol(fun);
@@ -734,4 +798,7 @@
 		printf("Error: Indexing a function.\n");
 		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		break;
+	case tic_ignore:
 		*rtitem = stype_recovery_titem(stype);
 		break;
Index: uspace/app/sbi/src/tdata.c
===================================================================
--- uspace/app/sbi/src/tdata.c	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/tdata.c	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -148,4 +148,7 @@
 		tdata_tfun_print(titem->u.tfun);
 		break;
+	case tic_ignore:
+		printf("ignore");
+		break;
 	}
 }
Index: uspace/app/sbi/src/tdata_t.h
===================================================================
--- uspace/app/sbi/src/tdata_t.h	(revision 5db9084cb9b925c6758f4bc0fac5c31d7125ff35)
+++ uspace/app/sbi/src/tdata_t.h	(revision 4dd8529d49f0dfcebe110b2d6421fc0ef334ff51)
@@ -84,9 +84,16 @@
 
 typedef enum {
+	/** Primitive type item */
 	tic_tprimitive,
+	/** Object type item */
 	tic_tobject,
+	/** Array type item */
 	tic_tarray,
+	/** Generic type item */
 	tic_tgeneric,
-	tic_tfun
+	/** Function type item */
+	tic_tfun,
+	/** Special error-recovery type item */
+	tic_ignore
 } titem_class_t;
 
