• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/maloc/src/efence/print.c

00001 #include "efence.h"
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <stdarg.h>
00005 #include <string.h>
00006 #include <signal.h>
00007 
00008 /*
00009  * These routines do their printing without using stdio. Stdio can't
00010  * be used because it calls malloc(). Internal routines of a malloc()
00011  * debugger should not re-enter malloc(), so stdio is out.
00012  */
00013 
00014 /*
00015  * NUMBER_BUFFER_SIZE is the longest character string that could be needed
00016  * to represent an unsigned integer, assuming we might print in base 2.
00017  */
00018 #define    NUMBER_BUFFER_SIZE    (sizeof(ef_number) * NBBY)
00019 
00020 static void
00021 printNumber(ef_number number, ef_number base)
00022 {
00023            char                  buffer[NUMBER_BUFFER_SIZE];
00024            char *                s = &buffer[NUMBER_BUFFER_SIZE];
00025            int                   size;
00026            
00027            do {
00028                       ef_number  digit;
00029 
00030                       if ( --s == buffer )
00031                                  EF_Abort("Internal error printing number.");
00032 
00033                       digit = number % base;
00034 
00035                       if ( digit < 10 )
00036                                  *s = '0' + digit;
00037                       else
00038                                  *s = 'a' + digit - 10;
00039 
00040            } while ( (number /= base) > 0 );
00041 
00042            size = &buffer[NUMBER_BUFFER_SIZE] - s;
00043 
00044            if ( size > 0 )
00045                       write(2, s, size);
00046 }
00047 
00048 static void
00049 vprint(const char * pattern, va_list args)
00050 {
00051            static const char     bad_pattern[] =
00052             "\nBad pattern specifier %%%c in EF_Print().\n";
00053            const char *          s = pattern;
00054            char                  c;
00055 
00056            while ( (c = *s++) != '\0' ) {
00057                       if ( c == '%' ) {
00058                                  c = *s++;
00059                                  switch ( c ) {
00060                                  case '%':
00061                                             (void) write(2, &c, 1);
00062                                             break;
00063                                  case 'a':
00064                                             /*
00065                                              * Print an address passed as a void pointer.
00066                                              * The type of ef_number must be set so that
00067                                              * it is large enough to contain all of the
00068                                              * bits of a void pointer.
00069                                              */
00070                                             printNumber(
00071                                              (ef_number)va_arg(args, void *)
00072                                             ,0x10);
00073                                             break;
00074                                  case 's':
00075                                             {
00076                                                        const char *          string;
00077                                                        size_t                length;
00078 
00079                                                        string = va_arg(args, char *);
00080                                                        length = strlen(string);
00081 
00082                                                        (void) write(2, string, length);
00083                                             }
00084                                             break;
00085                                  case 'd':
00086                                             {
00087                                                        int        n = va_arg(args, int);
00088 
00089                                                        if ( n < 0 ) {
00090                                                                   char       c = '-';
00091                                                                   write(2, &c, 1);
00092                                                                   n = -n;
00093                                                        }
00094                                                        printNumber(n, 10);
00095                                             }
00096                                             break;
00097                                  case 'x':
00098                                             printNumber(va_arg(args, u_int), 0x10);
00099                                             break;
00100                                  case 'c':
00101                                             {
00102                                                        char       c = va_arg(args, int);
00103                                                        
00104                                                        (void) write(2, &c, 1);
00105                                             }
00106                                             break;
00107                                  default:
00108                                             {
00109                                                        EF_Print(bad_pattern, c);
00110                                             }
00111                       
00112                                  }
00113                       }
00114                       else
00115                                  (void) write(2, &c, 1);
00116            }
00117 }
00118 
00119 void
00120 EF_Abort(const char * pattern, ...)
00121 {
00122            va_list    args;
00123 
00124            va_start(args, pattern);
00125 
00126            EF_Print("\nElectricFence Aborting: ");
00127            vprint(pattern, args);
00128            EF_Print("\n");
00129 
00130            va_end(args);
00131 
00132            /*
00133             * I use kill(getpid(), SIGILL) instead of abort() because some
00134             * mis-guided implementations of abort() flush stdio, which can
00135             * cause malloc() or free() to be called.
00136             */
00137            kill(getpid(), SIGILL);
00138            /* Just in case something handles SIGILL and returns, exit here. */
00139            _exit(-1);
00140 }
00141 
00142 void
00143 EF_Exit(const char * pattern, ...)
00144 {
00145            va_list    args;
00146 
00147            va_start(args, pattern);
00148 
00149            EF_Print("\nElectricFence Exiting: ");
00150            vprint(pattern, args);
00151            EF_Print("\n");
00152 
00153            va_end(args);
00154 
00155            /*
00156             * I use _exit() because the regular exit() flushes stdio,
00157             * which may cause malloc() or free() to be called.
00158             */
00159            _exit(-1);
00160 }
00161 
00162 void
00163 EF_Print(const char * pattern, ...)
00164 {
00165            va_list    args;
00166 
00167            va_start(args, pattern);
00168            vprint(pattern, args);
00169            va_end(args);
00170 }

Generated on Wed Oct 20 2010 11:12:14 for APBS by  doxygen 1.7.2