Logo Search packages:      
Sourcecode: gambas version File versions  Download package

gbx_c_class.c

/***************************************************************************

  CClass.c

  The native class Class needed for introspection

  (c) 2000-2004 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

#define __GBX_C_CLASS_C

#include <ctype.h>

#include "gb_common.h"
#include "gbx_api.h"
#include "gambas.h"
#include "gbx_library.h"
#include "gbx_project.h"
#include "gbx_class.h"
#include "gbx_class_desc.h"
#include "gbx_exec.h"

#include "gbx_object.h"
#include "gbx_c_class.h"

PRIVATE CLASS_DESC_SYMBOL *_current_symbol = NULL;

PRIVATE CLASS_DESC *get_desc(CLASS *class, const char *name)
{
  long index;

  index = CLASS_find_symbol(class, name);
  if (index == NO_SYMBOL)
  {
    GB_Error((char *)E_NSYMBOL, name, class->name);
    return NULL;
  }
  else
    return class->table[index].desc;
}

/**************************************************************************************************/

BEGIN_METHOD(library_get, GB_STRING name)

  const char *name = GB_ToZeroString(ARG(name));
  LIBRARY *lib;

  lib = LIBRARY_find(name);

  if (lib == NULL)
  {
    GB_Error("Unknown library '&1'", name);
    return;
  }

  if (!LIBRARY_is_loaded(lib))
  {
    GB_Error("Library is not loaded");
    return;
  }

  GB_ReturnObject(lib);

END_METHOD


BEGIN_PROPERTY(library_count)

  GB_ReturnInt(LIBRARY_count);

END_PROPERTY


BEGIN_METHOD_VOID(library_next)

  LIBRARY **plib = (LIBRARY **)GB_GetEnum();

  *plib = LIBRARY_next(*plib);
  if (*plib == NULL)
    GB_StopEnum();
  else
    GB_ReturnObject(*plib);

END_METHOD


BEGIN_PROPERTY(library_name)

  GB_ReturnConstZeroString(OBJECT(LIBRARY)->name);

END_PROPERTY


BEGIN_PROPERTY(library_path)

  GB_ReturnString(PROJECT_lib_path);

END_PROPERTY


BEGIN_METHOD(library_load, GB_STRING name)

  const char *name = GB_ToZeroString(ARG(name));
  LIBRARY *lib;

  lib = LIBRARY_find(name);
  if (!lib)
    lib = LIBRARY_create(name);
  if (!LIBRARY_is_loaded(lib))
    LIBRARY_load(lib);

  GB_ReturnObject(lib);

END_METHOD


BEGIN_METHOD_VOID(library_unload)

  LIBRARY_unload(OBJECT(LIBRARY));

END_METHOD




/**************************************************************************************************/

BEGIN_METHOD(class_get, GB_STRING name)

  const char *name = GB_ToZeroString(ARG(name));
  CLASS *class = NULL;

  if (name != NULL)
    class = CLASS_look(name);

  if (class == NULL)
  {
    GB_Error("Unknown class '&1'", name);
    return;
  }

  if (!class->state)
  {
    GB_Error("Class is not loaded");
    return;
  }

  GB_ReturnObject(class);

END_METHOD


BEGIN_METHOD(class_load, GB_STRING name)

  CLASS *class;

  class = CLASS_get(GB_ToZeroString(ARG(name)));
  GB_ReturnObject(class);

END_METHOD


BEGIN_PROPERTY(class_name)

  GB_ReturnConstZeroString(OBJECT(CLASS)->name);

END_PROPERTY


BEGIN_METHOD_VOID(class_next)

  TABLE *table = CLASS_get_table();
  long *index = (long *)GB_GetEnum();
  CLASS *class;

  for(;;)
  {
    if (*index >= TABLE_count(table))
    {
      GB_StopEnum();
      break;
    }

    class = ((CLASS_SYMBOL *)TABLE_get_symbol(table, *index))->class;
    (*index)++;

    if (class->state)
    {
      GB_ReturnObject(class);
      break;
    }
  }

END_METHOD


BEGIN_PROPERTY(class_count)

  GB_ReturnInt(CLASS_count());

END_PROPERTY


BEGIN_PROPERTY(class_object_count)

  GB_ReturnInt(OBJECT(CLASS)->count);

END_PROPERTY


BEGIN_PROPERTY(class_hidden)

  GB_ReturnBoolean(*(OBJECT(CLASS)->name) == '.');

END_PROPERTY


BEGIN_PROPERTY(class_native)

  GB_ReturnBoolean(CLASS_is_native(OBJECT(CLASS)));

END_PROPERTY

/*
BEGIN_PROPERTY(class_library)

  GB_ReturnObject(OBJECT(CLASS)->belong);

END_PROPERTY
*/

BEGIN_PROPERTY(class_parent)

  GB_ReturnObject(OBJECT(CLASS)->parent);

END_PROPERTY



/**************************************************************************************************/

BEGIN_PROPERTY(class_symbols_count)

  GB_ReturnInt(OBJECT(CLASS)->n_desc);

END_PROPERTY


BEGIN_METHOD_VOID(class_symbols_next)

  CLASS *class = OBJECT(CLASS);
  long *index = (long *)GB_GetEnum();

/*_HIDDEN:*/

  if (*index >= class->n_desc)
  {
    GB_StopEnum();
    return;
  }

  /*cd = class->table[*index].desc;*/

  /*if (cd->symbol.name[0] == '$' || cd->symbol.name[0] == '@')
    goto _HIDDEN;*/

  /*GB_ReturnObject(&class->table[class->table[*index].sort].ref);*/
  GB_ReturnConstZeroString(class->table[class->table[*index].sort].desc->gambas.name);
  (*index)++;

END_METHOD


BEGIN_METHOD(class_symbol_get, GB_STRING name)

  CLASS *class = OBJECT(CLASS);
  CLASS_DESC_SYMBOL *cd = NULL;
  const char *name = GB_ToZeroString(ARG(name));

  if (name != NULL)
    cd = CLASS_get_symbol(class, name);

  if (cd == NULL)
  {
    GB_Error("Unknown symbol '&1'", name);
    return;
  }

  _current_symbol = cd;
  GB_ReturnObject(class);

END_METHOD


BEGIN_PROPERTY(class_instance)

  GB_ReturnObject(OBJECT(CLASS)->instance);

END_PROPERTY



/**************************************************************************************************/

BEGIN_PROPERTY(symbol_name)

  GB_ReturnConstString(_current_symbol->name, _current_symbol->len);

END_PROPERTY


BEGIN_PROPERTY(symbol_kind)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  switch(CLASS_DESC_get_type(cds->desc))
  {
    case CD_VARIABLE:
    case CD_STATIC_VARIABLE:
      GB_ReturnInt(1);
      return;

    case CD_PROPERTY:
    case CD_PROPERTY_READ:
    case CD_STATIC_PROPERTY:
    case CD_STATIC_PROPERTY_READ:
      GB_ReturnInt(2);
      return;

    case CD_METHOD:
    case CD_STATIC_METHOD:
      GB_ReturnInt(3);
      return;

    case CD_EVENT:
      GB_ReturnInt(4);
      return;

    case CD_CONSTANT:
      GB_ReturnInt(5);
      return;
      
    default:
      GB_ReturnInt(0);
      return;
  }

END_PROPERTY


BEGIN_PROPERTY(symbol_static)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  GB_ReturnBoolean(index(CD_STATIC_LIST, CLASS_DESC_get_type(cds->desc)) != NULL);

END_PROPERTY


BEGIN_PROPERTY(symbol_hidden)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  GB_ReturnBoolean(*cds->name == '_');

END_PROPERTY


BEGIN_PROPERTY(symbol_read_only)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  switch (CLASS_DESC_get_type(cds->desc))
  {
    case CD_PROPERTY:
    case CD_STATIC_PROPERTY:
      GB_ReturnBoolean(FALSE);
      break;

    default:
      GB_ReturnBoolean(TRUE);
      break;
  }

END_PROPERTY


BEGIN_PROPERTY(symbol_type)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  GB_ReturnConstZeroString(TYPE_to_string(cds->desc->property.type)); /* Valable pour tout symbole */

END_PROPERTY


BEGIN_PROPERTY(symbol_signature)

  CLASS_DESC_SYMBOL *cds = _current_symbol;

  GB_ReturnConstZeroString(CLASS_DESC_get_signature(cds->desc));

END_METHOD


BEGIN_PROPERTY(symbol_value)

  CLASS_DESC *desc = _current_symbol->desc;

  if (CLASS_DESC_get_type(desc) != CD_CONSTANT)
  {
    GB_ReturnNull();
    return;
  }

  if (desc->constant.type == T_STRING)
    GB_ReturnConstZeroString(desc->constant.value._string);
  else
    GB_ReturnPtr(desc->constant.type, (void *)&desc->constant.value);

END_PROPERTY




/**************************************************************************************************/


BEGIN_METHOD(object_get_property, GB_OBJECT object; GB_STRING property)

  const char *name;
  CLASS_DESC *desc;
  CLASS *class;
  char type;
  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  class = OBJECT_class(object);
  name = GB_ToZeroString(ARG(property));
  desc = get_desc(class, name);
  if (!desc)
    return;

  type = CLASS_DESC_get_type(desc);

  if (type == CD_PROPERTY || type == CD_PROPERTY_READ)
  {
    if (desc->property.native)
    {
      if (EXEC_call_native(desc->property.read, object, desc->property.type, 0))
        return;
    }
    else
    {
      EXEC.class = class;
      EXEC.object = object;
      EXEC.drop = FALSE;
      EXEC.nparam = 0;
      EXEC.native = FALSE;
      EXEC.index = (long)desc->property.read;
      //EXEC.func = &class->load->func[(long)desc->property.read];

      EXEC_function_keep();

      TEMP = *RP;
      RP->type = T_VOID;
    }
  }
  else if (type == CD_STATIC_PROPERTY || type == CD_STATIC_PROPERTY_READ)
    GB_Error((char *)E_STATIC, class->name, name);
  else
    GB_Error((char *)E_NPROPERTY, class->name, name);

END_METHOD


BEGIN_METHOD(object_set_property, GB_OBJECT object; GB_STRING property; GB_VARIANT value)

  const char *name;
  CLASS_DESC *desc;
  CLASS *class;
  char type;
  void *object = VARG(object);
  VALUE *value = (VALUE *)ARG(value);

  if (GB_CheckObject(object))
    return;

  class = OBJECT_class(object);
  name = GB_ToZeroString(ARG(property));
  desc = get_desc(class, name);
  if (!desc)
    return;

  type = CLASS_DESC_get_type(desc);

  if (type == CD_PROPERTY)
  {
    if (desc->property.native)
    {
      VALUE_conv(value, desc->property.type);

      if (EXEC_call_native(desc->property.write, object, 0, value))
        return;
    }
    else
    {
      *SP = *value;
      BORROW(SP);
      SP++;

      EXEC.class = class;
      EXEC.object = object;
      EXEC.drop = FALSE;
      EXEC.nparam = 1;
      EXEC.native = FALSE;
      EXEC.index = (long)desc->property.write;
      //EXEC.func = &class->load->func[(long)desc->property.write];

      EXEC_function();

      /*VALUE_write(value, OBJECT_get_prop_addr(object, desc), desc->property.type);*/
    }
  }
  else if (type == CD_PROPERTY_READ)
    GB_Error((char *)E_NWRITE);
  else if (type == CD_STATIC_PROPERTY || type == CD_STATIC_PROPERTY_READ)
    GB_Error((char *)E_STATIC, class->name, name);
  else
    GB_Error((char *)E_NPROPERTY, class->name, name);

END_METHOD


BEGIN_METHOD(object_attach, GB_OBJECT object; GB_OBJECT parent; GB_STRING name)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  OBJECT_attach(object, VARG(parent), GB_ToZeroString(ARG(name)));

END_METHOD



BEGIN_METHOD(object_detach, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  OBJECT_detach(object);

END_METHOD


BEGIN_METHOD(object_get_parent, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  GB_ReturnObject(OBJECT_parent(object));

END_METHOD


BEGIN_METHOD(object_class, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  GB_ReturnConstZeroString(OBJECT_class(object)->name);

END_METHOD


BEGIN_METHOD(object_call, GB_OBJECT object; GB_STRING method; GB_VARIANT param[0])

  int i;
  int np = GB_NParam();
  char *name = GB_ToZeroString(ARG(method));
  void *object = VARG(object);
  GB_FUNCTION func;
  CLASS *class;

  if (GB_CheckObject(object))
    return;

  STACK_check(GB_NParam());

  for (i = 0; i < np; i++)
  {
    *SP = SP[-np];
    PUSH();
  }

  class = OBJECT_class(object);

  if (GB_GetFunction(&func, object, name, NULL))
  {
    GB_Error((char *)E_NSYMBOL, name, class->name);
    return;
  }

  GB_Call(&func, np, FALSE);

END_METHOD


BEGIN_METHOD(object_is_valid, GB_OBJECT object)

  void *object = VARG(object);
  bool res;

  if (object == NULL)
    res = FALSE;
  else
    res = !(*((OBJECT *)object)->class->check)(object);
  
  GB_ReturnBoolean(res);

END_METHOD


BEGIN_METHOD(object_lock, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  OBJECT_lock(object, TRUE);

END_METHOD


BEGIN_METHOD(object_unlock, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  OBJECT_lock(object, FALSE);

END_METHOD


BEGIN_METHOD(object_is_locked, GB_OBJECT object)

  void *object = VARG(object);

  if (GB_CheckObject(object))
    return;

  GB_ReturnBoolean(OBJECT_is_locked(object));

END_METHOD


/**************************************************************************************************/


PUBLIC GB_DESC NATIVE_Symbol[] =
{
  GB_DECLARE(".Symbol", 0), GB_VIRTUAL_CLASS(),

  GB_PROPERTY_READ("Name", "s", symbol_name),
  GB_PROPERTY_READ("Kind", "i", symbol_kind),
  GB_PROPERTY_READ("Type", "s", symbol_type),
  GB_PROPERTY_READ("ReadOnly", "b", symbol_read_only),
  GB_PROPERTY_READ("Hidden", "b", symbol_hidden),
  GB_PROPERTY_READ("Signature", "s", symbol_signature),
  GB_PROPERTY_READ("Static", "b", symbol_static),
  GB_PROPERTY_READ("Value", "v", symbol_value),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_ClassSymbols[] =
{
  GB_DECLARE(".ClassSymbols", 0), GB_VIRTUAL_CLASS(),

  GB_METHOD("_next", "s", class_symbols_next, NULL),
  GB_PROPERTY_READ("Count", "i", class_symbols_count),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_Libraries[] =
{
  GB_DECLARE("Components", 0),  GB_VIRTUAL_CLASS(),

  GB_STATIC_METHOD("_next", "Component", library_next, NULL),
  GB_STATIC_METHOD("_get", "Component", library_get, "(Name)s"),
  GB_STATIC_PROPERTY_READ("Count", "i", library_count),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_Library[] =
{
  GB_DECLARE("Component", 0),  GB_VIRTUAL_CLASS(),

  GB_STATIC_METHOD("_get", "Component", library_get, "(Name)s"),
  GB_STATIC_PROPERTY_READ("Path", "s", library_path),

  GB_STATIC_METHOD("Load", "Component", library_load, "(Name)s"),

  GB_PROPERTY_READ("Name", "s", library_name),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_Classes[] =
{
  GB_DECLARE("Classes", 0),  GB_VIRTUAL_CLASS(),

  GB_STATIC_METHOD("_next", "Class", class_next, NULL),
  GB_STATIC_METHOD("_get", "Class", class_get, "(Name)s"),
  GB_STATIC_PROPERTY_READ("Count", "i", class_count),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_Class[] =
{
  GB_DECLARE("Class", 0),  GB_VIRTUAL_CLASS(),

  GB_STATIC_METHOD("Load", "Class", class_load, "(Name)s"),

  GB_METHOD("_get", ".Symbol", class_symbol_get, "(Name)s"),
  GB_PROPERTY_SELF("Symbols", ".ClassSymbols"),
  
  GB_PROPERTY_READ("Name", "s", class_name),
  GB_PROPERTY_READ("Hidden", "b", class_hidden),
  GB_PROPERTY_READ("Native", "b", class_native),
  GB_PROPERTY_READ("Parent", "Class", class_parent),
  //GB_PROPERTY_READ("Library", "Library", class_library),
  GB_PROPERTY_READ("Count", "i", class_object_count),
  GB_PROPERTY_READ("Instance", "o", class_instance),

  /*GB_METHOD("New", "Object", class_new, "."),*/

  GB_CONSTANT("Variable", "i", 1),
  GB_CONSTANT("Property", "i", 2),
  GB_CONSTANT("Method", "i", 3),
  GB_CONSTANT("Event", "i", 4),
  GB_CONSTANT("Constant", "i", 5),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_Object[] =
{
  GB_DECLARE("Object", 0),  GB_VIRTUAL_CLASS(),

  GB_STATIC_METHOD("GetProperty", "v", object_get_property, "(Object)o(Property)s"),
  GB_STATIC_METHOD("SetProperty", NULL, object_set_property, "(Object)o(Property)s(Value)v"),
  GB_STATIC_METHOD("Attach", NULL, object_attach, "(Object)o(Parent)o(Name)s"),
  GB_STATIC_METHOD("Detach", NULL, object_detach, "(Object)o"),
  GB_STATIC_METHOD("Class", "s", object_class, "(Object)o"),
  GB_STATIC_METHOD("Type", "s", object_class, "(Object)o"),
  GB_STATIC_METHOD("Parent", "o", object_get_parent, "(Object)o"),
  GB_STATIC_METHOD("Call", "v", object_call, "(Object)o(Method)s(Parameters)."),
  GB_STATIC_METHOD("IsValid", "b", object_is_valid, "(Object)o"),
  GB_STATIC_METHOD("Lock", NULL, object_lock, "(Object)o"),
  GB_STATIC_METHOD("Unlock", NULL, object_unlock, "(Object)o"),
  GB_STATIC_METHOD("IsLocked", "b", object_is_locked, "(Object)o"),

  GB_END_DECLARE
};




Generated by  Doxygen 1.6.0   Back to index