source: trunk/instant_messenger/socket/BKP_20071105/BKP_20071026/BKP_20071019/BKP_20071018/BKP_20071009/cexcept.h @ 151

Revision 151, 9.7 KB checked in by niltonneto, 16 years ago (diff)

Commit da nova versão do módulo, usando agente em C.
Vide Página do módulo do Trac:
http://www.expressolivre.org/dev/wiki/messenger

A versão anterior encontra-se na subpasta bkp (32/64).

Line 
1/*===
2cexcept.h 1.0.0 (2000-Jun-21-Wed)
3Adam M. Costello <amc@cs.berkeley.edu>
4
5An interface for exception-handling in ANSI C, developed jointly with
6Cosmin Truta <cosmin@cs.toronto.edu>.
7
8    Copyright (c) 2000 Adam M. Costello and Cosmin Truta.  Everyone
9    is hereby granted permission to do whatever they like with this
10    file, provided that if they modify it they take reasonable steps to
11    avoid confusing or misleading people about the authors, version,
12    and terms of use of the derived file.  The copyright holders make
13    no guarantees about the correctness of this file, and are not
14    responsible for any damage resulting from its use.
15
16If this interface is used by multiple .c files, they shouldn't include
17this header file directly.  Instead, create a wrapper header file that
18includes this header file and then invokes the define_exception_type
19macro (see below), and let your .c files include that header file.
20
21The interface consists of one type, one well-known name, and six macros.
22
23
24define_exception_type(type_name);
25
26    This macro is used like an external declaration.  It specifies
27    the type of object that gets copied from the exception thrower to
28    the exception catcher.  The type_name can be any type that can be
29    assigned to, that is, a non-constant arithmetic type, struct, union,
30    or pointer.  Examples:
31
32        define_exception_type(int);
33
34        enum exception { out_of_memory, bad_arguments, disk_full };
35        define_exception_type(enum exception);
36
37        struct exception { int code; const char *msg; };
38        define_exception_type(struct exception);
39
40
41struct exception_context;
42
43    This type may be used after the define_exception_type() macro has
44    been invoked.  A struct exception_context must be known to both
45    the thrower and the catcher.  It is expected that there be one
46    context for each thread that uses exceptions.  It would certainly
47    be dangerous for multiple threads to access the same context.
48    One thread can use multiple contexts, but that is likely to be
49    confusing and not typically useful.  The application can allocate
50    this structure in any way it pleases--automatic, static, or dynamic.
51    The application programmer should pretend not to know the structure
52    members, which are subject to change.
53
54
55struct exception_context *the_exception_context;
56
57    The Try/Catch and Throw statements (described below) implicitly
58    refer to a context, using the name the_exception_context.  It is
59    the application's responsibility to make sure that this name yields
60    the address of a mutable (non-constant) struct exception_context
61    wherever those statements are used.  Subject to that constraint, the
62    application may declare a variable of this name anywhere it likes
63    (inside a function, in a parameter list, or externally), and may
64    use whatever storage class specifiers (static, extern, etc) or type
65    qualifiers (const, volatile) it likes.  Examples:
66
67        static struct exception_context
68          * const the_exception_context = &foo;
69
70        { struct exception_context *the_exception_context = bar; ... }
71
72        int blah(struct exception_context *the_exception_context, ...);
73
74        extern struct exception_context the_exception_context[1];
75
76    The last example illustrates a trick that avoids creating a pointer
77    object separate from the structure object.
78
79    The name could even be a macro, for example:
80
81        struct exception_context ec_array[numthreads];
82        #define the_exception_context (ec_array + thread_id)
83
84    Be aware that the_exception_context is used several times by the
85    Try/Catch/Throw macros, so it shouldn't be expensive or have side
86    effects.  The expansion must be a drop-in replacement for an
87    identifier, so it's safest to put parentheses around it.
88
89
90void init_exception_context(struct exception_context *ec);
91
92    For context structures allocated statically (by an external
93    definition or using the "static" keyword), the implicit
94    initialization to all zeros is sufficient, but contexts allocated
95    by other means must be initialized using this macro before they
96    are used by a Try/Catch statement.  It does no harm to initialize
97    a context more than once (by using this macro on a statically
98    allocated context, or using this macro twice on the same context),
99    but a context must not be re-initialized after it has been used by a
100    Try/Catch statement.
101
102
103Try statement
104Catch (expression) statement
105
106    The Try/Catch/Throw macros are capitalized in order to avoid
107    confusion with the C++ keywords, which have subtly different
108    semantics.
109
110    A Try/Catch statement has a syntax similar to an if/else
111    statement, except that the parenthesized expression goes after
112    the second keyword rather than the first.  As with if/else,
113    there are two clauses, each of which may be a simple statement
114    ending with a semicolon or a brace-enclosed compound statement.
115    But whereas the else clause is optional, the Catch clause is
116    required.  The expression must be a modifiable lvalue (something
117    capable of being assigned to) of the exact same type passed to
118    define_exception_type().
119
120    If a Throw that uses the same exception context as the Try/Catch is
121    executed within the Try clause (typically within a function called
122    by the Try clause), and the exception is not caught by a nested
123    Try/Catch statement, then a copy of the exception will be assigned
124    to the expression, and control will jump to the Catch clause.  If no
125    such Throw is executed, then the assignment is not performed, and
126    the Catch clause is not executed.
127
128    Regardless of whether an exception is caught, the expression is
129    always evaluated exactly once, which is significant if it has side
130    effects, for example:
131
132        Try foo();
133        Catch (p[++i].e) { ... }
134
135    IMPORTANT: Jumping into or out of a Try clause (for example via
136    return, break, continue, goto, longjmp) is forbidden--the compiler
137    will not complain, but bad things will happen at run-time.  Jumping
138    into or out of a Catch clause is okay, and so is jumping around
139    inside a Try clause.  In many cases where one is tempted to return
140    from a Try clause, it will suffice to use Throw, and then return
141    from the Catch clause.  Another option is to set a flag variable and
142    use goto to jump to the end of the Try clause, then check the flag
143    after the Try/Catch statement.
144
145    IMPORTANT: The values of any non-volatile automatic variables
146    changed within the Try clause are undefined after an exception is
147    caught.  Therefore, variables modified inside the Try block whose
148    values are needed later outside the Try block must either use static
149    storage or be declared with the "volatile" type qualifier.
150
151
152Throw expression;
153
154    A Throw statement is very much like a return statement, except that
155    the expression is required.  Whereas return jumps back to the place
156    where the current function was called, Throw jumps back to the Catch
157    clause of the innermost enclosing Try clause.  The expression must
158    be compatible with the type passed to define_exception_type().  The
159    exception must be caught, otherwise the program may crash.
160
161    Slight limitation:  If the expression is a comma-expression it must
162    be enclosed in parentheses.
163
164
165Try statement
166Catch_anonymous statement
167
168    When the value of the exception is not needed, a Try/Catch statement
169    can use Catch_anonymous instead of Catch (expression).
170
171
172Everything below this point is for the benefit of the compiler.  The
173application programmer should pretend not to know any of it, because it
174is subject to change.
175
176===*/
177
178
179#ifndef CEXCEPT_H
180#define CEXCEPT_H
181
182
183#include <setjmp.h>
184
185#define define_exception_type(etype) \
186struct exception__state { \
187  etype *exception; \
188  jmp_buf env; \
189}
190
191struct exception_context { \
192  struct exception__state *last; \
193  int caught; \
194};
195
196#define init_exception_context(ec) ((void)((ec)->last = 0))
197
198#define Catch(e) exception__catch(&(e))
199#define Catch_anonymous exception__catch(0)
200
201#define Try \
202  { \
203    struct exception__state *exception__p, exception__s; \
204    int exception__i; \
205    exception__p = the_exception_context->last; \
206    the_exception_context->last = &exception__s; \
207    for (exception__i = 0; ; exception__i = 1) \
208      if (exception__i) { \
209        if (setjmp(exception__s.env) == 0) { \
210          if (&exception__s)
211
212#define exception__catch(e_addr) \
213          else { } \
214          the_exception_context->caught = 0; \
215        } \
216        else the_exception_context->caught = 1; \
217        the_exception_context->last = exception__p; \
218        break; \
219      } \
220      else exception__s.exception = e_addr; \
221  } \
222  if (!the_exception_context->caught) { } \
223  else
224
225/* Try ends with if(), and Catch begins and ends with else.  This     */
226/* ensures that the Try/Catch syntax is really the same as the        */
227/* if/else syntax.                                                    */
228/*                                                                    */
229/* We use &exception__s instead of 1 to appease compilers that        */
230/* warn about constant expressions inside if().  Most compilers       */
231/* should still recognize that &exception__s is never zero and avoid  */
232/* generating test code.                                              */
233/*                                                                    */
234/* We use the variable exception__i to start the loop at the bottom,  */
235/* rather than jump into the loop using a switch statement, to        */
236/* appease compilers that warn about jumping into loops.              */
237
238#define Throw \
239  for (;; longjmp(the_exception_context->last->env, 1)) \
240    if (the_exception_context->last->exception) \
241      *the_exception_context->last->exception =
242
243
244#endif /* CEXCEPT_H */
Note: See TracBrowser for help on using the repository browser.