home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / efence / part01 / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-01  |  2.9 KB  |  161 lines

  1. #include "efence.h"
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <stdarg.h>
  5. #include <string.h>
  6. #include <signal.h>
  7.  
  8. /*
  9.  * These routines do their printing without using stdio. Stdio can't
  10.  * be used because it calls malloc(). Internal routines of a malloc()
  11.  * debugger should not re-enter malloc(), so stdio is out.
  12.  */
  13.  
  14. /*
  15.  * NUMBER_BUFFER_SIZE is the longest character string that could be needed
  16.  * to represent an unsigned integer. Assuming unsigned integers might be as
  17.  * large as 64 bits, and we might print in base 2, let's set it to 64 bytes.
  18.  */
  19. #define    NUMBER_BUFFER_SIZE    64
  20.  
  21. static void
  22. printNumber(unsigned int number, unsigned int base)
  23. {
  24.     char        buffer[NUMBER_BUFFER_SIZE];
  25.     char *        s = &buffer[NUMBER_BUFFER_SIZE];
  26.     int        size;
  27.     
  28.     do {
  29.         unsigned int    digit;
  30.  
  31.         if ( --s == buffer )
  32.             EF_Abort("Internal error printing number.");
  33.  
  34.         digit = number % base;
  35.  
  36.         if ( digit < 10 )
  37.             *s = '0' + digit;
  38.         else
  39.             *s = 'a' + digit - 10;
  40.  
  41.     } while ( (number /= base) > 0 );
  42.  
  43.     size = &buffer[NUMBER_BUFFER_SIZE] - s;
  44.  
  45.     if ( size > 0 )
  46.         write(2, s, size);
  47. }
  48.  
  49. static void
  50. vprint(const char * pattern, va_list args)
  51. {
  52.     static const char    bad_pattern[] =
  53.      "\nBad pattern specifier %%%c in EF_Print().\n";
  54.     const char *    s = pattern;
  55.     char        c;
  56.  
  57.     while ( (c = *s++) != '\0' ) {
  58.         if ( c == '%' ) {
  59.             c = *s++;
  60.             switch ( c ) {
  61.             case '%':
  62.                 (void) write(2, &c, 1);
  63.                 break;
  64.             case 's':
  65.                 {
  66.                     const char *    string;
  67.                     size_t        length;
  68.  
  69.                     string = va_arg(args, char *);
  70.                     length = strlen(string);
  71.  
  72.                     (void) write(2, string, length);
  73.                 }
  74.                 break;
  75.             case 'd':
  76.                 {
  77.                     int    n = va_arg(args, int);
  78.  
  79.                     if ( n < 0 ) {
  80.                         char    c = '-';
  81.                         write(2, &c, 1);
  82.                         n = -n;
  83.                     }
  84.                     printNumber(n, 10);
  85.                 }
  86.                 break;
  87.             case 'x':
  88.                 printNumber(va_arg(args, u_int), 0x10);
  89.                 break;
  90.             case 'c':
  91.                 {
  92.                     char    c = va_arg(args, char);
  93.                     
  94.                     (void) write(2, &c, 1);
  95.                 }
  96.                 break;
  97.             default:
  98.                 {
  99.                     EF_Print(bad_pattern, c);
  100.                 }
  101.         
  102.             }
  103.         }
  104.         else
  105.             (void) write(2, &c, 1);
  106.     }
  107. }
  108.  
  109. void
  110. EF_Abort(const char * pattern, ...)
  111. {
  112.     va_list    args;
  113.  
  114.     va_start(args, pattern);
  115.  
  116.     EF_Print("\nElectricFence Aborting: ");
  117.     vprint(pattern, args);
  118.     EF_Print("\n");
  119.  
  120.     va_end(args);
  121.  
  122.     /*
  123.      * I use kill(getpid(), SIGILL) instead of abort() because some
  124.      * mis-guided implementations of abort() flush stdio, which can
  125.      * cause malloc() or free() to be called.
  126.      */
  127.     kill(getpid(), SIGILL);
  128.     /* Just in case something handles SIGILL and returns, exit here. */
  129.     _exit(-1);
  130. }
  131.  
  132. void
  133. EF_Exit(const char * pattern, ...)
  134. {
  135.     va_list    args;
  136.  
  137.     va_start(args, pattern);
  138.  
  139.     EF_Print("\nElectricFence Exiting: ");
  140.     vprint(pattern, args);
  141.     EF_Print("\n");
  142.  
  143.     va_end(args);
  144.  
  145.     /*
  146.      * I use _exit() because the regular exit() flushes stdio,
  147.      * which may cause malloc() or free() to be called.
  148.      */
  149.     _exit(-1);
  150. }
  151.  
  152. void
  153. EF_Print(const char * pattern, ...)
  154. {
  155.     va_list    args;
  156.  
  157.     va_start(args, pattern);
  158.     vprint(pattern, args);
  159.     va_end(args);
  160. }
  161.