/*****************************************************************************\
*                                                                             *
*  Name   : test_symbol_tree                                                  *
*  Author : Chris Koeritz                                                     *
*                                                                             *
*  Purpose:                                                                   *
*                                                                             *
*    Creates a symbol_tree and performs some operations on it to assure       *
*  basic functionality.                                                       *
*                                                                             *
*******************************************************************************
* Copyright (c) 1992-$now By Author.  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 of   *
* the License or (at your option) any later version.  This is online at:      *
*     http://www.fsf.org/copyleft/gpl.html                                    *
* Please send any updates to: fred@gruntose.com                               *
\*****************************************************************************/

#include <basis/utility.h>
#include <basis/guards.h>
#include <basis/istring.h>
#include <nodes/symbol_tree.h>

#include <stdlib.h>

#define DEBUG_SYMBOL_TREE

// ADD: adds the name and content to the symbol table.
#define ADD(name, content) \
  { chunk *to_stuff = new chunk \
      ((byte *)(char *)content, content.length() + 1); \
    symbol_table::add_outcomes added = syms->add(name, 0, to_stuff); \
    if (added == symbol_table::EXISTING_SYMBOL) \
      deadly_error(class_name(), "ADD name", "already in table"); }

int WINAPI WinMain(application_instance instance,
    application_instance prev_instance, LPSTR lpCmdLine, int nCmdShow)
{
  symbol_tree<chunk> *syms = new symbol_tree<chunk>;
  syms->push_scope("fleabitten.x");
  string freudname("blurgh");
  string freud("Sigmund Freud was a very freaked dude.");
  ADD(freudname, freud);
  syms->push_scope("cronkite_function");
  string borgname("borg");
  string borg("You will be assimilated.");
  ADD(borgname, borg);
  syms->pop_scope();
  string xname("X-Men");
  string x("The great unknown superhero cartoon.");
  ADD(xname, x);
  syms->pop_scope();
  string aname("fleeny-brickle");
  string a("lallax menick publum.");
  ADD(aname, a);
  syms->push_scope("slocum.c");
  string axname("ax");
  string ax("Lizzy Borden has a very large hatchet.");
  ADD(axname, ax);
  syms->pop_scope();
  syms->push_scope("fleen_speckle.q");
  string bloinkname("urg.");
  string bloink("this is a short and stupid string");
  ADD(bloinkname, bloink);
  syms->pop_scope();
  string faxname("fax");
  string fax("alligators in my teacup.");
  ADD(faxname, fax);
  string zname("eagle ovaries");
  string z("malfeasors beware");
  ADD(zname, z);

#ifdef DEBUG_SYMBOL_TREE
  p("This is the symbol tree before any manipulation\n"); syms->print();
#endif
  stack path;
#ifdef DEBUG_SYMBOL_TREE
  p("\nNow trying find of %s...\n", (char *)axname);
#endif
  symbol_table::find_outcomes found
    = syms->find(axname, symbol_tree::FULL_SEARCH, path);
  if (found != symbol_table::FOUND)
    deadly_error(class_name(), "first finding", "symbol not found");
#ifdef DEBUG_SYMBOL_TREE
  p("path to found object is:");
  syms->show_path(path);
  p("is this right?\n");
  p("dumping table at the location of the find\n");
#endif
  symbol_table *where = syms->get_table(path);
#ifdef DEBUG_SYMBOL_TREE
  where->print();
  p("is symbol listed?\n");
#endif

  int sym_content;
  chunk *content = NIL;
#ifdef DEBUG_SYMBOL_TREE
  p("Now trying the other find to just grab the symbol\n");
#endif
  content = syms->find(axname, symbol_tree::FULL_SEARCH, sym_content, found);
  if (found != symbol_table::FOUND) deadly_error(class_name(), "find", "not there");
#ifdef DEBUG_SYMBOL_TREE
  p("content of found symbol is %s\n", (char *)content);
  p("now packing the symbol tree...\n");
#endif
  int packed_size;
  byte *packed_form = syms->pack(packed_size);
#ifdef DEBUG_SYMBOL_TREE
  p("packed size is %d\n", packed_size);
#endif
  int chk1 = checksum((byte *)packed_form, packed_size);
#ifdef DEBUG_SYMBOL_TREE
  p("checksum is %d\n", chk1);
  p("now deleting old symbol tree...\n");
#endif
  delete syms;

#ifdef DEBUG_SYMBOL_TREE
  p("now unpacking from packed form\n");
#endif
  symbol_tree *new_syms = symbol_tree_unpack(packed_form, &chunk_unpack);
#ifdef DEBUG_SYMBOL_TREE
  p("got the unpacked form, and dumping it:\n"); new_syms->print();
  p("trying second pack\n");
#endif
  byte *new_pack = new_syms->pack(packed_size);
#ifdef DEBUG_SYMBOL_TREE
  p("packed size is %d\n", packed_size);
#endif
  int chk = checksum((byte *)new_pack, packed_size);
#ifdef DEBUG_SYMBOL_TREE
  p("checksum is %d\n", chk);
  p("about to delete sym\n");
#endif
  delete new_syms;

#ifdef DEBUG_SYMBOL_TREE
  p("second unpack...\n");
#endif
  symbol_tree *newest = symbol_tree_unpack(new_pack, &chunk_unpack);
#ifdef DEBUG_SYMBOL_TREE
  p("and here it is:\n"); newest->print();
#endif
  delete newest;

  guards::alert_message("symbol_tree:: works for those functions tested.");
  return 0;
}
