gambas-source-code/main/lib/debug/print.c
Benoît Minisini 91556cac06 [DEVELOPMENT ENVIRONMENT]
* NEW: The debug window has a button to switch between "normal view" and 
  "symbol view". In "normal view", array and collection contents are
  displayed. If the object is not an array or a collection, then all
  non-hidden symbols are displayed. In "symbol view", all objects symbols 
  are displayed, whatever the object type is.

[INTERPRETER]
* NEW: The debugger now can display collection-like objects. An object can 
  be displayed like a collection if it has a Count property, is enumerable,
  has a _get special method taking a string, and has a Key property that 
  returns the key of the last enumerated element.

[GB.DEBUG]
* NEW: The debugger now can display collection-like objects. An object can 
  be displayed like a collection if it has a Count property, is enumerable,
  has a _get special method taking a string, and has a Key property that 
  returns the key of the last enumerated element.

[GB.FORM]
* BUG: GridView.Clear resets the height of all rows to the default value.


git-svn-id: svn://localhost/gambas/trunk@4558 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2012-03-17 02:05:31 +00:00

508 lines
9.4 KiB
C

/***************************************************************************
print.c
(c) 2000-2012 Benoît Minisini <gambas@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __PRINT_C
// Do not include gbx_debug.h
#define __GBX_DEBUG_H
#include "gb_common.h"
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include "gb_error.h"
#include "gbx_type.h"
#include "gb_limit.h"
#include "gbx_class.h"
#include "gbx_object.h"
#include "gbx_local.h"
#include "gbx_variant.h"
#include "gambas.h"
#include "print.h"
static FILE *_where;
static int _level;
static void print_value(VALUE *value);
static void print_string(const char *s, int len)
{
int i;
uchar c;
fputc('"', _where);
for (i = 0; i < len; i++)
{
if (i > (DEBUG_OUTPUT_MAX_SIZE - 8))
{
fprintf(_where, "...");
break;
}
c = s[i];
if (c < 32)
{
if (c == 10)
fprintf(_where, "\\n");
else if (c == 13)
fprintf(_where, "\\r");
else if (c == 9)
fprintf(_where, "\\t");
else
fprintf(_where, "\\x%02X", c);
}
else if (c == '\"')
{
fprintf(_where, "\\\"");
}
else
{
fputc(c, _where);
}
}
fputc('"', _where);
}
#if 0
static void new_line(void)
{
int i;
fputc('\t', _where);
for (i = 1; i < _level; i++)
fprintf(_where, " ");
}
#endif
static void print_object(void *object)
{
//int i;
//char *key;
//VALUE value;
//long len;
fprintf(_where, "(%s %p)", OBJECT_class(object)->name, object);
/*
if (GB.Is(object, GB.FindClass("Collection")))
{
//if (_level > 1)
// new_line();
//fprintf(_where, "%s", OBJECT_class(object)->name);
GB_DEBUG.EnumCollection(object, NULL, NULL, NULL);
for (i = 0; i < 8; i++)
{
if (GB_DEBUG.EnumCollection(object, (GB_VARIANT *)&value, &key, &len))
break;
new_line();
fprintf(_where, "[");
print_string(key, len);
fprintf(_where, "] = ");
print_value(&value);
}
if (GB.Collection.Count(object) > 8)
{
new_line();
fprintf(_where, "... #%ld", GB.Collection.Count(object));
}
}
else if (GB.Is(object, GB.FindClass("Array")))
{
//if (_level > 1)
// new_line();
//fprintf(_where, "%s", OBJECT_class(object)->name);
for (i = 0; i < GB.Array.Count(object); i++)
{
if (i >= 8 && i < (GB.Array.Count(object) - 1))
{
new_line();
fprintf(_where, "...");
i = GB.Array.Count(object) - 1;
}
new_line();
GB_DEBUG.GetArrayValue(object, i, (GB_VALUE *)&value);
fprintf(_where, "[%d] = ", i);
print_value(&value);
}
}
*/
}
static void print_value(VALUE *value)
{
static void *jump[16] = {
&&__VOID, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
&&__STRING, &&__STRING, &&__POINTER, &&__VARIANT, &&__FUNCTION, &&__CLASS, &&__NULL
};
VALUE conv;
char *addr;
int len;
//*more = FALSE;
if (_level >= 4)
{
fprintf(_where, "...");
return;
}
_level++;
__CONV:
if (TYPE_is_object(value->type))
goto __OBJECT;
else
goto *jump[value->type];
__NULL:
fprintf(_where, "NULL");
goto __RETURN;
__BOOLEAN:
fprintf(_where, value->_boolean.value ? "TRUE" : "FALSE");
goto __RETURN;
__BYTE:
__SHORT:
__INTEGER:
fprintf(_where, "%d", value->_integer.value);
goto __RETURN;
__LONG:
fprintf(_where, "%" PRId64, value->_long.value);
goto __RETURN;
__DATE:
GB_DEBUG.FormatDate(GB.SplitDate((GB_DATE *)value), LF_STANDARD, NULL, 0, &addr, &len);
goto __PRINT;
__SINGLE:
GB_DEBUG.FormatNumber(value->_single.value, LF_SHORT_NUMBER, NULL, 0, &addr, &len, TRUE);
goto __PRINT;
__FLOAT:
GB_DEBUG.FormatNumber(value->_float.value, LF_STANDARD, NULL, 0, &addr, &len, TRUE);
__PRINT:
fprintf(_where, "%.*s", (int)len, addr);
goto __RETURN;
__STRING:
print_string(value->_string.addr + value->_string.start, value->_string.len);
goto __RETURN;
__OBJECT:
if (!value->_object.object)
goto __NULL;
//*more = !CLASS_is_native(OBJECT_class(value->_object.object));
print_object(value->_object.object);
goto __RETURN;
__VARIANT:
conv = *value;
value = &conv;
GB.Conv((GB_VALUE *)value, (GB_TYPE)value->_variant.vtype);
//VARIANT_undo(value);
goto __CONV;
__VOID:
fprintf(_where, "VOID");
goto __RETURN;
__CLASS:
{
CLASS *class = value->_class.class;
//*more = (!CLASS_is_native(class) && class->load->n_stat > 0);
fprintf(_where, "(%s)", class->name);
goto __RETURN;
}
__POINTER:
fprintf(_where, "(%p)", value->_pointer.value);
goto __RETURN;
__FUNCTION:
fprintf(_where, "FUNCTION");
goto __RETURN;
__RETURN:
_level--;
}
void PRINT_value(FILE *where, VALUE *value, bool format)
{
char *pval;
int lpval;
if (format)
{
_where = where;
_level = 0;
print_value(value);
//fputc('\n', _where);
}
else
{
GB_DEBUG.ToString((GB_VALUE *)value, &pval, &lpval);
fwrite(pval, sizeof(char), lpval, where);
}
}
void PRINT_symbol(FILE *where, const char *sym, int len)
{
GB_VALUE value;
_where = where;
if (GB_DEBUG.GetValue(sym, len, (GB_VARIANT *)(void *)&value))
{
fprintf(_where, "Unknown symbol");
return;
}
print_value((VALUE *)&value);
}
void PRINT_object(FILE *where, VALUE *value)
{
VALUE conv;
void *object;
int index;
int count = 0;
CLASS *class, *real_class;
CLASS_DESC_SYMBOL *cd;
char *key;
int len;
bool static_class;
int access;
int *dim;
_where = where;
if (value->type == T_VARIANT)
{
conv = *value;
value = &conv;
GB.Conv((GB_VALUE *)value, (GB_TYPE)value->_variant.vtype);
}
if (value->type < T_OBJECT && value->type != T_CLASS)
{
//fprintf(_where, "\n");
return;
}
real_class = NULL;
if (value->type == T_CLASS)
{
object = value->_class.class;
class = (CLASS *)object;
static_class = TRUE;
real_class = NULL;
}
else
{
object = value->_object.object;
real_class = (CLASS *)GB.GetClass(object);
if (value->type == T_OBJECT)
class = real_class;
else
class = value->_object.class;
if (real_class == class)
real_class = NULL;
/*if (value->type != T_OBJECT && value->_object.class->is_virtual)
{
}
else
class = (CLASS *)GB.GetClass(object);*/
//fprintf(stderr, "PRINT_object: %s %s\n", class->name, value->_object.class->name);
static_class = FALSE;
}
if (!object)
return;
fprintf(_where, "%s ", class->name);
if (real_class) fprintf(_where, "%s", real_class->name);
fputc(' ', _where);
access = GB_DEBUG.GetObjectAccessType(object, class, &count);
/*if (GB.Is(object, GB.FindClass("Collection")))
{
GB_COLLECTION_ITER iter;
count = GB.Collection.Count(object);
fprintf(_where, "C [%d]", count);
GB_DEBUG.EnumCollection(object, &iter, NULL, NULL, NULL);
for (i = 0; i < count; i++)
{
if (GB_DEBUG.EnumCollection(object, &iter, (GB_VARIANT *)&conv, &key, &len))
break;
fprintf(_where, " ");
print_string(key, len);
}
//fprintf(_where, "\n");
return;
}*/
if (access == GB_DEBUG_ACCESS_COLLECTION)
{
char *key = NULL;
fprintf(_where, "C: [%d]", count);
GB_DEBUG.EnumKeys(object, &key);
while (key)
{
fprintf(_where, " ");
print_string(key, STRING_length(key));
GB_DEBUG.EnumKeys(object, &key);
}
fprintf(_where, " ");
}
else if (GB.Is(object, GB.FindClass("Array")))
{
dim = GB_DEBUG.GetArrayBounds(object);
if (!dim)
fprintf(_where, "A: [%d] ", count);
else
{
fprintf(_where, "A: [");
for(;;)
{
len = *dim++;
if (len > 0)
fprintf(_where, "%d,", len);
else
{
fprintf(_where, "%d", -len);
break;
}
}
fprintf(_where, "] ");
}
}
else if (access == GB_DEBUG_ACCESS_ARRAY)
{
fprintf(_where, "A: [%d] ", count);
}
if (!class->is_virtual && real_class)
class = real_class;
fprintf(_where, "S:");
index = 0;
for(;;)
{
cd = (CLASS_DESC_SYMBOL *)GB_DEBUG.GetNextSortedSymbol(class, &index);
if (!cd)
break;
key = cd->name;
if (cd->len == 0 || (cd->len == 1 && key[0] == '.'))
continue;
switch(CLASS_DESC_get_type(cd->desc))
{
case CD_STATIC_VARIABLE:
case CD_STATIC_PROPERTY:
case CD_STATIC_PROPERTY_READ:
case CD_CONSTANT:
fprintf(_where, " %.*s", cd->len, key);
break;
}
}
if (count > 0 && static_class)
fprintf(_where, " [%d]", count);
fprintf(_where, " D:");
if (!static_class)
{
index = 0;
for(;;)
{
cd = (CLASS_DESC_SYMBOL *)GB_DEBUG.GetNextSortedSymbol(class, &index);
if (!cd)
break;
key = cd->name;
if (cd->len == 0 || (cd->len == 1 && key[0] == '.'))
continue;
switch(CLASS_DESC_get_type(cd->desc))
{
case CD_VARIABLE:
case CD_PROPERTY:
case CD_PROPERTY_READ:
case CD_STRUCT_FIELD:
fprintf(_where, " %.*s", cd->len, key);
break;
}
}
if (count > 0)
fprintf(_where, " [%d]", count);
}
//fprintf(_where, "\n");
}