# HG changeset patch # User Francisco J Ballesteros # Date 1328893756 0 # Node ID 257203b800f6651da9c0a62c8d3bf2d50194f682 # Parent 34ea01195f9f3c474ccda369eefcf36aa2cc816f error: handling like in the kernel for user programs. ix is now using this for it's file server. R=nixiedev, rminnich, john, nemo, quanstro CC=nix-dev http://codereview.appspot.com/5610052 diff -r 34ea01195f9f -r 257203b800f6 sys/include/error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/include/error.h Fri Feb 10 17:09:16 2012 +0000 @@ -0,0 +1,19 @@ +#pragma lib "liberror.a" +#pragma src "/sys/src/liberror" + +typedef struct Error Error; + +struct Error { + int nerr; + int nlabel; + jmp_buf label[1]; /* of [stack] actually */ +}; + +#pragma varargck argpos error 1 +#pragma varargck argpos esmprint 1 + +void errinit(int stack); +void noerror(void); +void error(char* msg, ...); +#define catcherror() setjmp((*__ep)->label[(*__ep)->nerr++]) +extern Error** __ep; diff -r 34ea01195f9f -r 257203b800f6 sys/man/2/error --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/man/2/error Fri Feb 10 17:09:16 2012 +0000 @@ -0,0 +1,70 @@ +.TH ERROR 2 +.SH NAME +errinit, noerror, error, catcherror \- local error handling utilities +.SH SYNOPSIS +.B #include +.br +.B #include +.br +.B #include +.PP +.B +void errinit(int stack) +.br +.B +void noerror(void) +.br +.B +void error(char* msg, ...) +.br +.B +void catcherror(void) +.SH DESCRIPTION +These routiles are tools for error handling. +.IR catcherror , +.IR noerror , +.IR error , +and +.IR errinit +provide exeption handling for C, in the same style of the similar routines used in +the kernel. +They can be used both with and without +the +.IR thread (2) +library. +.PP +.I Errinit +should be called before using any other. It should be called by each thread/process +using the error handling mechanism. Its argument, +indicaties the desired depth of the error stack for the calling process. +.PP +.I Catcherror +install an exception handling point. +.I Noerror +declares that there was no error catched, similar to the +.I poperror +function in the kernel. +.I Error +raises an error. If the argument is nil, the error string is unaltered. See the example. +.SH SOURCE +.B /sys/src/liberror +.SH EXAMPLE +Catch an error, and raise one. +.PP +.EX +void f(void) +{ + error("catch this!"); +} + +void +main(int argc, char **argv) +{ + errinit(32); + if (catcherror()){ + sysfatal("catched: %r"); + } + f(); + noerror(); +} +.EE diff -r 34ea01195f9f -r 257203b800f6 sys/src/liberror/error.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/liberror/error.c Fri Feb 10 17:09:16 2012 +0000 @@ -0,0 +1,46 @@ +#include +#include +#include + +Error** __ep; + +void +errinit(int stack) +{ + Error *e; + + e = mallocz(sizeof(Error) + sizeof(e->label)*(stack-1), 1); + if(e == nil) + sysfatal("errinit: no memory"); + if(__ep == nil) + __ep = privalloc(); + *__ep = e; + e->nlabel = stack; +} + +void +noerror(void) +{ + if((*__ep)->nerr > (*__ep)->nlabel - 3) + sysfatal("error stack about to overflow"); + if((*__ep)->nerr-- == 0) + sysfatal("noerror w/o catcherror"); +} + +void +error(char* msg, ...) +{ + char buf[500]; + va_list arg; + + if(msg != nil){ + va_start(arg, msg); + vseprint(buf, buf+sizeof(buf), msg, arg); + va_end(arg); + werrstr("%s", buf); + } + if((*__ep)->nerr == 0) + sysfatal("%s", buf); + (*__ep)->nerr--; + longjmp((*__ep)->label[(*__ep)->nerr], 1); +} diff -r 34ea01195f9f -r 257203b800f6 sys/src/liberror/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/liberror/mkfile Fri Feb 10 17:09:16 2012 +0000 @@ -0,0 +1,15 @@ +