Skip to content
Snippets Groups Projects
Forked from wine / wine
172406 commits behind the upstream repository.
debugstr.c 7.79 KiB
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "debugstr.h"
#include "debugtools.h"
#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);
  *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);
	    }
	}
    }
  *dst++ = '"';
  if (*src)
    {
      *dst++ = '.';
      *dst++ = '.';
      *dst++ = '.';
    }
  *dst = '\0';
  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';
  *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;
	  else 
	    {
	      *dst++ = '\\';
              sprintf(dst,"%04x",c);
              dst+=4;
	    }
	}
    }
  *dst++ = '"';
  if (*src)
    {
      *dst++ = '.';
      *dst++ = '.';
      *dst++ = '.';
    }
  *dst = '\0';
  return res;
}

/* ---------------------------------------------------------------------- */

LPSTR
debugstr_w (LPCWSTR s)
{
  return debugstr_wn (s, 80);
}

/* ---------------------------------------------------------------------- */
/* 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> */
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 )
{
    char resname[10];
    if (HIWORD(res)) return debugstr_w(res);
    sprintf(resname, "#%04x", LOWORD(res));
    return debugstr_a (resname);
}

/* ---------------------------------------------------------------------- */

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<' ')
	    fprintf (stderr, "\\0x%02x", *s);
	  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 */