+void trans_init(void); /** Initializes the transaction system for the current thread. Called automatically as needed. **/
+void trans_cleanup(void); /** Frees memory occupied by the transaction system pools for the current thread. **/
+
+struct trans *trans_open(void); /** Creates a new transaction. Used inside `TRANS_TRY`. **/
+struct trans *trans_get_current(void); /** Get a pointer to the currently running transaction, or NULL if there is none. **/
+void trans_commit(void); /** Commits the current transaction. **/
+void trans_rollback(void); /** Rolls back the current transaction. **/
+void trans_fold(void); /** Folds the current transaction to its parent. **/
+void trans_dump(void); /** Prints out a debugging dump of the transaction stack to stdout. **/
+
+struct mempool *trans_get_pool(void);
+
+/**
+ * Data associated with an exception. Usually, this structure is created
+ * by calling @trans_throw(), but if you want to pass more data, you can
+ * create your own exception and throw it using @trans_throw_exc().
+ **/
+struct exception {
+ const char *id; // Hierarchical identifier of the exception
+ const char *msg; // Error message to present to the user
+ void *object; // Object on which the exception happened
+ // More data specific for the particular `id' can follow
+};
+
+/** Creates an exception and throws it. The error message can contain `printf`-like formatting. **/
+void trans_throw(const char *id, void *object, const char *fmt, ...) FORMAT_CHECK(printf,3,4) NONRET;
+
+/** A `va_list` variant of @trans_throw(). **/
+void trans_vthrow(const char *id, void *object, const char *fmt, va_list args) NONRET;
+
+/** Throw an already constructed exception (or re-throw an exception you have caught). **/
+void trans_throw_exc(struct exception *x) NONRET;
+
+/** Declare the current exception caught and roll back the current transaction. Called from `TRANS_END`. **/
+void trans_caught(void);
+
+struct exception *trans_current_exc(void); /** Return the exception in flight, or NULL if there is none. **/
+
+#define TRANS_TRY do { \
+ struct trans *_t = trans_open(); \
+ if (!setjmp(_t->jmp)) \
+ {