⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cexcept.h

📁 png文件的解码和文件格式说明
💻 H
字号:
/*===cexcept.h 1.0.0 (2000-Jun-21-Wed)Adam M. Costello <amc@cs.berkeley.edu>An interface for exception-handling in ANSI C, developed jointly withCosmin Truta <cosmin@cs.toronto.edu>.    Copyright (c) 2000 Adam M. Costello and Cosmin Truta.  Everyone    is hereby granted permission to do whatever they like with this    file, provided that if they modify it they take reasonable steps to    avoid confusing or misleading people about the authors, version,    and terms of use of the derived file.  The copyright holders make    no guarantees about the correctness of this file, and are not    responsible for any damage resulting from its use.If this interface is used by multiple .c files, they shouldn't includethis header file directly.  Instead, create a wrapper header file thatincludes this header file and then invokes the define_exception_typemacro (see below), and let your .c files include that header file.The interface consists of one type, one well-known name, and six macros.define_exception_type(type_name);    This macro is used like an external declaration.  It specifies    the type of object that gets copied from the exception thrower to    the exception catcher.  The type_name can be any type that can be    assigned to, that is, a non-constant arithmetic type, struct, union,    or pointer.  Examples:        define_exception_type(int);        enum exception { out_of_memory, bad_arguments, disk_full };        define_exception_type(enum exception);        struct exception { int code; const char *msg; };        define_exception_type(struct exception);struct exception_context;    This type may be used after the define_exception_type() macro has    been invoked.  A struct exception_context must be known to both    the thrower and the catcher.  It is expected that there be one    context for each thread that uses exceptions.  It would certainly    be dangerous for multiple threads to access the same context.    One thread can use multiple contexts, but that is likely to be    confusing and not typically useful.  The application can allocate    this structure in any way it pleases--automatic, static, or dynamic.    The application programmer should pretend not to know the structure    members, which are subject to change.struct exception_context *the_exception_context;    The Try/Catch and Throw statements (described below) implicitly    refer to a context, using the name the_exception_context.  It is    the application's responsibility to make sure that this name yields    the address of a mutable (non-constant) struct exception_context    wherever those statements are used.  Subject to that constraint, the    application may declare a variable of this name anywhere it likes    (inside a function, in a parameter list, or externally), and may    use whatever storage class specifiers (static, extern, etc) or type    qualifiers (const, volatile) it likes.  Examples:        static struct exception_context          * const the_exception_context = &foo;        { struct exception_context *the_exception_context = bar; ... }        int blah(struct exception_context *the_exception_context, ...);        extern struct exception_context the_exception_context[1];    The last example illustrates a trick that avoids creating a pointer    object separate from the structure object.    The name could even be a macro, for example:        struct exception_context ec_array[numthreads];        #define the_exception_context (ec_array + thread_id)    Be aware that the_exception_context is used several times by the    Try/Catch/Throw macros, so it shouldn't be expensive or have side    effects.  The expansion must be a drop-in replacement for an    identifier, so it's safest to put parentheses around it.void init_exception_context(struct exception_context *ec);    For context structures allocated statically (by an external    definition or using the "static" keyword), the implicit    initialization to all zeros is sufficient, but contexts allocated    by other means must be initialized using this macro before they    are used by a Try/Catch statement.  It does no harm to initialize    a context more than once (by using this macro on a statically    allocated context, or using this macro twice on the same context),    but a context must not be re-initialized after it has been used by a    Try/Catch statement.Try statementCatch (expression) statement    The Try/Catch/Throw macros are capitalized in order to avoid    confusion with the C++ keywords, which have subtly different    semantics.    A Try/Catch statement has a syntax similar to an if/else    statement, except that the parenthesized expression goes after    the second keyword rather than the first.  As with if/else,    there are two clauses, each of which may be a simple statement    ending with a semicolon or a brace-enclosed compound statement.    But whereas the else clause is optional, the Catch clause is    required.  The expression must be a modifiable lvalue (something    capable of being assigned to) of the exact same type passed to    define_exception_type().    If a Throw that uses the same exception context as the Try/Catch is    executed within the Try clause (typically within a function called    by the Try clause), and the exception is not caught by a nested    Try/Catch statement, then a copy of the exception will be assigned    to the expression, and control will jump to the Catch clause.  If no    such Throw is executed, then the assignment is not performed, and    the Catch clause is not executed.    Regardless of whether an exception is caught, the expression is    always evaluated exactly once, which is significant if it has side    effects, for example:        Try foo();        Catch (p[++i].e) { ... }    IMPORTANT: Jumping into or out of a Try clause (for example via    return, break, continue, goto, longjmp) is forbidden--the compiler    will not complain, but bad things will happen at run-time.  Jumping    into or out of a Catch clause is okay, and so is jumping around    inside a Try clause.  In many cases where one is tempted to return    from a Try clause, it will suffice to use Throw, and then return    from the Catch clause.  Another option is to set a flag variable and    use goto to jump to the end of the Try clause, then check the flag    after the Try/Catch statement.    IMPORTANT: The values of any non-volatile automatic variables    changed within the Try clause are undefined after an exception is    caught.  Therefore, variables modified inside the Try block whose    values are needed later outside the Try block must either use static    storage or be declared with the "volatile" type qualifier.Throw expression;    A Throw statement is very much like a return statement, except that    the expression is required.  Whereas return jumps back to the place    where the current function was called, Throw jumps back to the Catch    clause of the innermost enclosing Try clause.  The expression must    be compatible with the type passed to define_exception_type().  The    exception must be caught, otherwise the program may crash.    Slight limitation:  If the expression is a comma-expression it must    be enclosed in parentheses.Try statementCatch_anonymous statement    When the value of the exception is not needed, a Try/Catch statement    can use Catch_anonymous instead of Catch (expression).Everything below this point is for the benefit of the compiler.  Theapplication programmer should pretend not to know any of it, because itis subject to change.===*/#ifndef CEXCEPT_H#define CEXCEPT_H#include <setjmp.h>#define define_exception_type(etype) \struct exception__state { \  etype *exception; \  jmp_buf env; \}struct exception_context { \  struct exception__state *last; \  int caught; \};#define init_exception_context(ec) ((void)((ec)->last = 0))#define Catch(e) exception__catch(&(e))#define Catch_anonymous exception__catch(0)#define Try \  { \    struct exception__state *exception__p, exception__s; \    int exception__i; \    exception__p = the_exception_context->last; \    the_exception_context->last = &exception__s; \    for (exception__i = 0; ; exception__i = 1) \      if (exception__i) { \        if (setjmp(exception__s.env) == 0) { \          if (&exception__s)#define exception__catch(e_addr) \          else { } \          the_exception_context->caught = 0; \        } \        else the_exception_context->caught = 1; \        the_exception_context->last = exception__p; \        break; \      } \      else exception__s.exception = e_addr; \  } \  if (!the_exception_context->caught) { } \  else/* Try ends with if(), and Catch begins and ends with else.  This     *//* ensures that the Try/Catch syntax is really the same as the        *//* if/else syntax.                                                    *//*                                                                    *//* We use &exception__s instead of 1 to appease compilers that        *//* warn about constant expressions inside if().  Most compilers       *//* should still recognize that &exception__s is never zero and avoid  *//* generating test code.                                              *//*                                                                    *//* We use the variable exception__i to start the loop at the bottom,  *//* rather than jump into the loop using a switch statement, to        *//* appease compilers that warn about jumping into loops.              */#define Throw \  for (;; longjmp(the_exception_context->last->env, 1)) \    if (the_exception_context->last->exception) \      *the_exception_context->last->exception =#endif /* CEXCEPT_H */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -