#ifndef STRUCTURES_H
#define STRUCTURES_H 1
#pragma interface

#include "value.h"
#include <String.h>
#include <iostream.h>
#include <fstream.h>

/************************************************************************
************ StringValHash:  a String->Value hash table  ****************
************************************************************************/

class h_pair {
  friend class StringValHash;
 protected:
  String* index;
  Value*  data;
  h_pair* next;
 public:
  h_pair(String*, Value*, h_pair*);
  ~h_pair();
};

#define HASH_WIDTH 4    /* can't change this without changing HASH(a)
                           and HASH_RE(a)                                */

class StringValHash {
  friend class Value;
  friend class Object;
 public:
  StringValHash();
  ~StringValHash();
  Value* lookup (String*);
  int add (Value*, String*);   /* returns 0 if string not used */
  int remove (String*);
  Value* list_vars();          /* makes a list of all values in table */
  char* pack_syms(char* buf);
  void dump_to_stdout();
 protected:
 h_pair* htable [HASH_WIDTH];
};


/** this function is used (only once) to create a token table initialized  **
 ** with all reserved words in the language.  defined in tokentable.C      **/
StringValHash* init_token_table();

/**********************************************************************
**************** SymVal_List:  a String->Value mapping stack **********
***********************************************************************/

typedef struct svl_rep {
    String* symbol;
    Value*  val;
    struct svl_rep* next;
};

class SymVal_List{
  friend class Frame;
 protected:
  struct svl_rep* pair_list;
 public:
  SymVal_List();
  ~SymVal_List();
  void push (String* s, Value* v);
  void pop ();
  Value* peek();
  String* peek_symbol();
  Value* lookup (String* s);
  int assign (String* s, Value* v);
};

/************************************************************************
**************** ReStringHash:  a regexp->String mapping list ***********
************************************************************************/

class ReList{
  friend class ReStringHash;
 protected:
  String* index;
  Regex*  condensed;
  String*  data;
  ReList* next;
 public:
  ReList(String*, Regex*, String*, ReList*);
  ~ReList();
};

class ReStringHash {
 public:
  ReStringHash();
 ~ReStringHash();
  Regex*  add (String* key, String* indata);
  int remove (String* pattern);
  int purge ();
  String* lookup (String* pattern);
  Val_List* lookup_all (String* pattern);
  Value* list_cmds();
  char* pack_cmds(char* buf);
  char* unpack (char* buf);
  void dump_to_stdout();
 protected:
  struct ReList * rtable [HASH_WIDTH];
};

int valid_regexp (String* key);

#define PACK_INT(buf, i)            \
    (buf)[0] = (((char*)(&i))[0]);        \
    (buf)[1] = (((char*)(&i))[1]);        \
    (buf)[2] = (((char*)(&i))[2]);        \
    if ((sizeof (long)) > 3)              \
       (buf)[3] = (((char*)(&i))[3]);

#define UNPACK_INT(buf, i)                \
    (((char*)(&i))[0]) = (buf)[0];        \
    (((char*)(&i))[1]) = (buf)[1];        \
    (((char*)(&i))[2]) = (buf)[2];        \
    if ((sizeof (long)) > 3)              \
       (((char*)(&i))[3]) = (buf)[3];

#define PACK_FLOAT(buf, f)                 \
    (buf)[0] = (((char*)(&f))[0]);         \
    (buf)[1] = (((char*)(&f))[1]);         \
    (buf)[2] = (((char*)(&f))[2]);         \
    (buf)[3] = (((char*)(&f))[3]);         \
    if ((sizeof (float)) > 4)              \
      {(buf)[4] = (((char*)(&f))[4]);      \
       (buf)[5] = (((char*)(&f))[5]);      \
       if ((sizeof (float)) > 6)           \
         {(buf)[6] = (((char*)(&f))[6]);   \
          (buf)[7] = (((char*)(&f))[7]);}}

#define UNPACK_FLOAT(buf, f)               \
    (((char*)(&f))[0]) = (buf)[0];         \
    (((char*)(&f))[1]) = (buf)[1];         \
    (((char*)(&f))[2]) = (buf)[2];         \
    (((char*)(&f))[3]) = (buf)[3];         \
    if ((sizeof (float)) > 4)              \
       {(((char*)(&f))[4]) = (buf)[4];     \
	(((char*)(&f))[5]) = (buf)[5];     \
	if ((sizeof (float)) > 6)          \
	  {(((char*)(&f))[6]) = (buf)[6];  \
	   (((char*)(&f))[7]) = (buf)[7];}}
	

#endif  /* STRUCTURES_H */