"Fossies" - the Fresh Open Source Software Archive

Member "pigz-2.8/try.c" (12 Apr 2021, 2616 Bytes) of package /linux/privat/pigz-2.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "try.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.6_vs_2.7.

    1 /* try.c -- try / catch / throw exception handling for C99
    2  * For copyright, version, and conditions of distribution and use, see try.h
    3  */
    4 
    5 /* See try.h for documentation.  This source file provides the global pointer
    6    and the functions needed by throw().  The pointer is thread-unique if
    7    pthread.h is included in try.h. */
    8 
    9 #include "try.h"
   10 #include <stdio.h>
   11 #include <string.h>
   12 #include <stdarg.h>
   13 
   14 /* Set up the try stack with a global pointer to the next try block.  The
   15    global is thread-unique if pthread.h is included in try.h. */
   16 #ifdef PTHREAD_ONCE_INIT
   17     pthread_key_t try_key_;
   18     static pthread_once_t try_once_ = PTHREAD_ONCE_INIT;
   19     static void try_create_(void)
   20     {
   21         int ret = pthread_key_create(&try_key_, NULL);
   22         assert(ret == 0 && "try: pthread_key_create() failed");
   23     }
   24     void try_setup_(void)
   25     {
   26         int ret = pthread_once(&try_once_, try_create_);
   27         assert(ret == 0 && "try: pthread_once() failed");
   28     }
   29 #else /* !PTHREAD_ONCE_INIT */
   30     try_t_ *try_stack_ = NULL;
   31 #endif /* PTHREAD_ONCE_INIT */
   32 
   33 /* Throw an exception.  This must always have at least two arguments, where the
   34    second argument can be a NULL.  The throw() macro is permitted to have one
   35    argument, since it appends a NULL argument in the call to this function. */
   36 void try_throw_(int code, char *fmt, ...)
   37 {
   38     /* save the thrown information in the try stack before jumping */
   39     try_setup_();
   40     assert(try_stack_ != NULL && "try: naked throw");
   41     try_stack_->ball.ret = 1;
   42     try_stack_->ball.code = code;
   43     try_stack_->ball.free = 0;
   44     try_stack_->ball.why = fmt;
   45 
   46     /* consider the second argument to be a string, and if it has formatting
   47        commands, process them with the subsequent arguments of throw, saving
   48        the result in allocated memory -- this if statement and clause must be
   49        updated for a different interpretation of the throw() arguments and
   50        different contents of the ball_t structure */
   51     if (fmt != NULL && strchr(fmt, '%') != NULL) {
   52         char *why, nul[1];
   53         size_t len;
   54         va_list ap1, ap2;
   55 
   56         va_start(ap1, fmt);
   57         va_copy(ap2, ap1);
   58         len = vsnprintf(nul, 1, fmt, ap1);
   59         va_end(ap1);
   60         why = malloc(len + 1);
   61         if (why == NULL)
   62             try_stack_->ball.why = "try: out of memory";
   63         else {
   64             vsnprintf(why, len + 1, fmt, ap2);
   65             va_end(ap2);
   66             try_stack_->ball.free = 1;
   67             try_stack_->ball.why = why;
   68         }
   69     }
   70 
   71     /* jump to the end of the nearest enclosing try block */
   72     longjmp(try_stack_->env, 1);
   73 }