#define DEBERROR(x) debug_message(x); return 0;

/*
 * In dieser Datei stehen diverse Routinen die beim Programmieren des
 * base-Debuggers nuetlich sind.
 */

void printflags( char *buffer, uint32 flags )
 {
  // *** Schreibt die Flags in den Buffer.
  buffer[0] = 0x00;
  strcat(buffer,"[");

#define APPEND_WS { strcat(buffer," "); }
  if (flags & NAME_INHERITED)
      { strcat(buffer,"i"); } else APPEND_WS;
  if (flags & TYPE_MOD_STATIC)
      { strcat(buffer,"S"); } else APPEND_WS;
  if (flags & TYPE_MOD_NO_MASK)
      { strcat(buffer,"N"); } else APPEND_WS;

  if (flags & TYPE_MOD_PRIVATE) // *** Pirivate und public schliessen sich aus
      { strcat(buffer,"P"); } else
  if (flags & TYPE_MOD_PUBLIC)
      { strcat(buffer,"p"); } else APPEND_WS;
  if (flags & TYPE_MOD_VARARGS)
      { strcat(buffer,"V"); } else APPEND_WS;
  if (flags & TYPE_MOD_VIRTUAL)
      { strcat(buffer,"v"); } else APPEND_WS;
  if (flags & TYPE_MOD_PROTECTED)
      { strcat(buffer,"p"); } else APPEND_WS;
  strcat(buffer,"]");
 }

struct function *locate_function( char *name, struct program *prog )
{
 // *** Sucht die Funktion mit dem Namen name im programm prog.
 int lauf1;
 int lauf2;
 struct function *temp;

 if (name == 0)
   {
    debug_message("*** DebugError: locate_function.name == 0 !\n");
    return 0;
   }
 if (prog->funktionsdaten == 0)
   {
    debug_message("*** DebugError: locate_funtion.prog->funktionsdaten == 0 !\n");
    return 0;
   }

 for (lauf1 = 0; lauf1 < prog->num_functions ; lauf1++)
  {
   if (prog->funktionsdaten[lauf1].name == 0)
    {
     debug_message("*** DebugError: locate_funtion.prog->funktionsdaten[lauf1].name == 0");
     return 0;
    }

   if (strcmp(prog->funktionsdaten[lauf1].name,name) == 0)
    { // *** Die Funktion hat den richtigen Namen !
     if (prog->funktionsdaten[lauf1].flags & NAME_INHERITED)
      { // *** MIST. Das Dings is inherited. Nun die Inherits durchsuchen.
       for (lauf2 = 0; lauf2 < prog->num_inherited; lauf2++)
	{
	 temp = locate_function(name,prog->inherit[lauf2].prog);
	 // *** Solange suchen, bis wir die richtige Funktion erwischen.
	 if (temp != 0)
	  { return temp; }
	}
      } else
      { // *** Da ham wir die Funktion. Zurueckspringen.
       return &(prog->funktionsdaten[lauf1]);
      }	
    }
  }
 return 0;
}

struct svalue *get_global_variable_pointer( char *name )
 {
  // *** Gibt den zeiger auf die Svalue einer Objektglobalen Variablen
  // *** zurueck. Wenn eine Solche Variable nicht exisitert, wird 0
  // *** zurueckgegeben.
  int lauf1;

  if ( name == 0 )
      { DEBERROR("*** DebugError: name == 0 !\n"); }

  for (lauf1 = 0; lauf1 < current_object->prog->num_variables; lauf1++)
   {
    if (current_object->prog->variable_names[lauf1].name == 0)
     {
      debug_message("*** DebugError: get_global_variable_pointer.c_o->p->v_n[l1].name == 0\n");
      return 0;
     }
    if (strcmp(current_object->prog->variable_names[lauf1].name,name) == 0)
     { // *** Gefunden !
//      return &(current_variables[lauf1]);
//       return &(csp->current_variables[lauf1]);
      return &(current_object->variables[lauf1]);
      // *** Gewagt, muesste aber funtkionieren !
     }
   }
  return 0;
 }

struct svalue *get_local_variable_pointer( char *name )
 {
  // *** Gibt den Zeiger auf die Svalue der lokalen Variable zurueck,
  // *** oder 0, wenn keine entsprechende lokale Variable gefunden werden konnte.

  // *** Dazu holen wir uns die aktuelle Funktion.
  struct function *tempzeiger;
  int lauf1;
  int lauf2;

  tempzeiger = locate_function( (char *) (*( (char **) (&csp->funstart[-5]) )),current_object->prog);

  if (tempzeiger == 0) return 0;
  // *** d.h. Funktion konnte nicht gefunden werden !
  if (tempzeiger->variable_names == 0) return 0;
  // *** So ein Aerger. Die Funktion hat garkeine lokalen Variablen.			
			
  lauf1 = -1;
  lauf2 = -1;
  do
   {
    lauf1++;
    if (strcmp(tempzeiger->variable_names[lauf1].name,name) == 0)
      { lauf2 = lauf1; }
   }
  while (tempzeiger->variable_names[lauf1].flags != 0xff);

   // *** Lauf2 -> Variable, lauf1 -> annzahl an Zeugs
   // *** lauf2 == -1 -> Variable nicht gefunden.
  if (lauf2 == -1) { return 0; }
  if (strcmp(tempzeiger->variable_names[lauf2].name,name) != 0) return 0;
			
  // *** So, das Dingsbums ist eine lokale Variable.			
  return &(inter_fp[lauf1-lauf2]);
  // *** Gewagt, aber es muesste funktionieren !
 }

void get_variable_data_for_svalue( char *buffer, struct svalue *variable )
 {
  int lauf1;
  char buf2[10000];
  struct hash_mapping *temphash;
  struct map_chain *temp_map_chain;
//  buffer[0] = 0x00;
  // *** Ganz langsam und ausfuehrlich !
  // *** Damit man es auch leicht verstehen kann, anders als den Rest des Drivers :(

#define ADDBUFFER(x)  strcat(buffer,x)

  strcat(buffer,"  Variablentyp : ");
  if (variable->type == T_INVALID)
      { ADDBUFFER(" Invalid (ups, wie kommt das hierher !?)"); } else
  if (variable->type == T_LVALUE)
      { ADDBUFFER("  LValue (ups, wie kommt das hierher !?)"); } else
  if (variable->type == T_NUMBER)
      { ADDBUFFER("  Number"); } else
  if (variable->type == T_STRING)
      { ADDBUFFER("  String"); } else
  if (variable->type == T_POINTER)
      { ADDBUFFER(" Pointer (d.h. ein Array)"); } else
  if (variable->type == T_OBJECT)
      { ADDBUFFER("  Objekt"); } else
  if (variable->type == T_MAPPING)
      { ADDBUFFER(" Mapping"); } else
  if (variable->type == T_FLOAT)
      { ADDBUFFER("   Float"); } else
  if (variable->type == T_CLOSURE)
      { ADDBUFFER(" Closure"); } else
  if (variable->type == T_SYMBOL)
      { ADDBUFFER("  Symbol"); } else
  if (variable->type == T_QUOTED_ARRAY)
      { ADDBUFFER(" Q-Array"); }

  ADDBUFFER("\n");
  if (variable->type == T_NUMBER)
   {
    sprintf(buf2,"        Wert : %d\n",variable->u.number);
    ADDBUFFER(buf2);
    if (variable->u.number == 0)
     {
      ADDBUFFER("Achtung !\nDieser Wert entspricht auch der \"uninitialisiert\" bzw. \"leer\"-Notation !\n");
     }
   } else
  if (variable->type == T_STRING)
   {
    sprintf(buf2,"          Wert : %s\n",variable->u.string);
    ADDBUFFER(buf2);
   } else
 if (variable->type == T_FLOAT)
  {
    sprintf(buf2,"        Wert : %g\n",READ_DOUBLE(variable));
    ADDBUFFER(buf2);
  } else
 if (variable->type == T_POINTER)
  {
   sprintf(buf2," Anzahl der Elemente : %d\n",VEC_SIZE(variable->u.vec));
   ADDBUFFER(buf2);
   sprintf(buf2,"Dump der Variablen : \n");
   ADDBUFFER(buf2);
   for (lauf1 = 0; lauf1 < VEC_SIZE(variable->u.vec) ; lauf1++)
    {
     sprintf(buf2,"Dump von Element %d der Variablen :\n",lauf1);
     ADDBUFFER(buf2);
     get_variable_data_for_svalue(buffer,&(variable->u.vec->item[lauf1]));
    }
  } else
 if (variable->type == T_MAPPING)
  { // *** Anm. Mappingausgabe is noch nicht so doll und sehr evtl. fehlerhaft ! */
   sprintf(buf2," Reference-Count : %d\n",variable->u.map->ref);
   ADDBUFFER(buf2);
   temphash = variable->u.map->hash;

   // *** Nun die einzelnen Hash-Tabellen durchgehen.
   for (lauf1 = 0; lauf1 < temphash->used; lauf1++)
    {
     temp_map_chain = temphash->chains[lauf1];
     // *** Tempmapchain zeigt jetzt auf das erste Element der jeweiligen
     // *** hashkette.
     while (temp_map_chain != 0)
      {
       sprintf(buf2," Mapping-Key : \n");
       ADDBUFFER(buf2);
       get_variable_data_for_svalue(buffer,&(temp_map_chain->key));
       ADDBUFFER("\n");
       sprintf(buf2," Mapping-Wert : \n");
       ADDBUFFER(buf2);
       get_variable_data_for_svalue(buffer,&(temp_map_chain->data));
       temp_map_chain = temp_map_chain->next;
       ADDBUFFER("\n\n");
      }
    }
  } else
 if (variable->type == T_OBJECT)
  {
    if (variable->u.ob == 0)
     { ADDBUFFER("Interner Fehler - Objektreferenz ungueltig !\n"); return; }
    if (variable->u.ob->name == 0)
     { ADDBUFFER("Interner Fehler - Kein referenzierter Objektname !\n"); return; }
	
    sprintf(buf2," referenziertes Objekt : %s\n",variable->u.ob->name);
    ADDBUFFER(buf2);
    ADDBUFFER("                 Flags : ");
    /* Das per Hand machen, wird sonst nirgends benoetigt. */
    if (variable->u.ob->flags & O_HEART_BEAT)
      ADDBUFFER("[Heartbeat]");
    if (variable->u.ob->flags & O_IS_WIZARD )
      ADDBUFFER("[Wizard]");
    if (variable->u.ob->flags & O_ENABLE_COMMANDS )
      ADDBUFFER("[Enable Commands]");
    if (variable->u.ob->flags & O_CLONE)
      ADDBUFFER("[Clone]");
    if (variable->u.ob->flags & O_SHADOW)
      ADDBUFFER("[Shadow]");

    ADDBUFFER("\n");
    sprintf(buf2,"                 Licht : %d\n",variable->u.ob->total_light);
    ADDBUFFER(buf2);
    sprintf(buf2,"       naechster Reset : %d\n",variable->u.ob->next_reset);
    ADDBUFFER(buf2);
       ADDBUFFER("              Enthaelt : ");
   if (variable->u.ob->contains != 0)
	{ ADDBUFFER(variable->u.ob->contains->name); } else
	{ ADDBUFFER("Nix, null, nada !"); }
   ADDBUFFER("\n");
       ADDBUFFER("              Umgebung : ");
   if (variable->u.ob->super != 0)
        { ADDBUFFER(variable->u.ob->super->name); } else
	{ ADDBUFFER("Nix, null, nada !"); }
    ADDBUFFER("\n");
    if (variable->u.ob->user != 0)
     {
      sprintf(buf2,"         Programmierer : %s\n",variable->u.ob->user->name);
      ADDBUFFER(buf2);
     } else ADDBUFFER("         Programmierer : Keiner, Niemand, anonym !\n");
    if (variable->u.ob->eff_user != 0)
     {
      sprintf(buf2,"         Effektive UID : %s\n",variable->u.ob->eff_user->name);
      ADDBUFFER(buf2);
     } else ADDBUFFER("         Effektive UID : Keine, nix, leer, nada !\n");
   } else
   {
    ADDBUFFER("Tut mir leid. Dieser Variablentyp kann noch nicht dargestellt werden !\nErinnere Sunblade mal, das es das nit vergisst !\n");
   }
  }
									
struct breakpoint *breakpoint_exists( int curr_line, char *curr_file )
 {
  // *** Diese Funtkion ueberpreuft, ob ein Breakpoint existiert,
  // *** der an der Zeile curr_line in der Datei curr_file gesetzt ist.
  struct breakpoint *tempbreak;

  tempbreak = first_breakpoint;
  while (tempbreak != 0)
   {
    if ((curr_line == tempbreak->line) &&
	(strcmp(curr_file,tempbreak->in_file) == 0))
     { // *** Da ist ein Breakpoint gefunden worden !
      return tempbreak;
     }
    tempbreak = tempbreak->next;
   }
  return 0;
 }


										
