Skip to content
Snippets Groups Projects
debugstr.c 7.79 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <string.h>
    #include <ctype.h>
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "debugstr.h"
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    #include "xmalloc.h"
    
    /* ---------------------------------------------------------------------- */
    
    #define SAVE_STRING_COUNT 50
    static void *strings[SAVE_STRING_COUNT];
    static int nextstring;
    
    /* ---------------------------------------------------------------------- */
    
    static void *
    gimme1 (int n)
    {
      void *res;
      if (strings[nextstring]) free (strings[nextstring]);
      res = strings[nextstring] = xmalloc (n);
      if (++nextstring == SAVE_STRING_COUNT) nextstring = 0;
      return res;
    }
    
    /* ---------------------------------------------------------------------- */
    
    LPSTR
    debugstr_an (LPCSTR src, int n)
    {
      LPSTR dst, res;
    
      if (!src) return "(null)";
      if (n < 0) n = 0;
    
      dst = res = gimme1 (n * 4 + 6);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      *dst++ = '"';
      while (n-- > 0 && *src)
        {
          BYTE c = *src++;
          switch (c)
    	{
    	case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
    	case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
    	case '\t': *dst++ = '\\'; *dst++ = 't'; break;
    	case '"': *dst++ = '\\'; *dst++ = '"'; break;
    	case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
    	default:
    	  if (c >= ' ' && c <= 126)
    	    *dst++ = c;
    	  else
    	    {
    	      *dst++ = '\\';
    	      *dst++ = '0' + ((c >> 6) & 7);
    	      *dst++ = '0' + ((c >> 3) & 7);
    	      *dst++ = '0' + ((c >> 0) & 7);
    	    }
    	}
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      if (*src)
        {
          *dst++ = '.';
          *dst++ = '.';
          *dst++ = '.';
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      return res;
    }
    
    /* ---------------------------------------------------------------------- */
    
    LPSTR
    debugstr_a (LPCSTR s)
    {
      return debugstr_an (s, 80);
    }
    
    /* ---------------------------------------------------------------------- */
    
    LPSTR
    debugstr_wn (LPCWSTR src, int n)
    {
      LPSTR dst, res;
    
      if (!src) return "(null)";
      if (n < 0) n = 0;
    
      dst = res = gimme1 (n * 5 + 7);
      *dst++ = 'L';
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      *dst++ = '"';
      while (n-- > 0 && *src)
        {
          WORD c = *src++;
          switch (c)
    	{
    	case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
    	case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
    	case '\t': *dst++ = '\\'; *dst++ = 't'; break;
    	case '"': *dst++ = '\\'; *dst++ = '"'; break;
    	case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
    	default:
    	  if (c >= ' ' && c <= 126)
    	    *dst++ = c;
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	    {
    	      *dst++ = '\\';
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      if (*src)
        {
          *dst++ = '.';
          *dst++ = '.';
          *dst++ = '.';
        }
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
      return res;
    }
    
    /* ---------------------------------------------------------------------- */
    
    LPSTR
    debugstr_w (LPCWSTR s)
    {
      return debugstr_wn (s, 80);
    }
    
    /* ---------------------------------------------------------------------- */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /* This routine returns a nicely formated name of the resource res
       If the resource name is a string, it will return '<res-name>'
       If it is a number, it will return #<4-digit-hex-number> */
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    LPSTR debugres_a( LPCSTR res )
    {
        char resname[10];
        if (HIWORD(res)) return debugstr_a(res);
        sprintf(resname, "#%04x", LOWORD(res));
        return debugstr_a (resname);
    }
    
    LPSTR debugres_w( LPCWSTR res )
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    {
        char resname[10];
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        if (HIWORD(res)) return debugstr_w(res);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
        sprintf(resname, "#%04x", LOWORD(res));
        return debugstr_a (resname);
    }
    
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    /* ---------------------------------------------------------------------- */
    
    void debug_dumpstr (LPCSTR s)
    {
      fputc ('"', stderr);
      while (*s)
        {
          switch (*s)
    	{
    	case '\\':
    	case '"':
    	  fputc ('\\', stderr);
    	  fputc (*s, stderr);
    	  break;
    	case '\n':
    	  fputc ('\\', stderr);
    	  fputc ('n', stderr);
    	  break;
    	case '\r':
    	  fputc ('\\', stderr);
    	  fputc ('r', stderr);
    	  break;
    	case '\t':
    	  fputc ('\\', stderr);
    	  fputc ('t', stderr);
    	  break;
    	default:
    	  if (*s<' ')
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	    fprintf (stderr, "\\0x%02x", *s);
    
    Alexandre Julliard's avatar
    Alexandre Julliard committed
    	  else
    	    fputc (*s, stderr);
    	}
          s++;
        }
      fputc ('"', stderr);
    }
    
    
    /* ---------------------------------------------------------------------- */
    
    int dbg_printf(const char *format, ...)
    {
        int ret;
        va_list valist;
    
        va_start(valist, format);
        ret = vfprintf(stderr, format, valist);
        va_end(valist);
        return ret;
    }
    
    
    
    
    /*--< Function >---------------------------------------------------------
    **  
    **              debugstr_hex_dump
    **              
    **  Description:
    **      This function creates a hex dump, with a readable ascii
    **  section, for displaying memory.
    **  
    **  Parameters:
    **      1.  ptr             Pointer to memory
    **      2.  len             How much to dump.
    **
    **  Returns:
    **    Temporarily allocated buffer, with the hex dump in it.
    **  Don't rely on this pointer being around for very long, just
    **  long enough to use it in a TRACE statement; e.g.:
    **  TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x)));
    **          
    **-------------------------------------------------------------------------*/
    LPSTR 
    debugstr_hex_dump (const void *ptr, int len)
    {
        /* Locals */
        char          dumpbuf[59];
        char          charbuf[20];
        char          tempbuf[8];
        const char    *p;
        int           i;
        unsigned int  nosign;
        LPSTR         dst;
        LPSTR         outptr;
    
    /* Begin function dbg_hex_dump */
    
        /*-----------------------------------------------------------------------
        **  Allocate an output buffer
        **      A reasonable value is one line overhand (80 chars), and
        **      then one line (80) for every 16 bytes.
        **---------------------------------------------------------------------*/
        outptr = dst = gimme1 ((len * (80 / 16)) + 80);
    
        /*-----------------------------------------------------------------------
        **  Loop throught the input buffer, one character at a time
        **---------------------------------------------------------------------*/
        for (i = 0, p = ptr; (i < len); i++, p++)
        {
    
            /*-------------------------------------------------------------------
            **  If we're just starting a line, 
            **      we need to possibly flush the old line, and then
            **      intialize the line buffer.
            **-----------------------------------------------------------------*/
            if ((i % 16) == 0)
            {
                if (i)
                {
                    sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
                    outptr += strlen(outptr);
                }
                sprintf (dumpbuf, "%04x: ", i);
                strcpy (charbuf, "");
            }
    
            /*-------------------------------------------------------------------
            **  Add the current data byte to the dump section.
            **-----------------------------------------------------------------*/
            nosign = (unsigned char) *p;
            sprintf (tempbuf, "%02X", nosign);
    
            /*-------------------------------------------------------------------
            **  If we're two DWORDS through, add a hyphen for readability,
            **      if it's a DWORD boundary, add a space for more
            **      readability.
            **-----------------------------------------------------------------*/
            if ((i % 16) == 7)
                strcat(tempbuf, " - ");
            else if ( (i % 4) == 3)
                strcat(tempbuf, " ");
            strcat (dumpbuf, tempbuf);
    
            /*-------------------------------------------------------------------
            **  Add the current byte to the character display part of the
            **      hex dump
            **-----------------------------------------------------------------*/
            sprintf (tempbuf, "%c", isprint(*p) ? *p : '.');
            strcat (charbuf, tempbuf);
        }
    
        /*-----------------------------------------------------------------------
        **  Flush the last line, if any
        **---------------------------------------------------------------------*/
        if (i > 0)
        {
            sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
            outptr += strlen(outptr);
        }
    
        return(dst);
    } /* End function dbg_hex_dump */