#ifndef lint
static char *RCSid = "$Id: debug.c,v 1.11 1993/05/07 20:10:58 anders Exp anders $";
#endif

/*
 *  The Regina Rexx Interpreter
 *  Copyright (C) 1992-1994  Anders Christensen <anders@pvv.unit.no>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "rexx.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#ifndef NDEBUG

void dumpvars( variableptr *hashptr ) 
{ 
   variableptr ptr=NULL, tptr=NULL ;
   extern proclevel currlevel ;
   int i=0, j=0 ;

   if (hashptr==NULL)
      hashptr = currlevel->vars ;
   
   printf("\nDumping variables to <stdout>\n") ;
   for (i=0;i!=256;i++) {
      if (hashptr[i]!=NULL)
         printf("   Variables from bin no %d\n",i) ;
      for (ptr=hashptr[i];ptr!=NULL;ptr=ptr->next)  
         if ((ptr->name->value)[strlen(ptr->name->value)-1]=='.') {
            printf("   >>> Stem    : //%s// Default: //%s//  Values:\n",
                  ptr->name->value,(ptr->value)?(ptr->value->value):"<none>") ;
            for (j=0;j<256;j++) {
               if ((tptr=((ptr->index))[j])) {
                  printf("      Sub-bin no %d\n",j) ;
                  for (;tptr;tptr=tptr->next) 
                     if ((tptr->value)&&(tptr->name))
                        printf("      >>> Variable: //%s// Value: //%s//\n",
                              tptr->name->value,tptr->value->value) ; } ; } ; }
         else 
            printf("   >>> Variable: //%s// Value: //%s//\n",
                                    ptr->name->value,ptr->value->value) ; }

   return ;
}


void dumptree(treenode *this, int level) 
{
   int i=0, j=0 ;

   for (i=0;i!=level;i++)
      printf("  ") ;
   
   printf(">>> in type=%d == %s\n", this->type, getsym(this->type)) ; 
/*
   if ((this->value)!=NULL) {
      for (i=0;i!=level;i++) printf("  ") ;
      printf("Value: //%s//\n", this->value) ; } ;
 */
   if ((this->name)!=NULL) {
      for (i=0;i!=level;i++) printf("  ") ;
      printf("Name: //%s//\n", this->name->value) ; } ;

   if ((this->charnr)!=0) {
      for (i=0;i!=level;i++) printf("  ") ;
      printf("Lineno: %d   Charno: %d\n", this->lineno, this->charnr) ; } ;

   for (j=0;j!=5;j++)
      if (this->p[j]!=NULL) {
         for (i=0;i!=level;i++) 
            printf("  ") ;
         printf("==> (%d) going down in branch %d, type %d = %s\n",
                this->type,j+1,this->p[j]->type,getsym(this->p[j]->type)) ;
         dumptree( this->p[j], level+1 ) ; }
         
   for (i=0;i!=level;i++) 
      printf("  ") ;
   printf("<<< out of type=%d = %s\n", this->type,getsym(this->type)) ; 

}

#endif /* !NDEBUG */


extern sysinfobox *systeminfo ;

int numsourcelines( void )
{
   extern sysinfobox *systeminfo ;
   return (systeminfo->lastline) ? systeminfo->lastline->lineno : 0 ;
}



#ifdef TRACEMEM
void marksource( lineboxptr ptr )
{
   for (;ptr;ptr=ptr->next) {
      markmemory( ptr->line,TRC_SOURCEL ) ;
      markmemory( (char *)ptr, TRC_SOURCE ) ; }
}
#endif


streng *sourceline( int line, lineboxptr first, lineboxptr last ) 
{
   static lineboxptr ptr=NULL ;
/*
   extern sysinfo systeminfo ;

   if (!ptr) 
      ptr = systeminfo->firstline ; 
 */
   ptr = first ;

   for (;ptr;) 
   {
      if (ptr->lineno==line)
         return ptr->line ;
      else 
         ptr = (ptr->lineno<line) ? ptr->next : ptr->prev ;
   }

   return NULL ;
}



streng *getsourceline( int line, int charnr, lineboxptr first, lineboxptr last )
{
   int dquote=0, squote=0 ;
   streng *string=NULL, *ptr=NULL ;
   char *chptr=NULL, *chend=NULL, *outptr=NULL, *tmptr=NULL ;

   assert( charnr>=0 ) ;
   if (!charnr)
     charnr++ ;

   ptr = sourceline(line,first,last) ;
/*   assert( ptr ) ; */
   if (!ptr)
      return nullstringptr() ;

   chptr = ptr->value + --charnr ;
   chend = ptr->value + ptr->len ;
   for (; isspace(*chptr); chptr++) ;
   string = Str_make(BUFFERSIZE+1) ;
   outptr = string->value ;

   for (;;)
   {
      if (chptr>=chend)
         break ;

      if (!squote && *chptr=='\"')
         dquote = !dquote ;

      else if (!dquote && *chptr=='\'')
         squote = !squote ;

      else if (!(dquote || squote))
      {
         switch (*chptr)
         {
            case ',':
               for(tmptr=chptr+1; isspace(*tmptr); tmptr++ ) ;
               assert( tmptr<=chend ) ;
               if (tmptr==chend)
               {
                  *(outptr++) = ' ' ;
                  ptr = sourceline(++line,first,last) ;
                  chptr = ptr->value ;
                  chend = chptr + ptr->len ;
                  for(; isspace(*tmptr); tmptr++) ;
               }
               break ;
           
            case ':':
               *(outptr++) = *chptr ;

            case ';':
               goto endloop ;

         }
      }

      *(outptr++) = *(chptr++) ;
   }

endloop:
   assert( outptr - string->value <= BUFFERSIZE ) ;   
   string->len = outptr - string->value ;
   return string ;
}

