- More work on scripting interface
authorMatthias Braun <matze@braunis.de>
Wed, 4 May 2005 17:15:32 +0000 (17:15 +0000)
committerMatthias Braun <matze@braunis.de>
Wed, 4 May 2005 17:15:32 +0000 (17:15 +0000)
- Moved remaining stuff from lib directory into src directory

SVN-Revision: 2394

207 files changed:
data/levels/test/foresttheme.stl
data/levels/test/noloktest.stl
lib/app/.cvsignore [deleted file]
lib/app/gettext.h [deleted file]
lib/app/globals.cpp [deleted file]
lib/app/globals.h [deleted file]
lib/app/setup.cpp [deleted file]
lib/app/setup.h [deleted file]
lib/app/tinygettext.cpp [deleted file]
lib/app/tinygettext.h [deleted file]
lib/lisp/.cvsignore [deleted file]
lib/math/.cvsignore [deleted file]
lib/math/aatriangle.h [deleted file]
lib/math/physic.cpp [deleted file]
lib/math/physic.h [deleted file]
lib/math/rectangle.h [deleted file]
lib/math/vector.cpp [deleted file]
lib/math/vector.h [deleted file]
lib/special/.cvsignore [deleted file]
lib/special/frame_rate.cpp [deleted file]
lib/special/frame_rate.h [deleted file]
lib/special/timer.cpp [deleted file]
lib/special/timer.h [deleted file]
lib/utils/.cvsignore [deleted file]
lib/video/.cvsignore [deleted file]
src/Jamfile
src/audio/musicref.cpp
src/audio/sound_manager.cpp
src/audio/sound_manager.h
src/badguy/badguy.cpp
src/badguy/badguy.h
src/badguy/mriceblock.cpp
src/badguy/nolok_01.cpp
src/badguy/yeti.cpp
src/collision.h
src/collision_grid.h
src/collision_grid_iterator.h
src/collision_hit.h
src/control/joystickkeyboardcontroller.cpp
src/control/joystickkeyboardcontroller.h
src/file_system.cpp [new file with mode: 0644]
src/file_system.h [new file with mode: 0644]
src/game_session.cpp
src/game_session.h
src/gameconfig.cpp
src/gettext.h [new file with mode: 0644]
src/gui/button.cpp
src/gui/button.h
src/gui/menu.cpp
src/gui/menu.h
src/gui/mousecursor.cpp
src/gui/mousecursor.h
src/level.cpp
src/level_subset.cpp
src/level_subset.h
src/leveleditor.cpp
src/leveleditor.h
src/lisp/parser.cpp
src/main.cpp
src/main.h
src/math/aatriangle.h [new file with mode: 0644]
src/math/rectangle.h [new file with mode: 0644]
src/math/vector.cpp [new file with mode: 0644]
src/math/vector.h [new file with mode: 0644]
src/misc.cpp
src/misc.h
src/object/background.cpp
src/object/background.h
src/object/bell.h
src/object/block.h
src/object/bullet.cpp
src/object/bullet.h
src/object/camera.cpp
src/object/camera.h
src/object/coin.h
src/object/fireworks.cpp
src/object/flower.cpp
src/object/flower.h
src/object/gameobjs.cpp
src/object/gameobjs.h
src/object/growup.cpp
src/object/growup.h
src/object/oneup.h
src/object/particlesystem.cpp
src/object/particlesystem.h
src/object/platform.h
src/object/player.cpp
src/object/player.h
src/object/portable.h
src/object/rock.h
src/object/specialriser.cpp
src/object/specialriser.h
src/object/star.h
src/object/tilemap.cpp
src/object/tilemap.h
src/object/unstable_tile.h
src/object_factory.h
src/physic.cpp [new file with mode: 0644]
src/physic.h [new file with mode: 0644]
src/resources.cpp
src/resources.h
src/scripting/Jamfile [new file with mode: 0644]
src/scripting/camera.cpp [new file with mode: 0644]
src/scripting/camera.h [new file with mode: 0644]
src/scripting/display.cpp [new file with mode: 0644]
src/scripting/display.h [new file with mode: 0644]
src/scripting/functions.cpp [new file with mode: 0644]
src/scripting/functions.h [new file with mode: 0644]
src/scripting/level.cpp [new file with mode: 0644]
src/scripting/level.h [new file with mode: 0644]
src/scripting/script_interpreter.h [new file with mode: 0644]
src/scripting/scripted_object.cpp [new file with mode: 0644]
src/scripting/scripted_object.h [new file with mode: 0644]
src/scripting/semantic.cache [new file with mode: 0644]
src/scripting/sound.cpp [new file with mode: 0644]
src/scripting/sound.h [new file with mode: 0644]
src/scripting/wrapper.cpp [new file with mode: 0644]
src/scripting/wrapper.h [new file with mode: 0644]
src/scripting/wrapper.interface.h [new file with mode: 0644]
src/scripting/wrapper_util.cpp [new file with mode: 0644]
src/scripting/wrapper_util.h [new file with mode: 0644]
src/sector.cpp
src/sector.h
src/sprite/sprite.cpp
src/sprite/sprite_data.cpp
src/squirrel/Jamfile [new file with mode: 0644]
src/squirrel/README [new file with mode: 0644]
src/squirrel/include/sqstdaux.h [new file with mode: 0644]
src/squirrel/include/sqstdblob.h [new file with mode: 0644]
src/squirrel/include/sqstdio.h [new file with mode: 0644]
src/squirrel/include/sqstdmath.h [new file with mode: 0644]
src/squirrel/include/sqstdstring.h [new file with mode: 0644]
src/squirrel/include/sqstdsystem.h [new file with mode: 0644]
src/squirrel/include/squirrel.h [new file with mode: 0644]
src/squirrel/sqstdlib/Makefile [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdaux.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdblob.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdblobimpl.h [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdio.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdlib.dsp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdmath.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdrex.c [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdstream.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdstream.h [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdstring.cpp [new file with mode: 0644]
src/squirrel/sqstdlib/sqstdsystem.cpp [new file with mode: 0644]
src/squirrel/squirrel/Makefile [new file with mode: 0644]
src/squirrel/squirrel/sqapi.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqarray.h [new file with mode: 0644]
src/squirrel/squirrel/sqbaselib.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqclass.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqclass.h [new file with mode: 0644]
src/squirrel/squirrel/sqclosure.h [new file with mode: 0644]
src/squirrel/squirrel/sqcompiler.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqcompiler.h [new file with mode: 0644]
src/squirrel/squirrel/sqdebug.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqfuncproto.h [new file with mode: 0644]
src/squirrel/squirrel/sqfuncstate.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqfuncstate.h [new file with mode: 0644]
src/squirrel/squirrel/sqlexer.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqlexer.h [new file with mode: 0644]
src/squirrel/squirrel/sqmem.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqobject.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqobject.h [new file with mode: 0644]
src/squirrel/squirrel/sqopcodes.h [new file with mode: 0644]
src/squirrel/squirrel/sqpcheader.h [new file with mode: 0644]
src/squirrel/squirrel/sqstate.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqstate.h [new file with mode: 0644]
src/squirrel/squirrel/sqstring.h [new file with mode: 0644]
src/squirrel/squirrel/sqtable.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqtable.h [new file with mode: 0644]
src/squirrel/squirrel/squirrel.dsp [new file with mode: 0644]
src/squirrel/squirrel/squserdata.h [new file with mode: 0644]
src/squirrel/squirrel/squtils.h [new file with mode: 0644]
src/squirrel/squirrel/sqvm.cpp [new file with mode: 0644]
src/squirrel/squirrel/sqvm.h [new file with mode: 0644]
src/statistics.cpp
src/statistics.h
src/textscroller.cpp
src/tile.cpp
src/tile.h
src/tile_manager.cpp
src/timer.cpp
src/timer.h
src/tinygettext/tinygettext.cpp [new file with mode: 0644]
src/tinygettext/tinygettext.h [new file with mode: 0644]
src/title.cpp
src/trigger/door.cpp
src/trigger/hatch.cpp
src/trigger/secretarea_trigger.cpp
src/trigger/secretarea_trigger.h
src/trigger/trigger_base.h
src/video/drawing_context.cpp
src/video/drawing_context.h
src/video/font.cpp
src/video/screen.cpp
src/video/screen.h
src/video/surface.cpp
src/worldmap.cpp
tools/Jamfile [new file with mode: 0644]
tools/miniswig/create_wrapper.cpp
tools/miniswig/create_wrapper.h
tools/miniswig/globals.h
tools/miniswig/lexer.ll
tools/miniswig/main.cpp
tools/miniswig/parser.yy
tools/miniswig/tree.h

index e3e90bf..6320134 100644 (file)
@@ -4,7 +4,6 @@
   (name "Forest Theme Test")
   (author "Marek Moeckel")
   (time 300)
-  (end-sequence-animation "none")
   (sector
     (name "main")
     (gravity 10)
index b06c294..00e1cce 100644 (file)
@@ -4,7 +4,6 @@
   (name "Nolok Test")
   (author "Marek")
   (time 500)
-  (end-sequence-animation "none")
   (sector
     (name "main")
     (gravity 10)
diff --git a/lib/app/.cvsignore b/lib/app/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/lib/app/gettext.h b/lib/app/gettext.h
deleted file mode 100644 (file)
index 1d4d6bc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 
-   This program 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, 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-   USA.  */
-
-#ifndef _LIBGETTEXT_H
-#define _LIBGETTEXT_H 1
-
-#include "globals.h"
-
-#define _(String) \
-  SuperTux::dictionary_manager.get_dictionary().translate(String).c_str()
-#define N_(id, id2, num) \
-  SuperTux::dictionary_manager.get_dictionary().translate(id, di2, num).c_str()
-
-#endif /* _LIBGETTEXT_H */
diff --git a/lib/app/globals.cpp b/lib/app/globals.cpp
deleted file mode 100644 (file)
index 5327778..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 SuperTux Development Team, see AUTHORS for details
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#include <config.h>
-
-#include "app/globals.h"
-#include "special/timer.h"
-
-namespace SuperTux {
-
-TinyGetText::DictionaryManager dictionary_manager;
-TinyGetText::Dictionary* dictionary = 0;
-
-/** The datadir prefix prepended when loading game data file */
-std::string datadir;
-std::string package_symbol_name;
-std::string package_name;
-std::string package_version;
-
-int screen_width  = SCREEN_WIDTH;
-int screen_height = SCREEN_HEIGHT;
-
-JoystickKeymap::JoystickKeymap()
-{
-  a_button     = 0;
-  b_button     = 1;
-  start_button = 2;
-  
-  x_axis = 0;
-  y_axis = 1;
-    
-  dead_zone = 4096;
-}
-
-JoystickKeymap joystick_keymap;
-
-SDL_Surface * screen;
-MouseCursor * mouse_cursor;
-
-#if 0
-int joystick_num = 0;
-char* level_startup_file = 0;
-bool launch_leveleditor_mode = false;
-bool launch_worldmap_mode = false;
-bool flip_levels_mode = false;
-#endif
-
-/* SuperTux directory ($HOME/.supertux) and save directory($HOME/.supertux/save) */
-std::string user_dir;
-
-SDL_Joystick * js;
-
-/* Returns 1 for every button event, 2 for a quit event and 0 for no event. */
-int wait_for_event(SDL_Event& event, unsigned int min_delay,
-    unsigned int max_delay, bool empty_events)
-{
-  int i;
-  Timer maxdelay;
-  Timer mindelay;
-  
-  maxdelay.init(false);
-  mindelay.init(false);
-
-  if(max_delay < min_delay)
-    max_delay = min_delay;
-
-  maxdelay.start(max_delay);
-  mindelay.start(min_delay);
-
-  if(empty_events)
-    while (SDL_PollEvent(&event))
-    {}
-
-  /* Handle events: */
-
-  for(i = 0; maxdelay.check() || !i; ++i)
-    {
-      while (SDL_PollEvent(&event))
-        {
-          if(!mindelay.check())
-            {
-              if (event.type == SDL_QUIT)
-                {
-                  /* Quit event - quit: */
-                  return 2;
-                }
-              else if (event.type == SDL_KEYDOWN)
-                {
-                  /* Keypress - skip intro: */
-
-                  return 1;
-                }
-              else if (event.type == SDL_JOYBUTTONDOWN)
-                {
-                  /* Fire button - skip intro: */
-
-                  return 1;
-                }
-              else if (event.type == SDL_MOUSEBUTTONDOWN)
-                {
-                  /* Mouse button - skip intro: */
-                  return 1;
-                }
-            }
-        }
-      SDL_Delay(10);
-    }
-
-  return 0;
-}
-
-} //namespace SuperTux
diff --git a/lib/app/globals.h b/lib/app/globals.h
deleted file mode 100644 (file)
index 850707d..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Bill Kendrick <bill@newbreedsoftware.com>
-//                     Tobias Glaesser <tobi.web@gmx.de>
-//                     Ingo Ruhnke <grumbel@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#ifndef SUPERTUX_GLOBALS_H
-#define SUPERTUX_GLOBALS_H
-
-#include <string>
-
-#include "SDL.h"
-
-#include "video/font.h"
-#include "tinygettext.h"
-
-namespace SuperTux
-  {
-
-  extern TinyGetText::DictionaryManager dictionary_manager;
-  extern TinyGetText::Dictionary* dictionary;
-  
-  class MouseCursor;
-
-  extern std::string datadir;
-
-  struct JoystickKeymap
-    {
-      int a_button;
-      int b_button;
-      int start_button;
-
-      int x_axis;
-      int y_axis;
-
-      int dead_zone;
-
-      JoystickKeymap();
-    };
-
-  extern JoystickKeymap joystick_keymap;
-
-  extern MouseCursor * mouse_cursor;
-
-#define SCREEN_WIDTH  800
-#define SCREEN_HEIGHT 600
-
-  /** The number of the joystick that will be use in the game */
-  extern int joystick_num;
-
-  /* SuperTux directory ($HOME/.supertux) */
-  extern std::string user_dir;
-  
-  extern SDL_Joystick * js;
-
-  int wait_for_event(SDL_Event& event,unsigned int min_delay = 0, unsigned int max_delay = 0, bool empty_events = false);
-
-} //namespace SuperTux
-
-#endif /* SUPERTUX_GLOBALS_H */
diff --git a/lib/app/setup.cpp b/lib/app/setup.cpp
deleted file mode 100644 (file)
index 4362c17..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#include <config.h>
-
-#include <cassert>
-#include <cstdio>
-#include <iostream>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <unistd.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#ifndef WIN32
-#include <libgen.h>
-#endif
-
-#include <cctype>
-
-#include "globals.h"
-#include "setup.h"
-
-using namespace SuperTux;
-
-#ifdef WIN32
-#define mkdir(dir, mode)    mkdir(dir)
-#endif
-
-/* Does the given file exist and is it accessible? */
-bool FileSystem::faccessible(const std::string& filename)
-{
-  struct stat filestat;
-  if (stat(filename.c_str(), &filestat) == -1)
-    {
-      return false;
-    }
-  else
-    {
-      if(S_ISREG(filestat.st_mode))
-        return true;
-      else
-        return false;
-    }
-}
-
-/* Can we write to this location? */
-bool FileSystem::fwriteable(const std::string& filename)
-{
-  FILE* fi;
-  fi = fopen(filename.c_str(), "wa");
-  if (fi == NULL)
-    {
-      return false;
-    }
-  fclose(fi);
-  return true;
-}
-
-/* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
-bool FileSystem::fcreatedir(const std::string& relative_dir)
-{
-  std::string path = user_dir + "/" + relative_dir + "/";
-  if(mkdir(path.c_str(),0755) != 0)
-    {
-      path = datadir + "/" + relative_dir + "/";
-      if(mkdir(path.c_str(),0755) != 0)
-        {
-          return false;
-        }
-      else
-        {
-          return true;
-        }
-    }
-  else
-    {
-      return true;
-    }
-}
-
-/* Get all names of sub-directories in a certain directory. */
-/* Returns the number of sub-directories found. */
-/* Note: The user has to free the allocated space. */
-std::set<std::string> FileSystem::dsubdirs(const std::string &rel_path,const  std::string& expected_file)
-{
-  DIR *dirStructP;
-  struct dirent *direntp;
-  std::set<std::string> sdirs;
-  std::string filename;
-  std::string path = user_dir + "/" + rel_path;
-
-  if((dirStructP = opendir(path.c_str())) != NULL)
-    {
-      while((direntp = readdir(dirStructP)) != NULL)
-        {
-          std::string absolute_filename;
-          struct stat buf;
-
-          absolute_filename = path + "/" + direntp->d_name;
-
-          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
-            {
-              if(!expected_file.empty())
-                {
-                  filename = path + "/" + direntp->d_name + "/" + expected_file;
-                  if(!faccessible(filename))
-                    continue;
-                }
-
-             sdirs.insert(direntp->d_name);
-            }
-        }
-      closedir(dirStructP);
-    }
-
-  path = datadir + "/" + rel_path;
-  if((dirStructP = opendir(path.c_str())) != NULL)
-    {
-      while((direntp = readdir(dirStructP)) != NULL)
-        {
-          std::string absolute_filename;
-          struct stat buf;
-
-          absolute_filename = path + "/" + direntp->d_name;
-
-          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
-            {
-              if(!expected_file.empty())
-                {
-                  filename = path + "/" + direntp->d_name + "/" + expected_file;
-                  if(!faccessible(filename.c_str()))
-                    {
-                      continue;
-                    }
-                  else
-                    {
-                      filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
-                      if(faccessible(filename.c_str()))
-                        continue;
-                    }
-                }
-
-             sdirs.insert(direntp->d_name);
-            }
-        }
-      closedir(dirStructP);
-    }
-
-  return sdirs;
-}
-
-std::set<std::string> FileSystem::dfiles(const std::string& rel_path, const  std::string& glob, const  std::string& exception_str)
-{
-  DIR *dirStructP;
-  struct dirent *direntp;
-  std::set<std::string> sdirs;
-  std::string path = user_dir + "/" + rel_path;
-
-  if((dirStructP = opendir(path.c_str())) != NULL)
-    {
-      while((direntp = readdir(dirStructP)) != NULL)
-        {
-          std::string absolute_filename;
-          struct stat buf;
-
-          absolute_filename = path + "/" + direntp->d_name;
-
-          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
-            {
-              if(!exception_str.empty())
-                {
-                  if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
-                    continue;
-                }
-              if(!glob.empty())
-                if(strstr(direntp->d_name,glob.c_str()) == NULL)
-                  continue;
-
-             sdirs.insert(direntp->d_name);
-            }
-        }
-      closedir(dirStructP);
-    }
-
-  path = datadir + "/" + rel_path;
-  if((dirStructP = opendir(path.c_str())) != NULL)
-    {
-      while((direntp = readdir(dirStructP)) != NULL)
-        {
-          std::string absolute_filename;
-          struct stat buf;
-
-          absolute_filename = path + "/" + direntp->d_name;
-
-          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
-            {
-              if(!exception_str.empty())
-                {
-                  if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
-                    continue;
-                }
-              if(!glob.empty())
-                if(strstr(direntp->d_name,glob.c_str()) == NULL)
-                  continue;
-
-             sdirs.insert(direntp->d_name);
-            }
-        }
-      closedir(dirStructP);
-    }
-
-  return sdirs;
-}
-
-std::string FileSystem::dirname(const std::string& filename)
-{
-  std::string::size_type p = filename.find_last_of('/');
-  if(p == std::string::npos)                              
-    return "";
-  
-  return filename.substr(0, p+1);
-}
-
-std::set<std::string> FileSystem::read_directory(const std::string& pathname)
-{
-  std::set<std::string> dirnames;
-  
-  DIR* dir = opendir(pathname.c_str());
-  if (dir)
-    {
-      struct dirent *direntp;
-      
-      while((direntp = readdir(dir)))
-        {
-          dirnames.insert(direntp->d_name);
-        }
-      
-      closedir(dir);
-    }
-
-  return dirnames;
-}
diff --git a/lib/app/setup.h b/lib/app/setup.h
deleted file mode 100644 (file)
index 98e947f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#ifndef SUPERTUX_SETUP_H
-#define SUPERTUX_SETUP_H
-
-#include <vector>
-#include <set>
-#include <string>
-
-namespace SuperTux {
-
-/// File system utility functions
-struct FileSystem
-  {
-    static bool faccessible(const std::string& filename);
-    static bool fcreatedir(const std::string& relative_dir);
-    static bool fwriteable(const std::string& filename);
-    static std::set<std::string> read_directory(const std::string& pathname);
-    static std::set<std::string> dsubdirs(const std::string& rel_path, const std::string& expected_file);
-    static std::set<std::string> dfiles(const std::string& rel_path, const std::string& glob, const std::string& exception_str);
-
-    static std::string dirname(const std::string& filename);
-  };
-
-} //namespace SuperTux
-
-#endif /*SUPERTUX_SETUP_H*/
-
diff --git a/lib/app/tinygettext.cpp b/lib/app/tinygettext.cpp
deleted file mode 100644 (file)
index dd73e80..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-//  $Id$
-// 
-//  TinyGetText - A small flexible gettext() replacement
-//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#include <config.h>
-
-#include <sys/types.h>
-#include <iconv.h>
-#include <dirent.h>
-#include <fstream>
-#include <iostream>
-#include <ctype.h>
-#include <errno.h>
-#include "tinygettext.h"
-
-//#define TRANSLATION_DEBUG
-
-namespace TinyGetText {
-
-/** Convert \a which is in \a from_charset to \a to_charset and return it */
-std::string convert(const std::string& text,
-                    const std::string& from_charset,
-                    const std::string& to_charset)           
-{
-  if (from_charset == to_charset)
-    return text;
-
-  iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str());
-  
-  size_t in_len = text.length();
-  size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough        
-
-  char*  out_orig = new char[out_len];
-  char*  in_orig  = new char[in_len+1];
-  strcpy(in_orig, text.c_str());
-
-  char* out = out_orig;
-  char* in  = in_orig;
-  size_t out_len_temp = out_len; // iconv is counting down the bytes it has
-                                 // written from this...
-
-  size_t retval = iconv(cd, &in, &in_len, &out, &out_len_temp);
-  out_len -= out_len_temp; // see above
-  if (retval == (size_t) -1)
-    {
-      std::cerr << strerror(errno) << std::endl;
-      std::cerr << "Error: conversion from " << from_charset
-                << " to " << to_charset << " went wrong: " << retval << std::endl;
-      return "";
-    }
-  iconv_close(cd);
-
-  std::string ret(out_orig, out_len);
-  delete[] out_orig;
-  delete[] in_orig;
-  return ret;
-}
-
-bool has_suffix(const std::string& lhs, const std::string rhs)
-{
-  if (lhs.length() < rhs.length())
-    return false;
-  else
-    return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
-}
-
-bool has_prefix(const std::string& lhs, const std::string rhs)
-{
-  if (lhs.length() < rhs.length())
-    return false;
-  else
-    return lhs.compare(0, rhs.length(), rhs) == 0;
-}
-
-int plural1(int )     { return 0; }
-int plural2_1(int n)  { return (n != 1); }
-int plural2_2(int n)  { return (n > 1); }
-int plural3_lv(int n) { return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); }
-int plural3_ga(int n) { return n==1 ? 0 : n==2 ? 1 : 2; }
-int plural3_lt(int n) { return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2); }
-int plural3_1(int n)  { return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
-int plural3_sk(int n) { return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; }
-int plural3_pl(int n) { return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
-int plural3_sl(int n) { return (n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3); }
-
-/** Language Definitions */
-//*{
-LanguageDef lang_hu("hu", "Hungarian",         1, plural1); // "nplurals=1; plural=0;"
-LanguageDef lang_ja("ja", "Japanese",          1, plural1); // "nplurals=1; plural=0;"
-LanguageDef lang_ko("ko", "Korean",            1, plural1); // "nplurals=1; plural=0;"
-LanguageDef lang_tr("tr", "Turkish",           1, plural1); // "nplurals=1; plural=0;"
-LanguageDef lang_da("da", "Danish",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_nl("nl", "Dutch",             2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_en("en", "English",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_fo("fo", "Faroese",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_de("de", "German",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_nb("nb", "Norwegian Bokmal",  2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_no("no", "Norwegian",         2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_nn("nn", "Norwegian Nynorsk", 2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_sv("sv", "Swedish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_et("et", "Estonian",          2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_fi("fi", "Finnish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_el("el", "Greek",             2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_he("he", "Hebrew",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_it("it", "Italian",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_pt("pt", "Portuguese",        2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_es("es", "Spanish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_eo("eo", "Esperanto",         2, plural2_1); // "nplurals=2; plural=(n != 1);"
-LanguageDef lang_fr("fr", "French",            2, plural2_2); // "nplurals=2; plural=(n > 1);"
-LanguageDef lang_pt_BR("pt_BR", "Brazilian",   2, plural2_2); // "nplurals=2; plural=(n > 1);"
-LanguageDef lang_lv("lv", "Latvian",           3, plural3_lv); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
-LanguageDef lang_ga("ga", "Irish",             3, plural3_ga); // "nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"
-LanguageDef lang_lt("lt", "Lithuanian",        3, plural3_lt); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"
-LanguageDef lang_hr("hr", "Croatian",          3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
-LanguageDef lang_cs("cs", "Czech",             3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
-LanguageDef lang_ru("ru", "Russian",           3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
-LanguageDef lang_uk("uk", "Ukrainian",         3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
-LanguageDef lang_sk("sk", "Slovak",            3, plural3_sk); // "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
-LanguageDef lang_pl("pl", "Polish",            3, plural3_pl); // "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
-LanguageDef lang_sl("sl", "Slovenian",         3, plural3_sl); // "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
-//*}
-
-LanguageDef&
-get_language_def(const std::string& name)
-{
-  if (name == "hu") return lang_hu;
-  else if (name == "ja") return lang_ja;
-  else if (name == "ko") return lang_ko;
-  else if (name == "tr") return lang_tr;
-  else if (name == "da") return lang_da;
-  else if (name == "nl") return lang_nl;
-  else if (name == "en") return lang_en;
-  else if (name == "fo") return lang_fo;
-  else if (name == "de") return lang_de;
-  else if (name == "nb") return lang_nb;
-  else if (name == "no") return lang_no;
-  else if (name == "nn") return lang_nn;
-  else if (name == "sv") return lang_sv;
-  else if (name == "et") return lang_et;
-  else if (name == "fi") return lang_fi;
-  else if (name == "el") return lang_el;
-  else if (name == "he") return lang_he;
-  else if (name == "it") return lang_it;
-  else if (name == "pt") return lang_pt;
-  else if (name == "es") return lang_es;
-  else if (name == "eo") return lang_eo;
-  else if (name == "fr") return lang_fr;
-  else if (name == "pt_BR") return lang_pt_BR;
-  else if (name == "lv") return lang_lv;
-  else if (name == "ga") return lang_ga;
-  else if (name == "lt") return lang_lt;
-  else if (name == "hr") return lang_hr;
-  else if (name == "cs") return lang_cs;
-  else if (name == "ru") return lang_ru;
-  else if (name == "uk") return lang_uk;
-  else if (name == "sk") return lang_sk;
-  else if (name == "pl") return lang_pl;
-  else if (name == "sl") return lang_sl;
-  else return lang_en; 
-}
-
-DictionaryManager::DictionaryManager()
-  : current_dict(&empty_dict)
-{
-  parseLocaleAliases();
-  // setup language from environment vars
-  const char* lang = getenv("LC_ALL");
-  if(!lang)
-    lang = getenv("LC_MESSAGES");
-  if(!lang)
-    lang = getenv("LANG");
-  
-  if(lang)
-    set_language(lang);
-}
-
-void
-DictionaryManager::parseLocaleAliases()
-{
-  // try to parse language alias list
-  std::ifstream in("/usr/share/locale/locale.alias");
-  
-  char c = ' ';
-  while(in.good() && !in.eof()) {
-    while(isspace(c) && !in.eof())
-      in.get(c);
-    
-    if(c == '#') { // skip comments
-      while(c != '\n' && !in.eof())
-        in.get(c);
-      continue;
-    }
-    
-    std::string alias;
-    while(!isspace(c) && !in.eof()) {
-      alias += c;
-      in.get(c);
-    }
-    while(isspace(c) && !in.eof())
-      in.get(c);
-    std::string language;
-    while(!isspace(c) && !in.eof()) {
-      language += c;
-      in.get(c);
-    }
-
-    if(in.eof())
-      break;
-    set_language_alias(alias, language);
-  }
-}
-  
-Dictionary&
-DictionaryManager::get_dictionary(const std::string& spec)
-{
-  std::string lang = get_language_from_spec(spec);
-  Dictionaries::iterator i = dictionaries.find(get_language_from_spec(lang));
-  if (i != dictionaries.end())
-    {
-      return i->second;
-    }
-  else // Dictionary for languages lang isn't loaded, so we load it
-    {
-      //std::cout << "get_dictionary: " << lang << std::endl;
-      Dictionary& dict = dictionaries[lang];
-
-      dict.set_language(get_language_def(lang));
-      if(charset != "")
-        dict.set_charset(charset);
-
-      for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
-        {
-          DIR* dir = opendir(p->c_str());
-          if (!dir)
-            {
-              std::cerr << "Error: opendir() failed on " << *p << std::endl;
-            }
-          else
-            {
-              struct dirent* ent;
-              while((ent = readdir(dir)))
-                {
-                  if (std::string(ent->d_name) == lang + ".po")
-                    {
-                      std::string pofile = *p + "/" + ent->d_name;
-                      std::ifstream in(pofile.c_str());
-                      if (!in)
-                        {
-                          std::cerr << "Error: Failure file opening: " << pofile << std::endl;
-                        }
-                      else
-                        {
-                          read_po_file(dict, in);
-                        }
-                    }
-                }
-              closedir(dir);
-            }
-        }
-
-      return dict;
-    }
-}
-
-std::set<std::string>
-DictionaryManager::get_languages()
-{
-  std::set<std::string> languages;
-
-  for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
-    {
-      DIR* dir = opendir(p->c_str());
-      if (!dir)
-        {
-          std::cerr << "Error: opendir() failed on " << *p << std::endl;
-        }
-      else
-        {
-          struct dirent* ent;
-          while((ent = readdir(dir)))
-            {
-              if (has_suffix(ent->d_name, ".po"))
-                {
-                  std::string filename = ent->d_name;
-                  languages.insert(filename.substr(0, filename.length()-3));
-                }
-            }
-          closedir(dir);
-        }
-    }  
-  return languages;
-}
-
-void
-DictionaryManager::set_language(const std::string& lang)
-{
-  language = get_language_from_spec(lang);
-  current_dict = & (get_dictionary(language));
-}
-
-void
-DictionaryManager::set_charset(const std::string& charset)
-{
-  dictionaries.clear(); // changing charset invalidates cache
-  this->charset = charset;
-  set_language(language);
-}
-
-void
-DictionaryManager::set_language_alias(const std::string& alias,
-    const std::string& language)
-{
-  language_aliases.insert(std::make_pair(alias, language));
-}
-
-std::string
-DictionaryManager::get_language_from_spec(const std::string& spec)
-{
-  std::string lang = spec;
-  Aliases::iterator i = language_aliases.find(lang);
-  if(i != language_aliases.end()) {
-    lang = i->second;
-  }
-  
-  std::string::size_type s = lang.find_first_of("_.");
-  if(s == std::string::npos)
-    return lang;
-
-  return std::string(lang, 0, s);  
-}
-
-void
-DictionaryManager::add_directory(const std::string& pathname)
-{
-  dictionaries.clear(); // adding directories invalidates cache
-  search_path.push_back(pathname);
-  set_language(language);
-}
-
-//---------------------------------------------------------------------------
-
-Dictionary::Dictionary(const LanguageDef& language_, const std::string& charset_)
-  : language(language_), charset(charset_)
-{
-}
-
-Dictionary::Dictionary()
-  : language(lang_en)
-{
-}
-
-std::string
-Dictionary::get_charset() const
-{
-  return charset;
-}
-
-void
-Dictionary::set_charset(const std::string& charset_)
-{
-  charset = charset_;
-}
-
-void
-Dictionary::set_language(const LanguageDef& lang)
-{
-  language = lang;
-}
-
-std::string
-Dictionary::translate(const std::string& msgid, const std::string& msgid2, int num) 
-{
-  PluralEntries::iterator i = plural_entries.find(msgid);
-  std::map<int, std::string>& msgstrs = i->second;
-
-  if (i != plural_entries.end() && !msgstrs.empty())
-    {
-      int g = language.plural(num);
-      std::map<int, std::string>::iterator j = msgstrs.find(g);
-      if (j != msgstrs.end())
-        {
-          return j->second;
-        }
-      else
-        {
-          // Return the first translation, in case we can't translate the specific number
-          return msgstrs.begin()->second;
-        }
-    }
-  else
-    {
-#ifdef TRANSLATION_DEBUG
-      std::cerr << "Warning: Couldn't translate: " << msgid << std::endl;
-      std::cerr << "Candidates: " << std::endl;
-      for (PluralEntries::iterator i = plural_entries.begin(); i != plural_entries.end(); ++i)
-        std::cout << "'" << i->first << "'" << std::endl;
-#endif
-
-      if (plural2_1(num)) // default to english rules
-        return msgid2;
-      else
-        return msgid;
-    }
-}
-
-std::string
-Dictionary::translate(const std::string& msgid) 
-{
-  Entries::iterator i = entries.find(msgid);
-  if (i != entries.end() && !i->second.empty())
-    {
-      return i->second;
-    }
-  else
-    {
-#ifdef TRANSLATION_DBEUG
-      std::cout << "Error: Couldn't translate: " << msgid << std::endl;
-#endif
-      return msgid;
-    }
-}
-  
-void
-Dictionary::add_translation(const std::string& msgid, const std::string& ,
-                            const std::map<int, std::string>& msgstrs)
-{
-  // Do we need msgid2 for anything? its after all supplied to the
-  // translate call, so we just throw it away
-  plural_entries[msgid] = msgstrs;
-}
-
-void 
-Dictionary::add_translation(const std::string& msgid, const std::string& msgstr) 
-{
-  entries[msgid] = msgstr;
-}
-
-class POFileReader
-{
-private:
-  struct Token
-  {
-    std::string keyword;
-    std::string content;
-  };
-
-  Dictionary& dict;
-
-  std::string from_charset;
-  std::string to_charset;
-
-  std::string current_msgid;
-  std::string current_msgid_plural;
-  std::map<int, std::string> msgstr_plural;
-
-  int line_num;
-
-  enum { WANT_MSGID, WANT_MSGSTR, WANT_MSGSTR_PLURAL, WANT_MSGID_PLURAL } state;
-
-public:
-  POFileReader(std::istream& in, Dictionary& dict_)
-    : dict(dict_)
-  {
-    state = WANT_MSGID;
-    line_num = 0;
-    tokenize_po(in);
-  }
-
-  void parse_header(const std::string& header)
-  {
-    // Seperate the header in lines
-    typedef std::vector<std::string> Lines;
-    Lines lines;
-    
-    std::string::size_type start = 0;
-    for(std::string::size_type i = 0; i < header.length(); ++i)
-      {
-        if (header[i] == '\n')
-          {
-            lines.push_back(header.substr(start, i - start));
-            start = i+1;
-          }
-      }
-
-    for(Lines::iterator i = lines.begin(); i != lines.end(); ++i)
-      {
-        if (has_prefix(*i, "Content-Type: text/plain; charset=")) {
-          from_charset = i->substr(strlen("Content-Type: text/plain; charset="));
-        }
-      }
-
-    if (from_charset.empty() || from_charset == "CHARSET")
-      {
-        std::cerr << "Error: Charset not specified for .po, fallback to ISO-8859-1" << std::endl;
-        from_charset = "ISO-8859-1";
-      }
-
-    to_charset = dict.get_charset();
-    if (to_charset.empty())
-      { // No charset requested from the dict, so we use the one from the .po 
-        to_charset = from_charset;
-        dict.set_charset(from_charset);
-      }
-  }
-
-  void add_token(const Token& token)
-  {
-    switch(state) 
-      {
-      case WANT_MSGID:
-        if (token.keyword == "msgid") 
-          {
-            current_msgid = token.content;
-            state = WANT_MSGID_PLURAL;
-          }
-        else if (token.keyword.empty())
-          {
-            //std::cerr << "Got EOF, everything looks ok." << std::endl;
-          }
-        else
-          {
-            std::cerr << "tinygettext: expected 'msgid' keyword, got " << token.keyword 
-                      << " at line " << line_num << std::endl;
-          }
-        break;
-    
-      case WANT_MSGID_PLURAL:
-        if (token.keyword == "msgid_plural") 
-          {
-            current_msgid_plural = token.content;
-            state = WANT_MSGSTR_PLURAL;
-          } 
-        else
-          {
-            state = WANT_MSGSTR;
-            add_token(token);
-          }
-        break;
-
-      case WANT_MSGSTR:
-        if (token.keyword == "msgstr") 
-          {
-            if (current_msgid == "") 
-              { // .po Header is hidden in the msgid with the empty string
-                parse_header(token.content);
-              }
-            else
-              {
-                dict.add_translation(current_msgid, convert(token.content, from_charset, to_charset));
-              }
-            state = WANT_MSGID;
-          } 
-        else
-          {
-            std::cerr << "tinygettext: expected 'msgstr' keyword, got " << token.keyword 
-                      << " at line " << line_num << std::endl;
-          }
-        break;
-
-      case WANT_MSGSTR_PLURAL:
-        if (has_prefix(token.keyword, "msgstr[")) 
-          {
-            int num;
-            if (sscanf(token.keyword.c_str(), "msgstr[%d]", &num) != 1) 
-              {
-                std::cerr << "Error: Couldn't parse: " << token.keyword << std::endl;
-              } 
-            else 
-              {
-                msgstr_plural[num] = convert(token.content, from_charset, to_charset);
-              }
-          }
-        else 
-          {
-            dict.add_translation(current_msgid, current_msgid_plural, msgstr_plural);
-
-            state = WANT_MSGID;
-            add_token(token);
-          }
-        break;
-      }
-  }
-  
-  inline int getchar(std::istream& in) 
-  {
-    int c = in.get();
-    if (c == '\n')
-      line_num += 1;
-    return c;
-  }
-  
-  void tokenize_po(std::istream& in)
-  {
-    enum State { READ_KEYWORD, 
-                 READ_CONTENT,
-                 READ_CONTENT_IN_STRING,
-                 SKIP_COMMENT };
-
-    State state = READ_KEYWORD;
-    int c;
-    Token token;
-
-    while((c = getchar(in)) != EOF)
-      {
-        //std::cout << "Lexing char: " << char(c) << " " << state << std::endl;
-        switch(state)
-          {
-          case READ_KEYWORD:
-            if (c == '#')
-              {
-                state = SKIP_COMMENT;
-              }
-            else
-              {
-                // Read a new token
-                token = Token();
-                
-                do { // Read keyword 
-                  token.keyword += c;
-                } while((c = getchar(in)) != EOF && !isspace(c));
-                in.unget();
-
-                state = READ_CONTENT;
-              }
-            break;
-
-          case READ_CONTENT:
-            while((c = getchar(in)) != EOF)
-              {
-                if (c == '"') { 
-                  // Found start of content
-                  state = READ_CONTENT_IN_STRING;
-                  break;
-                } else if (isspace(c)) {
-                  // skip
-                } else { // Read something that may be a keyword
-                  in.unget();
-                  state = READ_KEYWORD;
-                  add_token(token);
-                  break;
-                }
-              }
-            break;
-
-          case READ_CONTENT_IN_STRING:
-            if (c == '\\') {
-              c = getchar(in);
-              if (c != EOF)
-                {
-                  if (c == 'n') token.content += '\n';
-                  else if (c == 't') token.content += '\t';
-                  else if (c == 'r') token.content += '\r';
-                  else if (c == '"') token.content += '"';
-                  else
-                    {
-                      std::cout << "Unhandled escape character: " << char(c) << std::endl;
-                    }
-                }
-              else
-                {
-                  std::cout << "Unterminated string" << std::endl;
-                }
-            } else if (c == '"') { // Content string is terminated
-              state = READ_CONTENT;
-            } else {
-              token.content += c;
-            }
-            break;
-
-          case SKIP_COMMENT:
-            if (c == '\n')
-              state = READ_KEYWORD;
-            break;
-          }
-      }
-    add_token(token);
-  }
-};
-
-void read_po_file(Dictionary& dict_, std::istream& in) 
-{
-  POFileReader reader(in, dict_);
-}
-
-} // namespace TinyGetText
-
-/* EOF */
diff --git a/lib/app/tinygettext.h b/lib/app/tinygettext.h
deleted file mode 100644 (file)
index 207ce28..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-//  $Id$
-// 
-//  TinyGetText - A small flexible gettext() replacement
-//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#ifndef HEADER_TINYGETTEXT_H
-#define HEADER_TINYGETTEXT_H
-
-#include <map>
-#include <vector>
-#include <set>
-#include <string>
-
-namespace TinyGetText {
-
-typedef int (*PluralFunc)(int n);
-
-struct LanguageDef {
-  const char* code;
-  const char* name;
-  int         nplural;
-  PluralFunc  plural;
-
-  LanguageDef(const char* code_, const char* name_,  int nplural_, PluralFunc plural_)
-    : code(code_), name(name_), nplural(nplural_), plural(plural_)
-  {}
-};
-
-/** A simple dictionary class that mimics gettext() behaviour. Each
-    Dictionary only works for a single language, for managing multiple
-    languages and .po files at once use the DictionaryManager. */
-class Dictionary
-{
-private:
-  typedef std::map<std::string, std::string> Entries;
-  Entries entries;
-
-  typedef std::map<std::string, std::map<int, std::string> > PluralEntries;
-  PluralEntries plural_entries;
-
-  LanguageDef language;
-  std::string charset;
-public:
-  /** */
-  Dictionary(const LanguageDef& language_, const std::string& charset = "");
-
-  Dictionary();
-
-  /** Return the charset used for this dictionary */
-  std::string get_charset() const;
-
-  /** Set a charset for this dictionary, this will NOT convert stuff,
-      it is for information only, you have to convert stuff yourself
-      when you add it with \a add_translation() */
-  void set_charset(const std::string& charset);
-
-  /** Set the language that is used for this dictionary, this is
-      mainly needed to evaluate plural forms */
-  void set_language(const LanguageDef& lang);
-
-  /** Translate the string \a msgid to its correct plural form, based
-      on the number of items given by \a num. \a msgid2 is \a msgid in
-      plural form. */
-  std::string translate(const std::string& msgid, const std::string& msgid2, int num);
-
-  /** Translate the string \a msgid. */
-  std::string translate(const std::string& msgid);
-    
-  /** Add a translation from \a msgid to \a msgstr to the dictionary,
-      where \a msgid is the singular form of the message, msgid2 the
-      plural form and msgstrs a table of translations. The right
-      translation will be calculated based on the \a num argument to
-      translate(). */
-  void add_translation(const std::string& msgid, const std::string& msgid2,
-                       const std::map<int, std::string>& msgstrs);
-
-  /** Add a translation from \a msgid to \a msgstr to the
-      dictionary */
-  void add_translation(const std::string& msgid, const std::string& msgstr);
-};
-
-/** Manager class for dictionaries, you give it a bunch of directories
-    with .po files and it will then automatically load the right file
-    on demand depending on which language was set. */
-class DictionaryManager
-{
-private:
-  typedef std::map<std::string, Dictionary> Dictionaries;
-  Dictionaries dictionaries;
-  typedef std::vector<std::string> SearchPath;
-  SearchPath search_path;
-  typedef std::map<std::string, std::string> Aliases;
-  Aliases language_aliases;
-  std::string charset;
-  std::string language;
-  Dictionary* current_dict;
-  Dictionary empty_dict;
-
-public:
-  DictionaryManager();
-
-  /** Return the currently active dictionary, if none is set, an empty
-      dictionary is returned. */
-  Dictionary& get_dictionary()
-  { return *current_dict; }
-
-  /** Get dictionary for lang */
-  Dictionary& get_dictionary(const std::string& langspec);
-
-  /** Set a language based on a four? letter country code */
-  void set_language(const std::string& langspec);
-
-  /** Set a charset that will be set on the returned dictionaries */
-  void set_charset(const std::string& charset);
-
-  /** Define an alias for a language */
-  void set_language_alias(const std::string& alias, const std::string& lang);
-
-  /** Add a directory to the search path for dictionaries */
-  void add_directory(const std::string& pathname);
-  
-  /** Return a set of the available languages in their country code */
-  std::set<std::string> get_languages();
-
-private:
-  void parseLocaleAliases();
-  /// returns the language part in a language spec (like de_DE.UTF-8 -> de)
-  std::string get_language_from_spec(const std::string& spec);
-};
-
-/** Read the content of the .po file given as \a in into the
-    dictionary given as \a dict */
-void read_po_file(Dictionary& dict, std::istream& in);
-LanguageDef& get_language_def(const std::string& name);
-
-} // namespace TinyGetText
-
-#endif
-
-/* EOF */
diff --git a/lib/lisp/.cvsignore b/lib/lisp/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/lib/math/.cvsignore b/lib/math/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/lib/math/aatriangle.h b/lib/math/aatriangle.h
deleted file mode 100644 (file)
index 97cbae8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef __AATRIANGLE_H__
-#define __AATRIANGLE_H__
-
-#include "rectangle.h"
-
-namespace SuperTux
-{
-
-/**
- * An axis aligned triangle (ie. a triangle where 2 sides are parallel to the x-
- * and y-axis.
- */
-class AATriangle : public Rectangle
-{
-public:
-  /** Directions:
-   *
-   *    SOUTHEWEST    NORTHEAST   SOUTHEAST    NORTHWEST
-   *    *      or      *---*   or      *    or *---* 
-   *    | \             \  |         / |       |  /
-   *    |  \             \ |        /  |       | /
-   *    *---*              *       *---*       *
-   *
-   * Deform flags: (see docs/aatriangletypes.png for details)
-   */
-  enum Direction {
-    SOUTHWEST = 0,
-    NORTHEAST,
-    SOUTHEAST,
-    NORTHWEST,
-    DIRECTION_MASK = 0x0003,
-    DEFORM1 = 0x0010,
-    DEFORM2 = 0x0020,
-    DEFORM3 = 0x0030,
-    DEFORM4 = 0x0040,
-    DEFORM_MASK = 0x0070
-  };
-
-  AATriangle()
-    : dir(SOUTHWEST)
-  {
-  }
-  AATriangle(const Vector& v1, const Vector& v2, int newdir)
-    : Rectangle(v1, v2), dir(newdir)
-  {
-  }
-
-  int dir;
-};
-
-}
-
-#endif
-
diff --git a/lib/math/physic.cpp b/lib/math/physic.cpp
deleted file mode 100644 (file)
index 6276a09..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#include <config.h>
-
-#include <cstdio>
-
-#include "math/physic.h"
-
-using namespace SuperTux;
-
-Physic::Physic()
-    : ax(0), ay(0), vx(0), vy(0), gravity_enabled(true)
-{
-}
-
-Physic::~Physic()
-{
-}
-
-void
-Physic::reset()
-{
-    ax = ay = vx = vy = 0;
-    gravity_enabled = true;
-}
-
-void
-Physic::set_velocity_x(float nvx)
-{
-  vx = nvx;
-}
-
-void
-Physic::set_velocity_y(float nvy)
-{
-  vy = -nvy;
-}
-
-void
-Physic::set_velocity(float nvx, float nvy)
-{
-  vx = nvx;
-  vy = -nvy;
-}
-
-void Physic::inverse_velocity_x()
-{
-vx = -vx;
-}
-
-void Physic::inverse_velocity_y()
-{
-vy = -vy;
-}
-
-float
-Physic::get_velocity_x()
-{
-    return vx;
-}
-
-float
-Physic::get_velocity_y()
-{
-    return -vy;
-}
-
-void
-Physic::set_acceleration_x(float nax)
-{
-  ax = nax;
-}
-
-void
-Physic::set_acceleration_y(float nay)
-{
-  ay = -nay;
-}
-
-void
-Physic::set_acceleration(float nax, float nay)
-{
-    ax = nax;
-    ay = -nay;
-}
-
-float
-Physic::get_acceleration_x()
-{
-    return ax;
-}
-
-float
-Physic::get_acceleration_y()
-{
-    return -ay;
-}
-
-void
-Physic::enable_gravity(bool enable_gravity)
-{
-  gravity_enabled = enable_gravity;
-}
-
-Vector
-Physic::get_movement(float elapsed_time)
-{
-  float grav = gravity_enabled ? 1000 : 0;
-  
-  Vector result(
-      vx * elapsed_time + ax * elapsed_time * elapsed_time,
-      vy * elapsed_time + (ay + grav) * elapsed_time * elapsed_time
-  );
-  vx += ax * elapsed_time;
-  vy += (ay + grav) * elapsed_time;  
-
-  return result;
-}
-
diff --git a/lib/math/physic.h b/lib/math/physic.h
deleted file mode 100644 (file)
index 71d7ccd..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#ifndef SUPERTUX_PHYSIC_H
-#define SUPERTUX_PHYSIC_H
-
-#include "math/vector.h"
-
-namespace SuperTux
-  {
-
-  /// Physics engine.
-  /** This is a very simplistic physics engine handling accelerated and constant
-    * movement along with gravity.
-    */
-  class Physic
-    {
-    public:
-      Physic();
-      ~Physic();
-
-      /// Resets all velocities and accelerations to 0.
-      void reset();
-
-      /// Sets velocity to a fixed value.
-      void set_velocity(float vx, float vy);
-
-      void set_velocity_x(float vx);
-      void set_velocity_y(float vy);
-
-      /// Velocities invertion.
-      void inverse_velocity_x();
-      void inverse_velocity_y();
-
-      float get_velocity_x();
-      float get_velocity_y();
-
-      /// Set acceleration.
-      /** Sets acceleration applied to the object. (Note that gravity is
-       * eventually added to the vertical acceleration)
-       */
-      void set_acceleration(float ax, float ay);
-
-      void set_acceleration_x(float ax);
-      void set_acceleration_y(float ay);
-
-      float get_acceleration_x();
-      float get_acceleration_y();
-
-      /// Enables or disables handling of gravity.
-      void enable_gravity(bool gravity_enabled);
-
-      Vector get_movement(float elapsed_time);
-
-    private:
-      /// horizontal and vertical acceleration
-      float ax, ay;
-      /// horizontal and vertical velocity
-      float vx, vy;
-      /// should we respect gravity in out calculations?
-      bool gravity_enabled;
-    };
-
-} //namespace SuperTux
-
-#endif /*SUPERTUX_PHYSIC_H*/
diff --git a/lib/math/rectangle.h b/lib/math/rectangle.h
deleted file mode 100644 (file)
index e0254bc..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef __RECTANGLE_H__
-#define __RECTANGLE_H__
-
-#include <assert.h>
-#include "vector.h"
-
-namespace SuperTux
-{
-
-/** This class represents a rectangle.
- * (Implementation Note) We're using upper left and lower right point instead of
- * upper left and width/height here, because that makes the collision dectection
- * a little bit efficienter.
- */
-class Rectangle
-{
-public:
-  Rectangle()
-  { }
-
-  Rectangle(const Vector& np1, const Vector& np2)
-    : p1(np1), p2(np2)
-  {
-  }
-
-  Rectangle(float x1, float y1, float x2, float y2)
-    : p1(x1, y1), p2(x2, y2)
-  {
-    assert(p1.x <= p2.x && p1.y <= p2.y);
-  }
-
-  float get_width() const
-  { return p2.x - p1.x; }
-
-  float get_height() const
-  { return p2.y - p1.y; }
-
-  Vector get_middle() const
-  { return Vector((p1.x+p2.x)/2, (p1.y+p2.y)/2); }
-
-  void set_pos(const Vector& v)
-  {
-    move(v-p1);
-  }
-
-  void set_height(float height)
-  {
-    p2.y = p1.y + height;
-  }
-  void set_width(float width)
-  {
-    p2.x = p1.x + width;
-  }
-  void set_size(float width, float height)
-  {
-    set_width(width);
-    set_height(height);
-  }                                         
-
-  void move(const Vector& v)
-  {
-    p1 += v;
-    p2 += v;
-  }
-
-  bool inside(const Vector& v) const
-  {
-    return v.x >= p1.x && v.y >= p1.y && v.x < p2.x && v.y < p2.y;
-  }
-  bool inside(const Rectangle& other) const
-  {
-    if(p1.x >= other.p2.x || other.p1.x >= p2.x)
-      return false;
-    if(p1.y >= other.p2.y || other.p1.y >= p2.y)
-      return false;
-
-    return true;
-  }
-   
-  // leave these 2 public to safe the headaches of set/get functions for such
-  // simple things :)
-
-  /// upper left edge
-  Vector p1;
-  /// lower right edge
-  Vector p2;
-};
-
-}
-
-#endif
-
diff --git a/lib/math/vector.cpp b/lib/math/vector.cpp
deleted file mode 100644 (file)
index 66a8352..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#include <config.h>
-
-#include <cmath>
-
-#include "math/vector.h"
-
-using namespace SuperTux;
-
-Vector Vector::unit() const
-{
-  return *this / norm();
-}
-
-float Vector::norm() const
-{
-  return sqrt(x*x + y*y);
-}
diff --git a/lib/math/vector.h b/lib/math/vector.h
deleted file mode 100644 (file)
index 31b171d..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-//  $Id$
-//
-//  SuperTux -  A Jump'n Run
-//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#ifndef SUPERTUX_VECTOR_H
-#define SUPERTUX_VECTOR_H
-
-namespace SuperTux
-  {
-
-  /// 2D Vector.
-  /** Simple two dimensional vector. */
-  class Vector
-    {
-    public:
-      Vector(float nx, float ny)
-          : x(nx), y(ny)
-      { }
-      Vector(const Vector& other)
-          : x(other.x), y(other.y)
-      { }
-      Vector()
-          : x(0), y(0)
-      { }
-
-      bool operator ==(const Vector& other) const
-        {
-          return x == other.x && y == other.y;
-        }
-
-      bool operator !=(const Vector& other) const
-        {
-          return !(x == other.x && y == other.y);
-        }
-
-      const Vector& operator=(const Vector& other)
-      {
-        x = other.x;
-        y = other.y;
-        return *this;
-      }
-
-      Vector operator+(const Vector& other) const
-        {
-          return Vector(x + other.x, y + other.y);
-        }
-
-      Vector operator-(const Vector& other) const
-        {
-          return Vector(x - other.x, y - other.y);
-        }
-
-      Vector operator*(float s) const
-        {
-          return Vector(x * s, y * s);
-        }
-
-      Vector operator/(float s) const
-        {
-          return Vector(x / s, y / s);
-        }
-
-      Vector operator-() const
-        {
-          return Vector(-x, -y);
-        }
-
-      const Vector& operator +=(const Vector& other)
-      {
-        x += other.x;
-        y += other.y;
-        return *this;
-      }
-
-      const Vector& operator *=(float val)
-      {
-        x *= val;
-        y *= val;
-        return *this;
-      }
-
-      const Vector& operator /=(float val)
-      {
-        x /= val;
-        y /= val;
-        return *this;
-      }
-
-      /// Scalar product of 2 vectors
-      float operator*(const Vector& other) const
-        {
-          return x*other.x + y*other.y;
-        }
-
-      float norm() const;
-      Vector unit() const;
-
-      // ... add the other operators as needed, I'm too lazy now ...
-
-      float x, y; // leave this public, get/set methods just give me headaches
-      // for such simple stuff :)
-    };
-
-} //namespace SuperTux
-
-#endif /*SUPERTUX_VECTOR_H*/
-
diff --git a/lib/special/.cvsignore b/lib/special/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/lib/special/frame_rate.cpp b/lib/special/frame_rate.cpp
deleted file mode 100644 (file)
index cff4071..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#include <config.h>
-
-#include "SDL.h"
-
-#include "frame_rate.h"
-#include "timer.h"
-
-using namespace SuperTux;
-
-FrameRate::FrameRate(double fps)
-{
-  set_fps(fps);
-  set_frame_limit(true);
-}
-
-void FrameRate::start()
-{
-  update_time = last_update_time = Ticks::get();  
-}
-
-void FrameRate::set_fps(double fps)
-{
-  frame_ms = static_cast<unsigned int>(1000.f/fps);
-}
-
-void FrameRate::set_frame_limit(bool set_limit)
-{
-  frame_limit = set_limit;
-}
-
-double FrameRate::get()
-{
-  return ((double)(update_time-last_update_time))/(double)frame_ms;
-}
-
-void FrameRate::update()
-{
-  /* Set the time of the last update and the time of the current update */
-  last_update_time = update_time;
-  update_time      = Ticks::get();
-
-  /* Pause till next frame, if the machine running the game is too fast: */
-  /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
-     the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
-  if(frame_limit && last_update_time >= update_time - (frame_ms+2))
-    {
-      SDL_Delay(frame_ms);
-      update_time = Ticks::get();
-    }
-}
-
-void FrameRate::smooth_hanger()
-{
-      if( (update_time - last_update_time) > frame_ms*100)
-        update_time = last_update_time = Ticks::get();
-}
diff --git a/lib/special/frame_rate.h b/lib/special/frame_rate.h
deleted file mode 100644 (file)
index 646498d..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#ifndef SUPERTUX_FRAMERATE_H
-#define SUPERTUX_FRAMERATE_H
-
-namespace SuperTux
-  {
-
-  class FrameRate
-    {
-    public:
-      FrameRate() {};
-      FrameRate(double fps);
-      void start();
-      void set_fps(double fps);
-      void set_frame_limit(bool);
-      double get();
-      void update();
-      void smooth_hanger();
-    private:
-      unsigned int last_update_time;
-      unsigned int update_time;
-      unsigned int frame_ms;
-      bool frame_limit;
-    };
-
-} //namespace SuperTux
-
-#endif /*SUPERTUX_FRAMERATE_H*/
-
diff --git a/lib/special/timer.cpp b/lib/special/timer.cpp
deleted file mode 100644 (file)
index 1ff1349..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#include <config.h>
-
-#include "SDL.h"
-#include "timer.h"
-
-using namespace SuperTux;
-
-unsigned int Ticks::pause_ticks, Ticks::pause_count;
-
-unsigned int Ticks::get(void)
-{
-  if(pause_count != 0)
-    return /*SDL_GetTicks()*/ - pause_ticks /*- SDL_GetTicks()*/ + pause_count;
-  else
-    return SDL_GetTicks() - pause_ticks;
-}
-
-void Ticks::pause_init(void)
-{
-  pause_ticks = 0;
-  pause_count = 0;
-}
-
-void Ticks::pause_start(void)
-{
-  if(pause_count == 0)
-    pause_count = SDL_GetTicks();
-}
-
-void Ticks::pause_stop(void)
-{
-if(pause_count == 0)
-return;
-
-  pause_ticks += SDL_GetTicks() - pause_count;
-  pause_count = 0;
-}
-
-bool Ticks::pause_started(void)
-{
-if(pause_count == 0)
-return false;
-else
-return true;
-}
-
-Timer::Timer()
-{
-  init(true);
-}
-
-void
-Timer::init(bool game_ticks)
-{
-  period    = 0;
-  time      = 0;
-  get_ticks = game_ticks ? Ticks::get : SDL_GetTicks;
-}
-
-void
-Timer::start(unsigned int period_)
-{
-  time   = get_ticks();
-  period = period_;
-}
-
-void
-Timer::stop()
-{
-  if(get_ticks == get_ticks)
-    init(true);
-  else
-    init(false);
-}
-
-int
-Timer::check()
-{
-  if((time != 0) && (time + period > get_ticks()))
-    return true;
-  else
-    {
-      time = 0;
-      return false;
-    }
-}
-
-int
-Timer::started()
-{
-  if(time != 0)
-    return true;
-  else
-    return false;
-}
-
-int
-Timer::get_left()
-{
-  return (period - (get_ticks() - time));
-}
-
-int
-Timer::get_gone()
-{
-  return (get_ticks() - time);
-}
-
-void
-Timer::fwrite(FILE* fi)
-{
-  unsigned int diff_ticks;
-  int tick_mode;
-  if(time != 0)
-    diff_ticks = get_ticks() - time;
-  else
-    diff_ticks = 0;
-
-  ::fwrite(&period,sizeof(unsigned int),1,fi);
-  ::fwrite(&diff_ticks,sizeof(unsigned int),1,fi);
-  if(get_ticks == get_ticks)
-      tick_mode = true;
-  else
-      tick_mode = false;
-  ::fwrite(&tick_mode,sizeof(unsigned int),1,fi);
-}
-
-void
-Timer::fread(FILE* fi)
-{
-  unsigned int diff_ticks;
-  int tick_mode;
-
-  ::fread(&period,sizeof(unsigned int),1,fi);
-  ::fread(&diff_ticks,sizeof(unsigned int),1,fi);
-  ::fread(&tick_mode,sizeof(unsigned int),1,fi);
-
-  if (tick_mode)
-    get_ticks = get_ticks;
-  else
-    get_ticks = SDL_GetTicks;
-
-  if (diff_ticks != 0)
-    time = get_ticks() - diff_ticks;
-  else
-    time = 0;
-
-}
-
-/* EOF */
diff --git a/lib/special/timer.h b/lib/special/timer.h
deleted file mode 100644 (file)
index 1866a2c..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-//  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 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., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-
-#ifndef SUPERTUX_TIMER_H
-#define SUPERTUX_TIMER_H
-
-#include <cstdlib>
-
-namespace SuperTux
-  {
-
-  class Ticks
-    {
-    public:
-      /// Time a game is running. (Non-pause mode, etc.)
-      static unsigned int get();
-
-      static void pause_init();
-      static void pause_start();
-      static void pause_stop();
-      static bool pause_started();
-
-    private:
-      static unsigned int pause_ticks;
-      static unsigned int pause_count;
-
-    };
-
-  /// Timer
-  /** This class can be used as stop watch
-      for example. It's also possible to calculate
-      frames per seconds and things like that with it.
-      It's a general timing class, but it
-      can esspecially be used together with Ticks::get(). */
-  class Timer
-    {
-    public:
-      unsigned int period;
-      unsigned int time;
-      unsigned int (*get_ticks) (void);
-
-    public:
-      Timer();
-
-      /// Initialize the timer.
-      /** @param st_ticks: If true internally Ticks::get() is used, else SDL_GetTicks() is used. */
-      void init(bool game_ticks);
-
-      /// Start the timer with the given period (in ms).
-      void start(unsigned int period);
-
-      /// Stop the timer.
-      void stop();
-
-      /// Check if the timer is started and within its period.
-      /** If one of these requirements isn't the case the timer
-          is automatically reseted. */
-      int check();
-
-      /// Is the timer started?
-      int started();
-
-      /// Get time left until the last timing period is finished.
-      /** The returned value can be negative. */
-      int get_left();
-
-      /// Get the gone time, since last timer start.
-      /** The returned value can be negative. */
-      int  get_gone();
-
-      /// Write the timer value to a file (For save games in example).
-      void fwrite(FILE* fi);
-      /// Read a timer value from a file (From save games in example).
-      void fread(FILE* fi);
-    };
-
-} //namespace SuperTux
-
-#endif /*SUPERTUX_TIMER_H*/
-
-/* Local Variables: */
-/* mode:c++ */
-/* End: */
diff --git a/lib/utils/.cvsignore b/lib/utils/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/lib/video/.cvsignore b/lib/video/.cvsignore
deleted file mode 100644 (file)
index f8d9fd4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
index 82628ad..02e7ae9 100644 (file)
@@ -1,7 +1,11 @@
 SubDir TOP src ;
 
+SubInclude TOP src squirrel ;
+SubInclude TOP src scripting ;
+
 sources = 
     [ Wildcard *.cpp *.h ]
+    [ Wildcard math : *.cpp *.h ]
     [ Wildcard video : *.cpp *.h ]
     [ Wildcard audio : *.cpp *.h ]
     [ Wildcard gui : *.cpp *.h ]
@@ -14,8 +18,9 @@ sources =
 ;
 TRANSLATABLE_SOURCES += [ SearchSource $(sources) ] ;
 
-Application supertux : $(sources) ;
-LinkWith supertux : supertuxlib ;
+Application supertux : $(sources) $(wrapper_objects) ;
+LinkWith supertux : supertuxlib squirrel ;
 ExternalLibs supertux : SDL SDLMIXER SDLIMAGE GL ;
 Help supertux : "Build the supertux executable" ;
+IncludeDir supertux : squirrel/include ;
 
index f3d47ea..2bf8dd4 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include "audio/musicref.h"
 
-using namespace SuperTux;
-
 MusicRef::MusicRef()
   : music(0)
 {
index c7e624a..9d2883e 100644 (file)
 
 #include <cmath>
 #include <cassert>
+#include <iostream>
 #include <stdexcept>
 #include <sstream>
 
 #include "audio/sound_manager.h"
 #include "audio/musicref.h"
-#include "app/globals.h"
-#include "app/setup.h"
 #include "moving_object.h"
 #include "resources.h"
 
-using namespace SuperTux;
-
 SoundManager::SoundManager()
   : current_music(0), m_music_enabled(true) , m_sound_enabled(true),
     audio_device(false)
@@ -85,7 +82,7 @@ SoundManager::play_sound(const std::string& sound, const Vector& pos,
   // TODO make sure this formula is good
   float distance 
     = pos2.x- pos.x;
-  int loud = int(255.0/float(SCREEN_WIDTH*2) * fabsf(distance));
+  int loud = int(255.0/float(1600) * fabsf(distance));
   if(loud > 255)
     return;
 
index d0ddad5..09c0d00 100644 (file)
@@ -26,8 +26,6 @@
 #include "SDL_mixer.h"
 #include "math/vector.h"
 
-using namespace SuperTux;
-
 class MusicRef;
 class MovingObject;
 
index 42d56dd..6817efa 100644 (file)
@@ -205,7 +205,6 @@ BadGuy::kill_fall()
     physic.enable_gravity(true);
     set_state(STATE_FALLING);
   }
-  std::cout << "KILL_FALL - HITPOINTS: " << hitpoints << ", BULLET HP: " << bullet_hitpoints << std::endl;
 }
 
 void
index ecd753d..d5c948c 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __BADGUY_H__
 #define __BADGUY_H__
 
@@ -26,7 +25,7 @@
 #include "timer.h"
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "object/player.h"
 #include "serializable.h"
 #include "resources.h"
@@ -39,8 +38,6 @@
 #include "video/drawing_context.h"
 #include "sprite/sprite_manager.h"
 
-using namespace SuperTux;
-
 class BadGuy : public MovingObject, public Serializable
 {
 public:
index 82cec6f..b255576 100644 (file)
@@ -71,7 +71,6 @@ void
 MrIceBlock::active_action(float elapsed_time)
 {
   if(ice_state == ICESTATE_FLAT && flat_timer.check()) {
-    printf("unflat.\n");
     ice_state = ICESTATE_NORMAL;
     physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
     sprite->set_action(dir == LEFT ? "left" : "right");
@@ -161,7 +160,6 @@ MrIceBlock::collision_squished(Player& player)
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
       flat_timer.start(4);
       ice_state = ICESTATE_FLAT;
-      printf("flat.\n");
       break;
     case ICESTATE_FLAT:
       // kick
@@ -175,7 +173,6 @@ MrIceBlock::collision_squished(Player& player)
       physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED);
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
       ice_state = ICESTATE_KICKED;
-      printf("kicked.\n");
       break;
   }
 
index b171551..61c8b12 100644 (file)
@@ -149,7 +149,6 @@ Nolok_01::kill_fall()
    set_state(STATE_FALLING);
    Sector::current()->add_object(new Door((int)get_pos().x+32, 512, "sector1", "main2"));
   }
-  std::cout << "KILL_FALL - HITPOINTS: " << hitpoints << ", BULLET HP: " << bullet_hitpoints << std::endl;
 }
 
 IMPLEMENT_FACTORY(Nolok_01, "nolok_01")
index 3279275..c1da901 100644 (file)
@@ -235,7 +235,6 @@ Yeti::kill_fall()
     physic.enable_gravity(true);
     set_state(STATE_FALLING);
   }
-  std::cout << "KILL_FALL - HITPOINTS: " << hitpoints << ", BULLET HP: " << bullet_hitpoints << std::endl;
 }
 
 IMPLEMENT_FACTORY(Yeti, "yeti")
index 6b8662c..2c65c48 100644 (file)
 #ifndef __COLLISION_H__
 #define __COLLISION_H__
 
-namespace SuperTux {
 class Vector;
 class Rectangle;
 class AATriangle;
-}
-
-using namespace SuperTux;
-
 class CollisionHit;
 
 class Collision
index 1027562..d206c8c 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __COLLISION_GRID_H__
 #define __COLLISION_GRID_H__
 
 #include <vector>
 #include "moving_object.h"
 
-using namespace SuperTux;
-
 class CollisionGridIterator;
 
 /**
index d0f0fb8..fd3350b 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __COLLISION_GRID_ITERATOR_H__
 #define __COLLISION_GRID_ITERATOR_H__
 
 #include "math/rectangle.h"
 
-using namespace SuperTux;
-
 class CollisionGrid;
 
 class CollisionGridIterator
index cde4a31..4c4ccec 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "math/vector.h"
 
-using namespace SuperTux;
-
 /**
  * Used as return value for the collision functions, to indicate how the
  * collision should be handled
index d314dae..4f93091 100644 (file)
@@ -23,7 +23,7 @@
 #include <sstream>
 #include "joystickkeyboardcontroller.h"
 #include "gui/menu.h"
-#include "app/gettext.h"
+#include "gettext.h"
 #include "lisp/lisp.h"
 #include "lisp/list_iterator.h"
 #include "game_session.h"
@@ -71,12 +71,9 @@ JoystickKeyboardController::JoystickKeyboardController()
   keymap.insert(std::make_pair(SDLK_RETURN, MENU_SELECT));
   keymap.insert(std::make_pair(SDLK_KP_ENTER, MENU_SELECT));
   
-  joystick_count = SDL_NumJoysticks();
+  int joystick_count = SDL_NumJoysticks();
   min_joybuttons = -1;
   max_joybuttons = -1;
-#ifdef DEBUG
-  std::cout << "Found " << joystick_count << " joysticks.\n";
-#endif
   for(int i = 0; i < joystick_count; ++i) {
     SDL_Joystick* joystick = SDL_JoystickOpen(i);
     bool good = true;
@@ -91,8 +88,6 @@ JoystickKeyboardController::JoystickKeyboardController()
     }
     if(!good) {
       SDL_JoystickClose(joystick);
-      joysticks.push_back(0);
-      joystick_names.push_back("");
       continue;
     }
     
@@ -102,7 +97,6 @@ JoystickKeyboardController::JoystickKeyboardController()
       max_joybuttons = SDL_JoystickNumButtons(joystick);
     }
 
-    joystick_names.push_back(SDL_JoystickName(i));
     joysticks.push_back(joystick);
   }
 
@@ -618,9 +612,13 @@ JoystickKeyboardController::JoystickMenu::JoystickMenu(
 {
   add_label(_("Joystick Setup"));
   add_hl();
-  add_controlfield(Controller::JUMP, _("Jump"));
-  add_controlfield(Controller::ACTION, _("Shoot/Run"));
-  add_controlfield(Controller::PAUSE_MENU, _("Pause/Menu"));
+  if(controller->joysticks.size() > 0) {
+    add_controlfield(Controller::JUMP, _("Jump"));
+    add_controlfield(Controller::ACTION, _("Shoot/Run"));
+    add_controlfield(Controller::PAUSE_MENU, _("Pause/Menu"));
+  } else {
+    add_deactive(-1, _("No Joysticks found"));
+  }
   add_hl();
   add_back(_("Back"));
   update();
@@ -651,6 +649,9 @@ JoystickKeyboardController::JoystickMenu::menu_action(MenuItem* item)
 void
 JoystickKeyboardController::JoystickMenu::update()
 {
+  if(controller->joysticks.size() == 0)
+    return;
+
   // update menu
   get_item_by_id((int) Controller::JUMP).change_input(get_button_name(
     controller->reversemap_joybutton(Controller::JUMP)));
index 93fe1ac..150ddb3 100644 (file)
@@ -53,9 +53,7 @@ private:
   typedef std::map<SDLKey, Control> KeyMap;
   KeyMap keymap;
 
-  int joystick_count;
   std::vector<SDL_Joystick*> joysticks;
-  std::vector<std::string> joystick_names;
     
   typedef std::map<int, Control> ButtonMap;
   ButtonMap joy_button_map;
diff --git a/src/file_system.cpp b/src/file_system.cpp
new file mode 100644 (file)
index 0000000..af243f8
--- /dev/null
@@ -0,0 +1,222 @@
+#include <config.h>
+
+#include "file_system.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#ifndef WIN32
+#include <libgen.h>
+#endif
+
+#include "resources.h"
+
+#ifdef WIN32
+#define mkdir(dir, mode)    mkdir(dir)
+#endif
+
+namespace FileSystem
+{
+
+/* Does the given file exist and is it accessible? */
+bool faccessible(const std::string& filename)
+{
+  FILE* f = fopen(filename.c_str(), "r");
+  if(f == 0)
+    return false;
+
+  fclose(f);
+  return true;
+}
+
+/* Can we write to this location? */
+bool fwriteable(const std::string& filename)
+{
+  FILE* f = fopen(filename.c_str(), "wa");
+  if (f == 0)
+    return false;
+  
+  fclose(f);
+  return true;
+}
+
+/* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
+bool fcreatedir(const std::string& relative_dir)
+{
+  std::string path = user_dir + "/" + relative_dir + "/";
+  if(mkdir(path.c_str(),0755) == 0)
+    return true;
+  
+  path = datadir + "/" + relative_dir + "/";
+  if(mkdir(path.c_str(),0755) == 0)
+    return true;
+    
+  return false;
+}
+
+/* Get all names of sub-directories in a certain directory. */
+/* Returns the number of sub-directories found. */
+/* Note: The user has to free the allocated space. */
+std::set<std::string> dsubdirs(const std::string &rel_path,
+    const std::string& expected_file)
+{
+  DIR *dirStructP;
+  struct dirent *direntp;
+  std::set<std::string> sdirs;
+  std::string filename;
+  std::string path = user_dir + "/" + rel_path;
+
+  if((dirStructP = opendir(path.c_str())) != NULL)
+    {
+      while((direntp = readdir(dirStructP)) != NULL)
+        {
+          std::string absolute_filename;
+          struct stat buf;
+
+          absolute_filename = path + "/" + direntp->d_name;
+
+          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
+            {
+              if(!expected_file.empty())
+                {
+                  filename = path + "/" + direntp->d_name + "/" + expected_file;
+                  if(!faccessible(filename))
+                    continue;
+                }
+
+             sdirs.insert(direntp->d_name);
+            }
+        }
+      closedir(dirStructP);
+    }
+
+  path = datadir + "/" + rel_path;
+  if((dirStructP = opendir(path.c_str())) != NULL)
+    {
+      while((direntp = readdir(dirStructP)) != NULL)
+        {
+          std::string absolute_filename;
+          struct stat buf;
+
+          absolute_filename = path + "/" + direntp->d_name;
+
+          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
+            {
+              if(!expected_file.empty())
+                {
+                  filename = path + "/" + direntp->d_name + "/" + expected_file;
+                  if(!faccessible(filename.c_str()))
+                    {
+                      continue;
+                    }
+                  else
+                    {
+                      filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
+                      if(faccessible(filename.c_str()))
+                        continue;
+                    }
+                }
+
+             sdirs.insert(direntp->d_name);
+            }
+        }
+      closedir(dirStructP);
+    }
+
+  return sdirs;
+}
+
+std::set<std::string> dfiles(const std::string& rel_path,
+    const std::string& glob, const std::string& exception_str)
+{
+  DIR *dirStructP;
+  struct dirent *direntp;
+  std::set<std::string> sdirs;
+  std::string path = user_dir + "/" + rel_path;
+
+  if((dirStructP = opendir(path.c_str())) != NULL)
+    {
+      while((direntp = readdir(dirStructP)) != NULL)
+        {
+          std::string absolute_filename;
+          struct stat buf;
+
+          absolute_filename = path + "/" + direntp->d_name;
+
+          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
+            {
+              if(!exception_str.empty())
+                {
+                  if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
+                    continue;
+                }
+              if(!glob.empty())
+                if(strstr(direntp->d_name,glob.c_str()) == NULL)
+                  continue;
+
+             sdirs.insert(direntp->d_name);
+            }
+        }
+      closedir(dirStructP);
+    }
+
+  path = datadir + "/" + rel_path;
+  if((dirStructP = opendir(path.c_str())) != NULL)
+    {
+      while((direntp = readdir(dirStructP)) != NULL)
+        {
+          std::string absolute_filename;
+          struct stat buf;
+
+          absolute_filename = path + "/" + direntp->d_name;
+
+          if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
+            {
+              if(!exception_str.empty())
+                {
+                  if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
+                    continue;
+                }
+              if(!glob.empty())
+                if(strstr(direntp->d_name,glob.c_str()) == NULL)
+                  continue;
+
+             sdirs.insert(direntp->d_name);
+            }
+        }
+      closedir(dirStructP);
+    }
+
+  return sdirs;
+}
+
+std::string dirname(const std::string& filename)
+{
+  std::string::size_type p = filename.find_last_of('/');
+  if(p == std::string::npos)                              
+    return "";
+  
+  return filename.substr(0, p+1);
+}
+
+std::set<std::string> read_directory(const std::string& pathname)
+{
+  std::set<std::string> dirnames;
+  
+  DIR* dir = opendir(pathname.c_str());
+  if (dir)
+    {
+      struct dirent *direntp;
+      
+      while((direntp = readdir(dir)))
+        {
+          dirnames.insert(direntp->d_name);
+        }
+      
+      closedir(dir);
+    }
+
+  return dirnames;
+}
+
+}
+
diff --git a/src/file_system.h b/src/file_system.h
new file mode 100644 (file)
index 0000000..341e1fc
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __FILESYSTEM_H__
+#define __FILESYSTEM_H__
+
+#include <set>
+#include <string>
+
+namespace FileSystem
+{
+  bool faccessible(const std::string& filename);
+  bool fcreatedir(const std::string& relative_dir);
+  bool fwriteable(const std::string& filename);
+  std::set<std::string> read_directory(const std::string& pathname);
+  std::set<std::string> dsubdirs(const std::string& rel_path,
+          const std::string& expected_file);
+  std::set<std::string> dfiles(const std::string& rel_path,
+          const std::string& glob, const std::string& exception_str);
+  std::string dirname(const std::string& filename);
+}
+
+#endif
+
index 037099c..b4d44ad 100644 (file)
 #include <ctype.h>
 #endif
 
-#include "app/globals.h"
 #include "game_session.h"
 #include "video/screen.h"
-#include "app/setup.h"
 #include "gui/menu.h"
 #include "sector.h"
 #include "level.h"
@@ -57,7 +55,6 @@
 #include "lisp/lisp.h"
 #include "lisp/parser.h"
 #include "resources.h"
-#include "app/gettext.h"
 #include "worldmap.h"
 #include "misc.h"
 #include "statistics.h"
@@ -67,6 +64,8 @@
 #include "control/codecontroller.h"
 #include "control/joystickkeyboardcontroller.h"
 #include "main.h"
+#include "gameconfig.h"
+#include "gettext.h"
 
 // the engine will be run with a lofical framerate of 64fps.
 // We choose 64fps here because it is a power of 2, so 1/64 gives an "even"
@@ -217,8 +216,7 @@ GameSession::levelintro()
 
   context.do_drawing();
 
-  SDL_Event event;
-  wait_for_event(event,1000,3000,true);
+  wait_for_event(1.0, 3.0);
 }
 
 /* Reset Timers */
@@ -226,7 +224,6 @@ void
 GameSession::start_timers()
 {
   time_left.start(level->timelimit);
-  Ticks::pause_init();
 }
 
 void
@@ -240,10 +237,8 @@ GameSession::on_escape_press()
   } else if (!Menu::current()) {
     Menu::set_current(game_menu);
     game_menu->set_active_item(MNID_CONTINUE);
-    Ticks::pause_start();
     game_pause = true;
   } else {
-    Ticks::pause_stop();
     game_pause = false;
   }
 }
@@ -257,7 +252,6 @@ GameSession::process_events()
   // end of pause mode?
   if(!Menu::current() && game_pause) {
     game_pause = false;
-    Ticks::pause_stop();
   }
 
   if (end_sequence != NO_ENDSEQUENCE) {
@@ -796,8 +790,7 @@ GameSession::drawresultscreen()
 
   context.do_drawing();
   
-  SDL_Event event;
-  wait_for_event(event,2000,5000,true);
+  wait_for_event(2.0, 5.0);
 }
 
 std::string slotinfo(int slot)
@@ -830,33 +823,32 @@ bool process_load_game_menu()
 {
   int slot = load_game_menu->check();
 
-  if(slot != -1 && load_game_menu->get_item_by_id(slot).kind == MN_ACTION)
-    {
-      std::stringstream stream;
-      stream << slot;
-      std::string slotfile = user_dir + "/save/slot" + stream.str() + ".stsg";
+  if(slot == -1)
+    return false;
+  
+  if(load_game_menu->get_item_by_id(slot).kind != MN_ACTION)
+    return false;
+  
+  std::stringstream stream;
+  stream << slot;
+  std::string slotfile = user_dir + "/save/slot" + stream.str() + ".stsg";
 
-      fadeout(256);
-      DrawingContext context;
-      context.draw_text(white_text, "Loading...",
-                        Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT/2), CENTER_ALLIGN, LAYER_FOREGROUND1);
-      context.do_drawing();
+  fadeout(256);
+  DrawingContext context;
+  context.draw_text(white_text, "Loading...",
+                    Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT/2),
+                    CENTER_ALLIGN, LAYER_FOREGROUND1);
+  context.do_drawing();
 
-      WorldMapNS::WorldMap worldmap;
+  WorldMapNS::WorldMap worldmap;
 
-      worldmap.set_map_filename("/levels/world1/worldmap.stwm");
-      // Load the game or at least set the savegame_file variable
-      worldmap.loadgame(slotfile);
+  worldmap.set_map_filename("/levels/world1/worldmap.stwm");
+  // Load the game or at least set the savegame_file variable
+  worldmap.loadgame(slotfile);
 
-      worldmap.display();
+  worldmap.display();
 
-      Menu::set_current(main_menu);
+  Menu::set_current(main_menu);
 
-      Ticks::pause_stop();
-      return true;
-    }
-  else
-    {
-      return false;
-    }
+  return true;
 }
index 4ff1b82..72784a3 100644 (file)
 #ifndef SUPERTUX_GAMELOOP_H
 #define SUPERTUX_GAMELOOP_H
 
+#include <string>
 #include <SDL.h>
 #include "timer.h"
 #include "statistics.h"
-
-using namespace SuperTux;
+#include "math/vector.h"
 
 /* GameLoop modes */
-
 enum GameSessionMode {
   ST_GL_PLAY,
   ST_GL_TEST,
index 18c2dd2..2387c8c 100644 (file)
 #include <sstream>
 #include <fstream>
 
-#include "app/setup.h"
-#include "app/globals.h"
 #include "audio/sound_manager.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 #include "control/joystickkeyboardcontroller.h"
+#include "resources.h"
 #include "main.h"
 
-using namespace SuperTux;
-
 Config* config = 0;
 
 Config::Config()
diff --git a/src/gettext.h b/src/gettext.h
new file mode 100644 (file)
index 0000000..8ecae1a
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+   This program 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, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H
+
+#include "tinygettext/tinygettext.h"
+
+extern TinyGetText::DictionaryManager dictionary_manager;
+
+static inline const char* _(const char* message)
+{
+  return dictionary_manager.get_dictionary().translate(message).c_str();
+}
+
+static inline const char* N_(const char* id, const char* id2, int num)
+{
+  return dictionary_manager.get_dictionary().translate(id, id2, num).c_str();
+}
+
+#endif /* _LIBGETTEXT_H */
index d9f13c3..2f4580a 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include "SDL.h"
 #include <iostream>
 
+#include "main.h"
 #include "button.h"
 #include "mousecursor.h"
-#include "app/globals.h"
 #include "video/font.h"
 #include "video/surface.h"
 
-using namespace SuperTux;
-
 Font* Button::info_font = 0;
 extern SDL_Surface* screen;
 
index 6fc2249..700dbf0 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef SUPERTUX_BUTTON_H
 #define SUPERTUX_BUTTON_H
 
@@ -29,8 +28,6 @@
 
 class Surface;
 
-namespace SuperTux
-  {
 class ButtonGroup;
 
 enum {
@@ -91,6 +88,4 @@ private:
   int buttons_pair_nb;
 };
 
-} //namespace SuperTux
-
 #endif
index 361173c..d70b16a 100644 (file)
 #include <cassert>
 #include <stdexcept>
 
-#include "app/globals.h"
 #include "menu.h"
 #include "video/screen.h"
 #include "video/drawing_context.h"
-#include "app/setup.h"
-#include "app/gettext.h"
+#include "gettext.h"
 #include "math/vector.h"
 #include "main.h"
+#include "resources.h"
 #include "control/joystickkeyboardcontroller.h"
 
 static const int MENU_REPEAT_INITIAL = 400;
 static const int MENU_REPEAT_RATE = 200;
-static const int FLICK_CURSOR_TIME=500;
+static const int FLICK_CURSOR_TIME = 500;
 
 extern SDL_Surface* screen;
 
-using namespace SuperTux;
-
 Surface* checkbox;
 Surface* checkbox_checked;
 Surface* back;
@@ -128,7 +125,7 @@ Menu::push_current(Menu* pmenu)
     last_menus.push_back(current_);
 
   current_ = pmenu;
-  current_->effect.start(500);
+  current_->effect_ticks = SDL_GetTicks();
 }
 
 void
@@ -136,8 +133,7 @@ Menu::pop_current()
 {
   if (last_menus.size() >= 1) {
     current_ = last_menus.back();
-    current_->effect.start(500);
-
+    current_->effect_ticks = SDL_GetTicks();
     last_menus.pop_back();
   } else {
     current_ = 0;
@@ -150,7 +146,7 @@ Menu::set_current(Menu* menu)
   last_menus.clear();
 
   if (menu)
-    menu->effect.start(500);
+    menu->effect_ticks = SDL_GetTicks();
 
   current_ = menu;
   // just to be sure...
@@ -163,9 +159,6 @@ MenuItem::MenuItem(MenuItemKind _kind, int _id)
   toggled = false;
   selected = false;
   target_menu = 0;
-  input_flickering = false;
-  input_flickering_timer.init(true);
-  input_flickering_timer.start(FLICK_CURSOR_TIME);
 }
 
 void
@@ -182,19 +175,11 @@ MenuItem::change_input(const  std::string& text_)
 
 std::string MenuItem::get_input_with_symbol(bool active_item)
 {
-  if(!active_item)
+  if(!active_item) {
     input_flickering = true;
-  else
-    {
-      if(input_flickering_timer.get_left() < 0)
-        {
-          if(input_flickering)
-            input_flickering = false;
-          else
-            input_flickering = true;
-          input_flickering_timer.start(FLICK_CURSOR_TIME);
-        }
-    }
+  } else {
+    input_flickering = (SDL_GetTicks() / FLICK_CURSOR_TIME) % 2;
+  }
 
   char str[1024];
   if(input_flickering)
@@ -225,9 +210,6 @@ Menu::Menu()
   pos_y        = SCREEN_HEIGHT/2;
   arrange_left = 0;
   active_item  = -1;
-  effect.init(false);
-
-  repeat_timer.init(true);
 }
 
 void Menu::set_pos(int x, int y, float rw, float rh)
@@ -336,21 +318,24 @@ void
 Menu::action()
 {
   /** check main input controller... */
+  Uint32 ticks = SDL_GetTicks();
   if(main_controller->pressed(Controller::UP)) {
     menuaction = MENU_ACTION_UP;
-    repeat_timer.start(MENU_REPEAT_INITIAL);
+    menu_repeat_ticks = ticks + MENU_REPEAT_INITIAL;
   }
-  if(main_controller->hold(Controller::UP) && !repeat_timer.check()) {
+  if(main_controller->hold(Controller::UP) && 
+      menu_repeat_ticks != 0 && ticks > menu_repeat_ticks) {
     menuaction = MENU_ACTION_UP;
-    repeat_timer.start(MENU_REPEAT_RATE);
+    menu_repeat_ticks = ticks + MENU_REPEAT_RATE;
   } 
   if(main_controller->pressed(Controller::DOWN)) {
     menuaction = MENU_ACTION_DOWN;
-    repeat_timer.start(MENU_REPEAT_INITIAL);
+    menu_repeat_ticks = ticks + MENU_REPEAT_INITIAL;
   }
-  if(main_controller->hold(Controller::DOWN) && !repeat_timer.check()) {
+  if(main_controller->hold(Controller::DOWN) && 
+      menu_repeat_ticks != 0 && ticks > menu_repeat_ticks) {
     menuaction = MENU_ACTION_DOWN;
-    repeat_timer.start(MENU_REPEAT_RATE);
+    menu_repeat_ticks = ticks + MENU_REPEAT_RATE;
   }
   if(main_controller->pressed(Controller::JUMP)
      || main_controller->pressed(Controller::ACTION)
@@ -507,13 +492,13 @@ Menu::draw_item(DrawingContext& context, int index)
   MenuItem& pitem = *(items[index]);
 
   int effect_offset = 0;
-  {
-    int effect_time = 0;
-
-    if(effect.check())
-      effect_time = effect.get_left() / 4;
-
-    effect_offset = (index % 2) ? effect_time : -effect_time;
+  if(effect_ticks != 0) {
+    if(SDL_GetTicks() - effect_ticks > 500) {
+      effect_ticks = 0;
+    } else {
+      Uint32 effect_time = (500 - (SDL_GetTicks() - effect_ticks)) / 4;
+      effect_offset = (index % 2) ? effect_time : -effect_time;
+    }
   }
 
   Font* text_font = default_font;
@@ -764,7 +749,7 @@ Menu::is_toggled(int id) const
 void
 Menu::event(const SDL_Event& event)
 {
-  if(effect.started())
+  if(effect_ticks != 0)
     return;
 
   switch(event.type) {
index 46373b4..dba01bc 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "video/surface.h"
 #include "video/font.h"
-#include "special/timer.h"
 #include "mousecursor.h"
 
 bool confirm_dialog(Surface* background, std::string text);
@@ -82,7 +81,6 @@ private:
 
   /// keyboard key or joystick button
   bool input_flickering;
-  Timer input_flickering_timer;
 };
 
 class Menu
@@ -132,7 +130,7 @@ private:
   /* input implementation variables */
   int delete_character;
   char mn_input_char;
-  Timer repeat_timer;
+  Uint32 menu_repeat_ticks;
 
 public:
   static Font* default_font;
@@ -192,7 +190,7 @@ protected:
 private:
   void check_controlfield_change_event(const SDL_Event& event);  
   void draw_item(DrawingContext& context, int index);
-  Timer effect;
+  Uint32 effect_ticks;
   int arrange_left;
   int active_item;
 };
index bd3ff52..5a93563 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
-#include "app/globals.h"
 #include "video/drawing_context.h"
 #include "gui/mousecursor.h"
-
-using namespace SuperTux;
+#include "main.h"
 
 MouseCursor* MouseCursor::current_ = 0;
 extern SDL_Surface* screen;
 
-MouseCursor::MouseCursor(std::string cursor_file, int frames) : mid_x(0), mid_y(0)
+MouseCursor::MouseCursor(std::string cursor_file) : mid_x(0), mid_y(0)
 {
   cursor = new Surface(cursor_file, true);
   
   cur_state = MC_NORMAL;
-  cur_frame = 0;
-  tot_frames = frames;
 
-  timer.init(false);
-  timer.start(MC_FRAME_PERIOD);
-  
   SDL_ShowCursor(SDL_DISABLE);
 }
 
@@ -76,31 +68,18 @@ void MouseCursor::draw(DrawingContext& context)
   x = int(x * float(SCREEN_WIDTH)/screen->w);
   y = int(y * float(SCREEN_HEIGHT)/screen->h);
 
-  w = cursor->w / tot_frames;
+  w = cursor->w;
   h = cursor->h / MC_STATES_NB;
-  if(ispressed &SDL_BUTTON(1) || ispressed &SDL_BUTTON(2))
-    {
-      if(cur_state != MC_CLICK)
-        {
-          state_before_click = cur_state;
-          cur_state = MC_CLICK;
-        }
-    }
-  else
-    {
-      if(cur_state == MC_CLICK)
-        cur_state = state_before_click;
-    }
-
-  if(timer.get_left() < 0 && tot_frames > 1)
-    {
-      cur_frame++;
-      if(cur_frame++ >= tot_frames)
-        cur_frame = 0;
-
-      timer.start(MC_FRAME_PERIOD);
+  if(ispressed &SDL_BUTTON(1) || ispressed &SDL_BUTTON(2)) {
+    if(cur_state != MC_CLICK) {
+      state_before_click = cur_state;
+      cur_state = MC_CLICK;
     }
+  } else {
+    if(cur_state == MC_CLICK)
+      cur_state = state_before_click;
+  }
 
-  context.draw_surface_part(cursor, Vector(w*cur_frame, h*cur_state), Vector(w,
-        h), Vector(x-mid_x, y-mid_y), LAYER_GUI+100);
+  context.draw_surface_part(cursor, Vector(w, h*cur_state),
+          Vector(w, h), Vector(x-mid_x, y-mid_y), LAYER_GUI+100);
 }
index 0842b62..4bebe53 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_MOUSECURSOR_H
 #define SUPERTUX_MOUSECURSOR_H
 
 #include <string>
 
-#include "special/timer.h"
 #include "video/surface.h"
 
-namespace SuperTux
-  {
-
-  #define MC_FRAME_PERIOD 800  // in ms
-
-  #define MC_STATES_NB 3
+#define MC_STATES_NB 3
  
-  enum {
-    MC_NORMAL,
-    MC_CLICK,
-    MC_LINK,
-    MC_HIDE
-  };
-
-  /// Mouse cursor.
-  /** Used to create mouse cursors.
-      The mouse cursors can be animated
-      and can be used in four different states.
-      (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
-  class MouseCursor
-    {
-    public:
-      /// Constructor of MouseCursor.
-      /** Expects an imagefile for the cursor and  the number of animation frames it contains. */
-      MouseCursor(std::string cursor_file, int frames);
-      ~MouseCursor();
-      /// Get MouseCursor state.
-      /** (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
-      int state();
-      /// Set MouseCursor state.
-      /** (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
-      void set_state(int nstate);
-      /// Define the middle of a MouseCursor.
-      /** Useful for cross mouse cursor images in example. */
-      void set_mid(int x, int y);
+enum {
+  MC_NORMAL,
+  MC_CLICK,
+  MC_LINK,
+  MC_HIDE
+};
 
-      /// Draw MouseCursor on screen.
-      void draw(DrawingContext& context);
+/// Mouse cursor.
+/** Used to create mouse cursors.
+    The mouse cursors can be animated
+    and can be used in four different states.
+    (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
+class MouseCursor
+{
+public:
+  /// Constructor of MouseCursor.
+  /** Expects an imagefile for the cursor and  the number of animation frames it contains. */
+  MouseCursor(std::string cursor_file);
+  ~MouseCursor();
+  /// Get MouseCursor state.
+  /** (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
+  int state();
+  /// Set MouseCursor state.
+  /** (MC_NORMAL, MC_CLICK, MC_LINK or MC_HIDE) */
+  void set_state(int nstate);
+  /// Define the middle of a MouseCursor.
+  /** Useful for cross mouse cursor images in example. */
+  void set_mid(int x, int y);
 
-      /// Return the current cursor.
-      static MouseCursor* current()
-      {        return current_;      };
-      /// Set current cursor.
-      static void set_current(MouseCursor* pcursor)
-      {        current_ = pcursor;      };
+  /// Draw MouseCursor on screen.
+  void draw(DrawingContext& context);
 
-    private:
-      int mid_x, mid_y;
-      static MouseCursor* current_;
-      int state_before_click;
-      int cur_state;
-      int cur_frame, tot_frames;
-      Surface* cursor;
-      Timer timer;
-    };
+  /// Return the current cursor.
+  static MouseCursor* current()
+  {        return current_;      };
+  /// Set current cursor.
+  static void set_current(MouseCursor* pcursor)
+  {        current_ = pcursor;      };
 
-} // namespace SuperTux
+private:
+  int mid_x, mid_y;
+  static MouseCursor* current_;
+  int state_before_click;
+  int cur_state;
+  Surface* cursor;
+};
 
 #endif /*SUPERTUX_MOUSECURSOR_H*/
index ae81a34..b097cc4 100644 (file)
 #include <memory>
 #include <stdexcept>
 
-#include "app/globals.h"
-#include "app/setup.h"
 #include "video/screen.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "lisp/list_iterator.h"
 #include "lisp/writer.h"
 #include "level.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "sector.h"
 #include "tile.h"
 #include "resources.h"
+#include "file_system.h"
 #include "object/gameobjs.h"
 #include "object/camera.h"
 #include "object/tilemap.h"
index aa096cb..2366f8c 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <sstream>
 #include <stdexcept>
 #include <assert.h>
 #include <unistd.h>
-#include "app/setup.h"
 #include "level.h"
 #include "resources.h"
-#include "app/globals.h"
+#include "file_system.h"
 #include "video/surface.h"
 #include "level_subset.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 
-using namespace SuperTux;
-
 static bool has_suffix(const std::string& data, const std::string& suffix)
 {
   if (data.length() >= suffix.length())
index c6ed9a9..40f4b75 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef SUPERTUX_LEVEL_SUBSET_H
 #define SUPERTUX_LEVEL_SUBSET_H
 
 #include <vector>
 #include <string>
 
-using namespace SuperTux;
-
 /** This type holds meta-information about a level-subset. 
     It could be extended to handle manipulation of subsets. */
 class LevelSubset
index b84b4c4..7cc0756 100644 (file)
@@ -45,8 +45,6 @@
 #include "gui/button.h"
 #include "audio/sound_manager.h"
 #include "app/gettext.h"
-#include "app/setup.h"
-#include "app/globals.h"
 #include "sprite/sprite.h"
 #include "leveleditor.h"
 #include "resources.h"
index 16ac9da..de4065b 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef SUPERTUX_LEVELEDITOR_H
 #define SUPERTUX_LEVELEDITOR_H
 
+#if 0
+
 #include <set>
 #include <string>
 
@@ -150,3 +151,5 @@ private:
 };
 
 #endif
+
+#endif
index 08c5aa7..65f163a 100644 (file)
 #include <cassert>
 #include <iostream>
 
-#include "app/setup.h"
-#include "app/tinygettext.h"
+#include "tinygettext/tinygettext.h"
 #include "parser.h"
 #include "lisp.h"
+#include "file_system.h"
 
 namespace lisp
 {
@@ -58,7 +58,7 @@ Parser::parse(const std::string& filename)
   }
 
   if(dictionary_manager) {
-    dictionary_manager->add_directory(SuperTux::FileSystem::dirname(filename));
+    dictionary_manager->add_directory(FileSystem::dirname(filename));
     dictionary = & (dictionary_manager->get_dictionary());
   }
   
index bf94f28..8c3d7f8 100644 (file)
 #include <SDL.h>
 #include <SDL_mixer.h>
 #include <SDL_image.h>
+#include <SDL_opengl.h>
 
 #include "gameconfig.h"
 #include "resources.h"
-#include "app/globals.h"
-#include "app/setup.h"
-#include "app/gettext.h"
+#include "gettext.h"
 #include "audio/sound_manager.h"
+#include "video/surface.h"
 #include "control/joystickkeyboardcontroller.h"
 #include "misc.h"
+#include "title.h"
 #include "game_session.h"
+#include "file_system.h"
 
 SDL_Surface* screen = 0;
 JoystickKeyboardController* main_controller = 0;
+TinyGetText::DictionaryManager dictionary_manager;
 
 static void init_config()
 {
@@ -75,12 +78,6 @@ static void find_directories()
   user_dir = home;
   user_dir += "/.supertux";
 
-  // Remove .supertux config file from old versions
-  if(FileSystem::faccessible(user_dir)) {
-    std::cerr << "Removing old config file " << user_dir << "\n";
-    remove(user_dir.c_str());
-  }
-
   // create directories
   std::string savedir = user_dir + "/save";
   mkdir(user_dir.c_str(), 0755);
@@ -205,6 +202,13 @@ static void init_sdl()
   }
 
   SDL_EnableUNICODE(1);
+
+  // wait 100ms and clear SDL event queue because sometimes we have random
+  // joystick events in the queue on startup...
+  SDL_Delay(100);
+  SDL_Event dummy;
+  while(SDL_PollEvent(&dummy))
+      ;
 }
 
 static void check_gl_error()
@@ -335,6 +339,40 @@ static void quit_audio()
   }
 }
 
+void wait_for_event(float min_delay, float max_delay)
+{
+  assert(min_delay <= max_delay);
+  
+  Uint32 min = (Uint32) (min_delay * 1000);
+  Uint32 max = (Uint32) (max_delay * 1000);
+
+  SDL_Delay(min);
+
+  // clear even queue
+  SDL_Event event;
+  while (SDL_PollEvent(&event))
+  {}
+
+  /* Handle events: */
+  bool running = false;
+  Uint32 ticks = SDL_GetTicks();
+  while(running) {
+    while(SDL_PollEvent(&event)) {
+      switch(event.type) {
+        case SDL_QUIT:
+          throw std::runtime_error("received window close");
+        case SDL_KEYDOWN:
+        case SDL_JOYBUTTONDOWN:
+        case SDL_MOUSEBUTTONDOWN:
+          running = false;
+      }
+    }
+    if(SDL_GetTicks() - ticks >= (max - min))
+      running = false;
+    SDL_Delay(10);
+  }
+}
+
 int main(int argc, char** argv) 
 {
 #ifndef DEBUG // we want backtraces in debug mode so don't catch exceptions
index d76f8ab..3738c00 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __MAIN_H__
 #define __MAIN_H__
 
-enum GlobalGameState {
-  /** the title screen is showing */
-  STATE_TITLE,
-  /** the worldmap is shown */
-  STATE_WORLDMAP,
-  /** a level is played */
-  STATE_GAMESESSION
-};
-
 void init_video();
+void wait_for_event(float min_delay, float max_delay);
 
-class JoystickKeyboardController;
+static const int SCREEN_WIDTH = 800;
+static const int SCREEN_HEIGHT = 600;
 
 // global variables
+class JoystickKeyboardController;
 extern JoystickKeyboardController* main_controller;
 
 #endif
diff --git a/src/math/aatriangle.h b/src/math/aatriangle.h
new file mode 100644 (file)
index 0000000..4a2d81a
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __AATRIANGLE_H__
+#define __AATRIANGLE_H__
+
+#include "rectangle.h"
+
+/**
+ * An axis aligned triangle (ie. a triangle where 2 sides are parallel to the x-
+ * and y-axis.
+ */
+class AATriangle : public Rectangle
+{
+public:
+  /** Directions:
+   *
+   *    SOUTHEWEST    NORTHEAST   SOUTHEAST    NORTHWEST
+   *    *      or      *---*   or      *    or *---* 
+   *    | \             \  |         / |       |  /
+   *    |  \             \ |        /  |       | /
+   *    *---*              *       *---*       *
+   *
+   * Deform flags: (see docs/aatriangletypes.png for details)
+   */
+  enum Direction {
+    SOUTHWEST = 0,
+    NORTHEAST,
+    SOUTHEAST,
+    NORTHWEST,
+    DIRECTION_MASK = 0x0003,
+    DEFORM1 = 0x0010,
+    DEFORM2 = 0x0020,
+    DEFORM3 = 0x0030,
+    DEFORM4 = 0x0040,
+    DEFORM_MASK = 0x0070
+  };
+
+  AATriangle()
+    : dir(SOUTHWEST)
+  {
+  }
+  AATriangle(const Vector& v1, const Vector& v2, int newdir)
+    : Rectangle(v1, v2), dir(newdir)
+  {
+  }
+
+  int dir;
+};
+
+#endif
+
diff --git a/src/math/rectangle.h b/src/math/rectangle.h
new file mode 100644 (file)
index 0000000..f6be7a5
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __RECTANGLE_H__
+#define __RECTANGLE_H__
+
+#include <assert.h>
+#include "vector.h"
+
+/** This class represents a rectangle.
+ * (Implementation Note) We're using upper left and lower right point instead of
+ * upper left and width/height here, because that makes the collision dectection
+ * a little bit efficienter.
+ */
+class Rectangle
+{
+public:
+  Rectangle()
+  { }
+
+  Rectangle(const Vector& np1, const Vector& np2)
+    : p1(np1), p2(np2)
+  {
+  }
+
+  Rectangle(float x1, float y1, float x2, float y2)
+    : p1(x1, y1), p2(x2, y2)
+  {
+    assert(p1.x <= p2.x && p1.y <= p2.y);
+  }
+
+  float get_width() const
+  { return p2.x - p1.x; }
+
+  float get_height() const
+  { return p2.y - p1.y; }
+
+  Vector get_middle() const
+  { return Vector((p1.x+p2.x)/2, (p1.y+p2.y)/2); }
+
+  void set_pos(const Vector& v)
+  {
+    move(v-p1);
+  }
+
+  void set_height(float height)
+  {
+    p2.y = p1.y + height;
+  }
+  void set_width(float width)
+  {
+    p2.x = p1.x + width;
+  }
+  void set_size(float width, float height)
+  {
+    set_width(width);
+    set_height(height);
+  }                                         
+
+  void move(const Vector& v)
+  {
+    p1 += v;
+    p2 += v;
+  }
+
+  bool inside(const Vector& v) const
+  {
+    return v.x >= p1.x && v.y >= p1.y && v.x < p2.x && v.y < p2.y;
+  }
+  bool inside(const Rectangle& other) const
+  {
+    if(p1.x >= other.p2.x || other.p1.x >= p2.x)
+      return false;
+    if(p1.y >= other.p2.y || other.p1.y >= p2.y)
+      return false;
+
+    return true;
+  }
+   
+  // leave these 2 public to safe the headaches of set/get functions for such
+  // simple things :)
+
+  /// upper left edge
+  Vector p1;
+  /// lower right edge
+  Vector p2;
+};
+
+#endif
+
diff --git a/src/math/vector.cpp b/src/math/vector.cpp
new file mode 100644 (file)
index 0000000..7c914b3
--- /dev/null
@@ -0,0 +1,33 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <cmath>
+
+#include "math/vector.h"
+
+Vector Vector::unit() const
+{
+  return *this / norm();
+}
+
+float Vector::norm() const
+{
+  return sqrt(x*x + y*y);
+}
diff --git a/src/math/vector.h b/src/math/vector.h
new file mode 100644 (file)
index 0000000..38c1204
--- /dev/null
@@ -0,0 +1,115 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef SUPERTUX_VECTOR_H
+#define SUPERTUX_VECTOR_H
+
+/** Simple two dimensional vector. */
+class Vector
+{
+public:
+  Vector(float nx, float ny)
+      : x(nx), y(ny)
+  { }
+  Vector(const Vector& other)
+      : x(other.x), y(other.y)
+  { }
+  Vector()
+      : x(0), y(0)
+  { }
+
+  bool operator ==(const Vector& other) const
+    {
+      return x == other.x && y == other.y;
+    }
+
+  bool operator !=(const Vector& other) const
+    {
+      return !(x == other.x && y == other.y);
+    }
+
+  const Vector& operator=(const Vector& other)
+  {
+    x = other.x;
+    y = other.y;
+    return *this;
+  }
+
+  Vector operator+(const Vector& other) const
+    {
+      return Vector(x + other.x, y + other.y);
+    }
+
+  Vector operator-(const Vector& other) const
+    {
+      return Vector(x - other.x, y - other.y);
+    }
+
+  Vector operator*(float s) const
+    {
+      return Vector(x * s, y * s);
+    }
+
+  Vector operator/(float s) const
+    {
+      return Vector(x / s, y / s);
+    }
+
+  Vector operator-() const
+    {
+      return Vector(-x, -y);
+    }
+
+  const Vector& operator +=(const Vector& other)
+  {
+    x += other.x;
+    y += other.y;
+    return *this;
+  }
+
+  const Vector& operator *=(float val)
+  {
+    x *= val;
+    y *= val;
+    return *this;
+  }
+
+  const Vector& operator /=(float val)
+  {
+    x /= val;
+    y /= val;
+    return *this;
+  }
+
+  /// Scalar product of 2 vectors
+  float operator*(const Vector& other) const
+    {
+      return x*other.x + y*other.y;
+    }
+
+  float norm() const;
+  Vector unit() const;
+
+  // ... add the other operators as needed, I'm too lazy now ...
+
+  float x, y; // leave this public, get/set methods just give me headaches
+  // for such simple stuff :)
+};
+
+#endif
+
index ee48229..fcdd6f1 100644 (file)
 #include "misc.h"
 #include "main.h"
 #include "gameconfig.h"
-#include "app/globals.h"
 #include "game_session.h"
+#include "gui/menu.h"
+#include "gui/button.h"
+#include "title.h"
+#include "resources.h"
+#include "worldmap.h"
+#include "gettext.h"
 #include "control/joystickkeyboardcontroller.h"
 
 Menu* main_menu      = 0;
index 26ac338..0978b14 100644 (file)
 #ifndef SUPERTUX_MISC_H
 #define SUPERTUX_MISC_H
 
-#include "app/setup.h"
-#include "app/gettext.h"
-#include "gui/menu.h"
-#include "gameconfig.h"
-#include "title.h"
-#include "resources.h"
-#include "worldmap.h"
-#include "object/player.h"
-
 enum OptionsMenuIDs {
   MNID_FULLSCREEN,
   MNID_SOUND,
index a8c5edc..4995e97 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include "background.h"
-#include "app/globals.h"
 #include "camera.h"
 #include "video/drawing_context.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 #include "object_factory.h"
+#include "resources.h"
+#include "main.h"
 
 Background::Background()
   : type(INVALID), layer(LAYER_BACKGROUND0), image(0)
index 4b6253c..233d858 100644 (file)
@@ -16,7 +16,6 @@
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_BACKGROUND_H
 #define SUPERTUX_BACKGROUND_H
 
@@ -25,8 +24,6 @@
 #include "game_object.h"
 #include "serializable.h"
 
-using namespace SuperTux;
-
 class DisplayManager;
 
 namespace lisp {
index 12f134f..6241c6c 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __BELL_H__
 #define __BELL_H__
 
@@ -26,8 +25,6 @@
 #include "sprite/sprite.h"
 #include "serializable.h"
 
-using namespace SuperTux;
-
 /**
  * A bell: When tux touches it, it begins ringing and you will respawn at this
  * position.
index 2989ad8..43321f1 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __BLOCK_H__
 #define __BLOCK_H__
 
@@ -27,8 +26,6 @@
 class Sprite;
 class Player;
 
-using namespace SuperTux;
-
 class Block : public MovingObject
 {
 public:
index 0ee50dc..1b8279f 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <math.h>
@@ -25,9 +24,9 @@
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
-#include "app/globals.h"
 #include "sprite/sprite_manager.h"
 #include "badguy/badguy.h"
+#include "main.h"
 
 static const float BULLET_XM = 300;
 static const float BULLET_STARTING_YM = 0;
index 58df31b..6c49f84 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __BULLET_H__
 #define __BULLET_H__
 
 #include "moving_object.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "sprite/sprite.h"
 
-using namespace SuperTux;
-
 enum BulletsKind {
   FIRE_BULLET,
   ICE_BULLET
index f355917..476ca41 100644 (file)
@@ -16,7 +16,6 @@
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include <stdexcept>
 #include "player.h"
 #include "tilemap.h"
 #include "game_session.h"
-#include "app/globals.h"
 #include "sector.h"
+#include "main.h"
 #include "object_factory.h"
 
-using namespace SuperTux;
-
 Camera::Camera(Sector* newsector)
   : sector(newsector), do_backscrolling(true), scrollchange(NONE),
     auto_idx(0), auto_t(0)
index f8fbc4f..3c8d6c0 100644 (file)
@@ -16,7 +16,6 @@
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_CAMERA_H
 #define SUPERTUX_CAMERA_H
 
@@ -29,7 +28,6 @@
 #include "serializable.h"
 #include "timer.h"
 
-using namespace SuperTux;
 namespace lisp {
 class Lisp;
 }
index 949ebfc..3befd26 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __COIN_H__
 #define __COIN_H__
 
@@ -26,8 +25,6 @@
 
 class Sprite;
 
-using namespace SuperTux;
-
 class Coin : public MovingObject
 {
 public:
index 18648e0..69244bf 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include "fireworks.h"
 #include "sector.h"
 #include "camera.h"
 #include "gameobjs.h"
-#include "app/globals.h"
+#include "main.h"
 #include "video/drawing_context.h"
 #include "audio/sound_manager.h"
 
-using namespace SuperTux;
-
 Fireworks::Fireworks()
 {
   timer.start(.2);
index 4f52a2b..d07f71f 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <math.h>
@@ -26,7 +25,6 @@
 #include "camera.h"
 #include "sector.h"
 #include "player.h"
-#include "app/globals.h"
 #include "sprite/sprite_manager.h"
 
 Flower::Flower(const Vector& pos, Type _type)
index 8aa68cb..7e2956f 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __FLOWER_H__
 #define __FLOWER_H__
 
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
-
-using namespace SuperTux;
+#include "physic.h"
 
 class Flower : public MovingObject
 {
index 6a5d391..e863be3 100644 (file)
@@ -24,7 +24,6 @@
 #include <iostream>
 #include <cmath>
 
-#include "app/globals.h"
 #include "tile.h"
 #include "tile_manager.h"
 #include "game_session.h"
@@ -35,6 +34,7 @@
 #include "tilemap.h"
 #include "video/drawing_context.h"
 #include "camera.h"
+#include "main.h"
 
 BouncyCoin::BouncyCoin(const Vector& pos)
   : position(pos)
index 6cbac98..81a336a 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "video/surface.h"
 #include "timer.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "game_object.h"
 #include "moving_object.h"
 #include "serializable.h"
index 948955d..32420f1 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <math.h>
@@ -26,7 +25,6 @@
 #include "camera.h"
 #include "sector.h"
 #include "player.h"
-#include "app/globals.h"
 #include "sprite/sprite_manager.h"
 
 GrowUp::GrowUp(const Vector& pos)
index 4ea9ba9..b2407d8 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __GROWUP_H__
 #define __GROWUP_H__
 
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
-
-using namespace SuperTux;
+#include "physic.h"
 
 class GrowUp : public MovingObject
 {
index 505b98c..4c5794e 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __ONEUP_H__
 #define __ONEUP_H__
 
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
-
-using namespace SuperTux;
+#include "physic.h"
 
 class OneUp : public MovingObject
 {
index be1622a..2642f71 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-
 #include <config.h>
 
 #include <iostream>
 #include <cmath>
 
 #include "particlesystem.h"
-#include "app/globals.h"
 #include "video/drawing_context.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
+#include "resources.h"
+#include "main.h"
 
 ParticleSystem::ParticleSystem()
 {
index 4d1f799..526fbdd 100644 (file)
@@ -16,7 +16,6 @@
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_PARTICLESYSTEM_H
 #define SUPERTUX_PARTICLESYSTEM_H
 
@@ -26,8 +25,6 @@
 #include "game_object.h"
 #include "serializable.h"
 
-using namespace SuperTux;
-
 namespace lisp {
 class Lisp;
 }
index a8d3db7..71200f9 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __PLATFORM_H__
 #define __PLATFORM_H__
 
 #include "moving_object.h"
 #include "sprite/sprite.h"
 
-using namespace SuperTux;
-
 /**
  * This class is the base class for platforms that tux can stand on
  */
index 8093ab2..9357138 100644 (file)
@@ -23,8 +23,7 @@
 #include <iostream>
 #include <cassert>
 
-#include "app/globals.h"
-#include "app/gettext.h"
+#include "gettext.h"
 #include "sprite/sprite_manager.h"
 #include "player.h"
 #include "tile.h"
index 4d7ce21..c7693b4 100644 (file)
 #include "video/surface.h"
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "control/controller.h"
 #include "player_status.h"
 
-using namespace SuperTux;
-
 class BadGuy;
 class Portable;
 
index da77919..bfcef3f 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __PORTABLE_H__
 #define __PORTABLE_H__
 
 #include "moving_object.h"
 
-using namespace SuperTux;
-
 /**
  * An object that inherits from this object is considered "portable" and can
  * be carried around by the player.
index ff01810..f0ab98a 100644 (file)
@@ -22,7 +22,7 @@
 #define __ROCK_H__
 
 #include "moving_object.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "lisp/lisp.h"
 #include "portable.h"
 #include "serializable.h"
index 24ab26f..0058d6d 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <math.h>
@@ -25,7 +24,6 @@
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
-#include "app/globals.h"
 #include "sprite/sprite_manager.h"
 
 SpecialRiser::SpecialRiser(MovingObject* _child)
index 01f006e..5193256 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __SPECIALRISE_H__
 #define __SPECIALRISE_H__
 
 #include "moving_object.h"
 
-using namespace SuperTux;
-
 /**
  * special object that contains another object and slowly rises it out of a
  * bonus block.
index 8fd2760..2ad8da6 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __STAR_H__
 #define __STAR_H__
 
 #include "moving_object.h"
 #include "sprite/sprite.h"
-#include "math/physic.h"
-
-using namespace SuperTux;
+#include "physic.h"
 
 class Star : public MovingObject
 {
index 3832495..e845a2d 100644 (file)
 #include "tile.h"
 #include "resources.h"
 #include "tile_manager.h"
-#include "app/globals.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 #include "object_factory.h"
+#include "main.h"
 
 TileMap::TileMap()
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
index 8f389c0..b56ce0b 100644 (file)
@@ -16,7 +16,6 @@
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #ifndef SUPERTUX_TILEMAP_H
 #define SUPERTUX_TILEMAP_H
 
@@ -31,8 +30,6 @@ namespace lisp {
 class Lisp;
 }
 
-using namespace SuperTux;
-
 class Level;
 class TileManager;
 class Tile;
index 90cab4e..77a7cc2 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __UNSTABLE_TILE_H__
 #define __UNSTABLE_TILE_H__
 
 #include "moving_object.h"
 #include "lisp/lisp.h"
-#include "math/physic.h"
+#include "physic.h"
 #include "timer.h"
 
 class Sprite;
 class Player;
 
-using namespace SuperTux;
-
 /** A tile that starts falling down if tux stands to long on it */
 class UnstableTile : public MovingObject
 {
index bbf353b..efda690 100644 (file)
@@ -26,8 +26,6 @@
 #include "game_object.h"
 #include "math/vector.h"
 
-using namespace SuperTux;
-
 class Factory
 {
 public:
diff --git a/src/physic.cpp b/src/physic.cpp
new file mode 100644 (file)
index 0000000..39ad54e
--- /dev/null
@@ -0,0 +1,132 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+#include <config.h>
+
+#include "physic.h"
+
+Physic::Physic()
+    : ax(0), ay(0), vx(0), vy(0), gravity_enabled(true)
+{
+}
+
+Physic::~Physic()
+{
+}
+
+void
+Physic::reset()
+{
+    ax = ay = vx = vy = 0;
+    gravity_enabled = true;
+}
+
+void
+Physic::set_velocity_x(float nvx)
+{
+  vx = nvx;
+}
+
+void
+Physic::set_velocity_y(float nvy)
+{
+  vy = -nvy;
+}
+
+void
+Physic::set_velocity(float nvx, float nvy)
+{
+  vx = nvx;
+  vy = -nvy;
+}
+
+void Physic::inverse_velocity_x()
+{
+vx = -vx;
+}
+
+void Physic::inverse_velocity_y()
+{
+vy = -vy;
+}
+
+float
+Physic::get_velocity_x()
+{
+    return vx;
+}
+
+float
+Physic::get_velocity_y()
+{
+    return -vy;
+}
+
+void
+Physic::set_acceleration_x(float nax)
+{
+  ax = nax;
+}
+
+void
+Physic::set_acceleration_y(float nay)
+{
+  ay = -nay;
+}
+
+void
+Physic::set_acceleration(float nax, float nay)
+{
+    ax = nax;
+    ay = -nay;
+}
+
+float
+Physic::get_acceleration_x()
+{
+    return ax;
+}
+
+float
+Physic::get_acceleration_y()
+{
+    return -ay;
+}
+
+void
+Physic::enable_gravity(bool enable_gravity)
+{
+  gravity_enabled = enable_gravity;
+}
+
+Vector
+Physic::get_movement(float elapsed_time)
+{
+  float grav = gravity_enabled ? 1000 : 0;
+  
+  Vector result(
+      vx * elapsed_time + ax * elapsed_time * elapsed_time,
+      vy * elapsed_time + (ay + grav) * elapsed_time * elapsed_time
+  );
+  vx += ax * elapsed_time;
+  vy += (ay + grav) * elapsed_time;  
+
+  return result;
+}
+
diff --git a/src/physic.h b/src/physic.h
new file mode 100644 (file)
index 0000000..86114eb
--- /dev/null
@@ -0,0 +1,77 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+#ifndef SUPERTUX_PHYSIC_H
+#define SUPERTUX_PHYSIC_H
+
+#include "math/vector.h"
+
+/// Physics engine.
+/** This is a very simplistic physics engine handling accelerated and constant
+  * movement along with gravity.
+  */
+class Physic
+{
+public:
+  Physic();
+  ~Physic();
+
+  /// Resets all velocities and accelerations to 0.
+  void reset();
+
+  /// Sets velocity to a fixed value.
+  void set_velocity(float vx, float vy);
+
+  void set_velocity_x(float vx);
+  void set_velocity_y(float vy);
+
+  /// Velocities invertion.
+  void inverse_velocity_x();
+  void inverse_velocity_y();
+
+  float get_velocity_x();
+  float get_velocity_y();
+
+  /// Set acceleration.
+  /** Sets acceleration applied to the object. (Note that gravity is
+   * eventually added to the vertical acceleration)
+   */
+  void set_acceleration(float ax, float ay);
+
+  void set_acceleration_x(float ax);
+  void set_acceleration_y(float ay);
+
+  float get_acceleration_x();
+  float get_acceleration_y();
+
+  /// Enables or disables handling of gravity.
+  void enable_gravity(bool gravity_enabled);
+
+  Vector get_movement(float elapsed_time);
+
+private:
+  /// horizontal and vertical acceleration
+  float ax, ay;
+  /// horizontal and vertical velocity
+  float vx, vy;
+  /// should we respect gravity in out calculations?
+  bool gravity_enabled;
+};
+
+#endif
index 95bf48d..3544a52 100644 (file)
 //  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
-#include "app/globals.h"
 #include "sprite/sprite_manager.h"
-#include "app/setup.h"
 #include "gui/menu.h"
 #include "gui/button.h"
 #include "resources.h"
+#include "file_system.h"
 #include "tile_manager.h"
 #include "object/gameobjs.h"
 #include "object/player.h"
 
+std::string datadir;
+std::string user_dir;
+
 MusicRef herring_song;
 MusicRef level_end_song;
 MusicRef credits_song;
@@ -37,6 +38,8 @@ SpriteManager* sprite_manager = 0;
 TileManager* tile_manager = 0;
 SoundManager* sound_manager = 0;
 
+MouseCursor* mouse_cursor = 0;
+
 Font* gold_text;
 Font* blue_text;
 Font* gray_text;
@@ -56,7 +59,7 @@ void load_shared()
   arrow_right = new Surface(datadir + "/images/icons/right.png", true);
 
   /* Load the mouse-cursor */
-  mouse_cursor = new MouseCursor( datadir + "/images/status/mousecursor.png",1);
+  mouse_cursor = new MouseCursor(datadir + "/images/status/mousecursor.png");
   MouseCursor::set_current(mouse_cursor);
 
   /* Load global images: */
index 35f264f..c3bcbaa 100644 (file)
 #ifndef SUPERTUX_RESOURCES_H
 #define SUPERTUX_RESOURCES_H
 
+#include <string>
 #include "audio/musicref.h"
 
-using namespace SuperTux;
-
 class SpriteManager;
 class Menu;
 class Font;
 class Surface;
 class SoundManager;
 class TileManager;
+class MouseCursor;
 
 extern Surface* img_super_bkgd;
 extern Surface* tux_life;
@@ -47,6 +47,8 @@ extern Menu* game_menu;
 extern Menu* options_menu;
 extern Menu* load_game_menu;
 
+extern MouseCursor* mouse_cursor;
+
 extern Font* gold_text;
 extern Font* white_text;
 extern Font* blue_text;
@@ -55,6 +57,9 @@ extern Font* white_small_text;
 extern Font* white_big_text;
 extern Font* yellow_nums;
 
+extern std::string datadir;
+extern std::string user_dir;
+
 /** maps a virtual resource path to a real path (ie. levels/bla is mapped to
  * $DATADIR/levels/bla or $HOME/.supertux/levels/bla)
  * All paths inside the game should be handled in as virtual paths and then
diff --git a/src/scripting/Jamfile b/src/scripting/Jamfile
new file mode 100644 (file)
index 0000000..eb5c492
--- /dev/null
@@ -0,0 +1,49 @@
+SubDir TOP src scripting ;
+
+if $(MINISWIG)
+{
+    ##  MiniSwigRule outputcppfile : inputfile : modulename : flags
+    rule MiniSwigRule
+    {
+        local sources = [ SearchSource $(>) ] ;
+        local cppfile = [ LocateTarget $(<) : $(SUBDIR) ] ;
+        local headerfile = [ LocateTarget $(<:S=.h) : $(SUBDIR) ] ;
+        SEARCH on $(headerfile) = $(SOURCH_SOURCE) ;
+    
+        MiniSwig $(cppfile) : $(sources) ;
+        CPPFLAGS on $(cppfile) = $(CPPFLAGS) ;
+        headerfile on $(cppfile) = $(headerfile) ;
+        modulename on $(cppfile) = $(3) ;
+        FLAGS on $(cppfile) = $(4) ;
+
+        local object = [ CompileObject $(cppfile) ] ;
+
+        return $(object) ;
+    }
+
+    rule MiniSwig
+    {
+        Depends $(<) : $(>) $(MINISWIG) ;
+        Clean clean : $(<) ;
+    }
+
+    actions MiniSwig bind headerfile
+    {
+        $(CPP) -x c $(CPPFLAGS) $(>) -o $(LOCATE_OBJECTS)/miniswig.tmp
+        $(MINISWIG) --output-cpp $(<) --input $(LOCATE_OBJECTS)/miniswig.tmp --output-hpp $(headerfile) --module $(modulename) $(FLAGS)
+#        rm -f $(LOCATE_OBJECTS)/miniswig.tmp
+    }
+}
+
+wrapper_sources = [ Filter [ Wildcard *.cpp *.h ] : wrapper.cpp wrapper.h ] ;
+if ! $(MINISWIG)
+{
+    wrapper_sources += wrapper.cpp ;
+}
+wrapper_objects = [ CompileObjects $(wrapper_sources) ] ;
+if $(MINISWIG)
+{
+    wrapper_objects += 
+        [ MiniSwigRule wrapper.cpp : wrapper.interface.h : supertux : --select-namespace Scripting ] ;
+}
+
diff --git a/src/scripting/camera.cpp b/src/scripting/camera.cpp
new file mode 100644 (file)
index 0000000..82c5b87
--- /dev/null
@@ -0,0 +1,34 @@
+#include <config.h>
+
+#include <string>
+#include <stdio.h>
+#include "camera.h"
+
+#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__);
+
+namespace Scripting
+{
+  Camera::Camera()
+  { }
+
+  Camera::~Camera()
+  { }
+  
+  void
+  Camera::shake(float , float , float )
+  {
+    NOIMPL;
+  }
+  
+  void
+  Camera::set_pos(float , float )
+  {
+    NOIMPL;
+  }
+
+  void
+  Camera::set_mode(const std::string& )
+  {
+    NOIMPL;
+  }  
+}
diff --git a/src/scripting/camera.h b/src/scripting/camera.h
new file mode 100644 (file)
index 0000000..add5e5f
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __CAMERA_H__
+#define __CAMERA_H__
+
+namespace Scripting
+{
+
+class Camera
+{
+public:
+#ifndef SCRIPTING_API
+    Camera();
+    ~Camera();
+#endif
+
+    /** Shake the camera */
+    void shake(float speed, float x, float y);
+    /** Set camera to a specific coordinate */
+    void set_pos(float x, float y);
+    /** Set camera to a specific mode, can be "normal", "manual" */
+    void set_mode(const std::string& mode);
+};
+
+}
+
+#endif
+
diff --git a/src/scripting/display.cpp b/src/scripting/display.cpp
new file mode 100644 (file)
index 0000000..6da4e87
--- /dev/null
@@ -0,0 +1,21 @@
+#include <config.h>
+
+#include <string>
+#include <stdio.h>
+#include "display.h"
+
+#define NOIMPL      printf(__FUNCTION__ " not implemented\n");
+
+namespace Scripting
+{
+  Display::Display()
+  {}
+
+  Display::~Display()
+  {}
+
+  void
+  Display::set_effect(const std::string& )
+  {}
+}
+
diff --git a/src/scripting/display.h b/src/scripting/display.h
new file mode 100644 (file)
index 0000000..0cd2720
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __DISPLAY_H__
+#define __DISPLAY_H__
+
+namespace Scripting
+{
+
+class Display
+{
+public:
+#ifndef SCRIPTING_API
+    Display();
+    ~Display();
+#endif
+
+    void set_effect(const std::string& effect);
+};
+
+}
+
+#endif
+
diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp
new file mode 100644 (file)
index 0000000..b0b9429
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "functions.h"
+
+namespace Scripting
+{
+
+void wait(float secs)
+{
+    (void) secs;
+    printf("Wait not implemented.\n");
+}
+
+}
+
diff --git a/src/scripting/functions.h b/src/scripting/functions.h
new file mode 100644 (file)
index 0000000..e1769c0
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __FUNCTIONS_H__
+#define __FUNCTIONS_H__
+
+namespace Scripting
+{
+
+void wait(float secs);
+
+}
+
+#endif
+
diff --git a/src/scripting/level.cpp b/src/scripting/level.cpp
new file mode 100644 (file)
index 0000000..d29e18b
--- /dev/null
@@ -0,0 +1,28 @@
+#include <config.h>
+
+#include <string>
+#include <stdio.h>
+#include "level.h"
+
+#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__);
+
+namespace Scripting
+{
+  Level::Level()
+  {}
+
+  Level::~Level()
+  {}
+
+  void
+  Level::finish()
+  {
+    NOIMPL;
+  }
+
+  void
+  Level::spawn(const std::string& , const std::string& )
+  {
+    NOIMPL;
+  }
+}
diff --git a/src/scripting/level.h b/src/scripting/level.h
new file mode 100644 (file)
index 0000000..e021742
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __LEVEL_H__
+#define __LEVEL_H__
+
+namespace Scripting
+{
+
+class Level
+{
+public:
+#ifndef SCRIPTING_API
+    Level();
+    ~Level();
+#endif
+
+    /** Instantly finish the currently played level */
+    void finish();
+    /** spawn tux at specified sector and spawnpoint */
+    void spawn(const std::string& sector, const std::string& spawnpoint);
+};
+
+}
+
+#endif
+
diff --git a/src/scripting/script_interpreter.h b/src/scripting/script_interpreter.h
new file mode 100644 (file)
index 0000000..0ebe952
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __SCRIPT_INTERPRETER_H__
+#define __SCRIPT_INTERPRETER_H__
+
+class ScriptInterpreter
+{
+public:
+    ScriptInterpreter();
+    ~ScriptInterpreter();
+
+    void load_script(const std::istream& in);
+    void run_script();
+    void resume_script();
+    bool script_suspended() const;
+};
+
+#endif
+
diff --git a/src/scripting/scripted_object.cpp b/src/scripting/scripted_object.cpp
new file mode 100644 (file)
index 0000000..2694751
--- /dev/null
@@ -0,0 +1,75 @@
+#include <config.h>
+
+#include <string>
+#include <stdio.h>
+#include "scripted_object.h"
+
+#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__)
+
+namespace Scripting
+{
+  ScriptedObject::ScriptedObject()
+  {}
+
+  ScriptedObject::~ScriptedObject()
+  {}
+
+  void
+  ScriptedObject::set_animation(const std::string& )
+  {
+    NOIMPL;
+  }
+
+  std::string
+  ScriptedObject::get_animation()
+  {
+    NOIMPL;
+    return "";
+  }
+
+  void
+  ScriptedObject::move(float , float )
+  {
+    NOIMPL;
+  }
+
+  void
+  ScriptedObject::set_pos(float , float )
+  {
+    NOIMPL;
+  }
+
+  float
+  ScriptedObject::get_pos_x()
+  {
+    NOIMPL;
+    return -1;
+  }
+
+  float
+  ScriptedObject::get_pos_y()
+  {
+    NOIMPL;
+    return -1;
+  }
+
+  void
+  ScriptedObject::set_velocity(float , float )
+  {
+    NOIMPL;
+  }
+
+  float
+  ScriptedObject::get_velocity_x()
+  {
+    NOIMPL;
+    return -1;
+  }
+
+  float
+  ScriptedObject::get_velocity_y()
+  {
+    NOIMPL;
+    return -1;
+  }
+}
diff --git a/src/scripting/scripted_object.h b/src/scripting/scripted_object.h
new file mode 100644 (file)
index 0000000..b22fd08
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __SCRIPTED_OBJECT_H__
+#define __SCRIPTED_OBJECT_H__
+
+namespace Scripting
+{
+
+class ScriptedObject
+{
+public:
+#ifndef SCRIPTING_API
+    ScriptedObject();
+    virtual ~ScriptedObject();
+#endif
+
+    void set_animation(const std::string& animation);
+    std::string get_animation();
+
+    void move(float x, float y);
+    void set_pos(float x, float y);
+    float get_pos_x();
+    float get_pos_y();
+    void set_velocity(float x, float y);
+    float get_velocity_x();
+    float get_velocity_y();
+};
+
+}
+
+#endif
+
diff --git a/src/scripting/semantic.cache b/src/scripting/semantic.cache
new file mode 100644 (file)
index 0000000..02ff11e
--- /dev/null
@@ -0,0 +1,75 @@
+;; Object semantic.cache
+;; SEMANTICDB Tags save file
+(semanticdb-project-database "semantic.cache"
+  :file "semantic.cache"
+  :tables (list 
+   (semanticdb-table "camera.cpp"
+    :file "camera.cpp"
+    :pointmax 435
+    :major-mode 'c++-mode
+    :tokens '(("config.h" include t nil nil [1 20]) ("string" include t nil nil [22 39]) ("stdio.h" include t nil nil [40 58]) ("camera.h" include nil nil nil [59 78]) ("NOIMPL" variable nil nil ((const . t)) nil nil [80 152]) ("Scripting" type "namespace" (("Camera" function ("Camera" type "class") nil ((parent . "Camera") (constructor . t)) nil ((reparse-symbol . namespacesubparts)) [179 201]) ("Camera" function "void" nil ((parent . "Camera") (destructor . t)) nil ((reparse-symbol . namespacesubparts)) [205 228]) ("shake" function ("void") (("" variable "float" nil nil nil nil [255 262]) ("" variable "float" nil nil nil nil [263 270]) ("" variable "float" nil nil nil nil [271 278])) ((parent . "Camera")) nil ((reparse-symbol . namespacesubparts)) [234 298]) ("set_pos" function ("void") (("" variable "float" nil nil nil nil [327 334]) ("" variable "float" nil nil nil nil [335 342])) ((parent . "Camera")) nil ((reparse-symbol . namespacesubparts)) [304 362]) ("set_mode" function ("void") (("" variable ("std::string" type "class") nil ((const . t)) nil nil [390 410])) ((parent . "Camera")) nil ((reparse-symbol . namespacesubparts)) [366 430])) nil nil nil nil [155 434]))
+    :unmatched-syntax '((punctuation 152 . 153))
+    )
+   (semanticdb-table "camera.h"
+    :file "camera.h"
+    :pointmax 434
+    :major-mode 'c++-mode
+    :tokens '(("__CAMERA_H__" variable nil nil ((const . t)) nil nil [22 53]) ("Scripting" type "namespace" (("Camera" type "class" (("public" label ((reparse-symbol . classsubparts)) [82 89]) ("Camera" function ("Camera" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [116 125]) ("Camera" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [130 140]) ("shake" function ("void") (("speed" variable "float" nil nil nil nil [192 204]) ("x" variable "float" nil nil nil nil [205 213]) ("y" variable "float" nil nil nil nil [214 222])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [181 223]) ("set_pos" function ("void") (("x" variable "float" nil nil nil nil [288 296]) ("y" variable "float" nil nil nil nil [297 305])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [275 306]) ("set_mode" function ("void") (("mode" variable ("std::string" type "class") nil ((const . t)) nil nil [393 417])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [379 418])) nil nil nil ((reparse-symbol . namespacesubparts)) [67 421])) nil nil nil nil [44 424]))
+    :unmatched-syntax 'nil
+    )
+   (semanticdb-table "sound.h"
+    :file "sound.h"
+    :pointmax 261
+    :major-mode 'c++-mode
+    :tokens '(("__SOUND_H__" variable nil nil ((const . t)) nil nil [21 51]) ("Scripting" type "namespace" (("Sound" type "class" (("public" label ((reparse-symbol . classsubparts)) [79 86]) ("play_music" function ("void") (("musicfile" variable ("std::string" type "class") nil ((const . t)) nil nil [107 136])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [91 137]) ("play_sound" function ("void") (("soundfile" variable ("std::string" type "class") nil ((const . t)) nil nil [158 187])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [142 188]) ("Sound" function ("Sound" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [216 224]) ("Sound" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [229 238])) nil nil nil ((reparse-symbol . namespacesubparts)) [65 248])) nil nil nil nil [42 251]))
+    :unmatched-syntax 'nil
+    )
+   (semanticdb-table "sound.cpp"
+    :file "sound.cpp"
+    :pointmax 364
+    :major-mode 'c++-mode
+    :tokens '(("config.h" include t nil nil [1 20]) ("string" include t nil nil [22 39]) ("stdio.h" include t nil nil [40 58]) ("sound.h" include nil nil nil [59 77]) ("NOIMPL" variable nil nil ((const . t)) nil nil [79 151]) ("Scripting" type "namespace" (("Sound" function ("Sound" type "class") nil ((parent . "Sound") (constructor . t)) nil ((reparse-symbol . namespacesubparts)) [179 198]) ("Sound" function "void" nil ((parent . "Sound") (destructor . t)) nil ((reparse-symbol . namespacesubparts)) [202 223]) ("play_music" function ("void") (("" variable ("std::string" type "class") nil ((const . t)) nil nil [252 272])) ((parent . "Sound")) nil ((reparse-symbol . namespacesubparts)) [227 292]) ("play_sound" function ("void") (("" variable ("std::string" type "class") nil ((const . t)) nil nil [321 341])) ((parent . "Sound")) nil ((reparse-symbol . namespacesubparts)) [296 361])) nil nil nil nil [154 363]))
+    :unmatched-syntax '((punctuation 151 . 152))
+    )
+   (semanticdb-table "level.cpp"
+    :file "level.cpp"
+    :pointmax 355
+    :major-mode 'c++-mode
+    :tokens '(("config.h" include t nil nil [1 20]) ("string" include t nil nil [22 39]) ("stdio.h" include t nil nil [40 58]) ("level.h" include nil nil nil [59 77]) ("NOIMPL" variable nil nil ((const . t)) nil nil [79 151]) ("Scripting" type "namespace" (("Level" function ("Level" type "class") nil ((parent . "Level") (constructor . t)) nil ((reparse-symbol . namespacesubparts)) [178 197]) ("Level" function "void" nil ((parent . "Level") (destructor . t)) nil ((reparse-symbol . namespacesubparts)) [201 221]) ("finish" function ("void") nil ((parent . "Level")) nil ((reparse-symbol . namespacesubparts)) [225 267]) ("spawn" function ("void") (("" variable ("std::string" type "class") nil ((const . t)) nil nil [291 311]) ("" variable ("std::string" type "class") nil ((const . t)) nil nil [312 332])) ((parent . "Level")) nil ((reparse-symbol . namespacesubparts)) [271 352])) nil nil nil nil [154 354]))
+    :unmatched-syntax '((punctuation 151 . 152))
+    )
+   (semanticdb-table "level.h"
+    :file "level.h"
+    :pointmax 363
+    :major-mode 'c++-mode
+    :tokens '(("__LEVEL_H__" variable nil nil ((const . t)) nil nil [21 51]) ("Scripting" type "namespace" (("Level" type "class" (("public" label ((reparse-symbol . classsubparts)) [79 86]) ("Level" function ("Level" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [113 121]) ("Level" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [126 135]) ("finish" function ("void") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [203 217]) ("spawn" function ("void") (("sector" variable ("std::string" type "class") nil ((const . t)) nil nil [289 315]) ("spawnpoint" variable ("std::string" type "class") nil ((const . t)) nil nil [316 346])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [278 347])) nil nil nil ((reparse-symbol . namespacesubparts)) [65 350])) nil nil nil nil [42 353]))
+    :unmatched-syntax 'nil
+    )
+   (semanticdb-table "scripted_object.cpp"
+    :file "scripted_object.cpp"
+    :pointmax 952
+    :major-mode 'c++-mode
+    :tokens '(("config.h" include t nil nil [1 20]) ("string" include t nil nil [22 39]) ("stdio.h" include t nil nil [40 58]) ("scripted_object.h" include nil nil nil [59 87]) ("NOIMPL" variable nil nil ((const . t)) nil nil [89 161]) ("Scripting" type "namespace" (("ScriptedObject" function ("ScriptedObject" type "class") nil ((parent . "ScriptedObject") (constructor . t)) nil ((reparse-symbol . namespacesubparts)) [187 224]) ("ScriptedObject" function "void" nil ((parent . "ScriptedObject") (destructor . t)) nil ((reparse-symbol . namespacesubparts)) [228 266]) ("set_animation" function ("void") (("" variable ("std::string" type "class") nil ((const . t)) nil nil [307 327])) ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [270 347]) ("get_animation" function ("std::string" type "class") nil ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [351 431]) ("move" function ("void") (("" variable "float" nil nil nil nil [463 470]) ("" variable "float" nil nil nil nil [471 478])) ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [435 498]) ("set_pos" function ("void") (("" variable "float" nil nil nil nil [533 540]) ("" variable "float" nil nil nil nil [541 548])) ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [502 568]) ("get_pos_x" function ("float") nil ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [572 642]) ("get_pos_y" function ("float") nil ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [646 716]) ("set_velocity" function ("void") (("" variable "float" nil nil nil nil [756 763]) ("" variable "float" nil nil nil nil [764 771])) ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [720 791]) ("get_velocity_x" function ("float") nil ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [795 870]) ("get_velocity_y" function ("float") nil ((parent . "ScriptedObject")) nil ((reparse-symbol . namespacesubparts)) [874 949])) nil nil nil nil [163 951]))
+    :unmatched-syntax '((punctuation 635 . 636) (punctuation 634 . 635) (symbol 620 . 634) (FLOAT 612 . 617))
+    )
+   (semanticdb-table "scripted_object.h"
+    :file "scripted_object.h"
+    :pointmax 514
+    :major-mode 'c++-mode
+    :tokens '(("__SCRIPTED_OBJECT_H__" variable nil nil ((const . t)) nil nil [31 71]) ("Scripting" type "namespace" (("ScriptedObject" type "class" (("public" label ((reparse-symbol . classsubparts)) [108 115]) ("ScriptedObject" function ("ScriptedObject" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [142 159]) ("ScriptedObject" function "void" nil ((typemodifiers "virtual") (destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [164 190]) ("set_animation" function ("void") (("animation" variable ("std::string" type "class") nil ((const . t)) nil nil [222 251])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [203 252]) ("get_animation" function ("std::string" type "class") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [257 285]) ("move" function ("void") (("x" variable "float" nil nil nil nil [301 309]) ("y" variable "float" nil nil nil nil [310 318])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [291 319]) ("set_pos" function ("void") (("x" variable "float" nil nil nil nil [337 345]) ("y" variable "float" nil nil nil nil [346 354])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [324 355]) ("get_pos_x" function ("float") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [360 378]) ("get_pos_y" function ("float") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [383 401]) ("set_velocity" function ("void") (("x" variable "float" nil nil nil nil [424 432]) ("y" variable "float" nil nil nil nil [433 441])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [406 442]) ("get_velocity_x" function ("float") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [447 470]) ("get_velocity_y" function ("float") nil ((prototype . t)) nil ((reparse-symbol . classsubparts)) [475 498])) nil nil nil ((reparse-symbol . namespacesubparts)) [85 501])) nil nil nil nil [62 504]))
+    )
+   (semanticdb-table "display.cpp"
+    :file "display.cpp"
+    :pointmax 280
+    :major-mode 'c++-mode
+    :tokens '(("config.h" include t nil nil [1 20]) ("string" include t nil nil [22 39]) ("stdio.h" include t nil nil [40 58]) ("display.h" include nil nil nil [59 79]) ("NOIMPL" variable nil nil ((const . t)) nil nil [81 142]) ("Scripting" type "namespace" (("Display" function ("Display" type "class") nil ((parent . "Display") (constructor . t)) nil ((reparse-symbol . namespacesubparts)) [169 192]) ("Display" function "void" nil ((parent . "Display") (destructor . t)) nil ((reparse-symbol . namespacesubparts)) [196 220]) ("set_effect" function ("void") (("effect" variable ("std::string" type "class") nil ((const . t)) nil ((dirty . t)) [251 271])) ((parent . "Display")) nil ((reparse-symbol . namespacesubparts)) [224 276])) nil nil nil nil [145 278]))
+    :unmatched-syntax '((punctuation 142 . 143))
+    )
+   (semanticdb-table "display.h"
+    :file "display.h"
+    :pointmax 217
+    :major-mode 'c++-mode
+    :tokens '(("__DISPLAY_H__" variable nil nil ((const . t)) nil nil [23 55]) ("Scripting" type "namespace" (("Display" type "class" (("public" label ((reparse-symbol . classsubparts)) [85 92]) ("Display" function ("Display" type "class") nil ((constructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [119 129]) ("Display" function "void" nil ((destructor . t) (prototype . t)) nil ((reparse-symbol . classsubparts)) [134 145]) ("set_effect" function ("void") (("effect" variable ("std::string" type "class") nil ((const . t)) nil nil [174 200])) ((prototype . t)) nil ((reparse-symbol . classsubparts)) [158 201])) nil nil nil ((reparse-symbol . namespacesubparts)) [69 204])) nil nil nil nil [46 207]))
+    )
+   )
+  )
diff --git a/src/scripting/sound.cpp b/src/scripting/sound.cpp
new file mode 100644 (file)
index 0000000..a0589c7
--- /dev/null
@@ -0,0 +1,29 @@
+#include <config.h>
+
+#include <string>
+#include <stdio.h>
+#include "sound.h"
+
+#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__);
+
+namespace Scripting
+{
+
+  Sound::Sound()
+  {}
+
+  Sound::~Sound() 
+  {}
+
+  void
+  Sound::play_music(const std::string& )
+  {
+    NOIMPL;
+  }
+
+  void
+  Sound::play_sound(const std::string& )
+  {
+    NOIMPL;
+  }
+}
diff --git a/src/scripting/sound.h b/src/scripting/sound.h
new file mode 100644 (file)
index 0000000..66ac95a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __SOUND_H__
+#define __SOUND_H__
+
+namespace Scripting
+{
+
+class Sound
+{
+public:
+    void play_music(const std::string& musicfile);
+    void play_sound(const std::string& soundfile);
+
+#ifndef SCRIPTING_API
+    Sound();
+    ~Sound();
+#endif
+};
+
+}
+
+#endif
+
diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp
new file mode 100644 (file)
index 0000000..a7dd2f3
--- /dev/null
@@ -0,0 +1,381 @@
+/**
+ * WARNING: This file is automatically generated from './build/i686-pc-linux-gnu/debug/miniswig.tmp' - do not change
+ */
+
+#include <new>
+#include <string>
+#include <squirrel.h>
+#include "wrapper_util.h"
+#include "wrapper.interface.h"
+
+using namespace Scripting;
+
+static int Display_release_wrapper(SQUserPointer ptr, int )
+{
+  Display* _this = reinterpret_cast<Display*> (ptr);
+  delete _this;
+  return 0;
+}
+
+static int Display_construct_wrapper(HSQUIRRELVM v)
+{
+  Display* _this = new Display();
+  sq_setinstanceup(v, 1, _this);
+  sq_setreleasehook(v, 1, Display_release_wrapper);
+
+  return 0;
+}
+
+static int Display_set_effect_wrapper(HSQUIRRELVM v)
+{
+  Display* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  
+  _this->set_effect(arg0);
+  
+  return 0;
+}
+
+static int Camera_release_wrapper(SQUserPointer ptr, int )
+{
+  Camera* _this = reinterpret_cast<Camera*> (ptr);
+  delete _this;
+  return 0;
+}
+
+static int Camera_construct_wrapper(HSQUIRRELVM v)
+{
+  Camera* _this = new Camera();
+  sq_setinstanceup(v, 1, _this);
+  sq_setreleasehook(v, 1, Camera_release_wrapper);
+
+  return 0;
+}
+
+static int Camera_shake_wrapper(HSQUIRRELVM v)
+{
+  Camera* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  float arg1;
+  sq_getfloat(v, 3, &arg1);
+  float arg2;
+  sq_getfloat(v, 4, &arg2);
+  
+  _this->shake(arg0, arg1, arg2);
+  
+  return 0;
+}
+
+static int Camera_set_pos_wrapper(HSQUIRRELVM v)
+{
+  Camera* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  float arg1;
+  sq_getfloat(v, 3, &arg1);
+  
+  _this->set_pos(arg0, arg1);
+  
+  return 0;
+}
+
+static int Camera_set_mode_wrapper(HSQUIRRELVM v)
+{
+  Camera* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  
+  _this->set_mode(arg0);
+  
+  return 0;
+}
+
+static int Level_release_wrapper(SQUserPointer ptr, int )
+{
+  Level* _this = reinterpret_cast<Level*> (ptr);
+  delete _this;
+  return 0;
+}
+
+static int Level_construct_wrapper(HSQUIRRELVM v)
+{
+  Level* _this = new Level();
+  sq_setinstanceup(v, 1, _this);
+  sq_setreleasehook(v, 1, Level_release_wrapper);
+
+  return 0;
+}
+
+static int Level_finish_wrapper(HSQUIRRELVM v)
+{
+  Level* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  _this->finish();
+  
+  return 0;
+}
+
+static int Level_spawn_wrapper(HSQUIRRELVM v)
+{
+  Level* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  const char* arg1;
+  sq_getstring(v, 3, &arg1);
+  
+  _this->spawn(arg0, arg1);
+  
+  return 0;
+}
+
+static int ScriptedObject_release_wrapper(SQUserPointer ptr, int )
+{
+  ScriptedObject* _this = reinterpret_cast<ScriptedObject*> (ptr);
+  delete _this;
+  return 0;
+}
+
+static int ScriptedObject_construct_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this = new ScriptedObject();
+  sq_setinstanceup(v, 1, _this);
+  sq_setreleasehook(v, 1, ScriptedObject_release_wrapper);
+
+  return 0;
+}
+
+static int ScriptedObject_set_animation_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  
+  _this->set_animation(arg0);
+  
+  return 0;
+}
+
+static int ScriptedObject_get_animation_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  std::string return_value = _this->get_animation();
+  
+  sq_pushstring(v, return_value.c_str(), return_value.size());
+  return 1;
+}
+
+static int ScriptedObject_move_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  float arg1;
+  sq_getfloat(v, 3, &arg1);
+  
+  _this->move(arg0, arg1);
+  
+  return 0;
+}
+
+static int ScriptedObject_set_pos_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  float arg1;
+  sq_getfloat(v, 3, &arg1);
+  
+  _this->set_pos(arg0, arg1);
+  
+  return 0;
+}
+
+static int ScriptedObject_get_pos_x_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  float return_value = _this->get_pos_x();
+  
+  sq_pushfloat(v, return_value);
+  return 1;
+}
+
+static int ScriptedObject_get_pos_y_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  float return_value = _this->get_pos_y();
+  
+  sq_pushfloat(v, return_value);
+  return 1;
+}
+
+static int ScriptedObject_set_velocity_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  float arg1;
+  sq_getfloat(v, 3, &arg1);
+  
+  _this->set_velocity(arg0, arg1);
+  
+  return 0;
+}
+
+static int ScriptedObject_get_velocity_x_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  float return_value = _this->get_velocity_x();
+  
+  sq_pushfloat(v, return_value);
+  return 1;
+}
+
+static int ScriptedObject_get_velocity_y_wrapper(HSQUIRRELVM v)
+{
+  ScriptedObject* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  
+  float return_value = _this->get_velocity_y();
+  
+  sq_pushfloat(v, return_value);
+  return 1;
+}
+
+static int Sound_release_wrapper(SQUserPointer ptr, int )
+{
+  Sound* _this = reinterpret_cast<Sound*> (ptr);
+  delete _this;
+  return 0;
+}
+
+static int Sound_construct_wrapper(HSQUIRRELVM v)
+{
+  Sound* _this = new Sound();
+  sq_setinstanceup(v, 1, _this);
+  sq_setreleasehook(v, 1, Sound_release_wrapper);
+
+  return 0;
+}
+
+static int Sound_play_music_wrapper(HSQUIRRELVM v)
+{
+  Sound* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  
+  _this->play_music(arg0);
+  
+  return 0;
+}
+
+static int Sound_play_sound_wrapper(HSQUIRRELVM v)
+{
+  Sound* _this;
+  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  assert(_this != 0);
+  const char* arg0;
+  sq_getstring(v, 2, &arg0);
+  
+  _this->play_sound(arg0);
+  
+  return 0;
+}
+
+static int wait_wrapper(HSQUIRRELVM v)
+{
+  float arg0;
+  sq_getfloat(v, 2, &arg0);
+  
+  Scripting::wait(arg0);
+  
+  return 0;
+}
+
+WrappedFunction supertux_global_functions[] = {
+  { "wait", &wait_wrapper },
+  { 0, 0 }
+};
+
+static WrappedFunction supertux_Display_methods[] = {
+  { "constructor", &Display_construct_wrapper },
+  { "set_effect", &Display_set_effect_wrapper },
+};
+
+static WrappedFunction supertux_Camera_methods[] = {
+  { "constructor", &Camera_construct_wrapper },
+  { "shake", &Camera_shake_wrapper },
+  { "set_pos", &Camera_set_pos_wrapper },
+  { "set_mode", &Camera_set_mode_wrapper },
+};
+
+static WrappedFunction supertux_Level_methods[] = {
+  { "constructor", &Level_construct_wrapper },
+  { "finish", &Level_finish_wrapper },
+  { "spawn", &Level_spawn_wrapper },
+};
+
+static WrappedFunction supertux_ScriptedObject_methods[] = {
+  { "constructor", &ScriptedObject_construct_wrapper },
+  { "set_animation", &ScriptedObject_set_animation_wrapper },
+  { "get_animation", &ScriptedObject_get_animation_wrapper },
+  { "move", &ScriptedObject_move_wrapper },
+  { "set_pos", &ScriptedObject_set_pos_wrapper },
+  { "get_pos_x", &ScriptedObject_get_pos_x_wrapper },
+  { "get_pos_y", &ScriptedObject_get_pos_y_wrapper },
+  { "set_velocity", &ScriptedObject_set_velocity_wrapper },
+  { "get_velocity_x", &ScriptedObject_get_velocity_x_wrapper },
+  { "get_velocity_y", &ScriptedObject_get_velocity_y_wrapper },
+};
+
+static WrappedFunction supertux_Sound_methods[] = {
+  { "constructor", &Sound_construct_wrapper },
+  { "play_music", &Sound_play_music_wrapper },
+  { "play_sound", &Sound_play_sound_wrapper },
+};
+
+WrappedClass supertux_classes[] = {
+  { "Display", supertux_Display_methods },
+  { "Camera", supertux_Camera_methods },
+  { "Level", supertux_Level_methods },
+  { "ScriptedObject", supertux_ScriptedObject_methods },
+  { "Sound", supertux_Sound_methods },
+  { 0, 0 }
+};
+
diff --git a/src/scripting/wrapper.h b/src/scripting/wrapper.h
new file mode 100644 (file)
index 0000000..f25aea1
--- /dev/null
@@ -0,0 +1,13 @@
+/**
+ * WARNING: This file is automatically generated from './build/i686-pc-linux-gnu/debug/miniswig.tmp' - do not change
+ */
+#ifndef __supertux_WRAPPER_H__
+#define __supertux_WRAPPER_H__
+
+#include "wrapper_util.h"
+
+extern WrappedFunction supertux_global_functions[];
+extern WrappedClass supertux_classes[];
+
+#endif
+
diff --git a/src/scripting/wrapper.interface.h b/src/scripting/wrapper.interface.h
new file mode 100644 (file)
index 0000000..0b4513d
--- /dev/null
@@ -0,0 +1,9 @@
+/** This file is processes by miniswig to produce the scripting API */
+#define SCRIPTING_API
+
+#include "display.h"
+#include "camera.h"
+#include "level.h"
+#include "scripted_object.h"
+#include "sound.h"
+#include "functions.h"
diff --git a/src/scripting/wrapper_util.cpp b/src/scripting/wrapper_util.cpp
new file mode 100644 (file)
index 0000000..a16953a
--- /dev/null
@@ -0,0 +1,152 @@
+#include <config.h>
+
+#include <stdexcept>
+#include <sstream>
+#include "wrapper_util.h"
+
+static void register_function(HSQUIRRELVM v, SQFUNCTION func, const char* name)
+{
+    sq_pushstring(v, name, -1);
+    sq_newclosure(v, func, 0); //create a new function
+    sq_createslot(v, -3);
+}
+
+static void register_class(HSQUIRRELVM v, WrappedClass* wclass)
+{
+    sq_pushstring(v, wclass->name, -1);
+    sq_newclass(v, false);
+    for(WrappedFunction* func = wclass->functions; func->name != 0; ++func) {
+        register_function(v, func->f, func->name);
+    }
+    sq_createslot(v, -3);
+}
+
+void register_functions(HSQUIRRELVM v, WrappedFunction* functions)
+{
+    sq_pushroottable(v);
+    for(WrappedFunction* func = functions; func->name != 0; ++func) {
+        register_function(v, func->f, func->name);
+    }
+    sq_pop(v, 1);
+}
+
+void register_classes(HSQUIRRELVM v, WrappedClass* classes)
+{
+    sq_pushroottable(v);
+    for(WrappedClass* wclass = classes; wclass->name != 0; ++wclass) {
+        register_class(v, wclass);
+    }
+    sq_pop(v, 1);
+}
+
+static void print_stack(HSQUIRRELVM v)
+{
+    printf("--------------------------------------------------------------\n");
+    int count = sq_gettop(v);
+    for(int i = 1; i <= count; ++i) {
+        printf("%d: ",i);
+        switch(sq_gettype(v, i))
+        {
+            case OT_NULL:
+                printf("null");        
+                break;
+            case OT_INTEGER: {
+                int val;
+                sq_getinteger(v, i, &val);
+                printf("integer (%d)", val);
+                break;
+            }
+            case OT_FLOAT: {
+                float val;
+                sq_getfloat(v, i, &val);
+                printf("float (%f)", val);
+                break;
+            }
+            case OT_STRING: {
+                const char* val;
+                sq_getstring(v, i, &val);
+                printf("string (%s)", val);
+                break;    
+            }
+            case OT_TABLE:
+                printf("table");
+                break;
+            case OT_ARRAY:
+                printf("array");
+                break;
+            case OT_USERDATA:
+                printf("userdata");
+                break;
+            case OT_CLOSURE:        
+                printf("closure(function)");    
+                break;
+            case OT_NATIVECLOSURE:
+                printf("native closure(C function)");
+                break;
+            case OT_GENERATOR:
+                printf("generator");
+                break;
+            case OT_USERPOINTER:
+                printf("userpointer");
+                break;
+            case OT_CLASS:
+                printf("class");
+                break;
+            case OT_INSTANCE:
+                printf("instance");
+                break;
+            default:
+                printf("unknown?!?");
+                break;
+        }
+        printf("\n");
+    }
+    printf("--------------------------------------------------------------\n");
+}
+
+#define check(x)                                    \
+    if((x) < 0) {                                   \
+        std::stringstream msg;                      \
+        sq_getlasterror(v);                         \
+        const char* error;                          \
+        sq_getstring(v, -1, &error);                \
+        msg << "Error: " << error;                  \
+        throw std::runtime_error(msg.str());        \
+    }
+
+void expose_object(HSQUIRRELVM v, void* object, const char* type,
+        const char* name)
+{
+    // part1 of registration of the instance in the root table
+    sq_pushroottable(v);
+    sq_pushstring(v, name, -1);
+
+    // resolve class name
+    sq_pushroottable(v);
+    sq_pushstring(v, type, -1);
+    print_stack(v);
+    if(sq_get(v, -2) < 0) {
+        std::ostringstream msg;
+        msg << "Couldn't resolve squirrel type '" << type << "'.";
+        throw std::runtime_error(msg.str());
+    }
+    sq_remove(v, -2); // remove roottable
+    print_stack(v);
+
+    // create an instance and set pointer to c++ object
+    print_stack(v);
+    check(sq_createinstance(v, -1));
+    printf("after creatinstance\n");
+    print_stack(v);
+    check(sq_setinstanceup(v, -1, object));
+    printf("after setinstanceup\n");
+    print_stack(v);
+
+    sq_remove(v, -2); // remove class
+
+    // part2 of registration of the instance in the root table
+    print_stack(v);
+    check(sq_createslot(v, -3));
+    sq_pop(v, 1);
+}
+
diff --git a/src/scripting/wrapper_util.h b/src/scripting/wrapper_util.h
new file mode 100644 (file)
index 0000000..0eb0737
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __WRAPPERUTIL_HPP__
+#define __WRAPPERUTIL_HPP__
+
+#include <squirrel.h>
+
+struct WrappedFunction {
+    const char* name;
+    SQFUNCTION f;
+};
+struct WrappedClass {
+    const char* name;
+    WrappedFunction* functions;
+};
+
+void register_functions(HSQUIRRELVM v, WrappedFunction* functions);
+void register_classes(HSQUIRRELVM v, WrappedClass* classes);
+
+void expose_object(HSQUIRRELVM v, void* object, const char* type,
+        const char* name);
+
+#endif
index 46298c6..1470654 100644 (file)
@@ -26,7 +26,6 @@
 #include <fstream>
 #include <stdexcept>
 
-#include "app/globals.h"
 #include "sector.h"
 #include "player_status.h"
 #include "object/gameobjs.h"
index 64e2b3d..2067e09 100644 (file)
 #include "audio/musicref.h"
 #include "video/drawing_context.h"
 
-using namespace SuperTux;
-
-namespace SuperTux {
-class Rectangle;
-}
 namespace lisp {
 class Lisp;
 class Writer;
 }
 
+class Rectangle;
 class Sprite;
 class GameObject;
 class Player;
index 38a448d..28dc1fa 100644 (file)
@@ -23,8 +23,6 @@
 #include <cassert>
 #include <stdexcept>
 
-#include "app/globals.h"
-#include "app/setup.h"
 #include "sprite.h"
 #include "video/drawing_context.h"
 
index 16207ff..a369d66 100644 (file)
@@ -24,8 +24,7 @@
 #include <stdexcept>
 
 #include "sprite_data.h"
-#include "app/globals.h"
-#include "app/setup.h"
+#include "resources.h"
 #include "video/drawing_context.h"
 #include "lisp/list_iterator.h"
 
diff --git a/src/squirrel/Jamfile b/src/squirrel/Jamfile
new file mode 100644 (file)
index 0000000..556dd01
--- /dev/null
@@ -0,0 +1,10 @@
+SubDir TOP src squirrel ;
+
+Library squirrel
+    : [ Wildcard squirrel : *.cpp *.h ]
+      [ Wildcard sqstdlib : *.cpp *.h ]
+    : noinstall
+;
+IncludeDir squirrel : include ;
+C++Flags squirrel : -Wno-error -Wno-switch -Wno-missing-field-initializers
+-Wno-unused -Wno-parentheses -Wno-non-virtual-dtor -Wno-sign-compare ;
diff --git a/src/squirrel/README b/src/squirrel/README
new file mode 100644 (file)
index 0000000..a0776e9
--- /dev/null
@@ -0,0 +1,3 @@
+This directory contains the SQUIRREL programming language version 2.0.1 from
+http://squirrel.sourceforge.net
+Originally on zlib/png license.
diff --git a/src/squirrel/include/sqstdaux.h b/src/squirrel/include/sqstdaux.h
new file mode 100644 (file)
index 0000000..b900348
--- /dev/null
@@ -0,0 +1,16 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_AUXLIB_H_\r
+#define _SQSTD_AUXLIB_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);\r
+SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /* _SQSTD_AUXLIB_H_ */\r
diff --git a/src/squirrel/include/sqstdblob.h b/src/squirrel/include/sqstdblob.h
new file mode 100644 (file)
index 0000000..0237294
--- /dev/null
@@ -0,0 +1,20 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTDBLOB_H_\r
+#define _SQSTDBLOB_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size);\r
+SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr);\r
+SQUIRREL_API int sqstd_getblobsize(HSQUIRRELVM v,int idx);\r
+\r
+SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /*_SQSTDBLOB_H_*/\r
+\r
diff --git a/src/squirrel/include/sqstdio.h b/src/squirrel/include/sqstdio.h
new file mode 100644 (file)
index 0000000..9ea0230
--- /dev/null
@@ -0,0 +1,53 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTDIO_H_\r
+#define _SQSTDIO_H_\r
+\r
+#ifdef __cplusplus\r
+\r
+#define SQSTD_STREAM_TYPE_TAG 0x80000000\r
+\r
+struct SQStream {\r
+       virtual SQInteger Read(void *buffer, SQInteger size) = 0;\r
+       virtual SQInteger Write(void *buffer, SQInteger size) = 0;\r
+       virtual int Flush() = 0;\r
+       virtual long Tell() = 0;\r
+       virtual SQInteger Len() = 0;\r
+       virtual SQInteger Seek(long offset, int origin) = 0;\r
+       virtual bool IsValid() = 0;\r
+       virtual bool EOS() = 0;\r
+};\r
+\r
+extern "C" {\r
+#endif\r
+\r
+#define SQ_SEEK_CUR 0\r
+#define SQ_SEEK_END 1\r
+#define SQ_SEEK_SET 2\r
+\r
+typedef void* SQFILE;\r
+\r
+SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);\r
+SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);\r
+SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);\r
+SQUIRREL_API SQInteger sqstd_fseek(SQFILE , long , int);\r
+SQUIRREL_API long sqstd_ftell(SQFILE);\r
+SQUIRREL_API SQInteger sqstd_fflush(SQFILE);\r
+SQUIRREL_API SQInteger sqstd_fclose(SQFILE);\r
+SQUIRREL_API SQInteger sqstd_feof(SQFILE);\r
+\r
+SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);\r
+SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file);\r
+\r
+//compiler helpers\r
+SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);\r
+SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);\r
+SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);\r
+\r
+SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /*_SQSTDIO_H_*/\r
+\r
diff --git a/src/squirrel/include/sqstdmath.h b/src/squirrel/include/sqstdmath.h
new file mode 100644 (file)
index 0000000..420f2ce
--- /dev/null
@@ -0,0 +1,15 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_MATH_H_\r
+#define _SQSTD_MATH_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /*_SQSTD_MATH_H_*/\r
diff --git a/src/squirrel/include/sqstdstring.h b/src/squirrel/include/sqstdstring.h
new file mode 100644 (file)
index 0000000..83f55aa
--- /dev/null
@@ -0,0 +1,34 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_STRING_H_\r
+#define _SQSTD_STRING_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+//#define SQRex_True 1\r
+//#define SQRex_False 0\r
+\r
+typedef unsigned int SQRexBool;\r
+typedef struct SQRex SQRex;\r
+\r
+typedef struct {\r
+       const SQChar *begin;\r
+       int len;\r
+} SQRexMatch;\r
+\r
+SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);\r
+SQUIRREL_API void sqstd_rex_free(SQRex *exp);\r
+SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);\r
+SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);\r
+SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);\r
+SQUIRREL_API int sqstd_rex_getsubexpcount(SQRex* exp);\r
+SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp);\r
+\r
+SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /*_SQSTD_STRING_H_*/\r
diff --git a/src/squirrel/include/sqstdsystem.h b/src/squirrel/include/sqstdsystem.h
new file mode 100644 (file)
index 0000000..73099ae
--- /dev/null
@@ -0,0 +1,15 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_SYSTEMLIB_H_\r
+#define _SQSTD_SYSTEMLIB_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SQUIRREL_API int sqstd_register_systemlib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /* _SQSTD_SYSTEMLIB_H_ */\r
diff --git a/src/squirrel/include/squirrel.h b/src/squirrel/include/squirrel.h
new file mode 100644 (file)
index 0000000..a59dbf9
--- /dev/null
@@ -0,0 +1,368 @@
+/*\r
+Copyright (c) 2003-2005 Alberto Demichelis\r
+\r
+This software is provided 'as-is', without any \r
+express or implied warranty. In no event will the \r
+authors be held liable for any damages arising from \r
+the use of this software.\r
+\r
+Permission is granted to anyone to use this software \r
+for any purpose, including commercial applications, \r
+and to alter it and redistribute it freely, subject \r
+to the following restrictions:\r
+\r
+               1. The origin of this software must not be \r
+               misrepresented; you must not claim that \r
+               you wrote the original software. If you \r
+               use this software in a product, an \r
+               acknowledgment in the product \r
+               documentation would be appreciated but is \r
+               not required.\r
+\r
+               2. Altered source versions must be plainly \r
+               marked as such, and must not be \r
+               misrepresented as being the original \r
+               software.\r
+\r
+               3. This notice may not be removed or \r
+               altered from any source distribution.\r
+\r
+*/\r
+#ifndef _SQUIRREL_H_\r
+#define _SQUIRREL_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifndef SQUIRREL_API\r
+#define SQUIRREL_API extern\r
+#endif\r
+\r
+typedef float SQFloat;\r
+typedef int SQInteger;\r
+typedef void* SQUserPointer;\r
+typedef unsigned int SQBool;\r
+typedef int SQRESULT;\r
+\r
+#define SQTrue 1\r
+#define SQFalse        0\r
+\r
+\r
+struct SQVM;\r
+struct SQTable;\r
+struct SQArray;\r
+struct SQString;\r
+struct SQClosure;\r
+struct SQGenerator;\r
+struct SQNativeClosure;\r
+struct SQUserData;\r
+struct SQFunctionProto;\r
+struct SQRefCounted;\r
+struct SQClass;\r
+struct SQInstance;\r
+struct SQDelegable;\r
+\r
+#ifdef _UNICODE\r
+#define SQUNICODE\r
+#endif\r
+\r
+#ifdef SQUNICODE\r
+typedef unsigned short SQChar;\r
+#define _SC(a) L##a\r
+#define        scstrcmp        wcscmp\r
+#define scsprintf      swprintf\r
+#define scstrlen       wcslen\r
+#define scstrtod       wcstod\r
+#define scatoi         _wtoi\r
+#define scstrtoul      wcstoul\r
+#define scvsprintf     vswprintf\r
+#define scstrstr       wcsstr\r
+#define scisspace      iswspace\r
+#define scisdigit      iswdigit\r
+#define scisalpha      iswalpha\r
+#define sciscntrl      iswcntrl\r
+#define scisalnum      iswalnum\r
+#define scprintf       wprintf\r
+#define MAX_CHAR 0xFFFF\r
+#else\r
+typedef char SQChar;\r
+#define _SC(a) a\r
+#define        scstrcmp        strcmp\r
+#define scsprintf      sprintf\r
+#define scstrlen       strlen\r
+#define scstrtod       strtod\r
+#define scatoi         atoi\r
+#define scstrtoul      strtoul\r
+#define scvsprintf     vsprintf\r
+#define scstrstr       strstr\r
+#define scisspace      isspace\r
+#define scisdigit      isdigit\r
+#define sciscntrl      iscntrl\r
+#define scisalpha      isalpha\r
+#define scisalnum      isalnum\r
+#define scprintf       printf\r
+#define MAX_CHAR 0xFF\r
+#endif\r
+\r
+#define SQUIRREL_VERSION       _SC("Squirrel 2.0.1 stable")\r
+#define SQUIRREL_COPYRIGHT     _SC("Copyright (C) 2003-2005 Alberto Demichelis")\r
+#define SQUIRREL_AUTHOR                _SC("Alberto Demichelis")\r
+\r
+#define SQ_VMSTATE_IDLE                        0\r
+#define SQ_VMSTATE_RUNNING             1\r
+#define SQ_VMSTATE_SUSPENDED   2\r
+\r
+#define SQUIRREL_EOB 0\r
+#define SQ_BYTECODE_STREAM_TAG 0xFAFA\r
+\r
+#define SQOBJECT_REF_COUNTED   0x00800000\r
+#define SQOBJECT_NUMERIC               0x00080000\r
+#define SQOBJECT_DELEGABLE             0x08000000\r
+#define SQOBJECT_CANBEFALSE            0x80000000\r
+//typedef unsigned int SQObjectType;\r
+\r
+#define _RT_MASK 0x0000FFFF\r
+#define _RAW_TYPE(type) (type&_RT_MASK)\r
+\r
+#define _RT_NULL                       0x00000000\r
+#define _RT_INTEGER                    0x00000001\r
+#define _RT_FLOAT                      0x00000002\r
+#define _RT_BOOL                       0x00000004\r
+#define _RT_STRING                     0x00000008\r
+#define _RT_TABLE                      0x00000010\r
+#define _RT_ARRAY                      0x00000020\r
+#define _RT_USERDATA           0x00000040\r
+#define _RT_CLOSURE                    0x00000080\r
+#define _RT_NATIVECLOSURE      0x00000100\r
+#define _RT_GENERATOR          0x00000200\r
+#define _RT_USERPOINTER                0x00000400\r
+#define _RT_THREAD                     0x00000800\r
+#define _RT_FUNCPROTO          0x00001000\r
+#define _RT_CLASS                      0x00002000\r
+#define _RT_INSTANCE           0x00004000\r
+\r
+typedef enum {\r
+       OT_NULL =                       (_RT_NULL|SQOBJECT_CANBEFALSE),\r
+       OT_INTEGER =            (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),\r
+       OT_FLOAT =                      (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),\r
+       OT_BOOL =                       (_RT_BOOL|SQOBJECT_CANBEFALSE),\r
+       OT_STRING =                     (_RT_STRING|SQOBJECT_REF_COUNTED),\r
+       OT_TABLE =                      (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),\r
+       OT_ARRAY =                      (_RT_ARRAY|SQOBJECT_REF_COUNTED),\r
+       OT_USERDATA =           (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),\r
+       OT_CLOSURE =            (_RT_CLOSURE|SQOBJECT_REF_COUNTED),\r
+       OT_NATIVECLOSURE =      (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),\r
+       OT_GENERATOR =          (_RT_GENERATOR|SQOBJECT_REF_COUNTED),\r
+       OT_USERPOINTER =        _RT_USERPOINTER,\r
+       OT_THREAD =                     (_RT_THREAD|SQOBJECT_REF_COUNTED) ,\r
+       OT_FUNCPROTO =          (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only\r
+       OT_CLASS =                      (_RT_CLASS|SQOBJECT_REF_COUNTED),\r
+       OT_INSTANCE =           (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE)\r
+}SQObjectType;\r
+\r
+#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)\r
+\r
+\r
+typedef union tagSQObjectValue\r
+{\r
+       struct SQTable *pTable;\r
+       struct SQArray *pArray;\r
+       struct SQClosure *pClosure;\r
+       struct SQGenerator *pGenerator;\r
+       struct SQNativeClosure *pNativeClosure;\r
+       struct SQString *pString;\r
+       struct SQUserData *pUserData;\r
+       SQInteger nInteger;\r
+       SQFloat fFloat;\r
+       SQUserPointer pUserPointer;\r
+       struct SQFunctionProto *pFunctionProto;\r
+       struct SQRefCounted *pRefCounted;\r
+       struct SQDelegable *pDelegable;\r
+       struct SQVM *pThread;\r
+       struct SQClass *pClass;\r
+       struct SQInstance *pInstance;\r
+}SQObjectValue;\r
+\r
+\r
+typedef struct tagSQObject\r
+{\r
+       SQObjectValue _unVal;\r
+       SQObjectType _type;\r
+}SQObject;\r
+\r
+typedef struct tagSQStackInfos{\r
+       const SQChar* funcname;\r
+       const SQChar* source;\r
+       int line;\r
+}SQStackInfos;\r
+\r
+typedef struct SQVM* HSQUIRRELVM;\r
+typedef SQObject HSQOBJECT;\r
+typedef int (*SQFUNCTION)(HSQUIRRELVM);\r
+typedef int (*SQRELEASEHOOK)(SQUserPointer,int size);\r
+typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,int /*line*/,int /*column*/);\r
+typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);\r
+\r
+typedef int (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,int);\r
+typedef int (*SQREADFUNC)(SQUserPointer,SQUserPointer,int);\r
+\r
+typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);\r
+\r
+typedef struct tagSQRegFunction{\r
+       const SQChar *name;\r
+       SQFUNCTION f;\r
+       int nparamscheck;\r
+       const SQChar *typemask;\r
+}SQRegFunction;\r
+\r
+/*vm*/\r
+SQUIRREL_API HSQUIRRELVM sq_open(int initialstacksize);\r
+SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize);\r
+SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_close(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);\r
+SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);\r
+SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval);\r
+SQUIRREL_API int sq_getvmstate(HSQUIRRELVM v);\r
+\r
+/*compiler*/\r
+SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);\r
+SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror);\r
+SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo);\r
+SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);\r
+\r
+/*stack operations*/\r
+SQUIRREL_API void sq_push(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API void sq_pop(HSQUIRRELVM v,int nelemstopop);\r
+SQUIRREL_API void sq_remove(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API int sq_gettop(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_settop(HSQUIRRELVM v,int newtop);\r
+SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,int nsize);\r
+SQUIRREL_API int sq_cmp(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx);\r
+\r
+/*object creation handling*/\r
+SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size);\r
+SQUIRREL_API void sq_newtable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_newarray(HSQUIRRELVM v,int size);\r
+SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars);\r
+SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask);\r
+SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len);\r
+SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);\r
+SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n);\r
+SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b);\r
+SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);\r
+SQUIRREL_API void sq_pushnull(HSQUIRRELVM v);\r
+SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c);\r
+SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i);\r
+SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f);\r
+SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b);\r
+SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread);\r
+SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,int idx,SQUserPointer *p);\r
+SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag);\r
+SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag);\r
+SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag);\r
+SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook);\r
+SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize);\r
+SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars);\r
+SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name);\r
+SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p);\r
+SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag);\r
+SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);\r
+SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,int idx);\r
+\r
+/*object manipulation*/\r
+SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval);\r
+SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval);\r
+SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval); \r
+SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize); \r
+SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx); \r
+SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,int idx);\r
+SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval);\r
+SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,int idx);\r
+\r
+/*calls*/\r
+SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval);\r
+SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval);\r
+SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx);\r
+SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);\r
+SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);\r
+\r
+/*raw object handling*/\r
+SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po);\r
+SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);\r
+SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);\r
+SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);\r
+SQUIRREL_API void sq_resetobject(HSQOBJECT *po);\r
+SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o);\r
+SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);\r
+SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);\r
+\r
+/*GC*/\r
+SQUIRREL_API int sq_collectgarbage(HSQUIRRELVM v);\r
+\r
+/*serialization*/\r
+SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);\r
+SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);\r
+\r
+/*mem allocation*/\r
+SQUIRREL_API void *sq_malloc(unsigned int size);\r
+SQUIRREL_API void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize);\r
+SQUIRREL_API void sq_free(void *p,unsigned int size);\r
+\r
+/*debug*/\r
+SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,int level,SQStackInfos *si);\r
+SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);\r
+\r
+/*UTILITY MACRO*/\r
+#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)\r
+#define sq_istable(o) ((o)._type==OT_TABLE)\r
+#define sq_isarray(o) ((o)._type==OT_ARRAY)\r
+#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)\r
+#define sq_isclosure(o) ((o)._type==OT_CLOSURE)\r
+#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)\r
+#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)\r
+#define sq_isstring(o) ((o)._type==OT_STRING)\r
+#define sq_isinteger(o) ((o)._type==OT_INTEGER)\r
+#define sq_isfloat(o) ((o)._type==OT_FLOAT)\r
+#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)\r
+#define sq_isuserdata(o) ((o)._type==OT_USERDATA)\r
+#define sq_isthread(o) ((o)._type==OT_THREAD)\r
+#define sq_isnull(o) ((o)._type==OT_NULL)\r
+#define sq_isclass(o) ((o)._type==OT_CLASS)\r
+#define sq_isinstance(o) ((o)._type==OT_INSTANCE)\r
+#define sq_isbool(o) ((o)._type==OT_BOOL)\r
+#define sq_type(o) ((o)._type)\r
+\r
+#define SQ_OK (0)\r
+#define SQ_ERROR (-1)\r
+\r
+#define SQ_FAILED(res) (res<0)\r
+#define SQ_SUCCEEDED(res) (res>=0)\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /*_SQUIRREL_H_*/\r
diff --git a/src/squirrel/sqstdlib/Makefile b/src/squirrel/sqstdlib/Makefile
new file mode 100644 (file)
index 0000000..625f1b4
--- /dev/null
@@ -0,0 +1,21 @@
+SQUIRREL= ..\r
+\r
+\r
+OUT= $(SQUIRREL)/lib/libsqstdlib.a\r
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude\r
+\r
+SRCS= \\r
+       sqstdblob.cpp \\r
+       sqstdio.cpp \\r
+       sqstdstream.cpp \\r
+       sqstdmath.cpp \\r
+       sqstdsystem.cpp \\r
+       sqstdstring.cpp \\r
+       sqstdaux.cpp \\r
+       sqstdrex.c\r
+       \r
+       \r
+squirrel:\r
+       gcc -O3 -Os -c $(SRCS) $(INCZ)\r
+       ar rc $(OUT) *.o\r
+       rm *.o
\ No newline at end of file
diff --git a/src/squirrel/sqstdlib/sqstdaux.cpp b/src/squirrel/sqstdlib/sqstdaux.cpp
new file mode 100644 (file)
index 0000000..9609b50
--- /dev/null
@@ -0,0 +1,116 @@
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <sqstdaux.h>\r
+\r
+void sqstd_printcallstack(HSQUIRRELVM v)\r
+{\r
+       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       if(pf) {\r
+               SQStackInfos si;\r
+               SQInteger i;\r
+               SQFloat f;\r
+               const SQChar *s;\r
+               int level=1; //1 is to skip this function that is level 0\r
+               const SQChar *name=0; \r
+               int seq=0;\r
+               pf(v,_SC("\nCALLSTACK\n"));\r
+               while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))\r
+               {\r
+                       const SQChar *fn=_SC("unknown");\r
+                       const SQChar *src=_SC("unknown");\r
+                       if(si.funcname)fn=si.funcname;\r
+                       if(si.source)src=si.source;\r
+                       pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);\r
+                       level++;\r
+               }\r
+               level=0;\r
+               pf(v,_SC("\nLOCALS\n"));\r
+\r
+               for(level=0;level<10;level++){\r
+                       seq=0;\r
+                       while(name=sq_getlocal(v,level,seq))\r
+                       {\r
+                               seq++;\r
+                               switch(sq_gettype(v,-1))\r
+                               {\r
+                               case OT_NULL:\r
+                                       pf(v,_SC("[%s] NULL\n"),name);\r
+                                       break;\r
+                               case OT_INTEGER:\r
+                                       sq_getinteger(v,-1,&i);\r
+                                       pf(v,_SC("[%s] %d\n"),name,i);\r
+                                       break;\r
+                               case OT_FLOAT:\r
+                                       sq_getfloat(v,-1,&f);\r
+                                       pf(v,_SC("[%s] %.14g\n"),name,f);\r
+                                       break;\r
+                               case OT_USERPOINTER:\r
+                                       pf(v,_SC("[%s] USERPOINTER\n"),name);\r
+                                       break;\r
+                               case OT_STRING:\r
+                                       sq_getstring(v,-1,&s);\r
+                                       pf(v,_SC("[%s] \"%s\"\n"),name,s);\r
+                                       break;\r
+                               case OT_TABLE:\r
+                                       pf(v,_SC("[%s] TABLE\n"),name);\r
+                                       break;\r
+                               case OT_ARRAY:\r
+                                       pf(v,_SC("[%s] ARRAY\n"),name);\r
+                                       break;\r
+                               case OT_CLOSURE:\r
+                                       pf(v,_SC("[%s] CLOSURE\n"),name);\r
+                                       break;\r
+                               case OT_NATIVECLOSURE:\r
+                                       pf(v,_SC("[%s] NATIVECLOSURE\n"),name);\r
+                                       break;\r
+                               case OT_USERDATA:\r
+                                       pf(v,_SC("[%s] USERDATA\n"),name);\r
+                                       break;\r
+                               case OT_THREAD:\r
+                                       pf(v,_SC("[%s] THREAD\n"),name);\r
+                                       break;\r
+                               case OT_CLASS:\r
+                                       pf(v,_SC("[%s] CLASS\n"),name);\r
+                                       break;\r
+                               case OT_INSTANCE:\r
+                                       pf(v,_SC("[%s] INSTANCE\n"),name);\r
+                                       break;\r
+                               }\r
+                               sq_pop(v,1);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+static int _sqstd_aux_printerror(HSQUIRRELVM v)\r
+{\r
+       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       if(pf) {\r
+               const SQChar *sErr = 0;\r
+               if(sq_gettop(v)>=1) {\r
+                       if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr)))       {\r
+                               pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);\r
+                       }\r
+                       else{\r
+                               pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n"));\r
+                       }\r
+                       sqstd_printcallstack(v);\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,int line,int column)\r
+{\r
+       SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+       if(pf) {\r
+               pf(v,_SC("ERROR %s line=(%d) column=(%d) [%s]\n"),sErr,line,column,sSource);\r
+       }\r
+}\r
+\r
+void sqstd_seterrorhandlers(HSQUIRRELVM v)\r
+{\r
+       sq_setcompilererrorhandler(v,_sqstd_compiler_error);\r
+       sq_newclosure(v,_sqstd_aux_printerror,0);\r
+       sq_seterrorhandler(v);\r
+}\r
diff --git a/src/squirrel/sqstdlib/sqstdblob.cpp b/src/squirrel/sqstdlib/sqstdblob.cpp
new file mode 100644 (file)
index 0000000..6813f5f
--- /dev/null
@@ -0,0 +1,255 @@
+/* see copyright notice in squirrel.h */\r
+#include <new>\r
+#include <squirrel.h>\r
+#include <sqstdio.h>\r
+#include <string.h>\r
+#include <sqstdblob.h>\r
+#include "sqstdstream.h"\r
+#include "sqstdblobimpl.h"\r
+\r
+#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)\r
+\r
+//Blob\r
+\r
+\r
+#define SETUP_BLOB(v) \\r
+       SQBlob *self = NULL; \\r
+       { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_BLOB_TYPE_TAG))) \\r
+               return SQ_ERROR; }\r
+\r
+\r
+static int _blob_resize(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       SQInteger size;\r
+       sq_getinteger(v,2,&size);\r
+       if(!self->Resize(size))\r
+               return sq_throwerror(v,_SC("resize failed"));\r
+       return 0;\r
+}\r
+\r
+static void __swap_dword(unsigned int *n)\r
+{\r
+       *n=(unsigned int)(((*n&0xFF000000)>>24)  |\r
+                       ((*n&0x00FF0000)>>8)  |\r
+                       ((*n&0x0000FF00)<<8)  |\r
+                       ((*n&0x000000FF)<<24));\r
+}\r
+\r
+static void __swap_word(unsigned short *n)\r
+{\r
+       *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);\r
+}\r
+\r
+static int _blob_swap4(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       int num=(self->Len()-(self->Len()%4))>>2;\r
+       unsigned int *t=(unsigned int *)self->GetBuf();\r
+       for(int i = 0; i < num; i++) {\r
+               __swap_dword(&t[i]);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int _blob_swap2(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       int num=(self->Len()-(self->Len()%2))>>1;\r
+       unsigned short *t = (unsigned short *)self->GetBuf();\r
+       for(int i = 0; i < num; i++) {\r
+               __swap_word(&t[i]);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int _blob__set(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       SQInteger idx,val;\r
+       sq_getinteger(v,2,&idx);\r
+       sq_getinteger(v,3,&val);\r
+       if(idx < 0 || idx >= self->Len())\r
+               return sq_throwerror(v,_SC("index out of range"));\r
+       ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;\r
+       sq_push(v,3);\r
+       return 1;\r
+}\r
+\r
+static int _blob__get(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       SQInteger idx;\r
+       sq_getinteger(v,2,&idx);\r
+       if(idx < 0 || idx >= self->Len())\r
+               return sq_throwerror(v,_SC("index out of range"));\r
+       sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);\r
+       return 1;\r
+}\r
+\r
+static int _blob__nexti(HSQUIRRELVM v)\r
+{\r
+       SETUP_BLOB(v);\r
+       if(sq_gettype(v,2) == OT_NULL) {\r
+               sq_pushinteger(v, 0);\r
+               return 1;\r
+       }\r
+       SQInteger idx;\r
+       if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {\r
+               if(idx+1 < self->Len()) {\r
+                       sq_pushinteger(v, idx+1);\r
+                       return 1;\r
+               }\r
+               sq_pushnull(v);\r
+               return 1;\r
+       }\r
+       return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));\r
+}\r
+\r
+static int _blob__typeof(HSQUIRRELVM v)\r
+{\r
+       sq_pushstring(v,_SC("blob"),-1);\r
+       return 1;\r
+}\r
+\r
+static int _blob_releasehook(SQUserPointer p, int size)\r
+{\r
+       SQBlob *self = (SQBlob*)p;\r
+       delete self;\r
+       return 1;\r
+}\r
+\r
+static int _blob_constructor(HSQUIRRELVM v)\r
+{\r
+       SQInteger nparam = sq_gettop(v);\r
+       SQInteger size = 0;\r
+       if(nparam == 2) {\r
+               sq_getinteger(v, 2, &size);\r
+       }\r
+       if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
+       SQBlob *b = new SQBlob(size);\r
+       if(SQ_FAILED(sq_setinstanceup(v,1,b))) {\r
+               delete b;\r
+               return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
+       }\r
+       sq_setreleasehook(v,1,_blob_releasehook);\r
+       return 0;\r
+}\r
+\r
+#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}\r
+static SQRegFunction _blob_methods[] = {\r
+       _DECL_BLOB_FUNC(constructor,-1,_SC("xn")),\r
+       _DECL_BLOB_FUNC(resize,2,_SC("xn")),\r
+       _DECL_BLOB_FUNC(swap2,1,_SC("x")),\r
+       _DECL_BLOB_FUNC(swap4,1,_SC("x")),\r
+       _DECL_BLOB_FUNC(_set,3,_SC("xnn")),\r
+       _DECL_BLOB_FUNC(_get,2,_SC("xn")),\r
+       _DECL_BLOB_FUNC(_typeof,1,_SC("x")),\r
+       _DECL_BLOB_FUNC(_nexti,2,_SC("x")),\r
+       {0,0,0,0}\r
+};\r
+\r
+\r
+\r
+//GLOBAL FUNCTIONS\r
+\r
+static int _g_blob_casti2f(HSQUIRRELVM v)\r
+{\r
+       SQInteger i;\r
+       sq_getinteger(v,2,&i);\r
+       sq_pushfloat(v,*((SQFloat *)&i));\r
+       return 1;\r
+}\r
+\r
+static int _g_blob_castf2i(HSQUIRRELVM v)\r
+{\r
+       SQFloat f;\r
+       sq_getfloat(v,2,&f);\r
+       sq_pushinteger(v,*((SQInteger *)&f));\r
+       return 1;\r
+}\r
+\r
+static int _g_blob_swap2(HSQUIRRELVM v)\r
+{\r
+       SQInteger i;\r
+       sq_getinteger(v,2,&i);\r
+       short s=(short)i;\r
+       sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));\r
+       return 1;\r
+}\r
+\r
+static int _g_blob_swap4(HSQUIRRELVM v)\r
+{\r
+       SQInteger i;\r
+       sq_getinteger(v,2,&i);\r
+       __swap_dword((unsigned int *)&i);\r
+       sq_pushinteger(v,i);\r
+       return 1;\r
+}\r
+\r
+static int _g_blob_swapfloat(HSQUIRRELVM v)\r
+{\r
+       SQFloat f;\r
+       sq_getfloat(v,2,&f);\r
+       __swap_dword((unsigned int *)&f);\r
+       sq_pushfloat(v,f);\r
+       return 1;\r
+}\r
+\r
+#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}\r
+static SQRegFunction bloblib_funcs[]={\r
+       _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),\r
+       _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),\r
+       _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),\r
+       _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),\r
+       _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),\r
+       {0,0}\r
+};\r
+\r
+SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr)\r
+{\r
+       SQBlob *blob;\r
+       if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))\r
+               return -1;\r
+       *ptr = blob->GetBuf();\r
+       return SQ_OK;\r
+}\r
+\r
+int sqstd_getblobsize(HSQUIRRELVM v,int idx)\r
+{\r
+       SQBlob *blob;\r
+       if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))\r
+               return -1;\r
+       return blob->Len();\r
+}\r
+\r
+SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size)\r
+{\r
+       int top = sq_gettop(v);\r
+//     SQUserPointer p = sq_newuserdata(v, sizeof(SQBlob));\r
+//     sq_setreleasehook(v,-1,_blob_releasehook);\r
+//     sq_settypetag(v,-1,SQSTD_BLOB_TYPE_TAG);\r
+//     new (p) SQBlob(size);\r
+       sq_pushregistrytable(v);\r
+       sq_pushstring(v,_SC("std_blob"),-1);\r
+       if(SQ_SUCCEEDED(sq_get(v,-2))) {\r
+               sq_remove(v,-2); //removes the registry\r
+               sq_push(v,1); // push the this\r
+               sq_pushinteger(v,size); //size\r
+               SQBlob *blob = NULL;\r
+               if(SQ_SUCCEEDED(sq_call(v,2,SQTrue))\r
+                       && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG))) {\r
+                       sq_remove(v,-2);\r
+                       sq_remove(v,-2);\r
+                       return blob->GetBuf();\r
+               }\r
+       }\r
+       sq_settop(v,top);\r
+       return NULL;\r
+}\r
+\r
+SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)\r
+{\r
+       return declare_stream(v,_SC("blob"),SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);\r
+}\r
+\r
diff --git a/src/squirrel/sqstdlib/sqstdblobimpl.h b/src/squirrel/sqstdlib/sqstdblobimpl.h
new file mode 100644 (file)
index 0000000..6bcd48e
--- /dev/null
@@ -0,0 +1,108 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_BLOBIMPL_H_\r
+#define _SQSTD_BLOBIMPL_H_\r
+\r
+struct SQBlob : public SQStream\r
+{\r
+       SQBlob(int size) {\r
+               _size = size;\r
+               _allocated = size;\r
+               _buf = (unsigned char *)sq_malloc(size);\r
+               memset(_buf, 0, _size);\r
+               _ptr = 0;\r
+               _owns = true;\r
+       }\r
+       ~SQBlob() {\r
+               sq_free(_buf, _size);\r
+       }\r
+       SQInteger Write(void *buffer, SQInteger size) {\r
+               if(!CanAdvance(size)) {\r
+                       GrowBufOf(_ptr + size - _size);\r
+               }\r
+               memcpy(&_buf[_ptr], buffer, size);\r
+               _ptr += size;\r
+               return size;\r
+       }\r
+       SQInteger Read(void *buffer,SQInteger size) {\r
+               int n = size;\r
+               if(!CanAdvance(size)) {\r
+                       if((_size - _ptr) > 0)\r
+                               n = _size - _ptr;\r
+                       else return 0;\r
+               }\r
+               memcpy(buffer, &_buf[_ptr], n);\r
+               _ptr += n;\r
+               return n;\r
+       }\r
+       bool Resize(int n) {\r
+               if(!_owns) return false;\r
+               if(n != _allocated) {\r
+                       unsigned char *newbuf = (unsigned char *)sq_malloc(n);\r
+                       memset(newbuf,0,n);\r
+                       if(_size > n)\r
+                               memcpy(newbuf,_buf,n);\r
+                       else\r
+                               memcpy(newbuf,_buf,_size);\r
+                       sq_free(_buf,_allocated);\r
+                       _buf=newbuf;\r
+                       _allocated = n;\r
+                       if(_size > _allocated)\r
+                               _size = _allocated;\r
+                       if(_ptr > _allocated)\r
+                               _ptr = _allocated;\r
+               }\r
+               return true;\r
+       }\r
+       bool GrowBufOf(int n)\r
+       {\r
+               bool ret = true;\r
+               if(_size + n > _allocated) {\r
+                       if(_size + n > _size * 2)\r
+                               ret = Resize(_size + n);\r
+                       else\r
+                               ret = Resize(_size * 2);\r
+               }\r
+               _size = _size + n;\r
+               return ret;\r
+       }\r
+       bool CanAdvance(int n) {\r
+               if(_ptr+n>_size)return false;\r
+               return true;\r
+       }\r
+       SQInteger Seek(long offset, int origin) {\r
+               switch(origin) {\r
+                       case SQ_SEEK_SET:\r
+                               if(offset >= _size || offset < 0) return -1;\r
+                               _ptr = offset;\r
+                               break;\r
+                       case SQ_SEEK_CUR:\r
+                               if(_ptr + offset >= _size || _ptr + offset < 0) return -1;\r
+                               _ptr += offset;\r
+                               break;\r
+                       case SQ_SEEK_END:\r
+                               if(_size + offset >= _size || _size + offset < 0) return -1;\r
+                               _ptr = _size + offset;\r
+                               break;\r
+                       default: return -1;\r
+               }\r
+               return 0;\r
+       }\r
+       bool IsValid() {\r
+               return _buf?true:false;\r
+       }\r
+       bool EOS() {\r
+               return _ptr == _size;\r
+       }\r
+       int Flush() { return 0; }\r
+       long Tell() { return _ptr; }\r
+       SQInteger Len() { return _size; }\r
+       SQUserPointer GetBuf(){ return _buf; }\r
+private:\r
+       int _size;\r
+       int _allocated;\r
+       int _ptr;\r
+       unsigned char *_buf;\r
+       bool _owns;\r
+};\r
+\r
+#endif //_SQSTD_BLOBIMPL_H_\r
diff --git a/src/squirrel/sqstdlib/sqstdio.cpp b/src/squirrel/sqstdlib/sqstdio.cpp
new file mode 100644 (file)
index 0000000..5d02f55
--- /dev/null
@@ -0,0 +1,336 @@
+/* see copyright notice in squirrel.h */\r
+#include <new>\r
+#include <stdio.h>\r
+#include <squirrel.h>\r
+#include <sqstdio.h>\r
+#include "sqstdstream.h"\r
+\r
+#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)\r
+//basic API\r
+SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)\r
+{\r
+#ifndef _UNICODE\r
+       return (SQFILE)fopen(filename,mode);\r
+#else\r
+       return (SQFILE)_wfopen(filename,mode);\r
+#endif\r
+}\r
+\r
+SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)\r
+{\r
+       return (SQInteger)fread(buffer,size,count,(FILE *)file);\r
+}\r
+\r
+SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)\r
+{\r
+       return (SQInteger)fwrite(buffer,size,count,(FILE *)file);\r
+}\r
+\r
+SQInteger sqstd_fseek(SQFILE file, long offset, int origin)\r
+{\r
+       int realorigin;\r
+       switch(origin) {\r
+               case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;\r
+               case SQ_SEEK_END: realorigin = SEEK_END; break;\r
+               case SQ_SEEK_SET: realorigin = SEEK_SET; break;\r
+               default: return -1; //failed\r
+       }\r
+       return fseek((FILE *)file,offset,realorigin);\r
+}\r
+\r
+long sqstd_ftell(SQFILE file)\r
+{\r
+       return ftell((FILE *)file);\r
+}\r
+\r
+SQInteger sqstd_fflush(SQFILE file)\r
+{\r
+       return fflush((FILE *)file);\r
+}\r
+\r
+SQInteger sqstd_fclose(SQFILE file)\r
+{\r
+       return fclose((FILE *)file);\r
+}\r
+\r
+SQInteger sqstd_feof(SQFILE file)\r
+{\r
+       return feof((FILE *)file);\r
+}\r
+\r
+//File\r
+struct SQFile : public SQStream {\r
+       SQFile() { _handle = NULL; _owns = false;}\r
+       SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}\r
+       ~SQFile() { Close(); }\r
+       bool Open(const SQChar *filename ,const SQChar *mode) {\r
+               Close();\r
+               if(_handle = sqstd_fopen(filename,mode)) {\r
+                       _owns = true;\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+       void Close() {\r
+               if(_handle && _owns) { \r
+                       sqstd_fclose(_handle);\r
+                       _handle = NULL;\r
+                       _owns = false;\r
+               }\r
+       }\r
+       SQInteger Read(void *buffer,SQInteger size) {\r
+               return sqstd_fread(buffer,1,size,_handle);\r
+       }\r
+       SQInteger Write(void *buffer,SQInteger size) {\r
+               return sqstd_fwrite(buffer,1,size,_handle);\r
+       }\r
+       int Flush() {\r
+               return sqstd_fflush(_handle);\r
+       }\r
+       long Tell() {\r
+               return sqstd_ftell(_handle);\r
+       }\r
+       SQInteger Len() {\r
+               int prevpos=Tell();\r
+               Seek(0,SQ_SEEK_END);\r
+               int size=Tell();\r
+               Seek(prevpos,SQ_SEEK_SET);\r
+               return size;\r
+       }\r
+       SQInteger Seek(long offset, int origin) {\r
+               return sqstd_fseek(_handle,offset,origin);\r
+       }\r
+       bool IsValid() { return _handle?true:false; }\r
+       bool EOS() { return Tell()==Len()?true:false;}\r
+       SQFILE GetHandle() {return _handle;}\r
+private:\r
+       SQFILE _handle;\r
+       bool _owns;\r
+};\r
+\r
+static int _file__typeof(HSQUIRRELVM v)\r
+{\r
+       sq_pushstring(v,_SC("file"),-1);\r
+       return 1;\r
+}\r
+\r
+static int _file_releasehook(SQUserPointer p, int size)\r
+{\r
+       SQFile *self = (SQFile*)p;\r
+       delete self;\r
+       return 1;\r
+}\r
+\r
+static int _file_constructor(HSQUIRRELVM v)\r
+{\r
+       const SQChar *filename,*mode;\r
+       bool owns = true;\r
+       SQFile *f;\r
+       SQFILE newf;\r
+       if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {\r
+               sq_getstring(v, 2, &filename);\r
+               sq_getstring(v, 3, &mode);\r
+               newf = sqstd_fopen(filename, mode);\r
+               if(!newf) return sq_throwerror(v, _SC("cannot open file"));\r
+       } else if(sq_gettype(v,2) == OT_USERPOINTER) {\r
+               owns = !(sq_gettype(v,3) == OT_NULL);\r
+               sq_getuserpointer(v,2,&newf);\r
+       } else {\r
+               return sq_throwerror(v,_SC("wrong parameter"));\r
+       }\r
+       f = new SQFile(newf,owns);\r
+       if(SQ_FAILED(sq_setinstanceup(v,1,f))) {\r
+               delete f;\r
+               return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
+       }\r
+       sq_setreleasehook(v,1,_file_releasehook);\r
+       return 0;\r
+}\r
+\r
+//bindings\r
+#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}\r
+static SQRegFunction _file_methods[] = {\r
+       _DECL_FILE_FUNC(constructor,3,_SC("x")),\r
+       _DECL_FILE_FUNC(_typeof,1,_SC("x")),\r
+       {0,0,0,0},\r
+};\r
+\r
+\r
+\r
+SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)\r
+{\r
+       int top = sq_gettop(v);\r
+       sq_pushregistrytable(v);\r
+       sq_pushstring(v,_SC("std_file"),-1);\r
+       if(SQ_SUCCEEDED(sq_get(v,-2))) {\r
+               sq_remove(v,-2); //removes the registry\r
+               sq_pushroottable(v); // push the this\r
+               sq_pushuserpointer(v,file); //file\r
+               if(own){\r
+                       sq_pushinteger(v,1); //true\r
+               }\r
+               else{\r
+                       sq_pushnull(v); //false\r
+               }\r
+               if(SQ_SUCCEEDED( sq_call(v,3,SQTrue) )) {\r
+                       sq_remove(v,-2);\r
+                       return SQ_OK;\r
+               }\r
+       }\r
+       sq_settop(v,top);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file)\r
+{\r
+       SQFile *fileobj = NULL;\r
+       if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,SQSTD_FILE_TYPE_TAG))) {\r
+               *file = fileobj->GetHandle();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("not a file"));\r
+}\r
+\r
+\r
+static SQInteger _io_file_lexfeedASCII(SQUserPointer file)\r
+{\r
+       int ret;\r
+       char c;\r
+       if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
+               return c;\r
+       return 0;\r
+}\r
+\r
+static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)\r
+{\r
+       int ret;\r
+       wchar_t c;\r
+       if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
+               return (SQChar)c;\r
+       return 0;\r
+}\r
+\r
+int file_read(SQUserPointer file,SQUserPointer buf,int size)\r
+{\r
+       int ret;\r
+       if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;\r
+       return -1;\r
+}\r
+\r
+int file_write(SQUserPointer file,SQUserPointer p,int size)\r
+{\r
+       return sqstd_fwrite(p,1,size,(SQFILE)file);\r
+}\r
+\r
+SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)\r
+{\r
+       SQFILE file = sqstd_fopen(filename,_SC("rb"));\r
+       int ret;\r
+       unsigned short uc;\r
+       SQLEXREADFUNC func = _io_file_lexfeedASCII;\r
+       if(file && (ret=sqstd_fread(&uc,1,2,file))){\r
+               if(ret!=2) {\r
+                       sqstd_fclose(file);\r
+                       return sq_throwerror(v,_SC("io error"));\r
+               }\r
+               if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE\r
+                       sqstd_fseek(file,0,SQ_SEEK_SET);\r
+                       if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {\r
+                               sqstd_fclose(file);\r
+                               return SQ_OK;\r
+                       }\r
+               }\r
+               else { //SCRIPT\r
+                       if(uc==0xFEFF)\r
+                               func = _io_file_lexfeedWCHAR;\r
+                       else\r
+                               sqstd_fseek(file,0,SQ_SEEK_SET);\r
+\r
+                       if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){\r
+                               sqstd_fclose(file);\r
+                               return SQ_OK;\r
+                       }\r
+               }\r
+               sqstd_fclose(file);\r
+               return SQ_ERROR;\r
+       }\r
+       return sq_throwerror(v,_SC("cannot open the file"));\r
+}\r
+\r
+SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)\r
+{\r
+       if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {\r
+               sq_push(v,-2);\r
+               int ntop = sq_gettop(v);\r
+               if(SQ_SUCCEEDED(sq_call(v,1,retval))) {\r
+                       sq_remove(v,retval?-2:-1); //removes the closure\r
+                       return 1;\r
+               }\r
+               sq_pop(v,1); //removes the closure\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)\r
+{\r
+       SQFILE file = sqstd_fopen(filename,_SC("wb+"));\r
+       if(!file) return sq_throwerror(v,_SC("cannot open the file"));\r
+       if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {\r
+               sqstd_fclose(file);\r
+               return SQ_OK;\r
+       }\r
+       sqstd_fclose(file);\r
+       return SQ_ERROR; //forward the error\r
+}\r
+\r
+int _g_io_loadfile(HSQUIRRELVM v)\r
+{\r
+       const SQChar *filename;\r
+       SQBool printerror = SQFalse;\r
+       sq_getstring(v,2,&filename);\r
+       if(sq_gettop(v) >= 3) {\r
+               sq_getbool(v,3,&printerror);\r
+       }\r
+       if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))\r
+               return 1;\r
+       return SQ_ERROR; //propagates the error\r
+}\r
+\r
+int _g_io_dofile(HSQUIRRELVM v)\r
+{\r
+       const SQChar *filename;\r
+       SQBool printerror = SQFalse;\r
+       sq_getstring(v,2,&filename);\r
+       if(sq_gettop(v) >= 3) {\r
+               sq_getbool(v,3,&printerror);\r
+       }\r
+       sq_push(v,1); //repush the this\r
+       if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))\r
+               return 1;\r
+       return SQ_ERROR; //propagates the error\r
+}\r
+\r
+#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}\r
+static SQRegFunction iolib_funcs[]={\r
+       _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),\r
+       _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),\r
+       {0,0}\r
+};\r
+\r
+SQRESULT sqstd_register_iolib(HSQUIRRELVM v)\r
+{\r
+       int top = sq_gettop(v);\r
+       //create delegate\r
+       declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);\r
+       sq_pushstring(v,_SC("stdout"),-1);\r
+       sqstd_createfile(v,stdout,0);\r
+       sq_createslot(v,-3);\r
+       sq_pushstring(v,_SC("stdin"),-1);\r
+       sqstd_createfile(v,stdin,0);\r
+       sq_createslot(v,-3);\r
+       sq_pushstring(v,_SC("stderr"),-1);\r
+       sqstd_createfile(v,stderr,0);\r
+       sq_createslot(v,-3);\r
+       sq_settop(v,top);\r
+       return SQ_OK;\r
+}\r
diff --git a/src/squirrel/sqstdlib/sqstdlib.dsp b/src/squirrel/sqstdlib/sqstdlib.dsp
new file mode 100644 (file)
index 0000000..9fd09ef
--- /dev/null
@@ -0,0 +1,131 @@
+# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
+\r
+CFG=sqstdlib - Win32 Release\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "sqstdlib.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")\r
+!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_LocalPath ".."\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "sqstdlib - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
+# ADD RSC /l 0x410 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"\r
+\r
+!ELSEIF  "$(CFG)" == "sqstdlib - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
+# ADD RSC /l 0x410 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "sqstdlib - Win32 Release"\r
+# Name "sqstdlib - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdblob.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdio.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdmath.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdrex.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdstream.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdstring.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdaux.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdsystem.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdblobimpl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstdstream.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/src/squirrel/sqstdlib/sqstdmath.cpp b/src/squirrel/sqstdlib/sqstdmath.cpp
new file mode 100644 (file)
index 0000000..0b61373
--- /dev/null
@@ -0,0 +1,105 @@
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <math.h>\r
+#include <stdlib.h>\r
+#include <sqstdmath.h>\r
+\r
+#define SINGLE_ARG_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \\r
+       SQFloat f; \\r
+       sq_getfloat(v,2,&f); \\r
+       sq_pushfloat(v,(SQFloat)_funcname(f)); \\r
+       return 1; \\r
+}\r
+\r
+#define TWO_ARGS_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \\r
+       SQFloat p1,p2; \\r
+       sq_getfloat(v,2,&p1); \\r
+       sq_getfloat(v,3,&p2); \\r
+       sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \\r
+       return 1; \\r
+}\r
+\r
+static int math_srand(HSQUIRRELVM v)\r
+{\r
+       SQInteger i;\r
+       if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param"));\r
+       srand(i);\r
+       return 0;\r
+}\r
+\r
+static int math_rand(HSQUIRRELVM v)\r
+{\r
+       sq_pushinteger(v,rand());\r
+       return 1;\r
+}\r
+\r
+static int math_abs(HSQUIRRELVM v)\r
+{\r
+       SQInteger n;\r
+       sq_getinteger(v,2,&n);\r
+       sq_pushinteger(v,(SQInteger)abs(n)); \r
+       return 1; \r
+}\r
+\r
+SINGLE_ARG_FUNC(sqrt)\r
+SINGLE_ARG_FUNC(fabs)\r
+SINGLE_ARG_FUNC(sin)\r
+SINGLE_ARG_FUNC(cos)\r
+SINGLE_ARG_FUNC(asin)\r
+SINGLE_ARG_FUNC(acos)\r
+SINGLE_ARG_FUNC(log)\r
+SINGLE_ARG_FUNC(log10)\r
+SINGLE_ARG_FUNC(tan)\r
+SINGLE_ARG_FUNC(atan)\r
+TWO_ARGS_FUNC(atan2)\r
+TWO_ARGS_FUNC(pow)\r
+SINGLE_ARG_FUNC(floor)\r
+SINGLE_ARG_FUNC(ceil)\r
+SINGLE_ARG_FUNC(exp)\r
+\r
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck}\r
+static SQRegFunction mathlib_funcs[] = {\r
+       _DECL_FUNC(sqrt,2,_SC(".n")),\r
+       _DECL_FUNC(sin,2,_SC(".n")),\r
+       _DECL_FUNC(cos,2,_SC(".n")),\r
+       _DECL_FUNC(asin,2,_SC(".n")),\r
+       _DECL_FUNC(acos,2,_SC(".n")),\r
+       _DECL_FUNC(log,2,_SC(".n")),\r
+       _DECL_FUNC(log10,2,_SC(".n")),\r
+       _DECL_FUNC(tan,2,_SC(".n")),\r
+       _DECL_FUNC(atan,2,_SC(".n")),\r
+       _DECL_FUNC(atan2,3,_SC(".nn")),\r
+       _DECL_FUNC(pow,3,_SC(".nn")),\r
+       _DECL_FUNC(floor,2,_SC(".n")),\r
+       _DECL_FUNC(ceil,2,_SC(".n")),\r
+       _DECL_FUNC(exp,2,_SC(".n")),\r
+       _DECL_FUNC(srand,2,_SC(".n")),\r
+       _DECL_FUNC(rand,1,NULL),\r
+       _DECL_FUNC(fabs,2,_SC(".n")),\r
+       _DECL_FUNC(abs,2,_SC(".n")),\r
+       {0,0},\r
+};\r
+\r
+#ifndef M_PI\r
+#define M_PI (3.14159265358979323846)\r
+#endif\r
+\r
+SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)\r
+{\r
+       int i=0;\r
+       while(mathlib_funcs[i].name!=0) {\r
+               sq_pushstring(v,mathlib_funcs[i].name,-1);\r
+               sq_newclosure(v,mathlib_funcs[i].f,0);\r
+               sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);\r
+               sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);\r
+               sq_createslot(v,-3);\r
+               i++;\r
+       }\r
+       sq_pushstring(v,_SC("RAND_MAX"),-1);\r
+       sq_pushinteger(v,RAND_MAX);\r
+       sq_createslot(v,-3);\r
+       sq_pushstring(v,_SC("PI"),-1);\r
+       sq_pushfloat(v,(SQFloat)M_PI);\r
+       sq_createslot(v,-3);\r
+       return SQ_OK;\r
+}\r
diff --git a/src/squirrel/sqstdlib/sqstdrex.c b/src/squirrel/sqstdlib/sqstdrex.c
new file mode 100644 (file)
index 0000000..534f17d
--- /dev/null
@@ -0,0 +1,586 @@
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <setjmp.h>\r
+#include "sqstdstring.h"\r
+\r
+#ifdef _DEBUG\r
+#include <stdio.h>\r
+\r
+static const SQChar *g_nnames[] =\r
+{\r
+       _SC("NONE"),_SC("OP_GREEDY"),   _SC("OP_OR"),\r
+       _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),       _SC("OP_CLASS"),\r
+       _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),\r
+       _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")\r
+};\r
+\r
+#endif\r
+\r
+#define OP_GREEDY              MAX_CHAR+1 // * + ? {n}\r
+#define OP_OR                  MAX_CHAR+2\r
+#define OP_EXPR                        MAX_CHAR+3 //parentesis ()\r
+#define OP_NOCAPEXPR   MAX_CHAR+4 //parentesis (?:)\r
+#define OP_DOT                 MAX_CHAR+5\r
+#define OP_CLASS               MAX_CHAR+6\r
+#define OP_CCLASS              MAX_CHAR+7\r
+#define OP_NCLASS              MAX_CHAR+8 //negates class the [^\r
+#define OP_RANGE               MAX_CHAR+9\r
+#define OP_CHAR                        MAX_CHAR+10\r
+#define OP_EOL                 MAX_CHAR+11\r
+#define OP_BOL                 MAX_CHAR+12\r
+#define OP_WB                  MAX_CHAR+13\r
+\r
+#define SQREX_SYMBOL_ANY_CHAR '.'\r
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+'\r
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*'\r
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?'\r
+#define SQREX_SYMBOL_BRANCH '|'\r
+#define SQREX_SYMBOL_END_OF_STRING '$'\r
+#define SQREX_SYMBOL_BEGINNING_OF_STRING '^'\r
+#define SQREX_SYMBOL_ESCAPE_CHAR '\\'\r
+\r
+\r
+typedef int SQRexNodeType;\r
+\r
+typedef struct tagSQRexNode{\r
+       SQRexNodeType type;\r
+       long left;\r
+       long right;\r
+       int next;\r
+}SQRexNode;\r
+\r
+struct SQRex{\r
+       const SQChar *_eol;\r
+       const SQChar *_bol;\r
+       const SQChar *_p;\r
+       int _first;\r
+       int _op;\r
+       SQRexNode *_nodes;\r
+       int _nallocated;\r
+       int _nsize;\r
+       int _nsubexpr;\r
+       SQRexMatch *_matches;\r
+       int _currsubexp;\r
+       void *_jmpbuf;\r
+       const SQChar **_error;\r
+};\r
+\r
+static int sqstd_rex_list(SQRex *exp);\r
+\r
+static int sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)\r
+{\r
+       SQRexNode n;\r
+       n.type = type;\r
+       n.next = n.right = n.left = -1;\r
+       if(type == OP_EXPR)\r
+               n.right = exp->_nsubexpr++;\r
+       if(exp->_nallocated < (exp->_nsize + 1)) {\r
+               int oldsize = exp->_nallocated;\r
+               exp->_nallocated *= 2;\r
+               exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));\r
+       }\r
+       exp->_nodes[exp->_nsize++] = n;\r
+       return (int)exp->_nsize - 1;\r
+}\r
+\r
+static void sqstd_rex_error(SQRex *exp,const SQChar *error)\r
+{\r
+       if(exp->_error) *exp->_error = error;\r
+       longjmp(*((jmp_buf*)exp->_jmpbuf),-1);\r
+}\r
+\r
+static void sqstd_rex_expect(SQRex *exp, int n){\r
+       if((*exp->_p) != n) \r
+               sqstd_rex_error(exp, _SC("expected paren"));\r
+       exp->_p++;\r
+}\r
+\r
+static SQBool sqstd_rex_ischar(SQChar c)\r
+{\r
+       switch(c) {\r
+       case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE:\r
+       case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE:\r
+       case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING:\r
+       case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}':\r
+               return SQFalse;\r
+    }\r
+       return SQTrue;\r
+}\r
+\r
+static SQChar sqstd_rex_escapechar(SQRex *exp)\r
+{\r
+       if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){\r
+               exp->_p++;\r
+               switch(*exp->_p) {\r
+               case 'v': exp->_p++; return '\v';\r
+               case 'n': exp->_p++; return '\n';\r
+               case 't': exp->_p++; return '\t';\r
+               case 'r': exp->_p++; return '\r';\r
+               case 'f': exp->_p++; return '\f';\r
+               default: return (*exp->_p++);\r
+               }\r
+       } else if(!sqstd_rex_ischar(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));\r
+       return (*exp->_p++);\r
+}\r
+\r
+static int sqstd_rex_charclass(SQRex *exp,int classid)\r
+{\r
+       int n = sqstd_rex_newnode(exp,OP_CCLASS);\r
+       exp->_nodes[n].left = classid;\r
+       return n;\r
+}\r
+\r
+static int sqstd_rex_charnode(SQRex *exp,SQBool isclass)\r
+{\r
+       if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {\r
+               exp->_p++;\r
+               switch(*exp->_p) {\r
+                       case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');\r
+                       case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');\r
+                       case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');\r
+                       case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');\r
+                       case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');\r
+                       case 'a': case 'A': case 'w': case 'W': case 's': case 'S': \r
+                       case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': \r
+                       case 'p': case 'P': case 'l': case 'u': \r
+                               {\r
+                               SQChar t = *exp->_p;\r
+                               exp->_p++; \r
+                               return sqstd_rex_charclass(exp,t);\r
+                               }\r
+                       case 'b': \r
+                       case 'B':\r
+                               if(!isclass) {\r
+                                       int node = sqstd_rex_newnode(exp,OP_WB);\r
+                                       exp->_nodes[node].left = *exp->_p;\r
+                                       exp->_p++; \r
+                                       return node;\r
+                               } //else default\r
+                       default: return sqstd_rex_newnode(exp,(*exp->_p++));\r
+               }\r
+       }\r
+       else if(!sqstd_rex_ischar(*exp->_p)) {\r
+               \r
+               sqstd_rex_error(exp,_SC("letter expected"));\r
+       }\r
+       return sqstd_rex_newnode(exp,*exp->_p++);\r
+}\r
+static int sqstd_rex_class(SQRex *exp)\r
+{\r
+       int ret = -1;\r
+       int first = -1,chain;\r
+       if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){\r
+               ret = sqstd_rex_newnode(exp,OP_NCLASS);\r
+               exp->_p++;\r
+       }else ret = sqstd_rex_newnode(exp,OP_CLASS);\r
+       \r
+       if(*exp->_p == ']' || *exp->_p == '-'){\r
+               first = *exp->_p;\r
+               exp->_p++;\r
+       }\r
+       chain = ret;\r
+       while(*exp->_p != ']' && exp->_p != exp->_eol) {\r
+               if(*exp->_p == '-' && first != -1){ \r
+                       int r;\r
+                       if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));\r
+                       r = sqstd_rex_newnode(exp,OP_RANGE);\r
+                       if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));\r
+                       if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));\r
+                       exp->_nodes[r].left = exp->_nodes[first].type;\r
+                       exp->_nodes[r].right = sqstd_rex_escapechar(exp);\r
+            exp->_nodes[chain].next = r;\r
+                       chain = r;\r
+                       first = -1;\r
+               }\r
+               else{\r
+                       if(first!=-1){\r
+                               int c = first;\r
+                               exp->_nodes[chain].next = c;\r
+                               chain = c;\r
+                               first = sqstd_rex_charnode(exp,SQTrue);\r
+                       }\r
+                       else{\r
+                               first = sqstd_rex_charnode(exp,SQTrue);\r
+                       }\r
+               }\r
+       }\r
+       if(first!=-1){\r
+               int c = first;\r
+               exp->_nodes[chain].next = c;\r
+               chain = c;\r
+               first = -1;\r
+       }\r
+       /* hack? */\r
+       exp->_nodes[ret].left = exp->_nodes[ret].next;\r
+       exp->_nodes[ret].next = -1;\r
+       return ret;\r
+}\r
+\r
+static int sqstd_rex_parsenumber(SQRex *exp)\r
+{\r
+       int ret = *exp->_p-'0';\r
+       int positions = 10;\r
+       exp->_p++;\r
+       while(isdigit(*exp->_p)) {\r
+               ret = ret*10+(*exp->_p++-'0');\r
+               if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));\r
+               positions *= 10;\r
+       };\r
+       return ret;\r
+}\r
+\r
+static int sqstd_rex_element(SQRex *exp)\r
+{\r
+       int ret;\r
+       switch(*exp->_p)\r
+       {\r
+       case '(': {\r
+               int expr;\r
+               exp->_p++;\r
+               \r
+               \r
+               if(*exp->_p =='?') {\r
+                       exp->_p++;\r
+                       sqstd_rex_expect(exp,':');\r
+                       expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);\r
+               }\r
+               else\r
+                       expr = sqstd_rex_newnode(exp,OP_EXPR);\r
+               exp->_nodes[expr].left = sqstd_rex_list(exp);\r
+               ret = expr;\r
+               sqstd_rex_expect(exp,')');\r
+       }\r
+               break;\r
+       case '[':\r
+               exp->_p++;\r
+               ret = sqstd_rex_class(exp);\r
+               sqstd_rex_expect(exp,']');\r
+               break;\r
+       case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;\r
+       case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;\r
+       default:\r
+               ret = sqstd_rex_charnode(exp,SQFalse);\r
+               break;\r
+       }\r
+       /* scope block */\r
+       {\r
+               int op;\r
+               unsigned short p0 = 0, p1 = 0;\r
+               switch(*exp->_p){\r
+               case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end;\r
+               case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end;\r
+               case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end;\r
+               case '{':{\r
+                       exp->_p++;\r
+                       if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));\r
+                       p0 = sqstd_rex_parsenumber(exp);\r
+                       switch(*exp->_p) {\r
+                       case '}':\r
+                               p1 = p0; exp->_p++;\r
+                               goto __end;\r
+                       case ',':\r
+                               exp->_p++;\r
+                               p1 = 0xFFFF;\r
+                               if(isdigit(*exp->_p)){\r
+                                       p1 = sqstd_rex_parsenumber(exp);\r
+                               }\r
+                               sqstd_rex_expect(exp,'}');\r
+                               goto __end;\r
+                       default:\r
+                               sqstd_rex_error(exp,_SC(", or } expected"));\r
+                       }\r
+               }\r
+               __end: {\r
+                               int nnode = sqstd_rex_newnode(exp,OP_GREEDY);\r
+                               op = OP_GREEDY;\r
+                               exp->_nodes[nnode].left = ret;\r
+                               exp->_nodes[nnode].right = ((p0)<<16)|p1;\r
+                               ret = nnode;\r
+                       }\r
+               }\r
+       }\r
+       if(*exp->_p != SQREX_SYMBOL_BRANCH && *exp->_p != ')' && *exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE && *exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE && *exp->_p != '\0')\r
+               exp->_nodes[ret].next = sqstd_rex_element(exp);\r
+       return ret;\r
+}\r
+\r
+static int sqstd_rex_list(SQRex *exp)\r
+{\r
+       int ret=-1,e;\r
+       if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {\r
+               exp->_p++;\r
+               ret = sqstd_rex_newnode(exp,OP_BOL);\r
+       }\r
+       e = sqstd_rex_element(exp);\r
+       if(ret != -1) {\r
+               exp->_nodes[ret].next = e;\r
+       }\r
+       else ret = e;\r
+\r
+       if(*exp->_p == SQREX_SYMBOL_BRANCH) {\r
+               int temp;\r
+               exp->_p++;\r
+               temp = sqstd_rex_newnode(exp,OP_OR);\r
+               exp->_nodes[temp].left = ret;\r
+               exp->_nodes[temp].right = sqstd_rex_list(exp);\r
+               ret = temp;\r
+       }\r
+       return ret;\r
+}\r
+\r
+static SQBool sqstd_rex_matchcclass(int cclass,SQChar c)\r
+{\r
+       switch(cclass) {\r
+       case 'a': return isalpha(c)?SQTrue:SQFalse;\r
+       case 'A': return !isalpha(c)?SQTrue:SQFalse;\r
+       case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;\r
+       case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;\r
+       case 's': return isspace(c)?SQTrue:SQFalse;\r
+       case 'S': return !isspace(c)?SQTrue:SQFalse;\r
+       case 'd': return isdigit(c)?SQTrue:SQFalse;\r
+       case 'D': return !isdigit(c)?SQTrue:SQFalse;\r
+       case 'x': return isxdigit(c)?SQTrue:SQFalse;\r
+       case 'X': return !isxdigit(c)?SQTrue:SQFalse;\r
+       case 'c': return iscntrl(c)?SQTrue:SQFalse;\r
+       case 'C': return !iscntrl(c)?SQTrue:SQFalse;\r
+       case 'p': return ispunct(c)?SQTrue:SQFalse;\r
+       case 'P': return !ispunct(c)?SQTrue:SQFalse;\r
+       case 'l': return islower(c)?SQTrue:SQFalse;\r
+       case 'u': return isupper(c)?SQTrue:SQFalse;\r
+       }\r
+       return SQFalse; /*cannot happen*/\r
+}\r
+\r
+static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)\r
+{\r
+       do {\r
+               switch(node->type) {\r
+                       case OP_RANGE:\r
+                               if(c >= node->left && c <= node->right) return SQTrue;\r
+                               break;\r
+                       case OP_CCLASS:\r
+                               if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;\r
+                               break;\r
+                       default:\r
+                               if(c == node->type)return SQTrue;\r
+               }\r
+       } while((node->next != -1) && (node = &exp->_nodes[node->next]));\r
+       return SQFalse;\r
+}\r
+\r
+static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str)\r
+{\r
+       SQRexNodeType type = node->type;\r
+       switch(type) {\r
+       case OP_GREEDY: {\r
+               int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;\r
+               const SQChar *s=str, *good = str;\r
+               while((nmaches == 0xFFFF || nmaches < p1) \r
+                       && (s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s))) {\r
+                       good=s;\r
+                       nmaches++;\r
+                       if(s >= exp->_eol)\r
+                               break;\r
+               }\r
+               if(p0 == p1 && p0 == nmaches) return good;\r
+               else if(nmaches >= p0 && p1 == 0xFFFF) return good;\r
+               else if(nmaches >= p0 && nmaches <= p1) return good;\r
+               return NULL;\r
+       }\r
+       case OP_OR: {\r
+                       const SQChar *asd = str;\r
+                       SQRexNode *temp=&exp->_nodes[node->left];\r
+                       while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
+                               if(temp->next != -1)\r
+                                       temp = &exp->_nodes[temp->next];\r
+                               else\r
+                                       return asd;\r
+                       }\r
+                       asd = str;\r
+                       temp = &exp->_nodes[node->right];\r
+                       while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
+                               if(temp->next != -1)\r
+                                       temp = &exp->_nodes[temp->next];\r
+                               else\r
+                                       return asd;\r
+                       }\r
+                       return NULL;\r
+                       break;\r
+       }\r
+       case OP_EXPR:\r
+       case OP_NOCAPEXPR:{\r
+                       SQRexNode *n = &exp->_nodes[node->left];\r
+                       const SQChar *cur = str;\r
+                       int capture = -1;\r
+                       if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {\r
+                               capture = exp->_currsubexp;\r
+                               exp->_matches[capture].begin = cur;\r
+                               exp->_currsubexp++;\r
+                       }\r
+\r
+                       do {\r
+                               if(!(cur = sqstd_rex_matchnode(exp,n,cur))) {\r
+                                       if(capture != -1){\r
+                                               exp->_matches[capture].begin = 0;\r
+                                               exp->_matches[capture].len = 0;\r
+                                       }\r
+                                       return NULL;\r
+                               }\r
+                       } while((n->next != -1) && (n = &exp->_nodes[n->next]));\r
+\r
+                       if(capture != -1) \r
+                               exp->_matches[capture].len = cur - exp->_matches[capture].begin;\r
+                       return cur;\r
+       }                                \r
+       case OP_WB:\r
+               if(str == exp->_bol && !isspace(*str)\r
+                || (str == exp->_eol && !isspace(*(str-1)))\r
+                || (!isspace(*str) && isspace(*(str+1)))\r
+                || (isspace(*str) && !isspace(*(str+1))) ) {\r
+                       return (node->left == 'b')?str:NULL;\r
+               }\r
+               return (node->left == 'b')?NULL:str;\r
+       case OP_BOL:\r
+               if(str == exp->_bol) return str;\r
+               return NULL;\r
+       case OP_EOL:\r
+               if(str == exp->_eol) return str;\r
+               return NULL;\r
+       case OP_DOT:\r
+               *str++;\r
+               return str;\r
+       case OP_NCLASS:\r
+       case OP_CLASS:\r
+               if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {\r
+                       *str++;\r
+                       return str;\r
+               }\r
+               return NULL;\r
+       case OP_CCLASS:\r
+               if(sqstd_rex_matchcclass(node->left,*str)) {\r
+                       *str++;\r
+                       return str;\r
+               }\r
+               return NULL;\r
+       default: /* char */\r
+               if(*str != node->type) return NULL;\r
+               *str++;\r
+               return str;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+/* public api */\r
+SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)\r
+{\r
+       SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));\r
+       exp->_p = pattern;\r
+       exp->_nallocated = (int)scstrlen(pattern) * sizeof(SQChar);\r
+       exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));\r
+       exp->_nsize = 0;\r
+       exp->_matches = 0;\r
+       exp->_nsubexpr = 0;\r
+       exp->_first = sqstd_rex_newnode(exp,OP_EXPR);\r
+       exp->_error = error;\r
+       exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));\r
+       if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {\r
+               exp->_nodes[exp->_first].left=sqstd_rex_list(exp);\r
+               if(*exp->_p!='\0')\r
+                       sqstd_rex_error(exp,_SC("unexpected character"));\r
+#ifdef _DEBUG\r
+               {\r
+                       int nsize,i;\r
+                       SQRexNode *t;\r
+                       nsize = exp->_nsize;\r
+                       t = &exp->_nodes[0];\r
+                       scprintf(_SC("\n"));\r
+                       for(i = 0;i < nsize; i++) {\r
+                               if(exp->_nodes[i].type>MAX_CHAR)\r
+                                       scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);\r
+                               else\r
+                                       scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);\r
+                               scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);\r
+                       }\r
+                       scprintf(_SC("\n"));\r
+               }\r
+#endif\r
+               exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));\r
+               memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));\r
+       }\r
+       else{\r
+               sqstd_rex_free(exp);\r
+               return NULL;\r
+       }\r
+       return exp;\r
+}\r
+\r
+void sqstd_rex_free(SQRex *exp)\r
+{\r
+       if(exp) {\r
+               if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));\r
+               if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));\r
+               if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));\r
+               sq_free(exp,sizeof(SQRex));\r
+       }\r
+}\r
+\r
+SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)\r
+{\r
+       const SQChar* res = NULL;\r
+       exp->_bol = text;\r
+       exp->_eol = text + scstrlen(text);\r
+       exp->_currsubexp = 0;\r
+       res = sqstd_rex_matchnode(exp,exp->_nodes,text);\r
+       if(res == NULL || res != exp->_eol)\r
+               return SQFalse;\r
+       return SQTrue;\r
+}\r
+\r
+SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)\r
+{\r
+       const SQChar *cur = NULL;\r
+       int node = exp->_first;\r
+       if(text_begin >= text_end) return SQFalse;\r
+       exp->_bol = text_begin;\r
+       exp->_eol = text_end;\r
+       do {\r
+               cur = text_begin;\r
+               while(node != -1) {\r
+                       exp->_currsubexp = 0;\r
+                       cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur);\r
+                       if(!cur)\r
+                               break;\r
+                       node = exp->_nodes[node].next;\r
+               }\r
+               *text_begin++;\r
+       } while(cur == NULL && text_begin != text_end);\r
+\r
+       if(cur == NULL)\r
+               return SQFalse;\r
+\r
+       --text_begin;\r
+\r
+       if(out_begin) *out_begin = text_begin;\r
+       if(out_end) *out_end = cur;\r
+       return SQTrue;\r
+}\r
+\r
+SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)\r
+{\r
+       return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);\r
+}\r
+\r
+int sqstd_rex_getsubexpcount(SQRex* exp)\r
+{\r
+       return exp->_nsubexpr;\r
+}\r
+\r
+SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp)\r
+{\r
+       if( n<0 || n >= exp->_nsubexpr) return SQFalse;\r
+       *subexp = exp->_matches[n];\r
+       return SQTrue;\r
+}\r
+\r
diff --git a/src/squirrel/sqstdlib/sqstdstream.cpp b/src/squirrel/sqstdlib/sqstdstream.cpp
new file mode 100644 (file)
index 0000000..3cbc808
--- /dev/null
@@ -0,0 +1,396 @@
+/* see copyright notice in squirrel.h */\r
+#include <new>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <squirrel.h>\r
+#include <sqstdio.h>\r
+#include <sqstdblob.h>\r
+#include "sqstdstream.h"\r
+#include "sqstdblobimpl.h"\r
+\r
+#define SETUP_STREAM(v) \\r
+       SQStream *self = NULL; \\r
+       if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_STREAM_TYPE_TAG))) \\r
+               return sq_throwerror(v,_SC("invalid type tag")); \\r
+       if(!self->IsValid())  \\r
+               return sq_throwerror(v,_SC("the stream is invalid"));\r
+\r
+int _stream_readstr(HSQUIRRELVM v)\r
+{\r
+    SETUP_STREAM(v);\r
+       SQInteger type = _SC('a'), size = 0;\r
+       sq_getinteger(v, 2, &size);\r
+       if(size <= 0) return sq_throwerror(v,_SC("invalid size"));\r
+       if(sq_gettop(v) > 2)\r
+               sq_getinteger(v, 3, &type);\r
+       SQChar *dest = NULL;\r
+       switch(type) {\r
+       case _SC('a'): {\r
+               char *temp;\r
+               if(self->Read(sq_getscratchpad(v, size+1), size) != size)\r
+                       return sq_throwerror(v, _SC("io failure"));\r
+#ifdef _UNICODE\r
+               temp = (char*) sq_getscratchpad(v, size + (size * sizeof(SQChar)));\r
+               dest = (SQChar*) &temp[size];\r
+               size = (SQInteger)mbstowcs(dest, (const char*)temp, size);\r
+#else\r
+               temp = (char *) sq_getscratchpad(v, -1);\r
+               dest = temp;\r
+#endif\r
+                                  }\r
+               break;\r
+       case _SC('u'): {\r
+               wchar_t *temp;\r
+               if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)),size * sizeof(wchar_t)) != (size * sizeof(wchar_t)))\r
+                       return sq_throwerror(v, _SC("io failure"));\r
+               \r
+#ifdef _UNICODE\r
+               temp = (wchar_t*) sq_getscratchpad(v, -1);\r
+               dest = (SQChar*) temp;\r
+#else\r
+               temp = (wchar_t*) sq_getscratchpad(v,(size * 3) + (size * sizeof(wchar_t)));\r
+               dest = (char*) &temp[size];\r
+               size = (SQInteger)wcstombs(dest, (const wchar_t*)temp, size);\r
+#endif\r
+                                  }\r
+               break;\r
+       default:\r
+               return sq_throwerror(v, _SC("invalid coding"));\r
+       }\r
+\r
+       sq_pushstring(v, dest, size);\r
+       return 1;\r
+}\r
+\r
+int _stream_readblob(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       SQUserPointer data,blobp;\r
+       SQInteger size,res;\r
+       sq_getinteger(v,2,&size);\r
+       if(size > self->Len()) {\r
+               size = self->Len();\r
+       }\r
+       data = sq_getscratchpad(v,size);\r
+       res = self->Read(data,size);\r
+       if(res <= 0)\r
+               return sq_throwerror(v,_SC("no data left to read"));\r
+       blobp = sqstd_createblob(v,res);\r
+       memcpy(blobp,data,res);\r
+       return 1;\r
+}\r
+\r
+#define SAFE_READN(ptr,len) { \\r
+       if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \\r
+       }\r
+int _stream_readn(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       SQInteger format;\r
+       sq_getinteger(v, 2, &format);\r
+       switch(format) {\r
+       case 'i': {\r
+               int i;\r
+               SAFE_READN(&i, sizeof(i));\r
+               sq_pushinteger(v, i);\r
+                         }\r
+               break;\r
+       case 's': {\r
+               short s;\r
+               SAFE_READN(&s, sizeof(short));\r
+               sq_pushinteger(v, s);\r
+                         }\r
+               break;\r
+       case 'w': {\r
+               unsigned short w;\r
+               SAFE_READN(&w, sizeof(unsigned short));\r
+               sq_pushinteger(v, w);\r
+                         }\r
+               break;\r
+       case 'c': {\r
+               char c;\r
+               SAFE_READN(&c, sizeof(char));\r
+               sq_pushinteger(v, c);\r
+                         }\r
+               break;\r
+       case 'b': {\r
+               unsigned char c;\r
+               SAFE_READN(&c, sizeof(unsigned char));\r
+               sq_pushinteger(v, c);\r
+                         }\r
+               break;\r
+       case 'f': {\r
+               float f;\r
+               SAFE_READN(&f, sizeof(float));\r
+               sq_pushfloat(v, f);\r
+                         }\r
+               break;\r
+       case 'd': {\r
+               double d;\r
+               SAFE_READN(&d, sizeof(double));\r
+               sq_pushfloat(v, (SQFloat)d);\r
+                         }\r
+               break;\r
+       default:\r
+               return sq_throwerror(v, _SC("invalid format"));\r
+       }\r
+       return 1;\r
+}\r
+\r
+int _stream_writestr(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       const SQChar *str,*res;\r
+       SQInteger trgformat = 'a',len = 0;\r
+       sq_getstring(v,2,&str);\r
+       len = sq_getsize(v,2);\r
+       if(sq_gettop(v)>2)\r
+               sq_getinteger(v,3,&trgformat);\r
+       switch(trgformat)\r
+       {\r
+       case 'a':\r
+#ifdef _UNICODE\r
+               res = sq_getscratchpad(v,len*3);\r
+               len = (SQInteger) wcstombs((char *)res, (const wchar_t*)str, len);\r
+#else\r
+               res = str;\r
+#endif\r
+               self->Write((void *)res,len);\r
+               break;\r
+       case 'u':\r
+#ifdef _UNICODE\r
+               res = str;\r
+#else\r
+               res = sq_getscratchpad(v,len*sizeof(wchar_t));\r
+               len = (SQInteger) mbstowcs((wchar_t*)res, str, len);\r
+#endif\r
+               self->Write((void *)res,len*sizeof(wchar_t));\r
+               break;\r
+       default:\r
+               return sq_throwerror(v,_SC("wrong encoding"));\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+int _stream_writeblob(HSQUIRRELVM v)\r
+{\r
+       SQUserPointer data;\r
+       int size;\r
+       SETUP_STREAM(v);\r
+       if(SQ_FAILED(sqstd_getblob(v,2,&data)))\r
+               return sq_throwerror(v,_SC("invalid parameter"));\r
+       size = sqstd_getblobsize(v,2);\r
+       if(self->Write(data,size) != size)\r
+               return sq_throwerror(v,_SC("io error"));\r
+       sq_pushinteger(v,size);\r
+       return 1;\r
+}\r
+\r
+int _stream_writen(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       SQInteger format, ti;\r
+       SQFloat tf;\r
+       sq_getinteger(v, 3, &format);\r
+       switch(format) {\r
+       case 'i': {\r
+               int i;\r
+               sq_getinteger(v, 2, &ti);\r
+               i = ti;\r
+               self->Write(&i, sizeof(int));\r
+                         }\r
+               break;\r
+       case 's': {\r
+               short s;\r
+               sq_getinteger(v, 2, &ti);\r
+               s = ti;\r
+               self->Write(&s, sizeof(short));\r
+                         }\r
+               break;\r
+       case 'w': {\r
+               unsigned short w;\r
+               sq_getinteger(v, 2, &ti);\r
+               w = ti;\r
+               self->Write(&w, sizeof(unsigned short));\r
+                         }\r
+               break;\r
+       case 'c': {\r
+               char c;\r
+               sq_getinteger(v, 2, &ti);\r
+               c = ti;\r
+               self->Write(&c, sizeof(char));\r
+                                 }\r
+               break;\r
+       case 'b': {\r
+               unsigned char b;\r
+               sq_getinteger(v, 2, &ti);\r
+               b = ti;\r
+               self->Write(&b, sizeof(unsigned char));\r
+                         }\r
+               break;\r
+       case 'f': {\r
+               float f;\r
+               sq_getfloat(v, 2, &tf);\r
+               f = tf;\r
+               self->Write(&f, sizeof(float));\r
+                         }\r
+               break;\r
+       case 'd': {\r
+               double d;\r
+               sq_getfloat(v, 2, &tf);\r
+               d = tf;\r
+               self->Write(&d, sizeof(double));\r
+                         }\r
+               break;\r
+       default:\r
+               return sq_throwerror(v, _SC("invalid format"));\r
+       }\r
+       return 0;\r
+}\r
+\r
+int _stream_seek(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       SQInteger offset, origin = SQ_SEEK_SET;\r
+       sq_getinteger(v, 2, &offset);\r
+       if(sq_gettop(v) > 2) {\r
+               SQInteger t;\r
+               sq_getinteger(v, 3, &t);\r
+               switch(t) {\r
+                       case 'b': origin = SQ_SEEK_SET; break;\r
+                       case 'c': origin = SQ_SEEK_CUR; break;\r
+                       case 'e': origin = SQ_SEEK_END; break;\r
+                       default: return sq_throwerror(v,_SC("invalid origin"));\r
+               }\r
+       }\r
+       sq_pushinteger(v, self->Seek(offset, origin));\r
+       return 1;\r
+}\r
+\r
+int _stream_tell(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       sq_pushinteger(v, self->Tell());\r
+       return 1;\r
+}\r
+\r
+int _stream_len(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       sq_pushinteger(v, self->Len());\r
+       return 1;\r
+}\r
+\r
+int _stream_flush(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       if(!self->Flush())\r
+               sq_pushinteger(v, 1);\r
+       else\r
+               sq_pushnull(v);\r
+       return 1;\r
+}\r
+\r
+int _stream_eos(HSQUIRRELVM v)\r
+{\r
+       SETUP_STREAM(v);\r
+       if(self->EOS())\r
+               sq_pushinteger(v, 1);\r
+       else\r
+               sq_pushnull(v);\r
+       return 1;\r
+}\r
+\r
+static SQRegFunction _stream_methods[] = {\r
+       _DECL_STREAM_FUNC(readstr,-2,_SC("xnn")),\r
+       _DECL_STREAM_FUNC(readblob,2,_SC("xn")),\r
+       _DECL_STREAM_FUNC(readn,2,_SC("xn")),\r
+       _DECL_STREAM_FUNC(writestr,-2,_SC("xsn")),\r
+       _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),\r
+       _DECL_STREAM_FUNC(writen,3,_SC("xnn")),\r
+       _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),\r
+       _DECL_STREAM_FUNC(tell,1,_SC("x")),\r
+       _DECL_STREAM_FUNC(len,1,_SC("x")),\r
+       _DECL_STREAM_FUNC(eos,1,_SC("x")),\r
+       _DECL_STREAM_FUNC(flush,1,_SC("x")),\r
+       {0,0}\r
+};\r
+\r
+void init_streamclass(HSQUIRRELVM v)\r
+{\r
+       sq_pushregistrytable(v);\r
+       sq_pushstring(v,_SC("std_stream"),-1);\r
+       if(SQ_FAILED(sq_get(v,-2))) {\r
+               sq_pushstring(v,_SC("std_stream"),-1);\r
+               sq_newclass(v,SQFalse);\r
+               sq_settypetag(v,-1,SQSTD_STREAM_TYPE_TAG);\r
+               int i = 0;\r
+               while(_stream_methods[i].name != 0) {\r
+                       SQRegFunction &f = _stream_methods[i];\r
+                       sq_pushstring(v,f.name,-1);\r
+                       sq_newclosure(v,f.f,0);\r
+                       sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
+                       sq_createslot(v,-3);\r
+                       i++;\r
+               }\r
+               sq_createslot(v,-3);\r
+       }\r
+       else {\r
+               sq_pop(v,1); //result\r
+       }\r
+       sq_pop(v,1);\r
+}\r
+\r
+SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)\r
+{\r
+       if(sq_gettype(v,-1) != OT_TABLE)\r
+               return sq_throwerror(v,_SC("table expected"));\r
+       int top = sq_gettop(v);\r
+       //create delegate\r
+    init_streamclass(v);\r
+       sq_pushregistrytable(v);\r
+       sq_pushstring(v,reg_name,-1);\r
+       sq_pushstring(v,_SC("std_stream"),-1);\r
+       if(SQ_SUCCEEDED(sq_get(v,-3))) {\r
+               sq_newclass(v,SQTrue);\r
+               sq_settypetag(v,-1,typetag);\r
+               int i = 0;\r
+               while(methods[i].name != 0) {\r
+                       SQRegFunction &f = methods[i];\r
+                       sq_pushstring(v,f.name,-1);\r
+                       sq_newclosure(v,f.f,0);\r
+                       sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
+                       sq_setnativeclosurename(v,-1,f.name);\r
+                       sq_createslot(v,-3);\r
+                       i++;\r
+               }\r
+               sq_createslot(v,-3);\r
+               sq_pop(v,1);\r
+               \r
+               i = 0;\r
+               while(globals[i].name!=0)\r
+               {\r
+                       SQRegFunction &f = globals[i];\r
+                       sq_pushstring(v,f.name,-1);\r
+                       sq_newclosure(v,f.f,0);\r
+                       sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
+                       sq_setnativeclosurename(v,-1,f.name);\r
+                       sq_createslot(v,-3);\r
+                       i++;\r
+               }\r
+               //register the class in the target table\r
+               sq_pushstring(v,name,-1);\r
+               sq_pushregistrytable(v);\r
+               sq_pushstring(v,reg_name,-1);\r
+               sq_get(v,-2);\r
+               sq_remove(v,-2);\r
+               sq_createslot(v,-3);\r
+\r
+               sq_settop(v,top);\r
+               return SQ_OK;\r
+       }\r
+       sq_settop(v,top);\r
+       return SQ_ERROR;\r
+}\r
diff --git a/src/squirrel/sqstdlib/sqstdstream.h b/src/squirrel/sqstdlib/sqstdstream.h
new file mode 100644 (file)
index 0000000..a13bc4d
--- /dev/null
@@ -0,0 +1,20 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_STREAM_H_\r
+#define _SQSTD_STREAM_H_\r
+\r
+int _stream_readstr(HSQUIRRELVM v);\r
+int _stream_readblob(HSQUIRRELVM v);\r
+int _stream_readline(HSQUIRRELVM v);\r
+int _stream_readn(HSQUIRRELVM v);\r
+int _stream_writestr(HSQUIRRELVM v);\r
+int _stream_writeblob(HSQUIRRELVM v);\r
+int _stream_writen(HSQUIRRELVM v);\r
+int _stream_seek(HSQUIRRELVM v);\r
+int _stream_tell(HSQUIRRELVM v);\r
+int _stream_len(HSQUIRRELVM v);\r
+int _stream_eos(HSQUIRRELVM v);\r
+int _stream_flush(HSQUIRRELVM v);\r
+\r
+#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck}\r
+SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals);\r
+#endif /*_SQSTD_STREAM_H_*/\r
diff --git a/src/squirrel/sqstdlib/sqstdstring.cpp b/src/squirrel/sqstdlib/sqstdstring.cpp
new file mode 100644 (file)
index 0000000..728376b
--- /dev/null
@@ -0,0 +1,272 @@
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <sqstdstring.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+\r
+#ifdef _UNICODE\r
+#define scstrchr wcschr\r
+#define scsnprintf wsnprintf\r
+#define scatoi _wtoi\r
+#else\r
+#define scstrchr strchr\r
+#define scsnprintf snprintf\r
+#define scatoi atoi\r
+#endif\r
+#define MAX_FORMAT_LEN 20\r
+#define MAX_WFORMAT_LEN        3\r
+#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))\r
+\r
+static int validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, int n,int &width)\r
+{\r
+       SQChar swidth[MAX_WFORMAT_LEN];\r
+       int wc = 0;\r
+       int start = n;\r
+       fmt[0] = '%';\r
+       while (scstrchr(_SC("-+ #0"), src[n])) n++;\r
+       while (scisdigit(src[n])) {\r
+               swidth[wc] = src[n];\r
+               n++;\r
+               wc++;\r
+               if(wc>=MAX_WFORMAT_LEN)\r
+                       return sq_throwerror(v,_SC("width format too long"));\r
+       }\r
+       swidth[wc] = '\0';\r
+       if(wc > 0) {\r
+               width = scatoi(swidth);\r
+       }\r
+       else\r
+               width = 0;\r
+       if (src[n] == '.') {\r
+           n++;\r
+       \r
+               wc = 0;\r
+               while (scisdigit(src[n])) {\r
+                       swidth[wc] = src[n];\r
+                       n++;\r
+                       wc++;\r
+                       if(wc>=MAX_WFORMAT_LEN)\r
+                               return sq_throwerror(v,_SC("precision format too long"));\r
+               }\r
+               swidth[wc] = '\0';\r
+               if(wc > 0) {\r
+                       width += scatoi(swidth);\r
+               }\r
+       }\r
+       if (n-start > MAX_FORMAT_LEN )\r
+               return sq_throwerror(v,_SC("format too long"));\r
+       memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));\r
+       fmt[(n-start)+2] = '\0';\r
+       return n;\r
+}\r
+\r
+static int _string_format(HSQUIRRELVM v)\r
+{\r
+       const SQChar *format;\r
+       SQChar *dest;\r
+       SQChar fmt[MAX_FORMAT_LEN];\r
+       sq_getstring(v,2,&format);\r
+       int allocated = (sq_getsize(v,2)+1)*sizeof(SQChar);\r
+       dest = sq_getscratchpad(v,allocated);\r
+       int n = 0,i = 0, nparam = 3, w;\r
+       while(format[n] != '\0') {\r
+               if(format[n] != '%') {\r
+                       dest[i++] = format[n];\r
+                       n++;\r
+               }\r
+               else if(format[++n] == '%') {\r
+                       dest[i++] = '%';\r
+               }\r
+               else {\r
+                       if( nparam > sq_gettop(v) )\r
+                               return sq_throwerror(v,_SC("not enough paramters for the given format string"));\r
+                       n = validate_format(v,fmt,format,n,w);\r
+                       if(n < 0) return -1;\r
+                       int addlen = 0;\r
+                       int valtype = 0;\r
+                       const SQChar *ts;\r
+                       SQInteger ti;\r
+                       SQFloat tf;\r
+                       switch(format[n]) {\r
+                       case 's':\r
+                               if(SQ_FAILED(sq_getstring(v,nparam,&ts))) \r
+                                       return sq_throwerror(v,_SC("string expected for the specified format"));\r
+                               addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));\r
+                               valtype = 's';\r
+                               break;\r
+                       case 'i': case 'd': case 'c':case 'o':  case 'u':  case 'x':  case 'X':\r
+                               if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) \r
+                                       return sq_throwerror(v,_SC("integer expected for the specified format"));\r
+                               addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));\r
+                               valtype = 'i';\r
+                               break;\r
+                       case 'f': case 'g': case 'G': case 'e':  case 'E':\r
+                               if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) \r
+                                       return sq_throwerror(v,_SC("float expected for the specified format"));\r
+                               addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));\r
+                               valtype = 'f';\r
+                               break;\r
+                       default:\r
+                               return sq_throwerror(v,_SC("invalid format"));\r
+                       }\r
+                       n++;\r
+                       if((allocated-i) < addlen)\r
+                               allocated += addlen - (allocated-i);\r
+                       dest = sq_getscratchpad(v,allocated);\r
+                       switch(valtype) {\r
+                       case 's': i += scsprintf(&dest[i],fmt,ts); break;\r
+                       case 'i': i += scsprintf(&dest[i],fmt,ti); break;\r
+                       case 'f': i += scsprintf(&dest[i],fmt,tf); break;\r
+                       };\r
+                       nparam ++;\r
+               }\r
+       }\r
+       sq_pushstring(v,dest,i);\r
+       return 1;\r
+}\r
+\r
+#define SETUP_REX(v) \\r
+       SQRex *self = NULL; \\r
+       sq_getinstanceup(v,1,(SQUserPointer *)&self,0); \r
+\r
+static int _rexobj_releasehook(SQUserPointer p, int size)\r
+{\r
+       SQRex *self = ((SQRex *)p);\r
+       sqstd_rex_free(self);\r
+       return 1;\r
+}\r
+\r
+static int _regexp_match(HSQUIRRELVM v)\r
+{\r
+       SETUP_REX(v);\r
+       const SQChar *str;\r
+       sq_getstring(v,2,&str);\r
+       if(sqstd_rex_match(self,str) == SQTrue)\r
+       {\r
+               sq_pushinteger(v,1);\r
+               return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)\r
+{\r
+       sq_newtable(v);\r
+       sq_pushstring(v,_SC("begin"),-1);\r
+       sq_pushinteger(v,begin - str);\r
+       sq_rawset(v,-3);\r
+       sq_pushstring(v,_SC("end"),-1);\r
+       sq_pushinteger(v,end - str);\r
+       sq_rawset(v,-3);\r
+}\r
+\r
+static int _regexp_search(HSQUIRRELVM v)\r
+{\r
+       SETUP_REX(v);\r
+       const SQChar *str,*begin,*end;\r
+       SQInteger start = 0;\r
+       sq_getstring(v,2,&str);\r
+       if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);\r
+       if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {\r
+               _addrexmatch(v,str,begin,end);\r
+               return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int _regexp_capture(HSQUIRRELVM v)\r
+{\r
+       SETUP_REX(v);\r
+       const SQChar *str,*begin,*end;\r
+       SQInteger start = 0;\r
+       sq_getstring(v,2,&str);\r
+       if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);\r
+       if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {\r
+               SQInteger n = sqstd_rex_getsubexpcount(self);\r
+               SQRexMatch match;\r
+               sq_newarray(v,0);\r
+               for(SQInteger i = 0;i < n; i++) {\r
+                       sqstd_rex_getsubexp(self,i,&match);\r
+                       if(match.len > 0)\r
+                               _addrexmatch(v,str,match.begin,match.begin+match.len);\r
+                       else\r
+                               _addrexmatch(v,str,str,str); //empty match\r
+                       sq_arrayappend(v,-2);\r
+               }\r
+               return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int _regexp_subexpcount(HSQUIRRELVM v)\r
+{\r
+       SETUP_REX(v);\r
+       sq_pushinteger(v,sqstd_rex_getsubexpcount(self));\r
+       return 1;\r
+}\r
+\r
+static int _regexp_constructor(HSQUIRRELVM v)\r
+{\r
+       const SQChar *error,*pattern;\r
+       sq_getstring(v,2,&pattern);\r
+       SQRex *rex = sqstd_rex_compile(pattern,&error);\r
+       if(!rex) return sq_throwerror(v,error);\r
+       sq_setinstanceup(v,1,rex);\r
+       sq_setreleasehook(v,1,_rexobj_releasehook);\r
+       return 0;\r
+}\r
+\r
+static int _regexp__typeof(HSQUIRRELVM v)\r
+{\r
+       sq_pushstring(v,_SC("regexp"),-1);\r
+       return 1;\r
+}\r
+\r
+#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}\r
+static SQRegFunction rexobj_funcs[]={\r
+       _DECL_REX_FUNC(constructor,2,_SC(".s")),\r
+       _DECL_REX_FUNC(search,-2,_SC("xsn")),\r
+       _DECL_REX_FUNC(match,2,_SC("xs")),\r
+       _DECL_REX_FUNC(capture,-2,_SC("xsn")),\r
+       _DECL_REX_FUNC(subexpcount,1,_SC("x")),\r
+       _DECL_REX_FUNC(_typeof,1,_SC("x")),\r
+       {0,0}\r
+};\r
+\r
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}\r
+static SQRegFunction stringlib_funcs[]={\r
+       _DECL_FUNC(format,-2,_SC(".s")),\r
+       {0,0}\r
+};\r
+\r
+\r
+int sqstd_register_stringlib(HSQUIRRELVM v)\r
+{\r
+       sq_pushstring(v,_SC("regexp"),-1);\r
+       sq_newclass(v,SQFalse);\r
+       int i = 0;\r
+       while(rexobj_funcs[i].name != 0) {\r
+               SQRegFunction &f = rexobj_funcs[i];\r
+               sq_pushstring(v,f.name,-1);\r
+               sq_newclosure(v,f.f,0);\r
+               sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
+               sq_setnativeclosurename(v,-1,f.name);\r
+               sq_createslot(v,-3);\r
+               i++;\r
+       }\r
+       sq_createslot(v,-3);\r
+\r
+       i = 0;\r
+       while(stringlib_funcs[i].name!=0)\r
+       {\r
+               sq_pushstring(v,stringlib_funcs[i].name,-1);\r
+               sq_newclosure(v,stringlib_funcs[i].f,0);\r
+               sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);\r
+               sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);\r
+               sq_createslot(v,-3);\r
+               i++;\r
+       }\r
+       return 1;\r
+}\r
diff --git a/src/squirrel/sqstdlib/sqstdsystem.cpp b/src/squirrel/sqstdlib/sqstdsystem.cpp
new file mode 100644 (file)
index 0000000..615a350
--- /dev/null
@@ -0,0 +1,145 @@
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <time.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <sqstdsystem.h>\r
+\r
+#ifdef SQUNICODE\r
+#include <wchar.h>\r
+#define scgetenv _wgetenv\r
+#define scsystem _wsystem\r
+#define scasctime _wasctime\r
+#define scremove _wremove\r
+#define screname _wrename\r
+#else\r
+#define scgetenv getenv\r
+#define scsystem system\r
+#define scasctime asctime\r
+#define scremove remove\r
+#define screname rename\r
+#endif\r
+\r
+static int _system_getenv(HSQUIRRELVM v)\r
+{\r
+       const SQChar *s;\r
+       if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\r
+        sq_pushstring(v,scgetenv(s),-1);\r
+               return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+\r
+static int _system_system(HSQUIRRELVM v)\r
+{\r
+       const SQChar *s;\r
+       if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\r
+               sq_pushinteger(v,scsystem(s));\r
+               return 1;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong param"));\r
+}\r
+\r
+\r
+static int _system_clock(HSQUIRRELVM v)\r
+{\r
+       sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);\r
+       return 1;\r
+}\r
+\r
+static int _system_time(HSQUIRRELVM v)\r
+{\r
+       time_t t;\r
+       time(&t);\r
+       sq_pushinteger(v,*((SQInteger *)&t));\r
+       return 1;\r
+}\r
+\r
+static int _system_remove(HSQUIRRELVM v)\r
+{\r
+       const SQChar *s;\r
+       sq_getstring(v,2,&s);\r
+       if(scremove(s)==-1)\r
+               return sq_throwerror(v,_SC("remove() failed"));\r
+       return 0;\r
+}\r
+\r
+static int _system_rename(HSQUIRRELVM v)\r
+{\r
+       const SQChar *oldn,*newn;\r
+       sq_getstring(v,2,&oldn);\r
+       sq_getstring(v,3,&newn);\r
+       if(screname(oldn,newn)==-1)\r
+               return sq_throwerror(v,_SC("rename() failed"));\r
+       return 0;\r
+}\r
+\r
+static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val)\r
+{\r
+       sq_pushstring(v,name,-1);\r
+       sq_pushinteger(v,val);\r
+       sq_rawset(v,-3);\r
+}\r
+\r
+static int _system_date(HSQUIRRELVM v)\r
+{\r
+       time_t t;\r
+       SQInteger format = 'l';\r
+       if(sq_gettop(v) > 1) {\r
+               sq_getinteger(v,2,(SQInteger*)&t);\r
+               if(sq_gettop(v) > 2) {\r
+                       sq_getinteger(v,3,(SQInteger*)&format);\r
+               }\r
+       }\r
+       else {\r
+               time(&t);\r
+       }\r
+       tm *date;\r
+    if(format == 'u')\r
+               date = gmtime(&t);\r
+       else\r
+               date = localtime(&t);\r
+       if(!date)\r
+               return sq_throwerror(v,_SC("crt api failure"));\r
+       sq_newtable(v);\r
+       _set_integer_slot(v, _SC("sec"), date->tm_sec);\r
+    _set_integer_slot(v, _SC("min"), date->tm_min);\r
+    _set_integer_slot(v, _SC("hour"), date->tm_hour);\r
+    _set_integer_slot(v, _SC("day"), date->tm_mday);\r
+    _set_integer_slot(v, _SC("month"), date->tm_mon);\r
+    _set_integer_slot(v, _SC("year"), date->tm_year+1900);\r
+    _set_integer_slot(v, _SC("wday"), date->tm_wday);\r
+    _set_integer_slot(v, _SC("yday"), date->tm_yday);\r
+       return 1;\r
+}\r
+\r
+\r
+\r
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask}\r
+static SQRegFunction systemlib_funcs[]={\r
+       _DECL_FUNC(getenv,2,_SC(".s")),\r
+       _DECL_FUNC(system,2,_SC(".s")),\r
+       _DECL_FUNC(clock,1,NULL),\r
+       _DECL_FUNC(time,1,NULL),\r
+       _DECL_FUNC(date,-1,_SC(".nn")),\r
+       _DECL_FUNC(remove,2,_SC(".s")),\r
+       _DECL_FUNC(rename,3,_SC(".ss")),\r
+       {0,0}\r
+};\r
+\r
+\r
+int sqstd_register_systemlib(HSQUIRRELVM v)\r
+{\r
+       int i=0;\r
+       while(systemlib_funcs[i].name!=0)\r
+       {\r
+               sq_pushstring(v,systemlib_funcs[i].name,-1);\r
+               sq_newclosure(v,systemlib_funcs[i].f,0);\r
+               sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);\r
+               sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);\r
+               sq_createslot(v,-3);\r
+               i++;\r
+       }\r
+       return 1;\r
+}\r
diff --git a/src/squirrel/squirrel/Makefile b/src/squirrel/squirrel/Makefile
new file mode 100644 (file)
index 0000000..98f2fe6
--- /dev/null
@@ -0,0 +1,42 @@
+SQUIRREL= ..\r
+\r
+\r
+OUT= $(SQUIRREL)/lib/libsquirrel.a\r
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude\r
+DEFS= \r
+LIB=   stdc++\r
+\r
+OBJS= \\r
+       sqapi.o \\r
+       sqbaselib.o \\r
+       sqcompiler.o \\r
+       sqdebug.o \\r
+       sqlexer.o \\r
+       sqobject.o \\r
+       sqparser.o \\r
+       sqstate.o \\r
+       sqtable.o \\r
+       sqvm.o \\r
+       sqmem.o \\r
+       sqclass.o\r
+       \r
+SRCS= \\r
+       sqapi.cpp \\r
+       sqbaselib.cpp \\r
+       sqfuncstate.cpp \\r
+       sqdebug.cpp \\r
+       sqlexer.cpp \\r
+       sqobject.cpp \\r
+       sqcompiler.cpp \\r
+       sqstate.cpp \\r
+       sqtable.cpp \\r
+       sqmem.cpp \\r
+       sqvm.cpp \\r
+       sqclass.cpp\r
+\r
+       \r
+       \r
+squirrellib:\r
+       gcc -O3 -Os -c $(SRCS) $(INCZ) $(DEFS)\r
+       ar rc $(OUT) *.o\r
+       rm *.o
\ No newline at end of file
diff --git a/src/squirrel/squirrel/sqapi.cpp b/src/squirrel/squirrel/sqapi.cpp
new file mode 100644 (file)
index 0000000..2d269c2
--- /dev/null
@@ -0,0 +1,1074 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "sqarray.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+#include "squserdata.h"\r
+#include "sqfuncstate.h"\r
+#include "sqcompiler.h"\r
+#include "sqclass.h"\r
+\r
+bool sq_aux_gettypedarg(HSQUIRRELVM v,int idx,SQObjectType type,SQObjectPtr **o)\r
+{\r
+       *o = &stack_get(v,idx);\r
+       if(type(**o) != type){\r
+               SQObjectPtr oval = v->PrintObjVal(**o);\r
+               v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }\r
+\r
+#define sq_aux_paramscheck(v,count) \\r
+{ \\r
+       if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\\r
+}              \r
+\r
+int sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)\r
+{\r
+       v->_lasterror = e;\r
+       return SQ_ERROR;\r
+}\r
+\r
+int sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)\r
+{\r
+       scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type));\r
+       return sq_throwerror(v, _ss(v)->GetScratchPad(-1));\r
+}\r
+\r
+HSQUIRRELVM sq_open(int initialstacksize)\r
+{\r
+       SQSharedState *ss;\r
+       SQVM *v;\r
+       sq_new(ss, SQSharedState);\r
+       ss->Init();\r
+       v = (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
+       new (v) SQVM(ss);\r
+       ss->_root_vm = v;\r
+       if(v->Init(NULL, initialstacksize)) {\r
+               return v;\r
+       } else {\r
+               sq_delete(v, SQVM);\r
+               return NULL;\r
+       }\r
+       return v;\r
+}\r
+\r
+HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize)\r
+{\r
+       SQSharedState *ss;\r
+       SQVM *v;\r
+       ss=_ss(friendvm);\r
+       \r
+       v= (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
+       new (v) SQVM(ss);\r
+       \r
+       if(v->Init(friendvm, initialstacksize)) {\r
+               friendvm->Push(v);\r
+               return v;\r
+       } else {\r
+               sq_delete(v, SQVM);\r
+               return NULL;\r
+       }\r
+}\r
+\r
+int sq_getvmstate(HSQUIRRELVM v)\r
+{\r
+       if(v->_suspended)\r
+               return SQ_VMSTATE_SUSPENDED;\r
+       else { \r
+               if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING;\r
+               else return SQ_VMSTATE_IDLE;\r
+       }\r
+}\r
+\r
+void sq_seterrorhandler(HSQUIRRELVM v)\r
+{\r
+       SQObject o = stack_get(v, -1);\r
+       if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
+               v->_errorhandler = o;\r
+               v->Pop();\r
+       }\r
+}\r
+\r
+void sq_setdebughook(HSQUIRRELVM v)\r
+{\r
+       SQObject o = stack_get(v,-1);\r
+       if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
+               v->_debughook = o;\r
+               v->Pop();\r
+       }\r
+}\r
+\r
+void sq_close(HSQUIRRELVM v)\r
+{\r
+       SQSharedState *ss = _ss(v);\r
+       _thread(ss->_root_vm)->Finalize();\r
+       sq_delete(ss, SQSharedState);\r
+}\r
+\r
+SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)\r
+{\r
+       SQObjectPtr o;\r
+       if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {\r
+               v->Push(SQClosure::Create(_ss(v), _funcproto(o)));\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo)\r
+{\r
+       _ss(v)->_debuginfo = debuginfo?true:false;\r
+}\r
+\r
+void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)\r
+{\r
+       SQObjectPtr refs;\r
+       if(!ISREFCOUNTED(type(*po))) return;\r
+       if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {\r
+               refs = _integer(refs) + 1;\r
+       }\r
+       else{\r
+               refs = 1;\r
+       }\r
+       _table(_ss(v)->_refs_table)->NewSlot(*po, refs);\r
+}\r
+\r
+SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)\r
+{\r
+       SQObjectPtr refs;\r
+       if(!ISREFCOUNTED(type(*po))) return SQTrue;\r
+       if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {\r
+               int n = _integer(refs) - 1;\r
+               if(n <= 0) {\r
+                       _table(_ss(v)->_refs_table)->Remove(*po);\r
+                       sq_resetobject(po);\r
+               }\r
+               else {\r
+                       refs = n;_table(_ss(v)->_refs_table)->Set(*po, refs);\r
+                       return SQFalse;\r
+               }\r
+       }\r
+       return SQTrue;\r
+}\r
+\r
+const SQChar *sq_objtostring(HSQOBJECT *o) \r
+{\r
+       if(sq_type(*o) == OT_STRING) {\r
+               return o->_unVal.pString->_val;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+SQInteger sq_objtointeger(HSQOBJECT *o) \r
+{\r
+       if(sq_isnumeric(*o)) {\r
+               return tointeger(*o);\r
+       }\r
+       return 0;\r
+}\r
+\r
+SQFloat sq_objtofloat(HSQOBJECT *o) \r
+{\r
+       if(sq_isnumeric(*o)) {\r
+               return tofloat(*o);\r
+       }\r
+       return 0;\r
+}\r
+\r
+void sq_pushnull(HSQUIRRELVM v)\r
+{\r
+       v->Push(_null_);\r
+}\r
+\r
+void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len)\r
+{\r
+       if(s)\r
+               v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));\r
+       else v->Push(_null_);\r
+}\r
+\r
+void sq_pushinteger(HSQUIRRELVM v,SQInteger n)\r
+{\r
+       v->Push(n);\r
+}\r
+\r
+void sq_pushbool(HSQUIRRELVM v,SQBool b)\r
+{\r
+       v->Push(b?true:false);\r
+}\r
+\r
+void sq_pushfloat(HSQUIRRELVM v,SQFloat n)\r
+{\r
+       v->Push(n);\r
+}\r
+\r
+void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)\r
+{\r
+       v->Push(p);\r
+}\r
+\r
+SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size)\r
+{\r
+       SQUserData *ud = SQUserData::Create(_ss(v), size);\r
+       v->Push(ud);\r
+       return ud->_val;\r
+}\r
+\r
+void sq_newtable(HSQUIRRELVM v)\r
+{\r
+       v->Push(SQTable::Create(_ss(v), 0));    \r
+}\r
+\r
+void sq_newarray(HSQUIRRELVM v,int size)\r
+{\r
+       v->Push(SQArray::Create(_ss(v), size)); \r
+}\r
+\r
+SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)\r
+{\r
+       SQClass *baseclass = NULL;\r
+       if(hasbase) {\r
+               SQObjectPtr &base = stack_get(v,-1);\r
+               if(type(base) != OT_CLASS)\r
+                       return sq_throwerror(v,_SC("invalid base type"));\r
+               baseclass = _class(base);\r
+       }\r
+       SQClass *newclass = SQClass::Create(_ss(v), baseclass);\r
+       if(baseclass) v->Pop();\r
+       v->Push(newclass);      \r
+       return SQ_OK;\r
+}\r
+\r
+int sq_instanceof(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &inst = stack_get(v,-1);\r
+       SQObjectPtr &cl = stack_get(v,-2);\r
+       if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)\r
+               return sq_throwerror(v,_SC("invalid param type"));\r
+       return _instance(inst)->InstanceOf(_class(cl))?1:0;\r
+}\r
+\r
+SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx)\r
+{\r
+       sq_aux_paramscheck(v,2);\r
+       SQObjectPtr *arr;\r
+       _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
+       _array(*arr)->Append(v->GetUp(-1));\r
+       v->Pop(1);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval)\r
+{\r
+       sq_aux_paramscheck(v, 1);\r
+       SQObjectPtr *arr;\r
+       _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
+       if(_array(*arr)->Size() > 0) {\r
+        if(pushval != 0){ v->Push(_array(*arr)->Top()); }\r
+               _array(*arr)->Pop();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v, _SC("empty array"));\r
+}\r
+\r
+SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize)\r
+{\r
+       sq_aux_paramscheck(v,1);\r
+       SQObjectPtr *arr;\r
+       _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
+       if(_array(*arr)->Size() > 0) {\r
+               _array(*arr)->Resize(newsize);\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v, _SC("empty array"));\r
+}\r
+\r
+SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx)\r
+{\r
+       sq_aux_paramscheck(v, 1);\r
+       SQObjectPtr *o;\r
+       _GETSAFE_OBJ(v, idx, OT_ARRAY,o);\r
+       SQArray *arr = _array(*o);\r
+       if(arr->Size() > 0) {\r
+               SQObjectPtr t;\r
+               int size = arr->Size();\r
+               int n = size >> 1; size -= 1;\r
+               for(int i = 0; i < n; i++) {\r
+                       t = arr->_values[i];\r
+                       arr->_values[i] = arr->_values[size-i];\r
+                       arr->_values[size-i] = t;\r
+               }\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v, _SC("empty array"));\r
+}\r
+\r
+void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars)\r
+{\r
+       SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);\r
+       nc->_nparamscheck = 0;\r
+       for(unsigned int i = 0; i < nfreevars; i++) {\r
+               nc->_outervalues.push_back(v->Top());\r
+               v->Pop();\r
+       }\r
+       v->Push(SQObjectPtr(nc));       \r
+}\r
+\r
+SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars)\r
+{\r
+       SQObject o = stack_get(v, idx);\r
+       if(sq_isclosure(o)) {\r
+               SQClosure *c = _closure(o);\r
+               SQFunctionProto *proto = _funcproto(c->_function);\r
+               *nparams = (unsigned int)proto->_parameters.size();\r
+        *nfreevars = (unsigned int)c->_outervalues.size();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("the object is not a closure"));\r
+}\r
+\r
+SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name)\r
+{\r
+       SQObject o = stack_get(v, idx);\r
+       if(sq_isnativeclosure(o)) {\r
+               SQNativeClosure *nc = _nativeclosure(o);\r
+               nc->_name = SQString::Create(_ss(v),name);\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("the object is not a nativeclosure"));\r
+}\r
+\r
+SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask)\r
+{\r
+       SQObject o = stack_get(v, -1);\r
+       if(!sq_isnativeclosure(o))\r
+               return sq_throwerror(v, _SC("native closure expected"));\r
+       SQNativeClosure *nc = _nativeclosure(o);\r
+       nc->_nparamscheck = nparamscheck;\r
+       if(typemask) {\r
+               SQIntVec res;\r
+               if(!CompileTypemask(res, typemask))\r
+                       return sq_throwerror(v, _SC("invalid typemask"));\r
+               nc->_typecheck.copy(res);\r
+       }\r
+       else {\r
+               nc->_typecheck.resize(0);\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+void sq_pushroottable(HSQUIRRELVM v)\r
+{\r
+       v->Push(v->_roottable);\r
+}\r
+\r
+void sq_pushregistrytable(HSQUIRRELVM v)\r
+{\r
+       v->Push(_ss(v)->_registry);\r
+}\r
+\r
+SQRESULT sq_setroottable(HSQUIRRELVM v)\r
+{\r
+       SQObject o = stack_get(v, -1);\r
+       if(sq_istable(o) || sq_isnull(o)) {\r
+               v->_roottable = o;\r
+               v->Pop();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v, _SC("ivalid type"));\r
+}\r
+\r
+void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)\r
+{\r
+       v->_foreignptr = p;\r
+}\r
+\r
+SQUserPointer sq_getforeignptr(HSQUIRRELVM v)\r
+{\r
+       return v->_foreignptr;\r
+}\r
+\r
+void sq_push(HSQUIRRELVM v,int idx)\r
+{\r
+       v->Push(stack_get(v, idx));\r
+}\r
+\r
+SQObjectType sq_gettype(HSQUIRRELVM v,int idx)\r
+{\r
+       return type(stack_get(v, idx));\r
+}\r
+\r
+SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       if(sq_isnumeric(o)) {\r
+               *i = tointeger(o);\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       if(sq_isnumeric(o)) {\r
+               *f = tofloat(o);\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       if(sq_isbool(o)) {\r
+               *b = _integer(o);\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_STRING,o);\r
+       *c = _stringval(*o);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_THREAD,o);\r
+       *thread = _thread(*o);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_clone(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       v->Push(_null_);\r
+       if(!v->Clone(o, stack_get(v, -1))){\r
+               v->Pop();\r
+               return sq_aux_invalidtype(v, type(o));\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQInteger sq_getsize(HSQUIRRELVM v, int idx)\r
+{\r
+       SQObjectPtr &o = stack_get(v, idx);\r
+       SQObjectType type = type(o);\r
+       switch(type) {\r
+       case OT_STRING:         return _string(o)->_len;\r
+       case OT_TABLE:          return _table(o)->CountUsed();\r
+       case OT_ARRAY:          return _array(o)->Size();\r
+       case OT_USERDATA:       return _userdata(o)->_size;\r
+       default:\r
+               return sq_aux_invalidtype(v, type);\r
+       }\r
+}\r
+\r
+SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_USERDATA,o);\r
+       (*p) = _userdataval(*o);\r
+       if(typetag) *typetag = _userdata(*o)->_typetag;\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       switch(type(o)) {\r
+               case OT_USERDATA:       _userdata(o)->_typetag = typetag;       break;\r
+               case OT_CLASS:          _class(o)->_typetag = typetag;          break;\r
+               default:                        return sq_throwerror(v,_SC("invalid object type"));\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       switch(type(o)) {\r
+               case OT_USERDATA:       *typetag = _userdata(o)->_typetag;      break;\r
+               case OT_CLASS:          *typetag = _class(o)->_typetag;         break;\r
+               default:                        return sq_throwerror(v,_SC("invalid object type"));\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getuserpointer(HSQUIRRELVM v, int idx, SQUserPointer *p)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);\r
+       (*p) = _userpointer(*o);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
+       _instance(o)->_userpointer = p;\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag)\r
+{\r
+       SQObjectPtr &o = stack_get(v,idx);\r
+       if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
+       (*p) = _instance(o)->_userpointer;\r
+       if(typetag != 0) {\r
+               SQClass *cl = _instance(o)->_class;\r
+               do{\r
+                       if(cl->_typetag == typetag)\r
+                               return SQ_OK;\r
+                       cl = cl->_base;\r
+               }while(cl != NULL);\r
+               return sq_throwerror(v,_SC("invalid type tag"));\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+int sq_gettop(HSQUIRRELVM v)\r
+{\r
+       return (v->_top) - v->_stackbase;\r
+}\r
+\r
+void sq_settop(HSQUIRRELVM v, int newtop)\r
+{\r
+       int top = sq_gettop(v);\r
+       if(top > newtop)\r
+               sq_pop(v, top - newtop);\r
+       else\r
+               while(top < newtop) sq_pushnull(v);\r
+}\r
+\r
+void sq_pop(HSQUIRRELVM v, int nelemstopop)\r
+{\r
+       assert(v->_top >= nelemstopop);\r
+       v->Pop(nelemstopop);\r
+}\r
+\r
+void sq_remove(HSQUIRRELVM v, int idx)\r
+{\r
+       v->Remove(idx);\r
+}\r
+\r
+int sq_cmp(HSQUIRRELVM v)\r
+{\r
+       int res;\r
+       v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);\r
+       return res;\r
+}\r
+\r
+SQRESULT sq_createslot(HSQUIRRELVM v, int idx)\r
+{\r
+       sq_aux_paramscheck(v, 3);\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       if(type(self) == OT_TABLE || type(self) == OT_CLASS) {\r
+               SQObjectPtr &key = v->GetUp(-2);\r
+               if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
+               v->NewSlot(self, key, v->GetUp(-1));\r
+               v->Pop(2);\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval)\r
+{\r
+       sq_aux_paramscheck(v, 2);\r
+       SQObjectPtr *self;\r
+       _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
+       SQObjectPtr &key = v->GetUp(-1);\r
+       if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
+       SQObjectPtr res;\r
+       if(!v->DeleteSlot(*self, key, res)){\r
+               return SQ_ERROR;\r
+       }\r
+       if(pushval)     v->GetUp(-1) = res;\r
+       else v->Pop(1);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_set(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
+               v->Pop(2);\r
+               return SQ_OK;\r
+       }\r
+       v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_rawset(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
+       switch(type(self)) {\r
+       case OT_TABLE:\r
+               _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
+               v->Pop(2);\r
+               return SQ_OK;\r
+       break;\r
+       case OT_CLASS:\r
+               _class(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
+               v->Pop(2);\r
+               return SQ_OK;\r
+       break;\r
+       case OT_INSTANCE:\r
+               if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) {\r
+                       v->Pop(2);\r
+                       return SQ_OK;\r
+               }\r
+       break;\r
+       case OT_ARRAY:\r
+               if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
+                       v->Pop(2);\r
+                       return SQ_OK;\r
+               }\r
+       break;\r
+       default:\r
+               v->Pop(2);\r
+               return sq_throwerror(v, _SC("rawset works only on arrays,tables,calsses and instances"));\r
+       }\r
+       v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self = stack_get(v, idx);\r
+       SQObjectPtr &mt = v->GetUp(-1);\r
+       SQObjectType type = type(self);\r
+       switch(type) {\r
+       case OT_TABLE:\r
+               if(type(mt) == OT_TABLE) {\r
+                       if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}\r
+               else if(type(mt)==OT_NULL) {\r
+                       _table(self)->SetDelegate(NULL); v->Pop(); }\r
+               else return sq_aux_invalidtype(v,type);\r
+               break;\r
+       case OT_USERDATA:\r
+               if(type(mt)==OT_TABLE) {\r
+                       _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }\r
+               else if(type(mt)==OT_NULL) {\r
+                       _userdata(self)->SetDelegate(NULL); v->Pop(); }\r
+               else return sq_aux_invalidtype(v, type);\r
+               break;\r
+       default:\r
+                       return sq_aux_invalidtype(v, type);\r
+               break;\r
+       }\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval)\r
+{\r
+       sq_aux_paramscheck(v, 2);\r
+       SQObjectPtr *self;\r
+       _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
+       SQObjectPtr &key = v->GetUp(-1);\r
+       SQObjectPtr t;\r
+       if(_table(*self)->Get(key,t)) {\r
+               _table(*self)->Remove(key);\r
+       }\r
+       if(pushval != 0)\r
+               if(pushval)     v->GetUp(-1) = t;\r
+       else\r
+               v->Pop(1);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self=stack_get(v,idx);\r
+       switch(type(self)){\r
+       case OT_TABLE:\r
+               if(!_table(self)->_delegate)break;\r
+               v->Push(SQObjectPtr(_table(self)->_delegate));\r
+               return SQ_OK;\r
+               break;\r
+       case OT_USERDATA:\r
+               if(!_userdata(self)->_delegate)break;\r
+               v->Push(SQObjectPtr(_userdata(self)->_delegate));\r
+               return SQ_OK;\r
+               break;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong type"));\r
+}\r
+\r
+SQRESULT sq_get(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self=stack_get(v,idx);\r
+       if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
+               return SQ_OK;\r
+       v->Pop(1);\r
+       return sq_throwerror(v,_SC("the index doesn't exist"));\r
+}\r
+\r
+SQRESULT sq_rawget(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr &self=stack_get(v,idx);\r
+       switch(type(self)) {\r
+       case OT_TABLE:\r
+               if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
+                       return SQ_OK;\r
+               break;\r
+       case OT_CLASS:\r
+               if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
+                       return SQ_OK;\r
+               break;\r
+       case OT_INSTANCE:\r
+               if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
+                       return SQ_OK;\r
+               break;\r
+       case OT_ARRAY:\r
+               if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
+                       return SQ_OK;\r
+               break;\r
+       default:\r
+               v->Pop(1);\r
+               return sq_throwerror(v,_SC("rawget works only on arrays and tables"));\r
+       }       \r
+       v->Pop(1);\r
+       return sq_throwerror(v,_SC("the index doesn't exist"));\r
+}\r
+\r
+SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po)\r
+{\r
+       *po=stack_get(v,idx);\r
+       return SQ_OK;\r
+}\r
+\r
+const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx)\r
+{\r
+       unsigned int cstksize=v->_callsstack.size();\r
+       unsigned int lvl=(cstksize-level)-1;\r
+       int stackbase=v->_stackbase;\r
+       if(lvl<cstksize){\r
+               for(unsigned int i=0;i<level;i++){\r
+                       SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];\r
+                       stackbase-=ci._prevstkbase;\r
+               }\r
+               SQVM::CallInfo &ci=v->_callsstack[lvl];\r
+               if(type(ci._closure)!=OT_CLOSURE)\r
+                       return NULL;\r
+               SQClosure *c=_closure(ci._closure);\r
+               SQFunctionProto *func=_funcproto(c->_function);\r
+               return func->GetLocal(v,stackbase,idx,(ci._ip-func->_instructions._vals)-1);\r
+       }\r
+       return NULL;\r
+}\r
+\r
+void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)\r
+{\r
+       v->Push(SQObjectPtr(obj));\r
+}\r
+\r
+void sq_resetobject(HSQOBJECT *po)\r
+{\r
+       po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;\r
+}\r
+\r
+SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)\r
+{\r
+       v->_lasterror=SQString::Create(_ss(v),err);\r
+       return -1;\r
+}\r
+\r
+void sq_reseterror(HSQUIRRELVM v)\r
+{\r
+       v->_lasterror = _null_;\r
+}\r
+\r
+void sq_getlasterror(HSQUIRRELVM v)\r
+{\r
+       v->Push(v->_lasterror);\r
+}\r
+\r
+void sq_reservestack(HSQUIRRELVM v,int nsize)\r
+{\r
+       if (((unsigned int)v->_top + nsize) > v->_stack.size()) {\r
+               v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));\r
+       }\r
+}\r
+\r
+SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval)\r
+{\r
+       if(type(v->GetUp(-1))==OT_GENERATOR){\r
+               v->Push(_null_); //retval\r
+               if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),SQVM::ET_RESUME_GENERATOR))\r
+               {v->Raise_Error(v->_lasterror); return SQ_ERROR;}\r
+               if(!retval)\r
+                       v->Pop();\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("only generators can be resumed"));\r
+}\r
+\r
+SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval)\r
+{\r
+       SQObjectPtr res;\r
+       if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res)){\r
+               v->Pop(params);//pop closure and args\r
+               if(retval){\r
+                       v->Push(res); return SQ_OK;\r
+               }\r
+               return SQ_OK;\r
+       }\r
+       else {\r
+               v->Pop(params);\r
+               return SQ_ERROR;\r
+       }\r
+       if(!v->_suspended)\r
+               v->Pop(params);\r
+       return sq_throwerror(v,_SC("call failed"));\r
+}\r
+\r
+SQRESULT sq_suspendvm(HSQUIRRELVM v)\r
+{\r
+       return v->Suspend();\r
+}\r
+\r
+SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval)\r
+{\r
+       SQObjectPtr ret;\r
+       if(!v->_suspended)\r
+               return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));\r
+       if(wakeupret) {\r
+               v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval\r
+               v->Pop();\r
+       } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;\r
+       if(!v->Execute(_null_,v->_top,-1,-1,ret,SQVM::ET_RESUME_VM))\r
+               return SQ_ERROR;\r
+       if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) {\r
+               while (v->_top > 1) v->_stack[--v->_top] = _null_;\r
+       }\r
+       if(retval)\r
+               v->Push(ret);\r
+       return SQ_OK;\r
+}\r
+\r
+void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook)\r
+{\r
+       if(sq_gettop(v) >= 1){\r
+               SQObjectPtr &ud=stack_get(v,idx);\r
+               switch( type(ud) ) {\r
+               case OT_USERDATA:\r
+                       _userdata(ud)->_hook = hook;\r
+                       break;\r
+               case OT_INSTANCE:\r
+                       _instance(ud)->_hook = hook;\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)\r
+{\r
+       _ss(v)->_compilererrorhandler = f;\r
+}\r
+\r
+SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);\r
+       SQClosure *c=_closure(*o);\r
+       unsigned short tag = SQ_BYTECODE_STREAM_TAG;\r
+       if(w(up,&tag,2) != 2)\r
+               return sq_throwerror(v,_SC("io error"));\r
+       if(!_closure(*o)->Save(v,up,w))\r
+               return SQ_ERROR;\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)\r
+{\r
+       SQObjectPtr func=SQFunctionProto::Create();\r
+       SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func));\r
+       unsigned short tag;\r
+       if(r(up,&tag,2) != 2)\r
+               return sq_throwerror(v,_SC("io error"));\r
+       if(tag != SQ_BYTECODE_STREAM_TAG)\r
+               return sq_throwerror(v,_SC("invalid stream"));\r
+       if(!_closure(closure)->Load(v,up,r))\r
+               return SQ_ERROR;\r
+       v->Push(closure);\r
+       return SQ_OK;\r
+}\r
+\r
+SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize)\r
+{\r
+       return _ss(v)->GetScratchPad(minsize);\r
+}\r
+\r
+int sq_collectgarbage(HSQUIRRELVM v)\r
+{\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       return _ss(v)->CollectGarbage(v);\r
+#else\r
+       return -1;\r
+#endif\r
+}\r
+\r
+SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval)\r
+{\r
+       SQObjectPtr &self=stack_get(v,idx);\r
+       switch(type(self))\r
+       {\r
+       case OT_CLOSURE:\r
+               if(_closure(self)->_outervalues.size()>nval){\r
+                       _closure(self)->_outervalues[nval]=stack_get(v,-1);\r
+               }\r
+               else return sq_throwerror(v,_SC("invalid free var index"));\r
+               break;\r
+       case OT_NATIVECLOSURE:\r
+               if(_nativeclosure(self)->_outervalues.size()>nval){\r
+                       _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);\r
+               }\r
+               else return sq_throwerror(v,_SC("invalid free var index"));\r
+               break;\r
+       default:\r
+               return sq_aux_invalidtype(v,type(self));\r
+       }\r
+       v->Pop(1);\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_setattributes(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
+       SQObjectPtr &key = stack_get(v,-2);\r
+       SQObjectPtr &val = stack_get(v,-1);\r
+       SQObjectPtr attrs;\r
+       if(type(key) == OT_NULL) {\r
+               attrs = _class(*o)->_attributes;\r
+               _class(*o)->_attributes = val;\r
+               v->Pop(2);\r
+               v->Push(attrs);\r
+               return SQ_OK;\r
+       }else if(_class(*o)->GetAttributes(key,attrs)) {\r
+               _class(*o)->SetAttributes(key,val);\r
+               v->Pop(2);\r
+               v->Push(attrs);\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong index"));\r
+}\r
+\r
+SQRESULT sq_getattributes(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
+       SQObjectPtr &key = stack_get(v,-1);\r
+       SQObjectPtr attrs;\r
+       if(type(key) == OT_NULL) {\r
+               attrs = _class(*o)->_attributes;\r
+               v->Pop();\r
+               v->Push(attrs);\r
+               return SQ_OK;\r
+       }\r
+       else if(_class(*o)->GetAttributes(key,attrs)) {\r
+               v->Pop();\r
+               v->Push(attrs);\r
+               return SQ_OK;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong index"));\r
+}\r
+\r
+SQRESULT sq_getclass(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);\r
+       v->Push(SQObjectPtr(_instance(*o)->_class));\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_createinstance(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr *o = NULL;\r
+       _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
+       v->Push(_class(*o)->CreateInstance());\r
+       return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_next(HSQUIRRELVM v,int idx)\r
+{\r
+       SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;\r
+       if(type(o) == OT_GENERATOR) {\r
+               return sq_throwerror(v,_SC("cannot iterate a generator"));\r
+       }\r
+       bool finished;\r
+       if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished))\r
+               return SQ_ERROR;\r
+       if(!finished) {\r
+               v->Push(realkey);\r
+               v->Push(val);\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+struct BufState{\r
+       const SQChar *buf;\r
+       int ptr;\r
+       int size;\r
+};\r
+\r
+SQInteger buf_lexfeed(SQUserPointer file)\r
+{\r
+       BufState *buf=(BufState*)file;\r
+       if(buf->size<(buf->ptr+1))\r
+               return 0;\r
+       return buf->buf[buf->ptr++];\r
+}\r
+\r
+SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror) {\r
+       BufState buf;\r
+       buf.buf = s;\r
+       buf.size = size;\r
+       buf.ptr = 0;\r
+       return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);\r
+}\r
+\r
+void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx)\r
+{\r
+       dest->Push(stack_get(src,idx));\r
+}\r
+\r
+void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)\r
+{\r
+       _ss(v)->_printfunc = printfunc;\r
+}\r
+\r
+SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)\r
+{\r
+       return _ss(v)->_printfunc;\r
+}\r
+\r
+void *sq_malloc(unsigned int size)\r
+{\r
+       return SQ_MALLOC(size);\r
+}\r
+\r
+void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize)\r
+{\r
+       return SQ_REALLOC(p,oldsize,newsize);\r
+}\r
+void sq_free(void *p,unsigned int size)\r
+{\r
+       SQ_FREE(p,size);\r
+}\r
diff --git a/src/squirrel/squirrel/sqarray.h b/src/squirrel/squirrel/sqarray.h
new file mode 100644 (file)
index 0000000..b747e07
--- /dev/null
@@ -0,0 +1,77 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQARRAY_H_\r
+#define _SQARRAY_H_\r
+\r
+struct SQArray : public CHAINABLE_OBJ\r
+{\r
+private:\r
+       SQArray(SQSharedState *ss,int nsize){_values.resize(nsize);_uiRef=0;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
+       ~SQArray()\r
+       {\r
+               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+       }\r
+public:\r
+       static SQArray* Create(SQSharedState *ss,int nInitialSize){\r
+               SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));\r
+               new (newarray) SQArray(ss,nInitialSize);\r
+               return newarray;\r
+       }\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+#endif\r
+       void Finalize(){\r
+               _values.resize(0);\r
+       }\r
+       bool Get(const int nidx,SQObjectPtr &val)\r
+       {\r
+               if(nidx>=0 && nidx<(int)_values.size()){\r
+                       val=_values[nidx];\r
+                       return true;\r
+               }\r
+               else return false;\r
+       }\r
+       bool Set(const int nidx,const SQObjectPtr &val)\r
+       {\r
+               if(nidx>=0 && nidx<(int)_values.size()){\r
+                       _values[nidx]=val;\r
+                       return true;\r
+               }\r
+               else return false;\r
+       }\r
+       int Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)\r
+       {\r
+               unsigned int idx=TranslateIndex(refpos);\r
+               while(idx<_values.size()){\r
+                       //first found\r
+                       outkey=(SQInteger)idx;\r
+                       outval=_values[idx];\r
+                       //return idx for the next iteration\r
+                       return ++idx;\r
+               }\r
+               //nothing to iterate anymore\r
+               return -1;\r
+       }\r
+       SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; }\r
+       int Size() const {return _values.size();}\r
+       void Resize(int size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }\r
+       void Reserve(int size) { _values.reserve(size); }\r
+       void Append(const SQObject &o){_values.push_back(o);}\r
+       void Extend(const SQArray *a);\r
+       SQObjectPtr &Top(){return _values.top();}\r
+       void Pop(){_values.pop_back(); ShrinkIfNeeded(); }\r
+       void Insert(const SQObject& idx,const SQObject &val){_values.insert((unsigned int)tointeger(idx),val);}\r
+       void ShrinkIfNeeded() {\r
+               if(_values.size() <= _values.capacity()>>2) //shrink the array\r
+                       _values.shrinktofit();\r
+       }\r
+       void Remove(unsigned int idx){\r
+               _values.remove(idx);\r
+               ShrinkIfNeeded();\r
+       }\r
+       void Release()\r
+       {\r
+               sq_delete(this,SQArray);\r
+       }\r
+       SQObjectPtrVec _values;\r
+};\r
+#endif //_SQARRAY_H_\r
diff --git a/src/squirrel/squirrel/sqbaselib.cpp b/src/squirrel/squirrel/sqbaselib.cpp
new file mode 100644 (file)
index 0000000..c22f793
--- /dev/null
@@ -0,0 +1,781 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "sqarray.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+#include "sqclass.h"\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <ctype.h>\r
+\r
+bool str2num(const SQChar *s,SQObjectPtr &res)\r
+{\r
+       SQChar *end;\r
+       if(scstrstr(s,_SC("."))){\r
+               SQFloat r = SQFloat(scstrtod(s,&end));\r
+               if(s == end) return false;\r
+               while (scisspace((*end)) ) end++;\r
+               if (*end != _SC('\0')) return false;\r
+               res = r;\r
+               return true;\r
+       }\r
+       else{\r
+               const SQChar *t = s;\r
+               while(*t != _SC('\0')) if(!scisdigit(*t++)) return false;\r
+               res = SQInteger(scatoi(s));\r
+               return true;\r
+       }\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+static int base_collectgarbage(HSQUIRRELVM v)\r
+{\r
+       sq_pushinteger(v, sq_collectgarbage(v));\r
+       return 1;\r
+}\r
+#endif\r
+\r
+static int base_getroottable(HSQUIRRELVM v)\r
+{\r
+       v->Push(v->_roottable);\r
+       return 1;\r
+}\r
+\r
+static int base_setroottable(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,2);\r
+       if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;\r
+       v->Push(o);\r
+       return 1;\r
+}\r
+\r
+static int base_seterrorhandler(HSQUIRRELVM v)\r
+{\r
+       sq_seterrorhandler(v);\r
+       return 0;\r
+}\r
+\r
+static int base_setdebughook(HSQUIRRELVM v)\r
+{\r
+       sq_setdebughook(v);\r
+       return 0;\r
+}\r
+\r
+static int base_enabledebuginfo(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,2);\r
+       sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);\r
+       return 0;\r
+}\r
+\r
+static int base_getstackinfos(HSQUIRRELVM v)\r
+{\r
+       SQInteger level;\r
+       SQStackInfos si;\r
+       int seq = 0;\r
+       const SQChar *name = NULL;\r
+       sq_getinteger(v, -1, &level);\r
+       if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))\r
+       {\r
+               const SQChar *fn = _SC("unknown");\r
+               const SQChar *src = _SC("unknown");\r
+               if(si.funcname)fn = si.funcname;\r
+               if(si.source)src = si.source;\r
+               sq_newtable(v);\r
+               sq_pushstring(v, _SC("func"), -1);\r
+               sq_pushstring(v, fn, -1);\r
+               sq_createslot(v, -3);\r
+               sq_pushstring(v, _SC("src"), -1);\r
+               sq_pushstring(v, src, -1);\r
+               sq_createslot(v, -3);\r
+               sq_pushstring(v, _SC("line"), -1);\r
+               sq_pushinteger(v, si.line);\r
+               sq_createslot(v, -3);\r
+               sq_pushstring(v, _SC("locals"), -1);\r
+               sq_newtable(v);\r
+               seq=0;\r
+               while (name = sq_getlocal(v, level, seq)) {\r
+                       sq_pushstring(v, name, -1);\r
+                       sq_push(v, -2);\r
+                       sq_createslot(v, -4);\r
+                       sq_pop(v, 1);\r
+                       seq++;\r
+               }\r
+               sq_createslot(v, -3);\r
+               return 1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int base_assert(HSQUIRRELVM v)\r
+{\r
+       if(v->IsFalse(stack_get(v,2))){\r
+               return sq_throwerror(v,_SC("assertion failed"));\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int get_slice_params(HSQUIRRELVM v,int &sidx,int &eidx,SQObjectPtr &o)\r
+{\r
+       int top = sq_gettop(v);\r
+       sidx=0;\r
+       eidx=0;\r
+       o=stack_get(v,1);\r
+       SQObjectPtr &start=stack_get(v,2);\r
+       if(type(start)!=OT_NULL && sq_isnumeric(start)){\r
+               sidx=tointeger(start);\r
+       }\r
+       if(top>2){\r
+               SQObjectPtr &end=stack_get(v,3);\r
+               if(sq_isnumeric(end)){\r
+                       eidx=tointeger(end);\r
+               }\r
+       }\r
+       else {\r
+               eidx = sq_getsize(v,1);\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int base_print(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,2);\r
+       switch(type(o)){\r
+       case OT_STRING:\r
+               if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),_stringval(o));\r
+               break;\r
+       case OT_INTEGER:\r
+               if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%d"),_integer(o));\r
+               break;\r
+       case OT_FLOAT:\r
+               if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%.14g"),_float(o));\r
+               break;\r
+       default:{\r
+               SQObjectPtr tname;\r
+               v->TypeOf(o,tname);\r
+               if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("(%s)"),_stringval(tname));\r
+               }\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int base_compilestring(HSQUIRRELVM v)\r
+{\r
+       int nargs=sq_gettop(v);\r
+       const SQChar *src=NULL,*name=_SC("unnamedbuffer");\r
+       SQInteger size;\r
+       sq_getstring(v,2,&src);\r
+       size=sq_getsize(v,2);\r
+       if(nargs>2){\r
+               sq_getstring(v,3,&name);\r
+       }\r
+       if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))\r
+               return 1;\r
+       else\r
+               return SQ_ERROR;\r
+}\r
+\r
+static int base_newthread(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &func = stack_get(v,2);\r
+       int stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;\r
+       HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);\r
+       sq_move(newv,v,-2);\r
+       return 1;\r
+}\r
+\r
+static int base_suspend(HSQUIRRELVM v)\r
+{\r
+       return sq_suspendvm(v);\r
+}\r
+\r
+static int base_array(HSQUIRRELVM v)\r
+{\r
+       SQArray *a;\r
+       SQObject &size = stack_get(v,2);\r
+       if(sq_gettop(v) > 2) {\r
+               a = SQArray::Create(_ss(v),0);\r
+               a->Resize(tointeger(size),stack_get(v,3));\r
+       }\r
+       else {\r
+               a = SQArray::Create(_ss(v),tointeger(size));\r
+       }\r
+       v->Push(a);\r
+       return 1;\r
+}\r
+\r
+static int base_type(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o = stack_get(v,2);\r
+       v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));\r
+       return 1;\r
+}\r
+\r
+static SQRegFunction base_funcs[]={\r
+       //generic\r
+       {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},\r
+       {_SC("setdebughook"),base_setdebughook,2, NULL},\r
+       {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},\r
+       {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},\r
+       {_SC("getroottable"),base_getroottable,1, NULL},\r
+       {_SC("setroottable"),base_setroottable,2, NULL},\r
+       {_SC("assert"),base_assert,2, NULL},\r
+       {_SC("print"),base_print,2, NULL},\r
+       {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},\r
+       {_SC("newthread"),base_newthread,2, _SC(".c")},\r
+       {_SC("suspend"),base_suspend,-1, NULL},\r
+       {_SC("array"),base_array,-2, _SC(".n")},\r
+       {_SC("type"),base_type,2, NULL},\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},\r
+#endif\r
+       {0,0}\r
+};\r
+\r
+void sq_base_register(HSQUIRRELVM v)\r
+{\r
+       int i=0;\r
+       sq_pushroottable(v);\r
+       while(base_funcs[i].name!=0) {\r
+               sq_pushstring(v,base_funcs[i].name,-1);\r
+               sq_newclosure(v,base_funcs[i].f,0);\r
+               sq_setnativeclosurename(v,-1,base_funcs[i].name);\r
+               sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);\r
+               sq_createslot(v,-3);\r
+               i++;\r
+       }\r
+       sq_pushstring(v,_SC("_charsize_"),-1);\r
+       sq_pushinteger(v,sizeof(SQChar));\r
+       sq_createslot(v,-3);\r
+       sq_pop(v,1);\r
+}\r
+\r
+static int default_delegate_len(HSQUIRRELVM v)\r
+{\r
+       v->Push(SQInteger(sq_getsize(v,1)));\r
+       return 1;\r
+}\r
+\r
+static int default_delegate_tofloat(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,1);\r
+       switch(type(o)){\r
+       case OT_STRING:{\r
+               SQObjectPtr res;\r
+               if(str2num(_stringval(o),res)){\r
+                       v->Push(SQObjectPtr(tofloat(res)));\r
+                       break;\r
+               }}\r
+       case OT_INTEGER:case OT_FLOAT:\r
+               v->Push(SQObjectPtr(tofloat(o)));\r
+               break;\r
+       case OT_BOOL:\r
+               v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));\r
+               break;\r
+       default:\r
+               v->Push(_null_);\r
+               break;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int default_delegate_tointeger(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,1);\r
+       switch(type(o)){\r
+       case OT_STRING:{\r
+               SQObjectPtr res;\r
+               if(str2num(_stringval(o),res)){\r
+                       v->Push(SQObjectPtr(tointeger(res)));\r
+                       break;\r
+               }}\r
+       case OT_INTEGER:case OT_FLOAT:\r
+               v->Push(SQObjectPtr(tointeger(o)));\r
+               break;\r
+       case OT_BOOL:\r
+               v->Push(SQObjectPtr(_integer(o)?1:0));\r
+               break;\r
+       default:\r
+               v->Push(_null_);\r
+               break;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int default_delegate_tostring(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o=stack_get(v,1);\r
+       switch(type(o)){\r
+       case OT_STRING:\r
+               v->Push(o);\r
+               break;\r
+       case OT_INTEGER:\r
+               scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));\r
+               v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));\r
+               break;\r
+       case OT_FLOAT:\r
+               scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%.14g"),_float(o));\r
+               v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));\r
+               break;\r
+       case OT_BOOL:\r
+               v->Push(SQObjectPtr(SQString::Create(_ss(v),_integer(o)?_SC("true"):_SC("false"))));\r
+               break;\r
+       default:\r
+               v->Push(_null_);\r
+               break;\r
+       }\r
+       return 1;\r
+}\r
+\r
+static int number_delegate_tochar(HSQUIRRELVM v)\r
+{\r
+       SQObject &o=stack_get(v,1);\r
+       SQChar c=tointeger(o);\r
+       v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));\r
+       return 1;\r
+}\r
+\r
+\r
+/////////////////////////////////////////////////////////////////\r
+//TABLE DEFAULT DELEGATE\r
+\r
+static int table_rawdelete(HSQUIRRELVM v)\r
+{\r
+       if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))\r
+               return SQ_ERROR;\r
+       return 1;\r
+}\r
+\r
+\r
+static int container_rawexists(HSQUIRRELVM v)\r
+{\r
+       if(SQ_SUCCEEDED(sq_rawget(v,-2))) {\r
+               sq_pushbool(v,SQTrue);\r
+               return 1;\r
+       }\r
+       sq_pushbool(v,SQFalse);\r
+       return 1;\r
+}\r
+\r
+static int table_rawset(HSQUIRRELVM v)\r
+{\r
+       return sq_rawset(v,-3);\r
+}\r
+\r
+\r
+static int table_rawget(HSQUIRRELVM v)\r
+{\r
+       return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
+}\r
+\r
+SQRegFunction SQSharedState::_table_default_delegate_funcz[]={\r
+       {_SC("len"),default_delegate_len,1, _SC("t")},\r
+       {_SC("rawget"),table_rawget,2, _SC("t")},\r
+       {_SC("rawset"),table_rawset,3, _SC("t")},\r
+       {_SC("rawdelete"),table_rawdelete,2, _SC("t")},\r
+       {_SC("rawin"),container_rawexists,2, _SC("t")},\r
+       {0,0}\r
+};\r
+\r
+//ARRAY DEFAULT DELEGATE///////////////////////////////////////\r
+\r
+static int array_append(HSQUIRRELVM v)\r
+{\r
+       return sq_arrayappend(v,-2);\r
+}\r
+\r
+static int array_extend(HSQUIRRELVM v)\r
+{\r
+       _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));\r
+       return 0;\r
+}\r
+\r
+static int array_reverse(HSQUIRRELVM v)\r
+{\r
+       return sq_arrayreverse(v,-1);\r
+}\r
+\r
+static int array_pop(HSQUIRRELVM v)\r
+{\r
+       return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;\r
+}\r
+\r
+static int array_top(HSQUIRRELVM v)\r
+{\r
+       SQObject &o=stack_get(v,1);\r
+       if(_array(o)->Size()>0){\r
+               v->Push(_array(o)->Top());\r
+               return 1;\r
+       }\r
+       else return sq_throwerror(v,_SC("top() on a empty array"));\r
+}\r
+\r
+static int array_insert(HSQUIRRELVM v)\r
+{\r
+       SQObject &o=stack_get(v,1);\r
+       SQObject &idx=stack_get(v,2);\r
+       SQObject &val=stack_get(v,3);\r
+       _array(o)->Insert(idx,val);\r
+       return 0;\r
+}\r
+\r
+static int array_remove(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v, 1);\r
+       SQObject &idx = stack_get(v, 2);\r
+       if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));\r
+       SQObjectPtr val;\r
+       if(_array(o)->Get(tointeger(idx), val)) {\r
+               _array(o)->Remove(tointeger(idx));\r
+               v->Push(val);\r
+               return 1;\r
+       }\r
+       return sq_throwerror(v, _SC("idx out of range"));\r
+}\r
+\r
+static int array_resize(HSQUIRRELVM v)\r
+{\r
+       SQObject &o = stack_get(v, 1);\r
+       SQObject &nsize = stack_get(v, 2);\r
+       SQObjectPtr fill;\r
+       if(sq_isnumeric(nsize)) {\r
+               if(sq_gettop(v) > 2)\r
+                       fill = stack_get(v, 3);\r
+               _array(o)->Resize(tointeger(nsize),fill);\r
+               return 0;\r
+       }\r
+       return sq_throwerror(v, _SC("size must be a number"));\r
+}\r
+\r
+\r
+//QSORT ala Sedgewick\r
+bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,int func,int &ret)\r
+{\r
+       if(func < 0) {\r
+               if(!v->ObjCmp(a,b,ret)) return false;\r
+       }\r
+       else {\r
+               int top = sq_gettop(v);\r
+               sq_push(v, func);\r
+               sq_pushroottable(v);\r
+               v->Push(a);\r
+               v->Push(b);\r
+               if(SQ_FAILED(sq_call(v, 3, SQTrue))) {\r
+                       v->Raise_Error(_SC("compare func failed"));\r
+                       return false;\r
+               }\r
+               sq_getinteger(v, -1, &ret);\r
+               sq_settop(v, top);\r
+               return true;\r
+       }\r
+       return true;\r
+}\r
+//QSORT ala Sedgewick\r
+bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, int l, int r,int func)\r
+{\r
+       int i, j;\r
+       SQArray *a=_array(arr);\r
+       SQObjectPtr pivot,t;\r
+       if( l < r ){\r
+               pivot = a->_values[l];\r
+               i = l; j = r+1;\r
+               while(1){\r
+                       int ret;\r
+                       do { \r
+                               ++i; \r
+                               if(i > r) break;\r
+                               if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))\r
+                                       return false;\r
+                       } while( ret <= 0);\r
+                       do {\r
+                               --j; \r
+                               if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))\r
+                                       return false;\r
+                       }\r
+                       while( ret > 0 );\r
+                       if( i >= j ) break;\r
+                       t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;\r
+               }\r
+               t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;\r
+               if(!_qsort( v, arr, l, j-1,func)) return false;\r
+               if(!_qsort( v, arr, j+1, r,func)) return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+static int array_sort(HSQUIRRELVM v)\r
+{\r
+       //SQ_TRY {\r
+       int func = -1;\r
+       SQObjectPtr &o = stack_get(v,1);\r
+       SQObject &funcobj = stack_get(v,2);\r
+       if(_array(o)->Size() > 1) {\r
+               if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;\r
+               if(!_qsort(v, o, 0, _array(o)->Size()-1, func))\r
+                       return SQ_ERROR;\r
+\r
+       }\r
+       return 0;\r
+}\r
+static int array_slice(HSQUIRRELVM v)\r
+{\r
+       int sidx,eidx;\r
+       SQObjectPtr o;\r
+       if(get_slice_params(v,sidx,eidx,o)==-1)return -1;\r
+       if(sidx<0)sidx=_array(o)->Size()+sidx;\r
+       if(eidx<0)eidx=_array(o)->Size()+eidx;\r
+       if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));\r
+       SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);\r
+       SQObjectPtr t;\r
+       int count=0;\r
+       for(int i=sidx;i<eidx;i++){\r
+               _array(o)->Get(i,t);\r
+               arr->Set(count++,t);\r
+       }\r
+       v->Push(arr);\r
+       return 1;\r
+       \r
+}\r
+\r
+SQRegFunction SQSharedState::_array_default_delegate_funcz[]={\r
+       {_SC("len"),default_delegate_len,1, _SC("a")},\r
+       {_SC("append"),array_append,2, _SC("a")},\r
+       {_SC("extend"),array_extend,2, _SC("aa")},\r
+       {_SC("push"),array_append,2, _SC("a")},\r
+       {_SC("pop"),array_pop,1, _SC("a")},\r
+       {_SC("top"),array_top,1, _SC("a")},\r
+       {_SC("insert"),array_insert,3, _SC("an")},\r
+       {_SC("remove"),array_remove,2, _SC("an")},\r
+       {_SC("resize"),array_resize,-2, _SC("an")},\r
+       {_SC("reverse"),array_reverse,1, _SC("a")},\r
+       {_SC("sort"),array_sort,-1, _SC("ac")},\r
+       {_SC("slice"),array_slice,-1, _SC("ann")},\r
+       {0,0}\r
+};\r
+\r
+//STRING DEFAULT DELEGATE//////////////////////////\r
+static int string_slice(HSQUIRRELVM v)\r
+{\r
+       int sidx,eidx;\r
+       SQObjectPtr o;\r
+       if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;\r
+       if(sidx<0)sidx=_string(o)->_len+sidx;\r
+       if(eidx<0)eidx=_string(o)->_len+eidx;\r
+       if(eidx<sidx)\r
+               return sq_throwerror(v,_SC("wrong indexes"));\r
+       v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));\r
+       return 1;\r
+}\r
+\r
+static int string_find(HSQUIRRELVM v)\r
+{\r
+       int top,start_idx=0;\r
+       const SQChar *str,*substr,*ret;\r
+       if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){\r
+               if(top>2)sq_getinteger(v,3,&start_idx);\r
+               if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){\r
+                       ret=scstrstr(&str[start_idx],substr);\r
+                       if(ret){\r
+                               sq_pushinteger(v,(int)(ret-str));\r
+                               return 1;\r
+                       }\r
+               }\r
+               return 0;\r
+       }\r
+       return sq_throwerror(v,_SC("invalid param"));\r
+}\r
+\r
+#define STRING_TOFUNCZ(func) static int string_##func(HSQUIRRELVM v) \\r
+{ \\r
+       SQObject str=stack_get(v,1); \\r
+       int len=_string(str)->_len; \\r
+       const SQChar *sThis=_stringval(str); \\r
+       SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \\r
+       for(int i=0;i<len;i++) sNew[i]=func(sThis[i]); \\r
+       v->Push(SQString::Create(_ss(v),sNew,len)); \\r
+       return 1; \\r
+}\r
+\r
+\r
+STRING_TOFUNCZ(tolower)\r
+STRING_TOFUNCZ(toupper)\r
+\r
+SQRegFunction SQSharedState::_string_default_delegate_funcz[]={\r
+       {_SC("len"),default_delegate_len,1, _SC("s")},\r
+       {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},\r
+       {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},\r
+       {_SC("tostring"),default_delegate_tostring,1, _SC("s")},\r
+       {_SC("slice"),string_slice,-1, _SC(" s n  n")},\r
+       {_SC("find"),string_find,-2, _SC("s s n ")},\r
+       {_SC("tolower"),string_tolower,1, _SC("s")},\r
+       {_SC("toupper"),string_toupper,1, _SC("s")},\r
+       {0,0}\r
+};\r
+\r
+//INTEGER DEFAULT DELEGATE//////////////////////////\r
+SQRegFunction SQSharedState::_number_default_delegate_funcz[]={\r
+       {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},\r
+       {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},\r
+       {_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},\r
+       {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},\r
+       {0,0}\r
+};\r
+\r
+//CLOSURE DEFAULT DELEGATE//////////////////////////\r
+static int closure_call(HSQUIRRELVM v)\r
+{\r
+       return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue))?1:SQ_ERROR;\r
+}\r
+\r
+static int closure_acall(HSQUIRRELVM v)\r
+{\r
+       SQArray *aparams=_array(stack_get(v,2));\r
+       int nparams=aparams->Size();\r
+       v->Push(stack_get(v,1));\r
+       for(int i=0;i<nparams;i++)v->Push(aparams->_values[i]);\r
+       return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue))?1:SQ_ERROR;\r
+}\r
+\r
+SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
+       {_SC("call"),closure_call,-1, _SC("c")},\r
+       {_SC("acall"),closure_acall,2, _SC("ca")},\r
+       {0,0}\r
+};\r
+\r
+//GENERATOR DEFAULT DELEGATE\r
+static int generator_getstatus(HSQUIRRELVM v)\r
+{\r
+       SQObject &o=stack_get(v,1);\r
+       switch(_generator(o)->_state){\r
+               case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;\r
+               case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;\r
+               case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;\r
+       }\r
+       return 1;\r
+}\r
+\r
+SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={\r
+       {_SC("getstatus"),generator_getstatus,1, _SC("g")},\r
+       {0,0}\r
+};\r
+\r
+//THREAD DEFAULT DELEGATE\r
+\r
+static int thread_call(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr o = stack_get(v,1);\r
+       if(type(o) == OT_THREAD) {\r
+               int nparams = sq_gettop(v);\r
+               _thread(o)->Push(_thread(o)->_roottable);\r
+               for(int i = 2; i<(nparams+1); i++)\r
+                       sq_move(_thread(o),v,i);\r
+               if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue))) {\r
+                       sq_move(v,_thread(o),-1);\r
+                       return 1;\r
+               }\r
+               return SQ_ERROR;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong parameter"));\r
+}\r
+\r
+static int thread_wakeup(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr o = stack_get(v,1);\r
+       if(type(o) == OT_THREAD) {\r
+               SQVM *thread = _thread(o);\r
+               int state = sq_getvmstate(thread);\r
+               if(state != SQ_VMSTATE_SUSPENDED) {\r
+                       switch(state) {\r
+                               case SQ_VMSTATE_IDLE:\r
+                                       return sq_throwerror(v,_SC("cannot wakeup a idle thread"));\r
+                               break;\r
+                               case SQ_VMSTATE_RUNNING:\r
+                                       return sq_throwerror(v,_SC("cannot wakeup a running thread"));\r
+                               break;\r
+                       }\r
+               }\r
+                       \r
+               int wakeupret = sq_gettop(v)>1?1:0;\r
+               if(wakeupret) {\r
+                       sq_move(thread,v,2);\r
+               }\r
+               if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1))) {\r
+                       sq_move(v,thread,-1);\r
+                       sq_pop(thread,1);\r
+                       if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {\r
+                               sq_pop(thread,1);\r
+                       }\r
+                       return 1;\r
+               }\r
+               return SQ_ERROR;\r
+       }\r
+       return sq_throwerror(v,_SC("wrong parameter"));\r
+}\r
+\r
+static int thread_getstatus(HSQUIRRELVM v)\r
+{\r
+       SQObjectPtr &o = stack_get(v,1);\r
+       switch(sq_getvmstate(_thread(o))) {\r
+               case SQ_VMSTATE_IDLE:\r
+                       sq_pushstring(v,_SC("idle"),-1);\r
+               break;\r
+               case SQ_VMSTATE_RUNNING:\r
+                       sq_pushstring(v,_SC("running"),-1);\r
+               break;\r
+               case SQ_VMSTATE_SUSPENDED:\r
+                       sq_pushstring(v,_SC("suspended"),-1);\r
+               break;\r
+               default:\r
+                       return sq_throwerror(v,_SC("internal VM error"));\r
+       }\r
+       return 1;\r
+}\r
+\r
+SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {\r
+       {_SC("call"), thread_call, -1, _SC("v")},\r
+       {_SC("wakeup"), thread_wakeup, -1, _SC("v")},\r
+       {_SC("getstatus"), thread_getstatus, 1, _SC("v")},\r
+       {0,0},\r
+};\r
+\r
+static int class_getattributes(HSQUIRRELVM v)\r
+{\r
+       if(SQ_SUCCEEDED(sq_getattributes(v,-2)))\r
+               return 1;\r
+       return SQ_ERROR;\r
+}\r
+\r
+static int class_setattributes(HSQUIRRELVM v)\r
+{\r
+       if(SQ_SUCCEEDED(sq_setattributes(v,-3)))\r
+               return 1;\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {\r
+       {_SC("getattributes"), class_getattributes, 2, _SC("y.")},\r
+       {_SC("setattributes"), class_setattributes, 3, _SC("y..")},\r
+       {_SC("rawin"),container_rawexists,2, _SC("y")},\r
+       {0,0}\r
+};\r
+\r
+static int instance_getclass(HSQUIRRELVM v)\r
+{\r
+       if(SQ_SUCCEEDED(sq_getclass(v,1)))\r
+               return 1;\r
+       return SQ_ERROR;\r
+}\r
+\r
+SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {\r
+       {_SC("getclass"), instance_getclass, 1, _SC("x")},\r
+       {_SC("rawin"),container_rawexists,2, _SC("x")},\r
+       {0,0}\r
+};\r
+\r
diff --git a/src/squirrel/squirrel/sqclass.cpp b/src/squirrel/squirrel/sqclass.cpp
new file mode 100644 (file)
index 0000000..b9dcd9e
--- /dev/null
@@ -0,0 +1,184 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqtable.h"\r
+#include "sqclass.h"\r
+#include "sqclosure.h"\r
+\r
+SQClass::SQClass(SQSharedState *ss,SQClass *base)\r
+{\r
+       _uiRef=0;\r
+       _base = base;\r
+       _typetag = 0;\r
+       _metamethods.resize(MT_LAST); //size it to max size\r
+       if(_base) {\r
+               _defaultvalues.copy(base->_defaultvalues);\r
+               _methods.copy(base->_methods);\r
+               _metamethods.copy(base->_metamethods);\r
+               __ObjAddRef(_base);\r
+       }\r
+       _members = base?base->_members->Clone() : SQTable::Create(ss,0);\r
+       __ObjAddRef(_members);\r
+       _locked = false;\r
+       INIT_CHAIN();\r
+       ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
+}\r
+\r
+void SQClass::Finalize() { \r
+       _attributes = _null_;\r
+       _defaultvalues.resize(0);\r
+       _methods.resize(0);\r
+       _metamethods.resize(0);\r
+       __ObjRelease(_members);\r
+       if(_base) {\r
+               __ObjRelease(_base);\r
+       }\r
+}\r
+\r
+SQClass::~SQClass()\r
+{\r
+       REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
+       Finalize();\r
+}\r
+\r
+bool SQClass::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       SQObjectPtr temp;\r
+       if(_locked) \r
+               return false; //the slot already exists\r
+       if(_members->Get(key,temp) && type(temp) == OT_INTEGER) //overrides the default value\r
+       {\r
+               _defaultvalues[_integer(temp)].val = val;\r
+               return true;\r
+       }\r
+       if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) {\r
+               SQInteger mmidx;\r
+               if((mmidx = _sharedstate->GetMetaMethodIdxByName(key)) != -1) {\r
+                       _metamethods[mmidx] = val;\r
+               } \r
+               else {\r
+                       if(type(temp) == OT_NULL) {\r
+                               SQClassMemeber m;\r
+                               m.val = val;\r
+                               _members->NewSlot(key,SQObjectPtr((SQUserPointer)_methods.size()));\r
+                               _methods.push_back(m);\r
+                       }\r
+                       else {\r
+                               _methods[(int)_userpointer(temp)].val = val;\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
+       SQClassMemeber m;\r
+       m.val = val;\r
+       _members->NewSlot(key,SQObjectPtr((SQInteger)_defaultvalues.size()));\r
+       _defaultvalues.push_back(m);\r
+       return true;\r
+}\r
+\r
+SQInstance *SQClass::CreateInstance()\r
+{\r
+       if(!_locked) Lock();\r
+       return SQInstance::Create(_opt_ss(this),this);\r
+}\r
+\r
+int SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+       SQObjectPtr oval;\r
+       int idx = _members->Next(refpos,outkey,oval);\r
+       if(idx != -1) {\r
+               if(type(oval) != OT_INTEGER) {\r
+                       outval = _methods[(int)_userpointer(oval)].val;\r
+               }\r
+               else {\r
+                       outval = _defaultvalues[_integer(oval)].val;\r
+               }\r
+       }\r
+       return idx;\r
+}\r
+\r
+bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       SQObjectPtr idx;\r
+       if(_members->Get(key,idx)) {\r
+               if(type(idx) == OT_INTEGER)\r
+                       _defaultvalues[_integer(idx)].attrs = val;\r
+               else\r
+                       _methods[(int)_userpointer(idx)].attrs = val;\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)\r
+{\r
+       SQObjectPtr idx;\r
+       if(_members->Get(key,idx)) {\r
+               outval = (type(idx) == OT_INTEGER?_defaultvalues[_integer(idx)].attrs:_methods[(int)_userpointer(idx)].attrs);\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////\r
+void SQInstance::Init(SQSharedState *ss)\r
+{\r
+       _uiRef = 0;\r
+       _userpointer = NULL;\r
+       _hook = NULL;\r
+       __ObjAddRef(_class);\r
+       _delegate = _class->_members;\r
+       INIT_CHAIN();\r
+       ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
+}\r
+\r
+SQInstance::SQInstance(SQSharedState *ss, SQClass *c)\r
+{\r
+       _class = c;\r
+       _values.resize(_class->_defaultvalues.size());\r
+       for(unsigned int i = 0; i < _class->_defaultvalues.size(); i++) {\r
+               _values[i] = _class->_defaultvalues[i].val;\r
+       }\r
+       Init(ss);\r
+}\r
+\r
+SQInstance::SQInstance(SQSharedState *ss, SQInstance *i)\r
+{\r
+       _class = i->_class;\r
+       _values.copy(i->_values);\r
+       Init(ss);\r
+}\r
+\r
+void SQInstance::Finalize() \r
+{\r
+       __ObjRelease(_class);\r
+       _values.resize(0);\r
+}\r
+\r
+SQInstance::~SQInstance()\r
+{\r
+       REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
+       Finalize();\r
+}\r
+\r
+bool SQInstance::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res)\r
+{\r
+       if(type(_class->_metamethods[mm]) != OT_NULL) {\r
+               res = _class->_metamethods[mm];\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQInstance::InstanceOf(SQClass *trg)\r
+{\r
+       SQClass *parent = _class;\r
+       while(parent != NULL) {\r
+               if(parent == trg)\r
+                       return true;\r
+               parent = parent->_base;\r
+       }\r
+       return false;\r
+}\r
diff --git a/src/squirrel/squirrel/sqclass.h b/src/squirrel/squirrel/sqclass.h
new file mode 100644 (file)
index 0000000..b510f26
--- /dev/null
@@ -0,0 +1,104 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQCLASS_H_\r
+#define _SQCLASS_H_\r
+\r
+struct SQInstance;\r
+\r
+struct SQClassMemeber {\r
+       SQClassMemeber(){}\r
+       SQClassMemeber(const SQClassMemeber &o) {\r
+               val = o.val;\r
+               attrs = o.attrs;\r
+       }\r
+       SQObjectPtr val;\r
+       SQObjectPtr attrs;\r
+};\r
+\r
+typedef sqvector<SQClassMemeber> SQClassMemeberVec;\r
+\r
+struct SQClass : public CHAINABLE_OBJ\r
+{\r
+       SQClass(SQSharedState *ss,SQClass *base);\r
+public:\r
+       static SQClass* Create(SQSharedState *ss,SQClass *base) {\r
+               SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));\r
+               new (newclass) SQClass(ss, base);\r
+               return newclass;\r
+       }\r
+       ~SQClass();\r
+       bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);\r
+       bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
+               if(_members->Get(key,val)) {\r
+                       val = (type(val) == OT_INTEGER?_defaultvalues[_integer(val)].val:_methods[(int)_userpointer(val)].val);\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+       bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);\r
+       bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);\r
+       void Lock() { _locked = true; if(_base) _base->Lock(); }\r
+       void Release() { sq_delete(this, SQClass);      }\r
+       void Finalize();\r
+       void Mark(SQCollectable ** );\r
+       int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+       SQInstance *CreateInstance();\r
+       SQTable *_members;\r
+       //SQTable *_properties;\r
+       SQClass *_base;\r
+       SQClassMemeberVec _defaultvalues;\r
+       SQClassMemeberVec _methods;\r
+       SQObjectPtrVec _metamethods;\r
+       SQObjectPtr _attributes;\r
+       unsigned int _typetag;\r
+       bool _locked;\r
+};\r
+\r
+struct SQInstance : public SQDelegable \r
+{\r
+       void Init(SQSharedState *ss);\r
+       SQInstance(SQSharedState *ss, SQClass *c);\r
+       SQInstance(SQSharedState *ss, SQInstance *c);\r
+public:\r
+       static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {\r
+               SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));\r
+               new (newinst) SQInstance(ss, theclass);\r
+               return newinst;\r
+       }\r
+       SQInstance *Clone(SQSharedState *ss)\r
+       {\r
+               SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));\r
+               new (newinst) SQInstance(ss, this);\r
+               return newinst;\r
+       }\r
+       ~SQInstance();\r
+       bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {\r
+               if(_class->_members->Get(key,val)) {\r
+                       val = (type(val) == OT_INTEGER?_values[_integer(val)]:_class->_methods[(int)_userpointer(val)].val);\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+       bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {\r
+               SQObjectPtr idx;\r
+               if(_class->_members->Get(key,idx) && type(idx) == OT_INTEGER) {\r
+            _values[_integer(idx)] = val;\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+       void Release() { \r
+               if (_hook) { _hook(_userpointer,0);}\r
+               sq_delete(this, SQInstance);\r
+       }\r
+       void Finalize();\r
+       void Mark(SQCollectable ** );\r
+       bool InstanceOf(SQClass *trg);\r
+       bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);\r
+\r
+       SQClass *_class;\r
+       SQUserPointer _userpointer;\r
+       SQRELEASEHOOK _hook;\r
+       SQObjectPtrVec _values;\r
+};\r
+\r
+#endif //_SQCLASS_H_\r
diff --git a/src/squirrel/squirrel/sqclosure.h b/src/squirrel/squirrel/sqclosure.h
new file mode 100644 (file)
index 0000000..724019a
--- /dev/null
@@ -0,0 +1,101 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQCLOSURE_H_\r
+#define _SQCLOSURE_H_\r
+\r
+struct SQFunctionProto;\r
+\r
+struct SQClosure : public CHAINABLE_OBJ\r
+{\r
+private:\r
+       SQClosure(SQSharedState *ss,SQFunctionProto *func){_uiRef=0;_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
+public:\r
+       static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){\r
+               SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));\r
+               new (nc) SQClosure(ss,func);\r
+               return nc;\r
+       }\r
+       void Release(){\r
+               sq_delete(this,SQClosure);\r
+       }\r
+       ~SQClosure()\r
+       {\r
+               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+       }\r
+       bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
+       bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize(){_outervalues.resize(0); }\r
+#endif\r
+       SQObjectPtr _function;\r
+       SQObjectPtrVec _outervalues;\r
+};\r
+//////////////////////////////////////////////\r
+struct SQGenerator : public CHAINABLE_OBJ \r
+{\r
+       enum SQGeneratorState{eRunning,eSuspended,eDead};\r
+private:\r
+       SQGenerator(SQSharedState *ss,SQClosure *closure){_uiRef=0;_closure=closure;_state=eRunning;_ci._generator=_null_;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
+public:\r
+       static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){\r
+               SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));\r
+               new (nc) SQGenerator(ss,closure);\r
+               return nc;\r
+       }\r
+       ~SQGenerator()\r
+       {\r
+               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+       }\r
+    void Kill(){\r
+               _state=eDead;\r
+               _stack.resize(0);\r
+               _closure=_null_;}\r
+       void Release(){\r
+               sq_delete(this,SQGenerator);\r
+       }\r
+       bool Yield(SQVM *v);\r
+       bool Resume(SQVM *v,int target);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize(){_stack.resize(0);_closure=_null_;}\r
+#endif\r
+       SQObjectPtr _closure;\r
+       SQObjectPtrVec _stack;\r
+       SQObjectPtrVec _vargsstack;\r
+       SQVM::CallInfo _ci;\r
+       ExceptionsTraps _etraps;\r
+       SQGeneratorState _state;\r
+};\r
+\r
+struct SQNativeClosure : public CHAINABLE_OBJ\r
+{\r
+private:\r
+       SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_uiRef=0;_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);       }\r
+public:\r
+       static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)\r
+       {\r
+               SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));\r
+               new (nc) SQNativeClosure(ss,func);\r
+               return nc;\r
+       }\r
+       ~SQNativeClosure()\r
+       {\r
+               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+       }\r
+       void Release(){\r
+               sq_delete(this,SQNativeClosure);\r
+       }\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize(){_outervalues.resize(0);}\r
+#endif\r
+       SQFUNCTION _function;\r
+       SQObjectPtr _name;\r
+       SQObjectPtrVec _outervalues;\r
+       SQIntVec _typecheck;\r
+       int _nparamscheck;\r
+};\r
+\r
+\r
+\r
+#endif //_SQCLOSURE_H_\r
diff --git a/src/squirrel/squirrel/sqcompiler.cpp b/src/squirrel/squirrel/sqcompiler.cpp
new file mode 100644 (file)
index 0000000..116bac8
--- /dev/null
@@ -0,0 +1,1188 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include <stdarg.h>\r
+#include "sqopcodes.h"\r
+#include "sqstring.h"\r
+#include "sqfuncproto.h"\r
+#include "sqfuncstate.h"\r
+#include "sqcompiler.h"\r
+#include "sqlexer.h"\r
+#include "sqvm.h"\r
+\r
+#define DEREF_NO_DEREF -1\r
+#define DEREF_FIELD            -2\r
+\r
+struct ExpState\r
+{\r
+       ExpState()\r
+       {\r
+               _deref = DEREF_NO_DEREF;\r
+               _freevar = false;\r
+               _class_or_delete = false;\r
+               _funcarg = false;\r
+       }\r
+       bool _class_or_delete;\r
+       bool _funcarg;\r
+       bool _freevar;\r
+       int _deref;\r
+};\r
+\r
+typedef sqvector<ExpState> ExpStateVec;\r
+\r
+#define _exst (_expstates.top())\r
+\r
+#define BEGIN_BREAKBLE_BLOCK() int __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
+                                                       int __ncontinues__=_fs->_unresolvedcontinues.size(); \\r
+                                                       _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);\r
+\r
+#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \\r
+                                       __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \\r
+                                       if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \\r
+                                       if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \\r
+                                       _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}\r
+\r
+class SQCompiler\r
+{\r
+public:\r
+       SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)\r
+       {\r
+               _vm=v;\r
+               _lex.Init(_ss(v), rg, up);\r
+               _sourcename = SQString::Create(_ss(v), sourcename);\r
+               _lineinfo = lineinfo;_raiseerror = raiseerror;\r
+       }\r
+       void Error(const SQChar *s, ...)\r
+       {\r
+               static SQChar temp[256];\r
+               va_list vl;\r
+               va_start(vl, s);\r
+               scvsprintf(temp, s, vl);\r
+               va_end(vl);\r
+               throw ParserException(temp);\r
+       }\r
+       void Lex(){     _token = _lex.Lex();}\r
+       void PushExpState(){ _expstates.push_back(ExpState()); }\r
+       bool IsDerefToken(int tok)\r
+       {\r
+               switch(tok){\r
+               case _SC('='): case _SC('('): case TK_NEWSLOT:\r
+               case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;\r
+               }\r
+               return false;\r
+       }\r
+       ExpState PopExpState()\r
+       {\r
+               ExpState ret = _expstates.top();\r
+               _expstates.pop_back();\r
+               return ret;\r
+       }\r
+       SQObjectPtr Expect(int tok)\r
+       {\r
+               SQObjectPtr ret;\r
+               if(_token != tok) {\r
+                       if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {\r
+                               //ret = SQString::Create(_ss(_vm),_SC("constructor"));\r
+                               //do nothing\r
+                       }\r
+                       else {\r
+                               if(tok > 255) {\r
+                                       switch(tok)\r
+                                       {\r
+                                       case TK_IDENTIFIER:\r
+                                               ret = SQString::Create(_ss(_vm), _SC("IDENTIFIER"));\r
+                                               break;\r
+                                       case TK_STRING_LITERAL:\r
+                                               ret = SQString::Create(_ss(_vm), _SC("STRING_LITERAL"));\r
+                                               break;\r
+                                       case TK_INTEGER:\r
+                                               ret = SQString::Create(_ss(_vm), _SC("INTEGER"));\r
+                                               break;\r
+                                       case TK_FLOAT:\r
+                                               ret = SQString::Create(_ss(_vm), _SC("FLOAT"));\r
+                                               break;\r
+                                       default:\r
+                                               ret = _lex.Tok2Str(tok);\r
+                                       }\r
+                                       Error(_SC("expected '%s'"), _stringval(ret));\r
+                               }\r
+                               Error(_SC("expected '%c'"), tok);\r
+                       }\r
+               }\r
+               switch(tok)\r
+               {\r
+               case TK_IDENTIFIER:\r
+                       ret = SQString::Create(_ss(_vm), _lex._svalue);\r
+                       break;\r
+               case TK_STRING_LITERAL:\r
+                       ret = SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1);\r
+                       break;\r
+               case TK_INTEGER:\r
+                       ret = _lex._nvalue;\r
+                       break;\r
+               case TK_FLOAT:\r
+                       ret = _lex._fvalue;\r
+                       break;\r
+               }\r
+               Lex();\r
+               return ret;\r
+       }\r
+       bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }\r
+       void OptionalSemicolon()\r
+       {\r
+               if(_token == _SC(';')) { Lex(); return; }\r
+               if(!IsEndOfStatement()) {\r
+                       Error(_SC("end of statement expected (; or lf)"));\r
+               }\r
+       }\r
+       void MoveIfCurrentTargetIsLocal() {\r
+               int trg = _fs->TopTarget();\r
+               if(_fs->IsLocal(trg)) {\r
+                       trg = _fs->PopTarget(); //no pops the target and move it\r
+                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);\r
+               }\r
+       }\r
+       bool Compile(SQObjectPtr &o)\r
+       {\r
+               SQ_TRY {\r
+                       _debugline = 1;\r
+                       _debugop = 0;\r
+                       Lex();\r
+                       SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), NULL);\r
+                       _funcproto(funcstate._func)->_name = SQString::Create(_ss(_vm), _SC("main"));\r
+                       _fs = &funcstate;\r
+                       _fs->AddParameter(SQString::Create(_ss(_vm), _SC("this")));\r
+                       _funcproto(_fs->_func)->_sourcename = _sourcename;\r
+                       int stacksize = _fs->GetStackSize();\r
+                       while(_token > 0){\r
+                               Statement();\r
+                               if(_lex._prevtoken != _SC('}')) OptionalSemicolon();\r
+                       }\r
+                       CleanStack(stacksize);\r
+                       _fs->AddLineInfos(_lex._currentline, _lineinfo, true);\r
+                       _fs->AddInstruction(_OP_RETURN, 0xFF);\r
+                       _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;\r
+                       _fs->SetStackSize(0);\r
+                       _fs->Finalize();\r
+                       o = _fs->_func;\r
+#ifdef _DEBUG_DUMP\r
+                       _fs->Dump();\r
+#endif\r
+               }\r
+               SQ_CATCH(ParserException,ex){\r
+                       if(_raiseerror && _ss(_vm)->_compilererrorhandler){\r
+                               SQObjectPtr ret;\r
+                               _ss(_vm)->_compilererrorhandler(_vm, ex.desc, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
+                                       _lex._currentline, _lex._currentcolumn);\r
+                       }\r
+                       _vm->_lasterror = SQString::Create(_ss(_vm), ex.desc, -1);\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+       void Statements()\r
+       {\r
+               while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {\r
+                       Statement();\r
+                       if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
+               }\r
+       }\r
+       void Statement()\r
+       {\r
+               _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
+               switch(_token){\r
+               case _SC(';'):  Lex();                                  break;\r
+               case TK_IF:             IfStatement();                  break;\r
+               case TK_WHILE:          WhileStatement();               break;\r
+               case TK_DO:             DoWhileStatement();             break;\r
+               case TK_FOR:            ForStatement();                 break;\r
+               case TK_FOREACH:        ForEachStatement();             break;\r
+               case TK_SWITCH: SwitchStatement();              break;\r
+               case TK_LOCAL:          LocalDeclStatement();   break;\r
+               case TK_RETURN:\r
+               case TK_YIELD: {\r
+                       SQOpcode op;\r
+                       if(_token == TK_RETURN) {\r
+                               op = _OP_RETURN;\r
+                               \r
+                       }\r
+                       else {\r
+                               op = _OP_YIELD;\r
+                               _funcproto(_fs->_func)->_bgenerator = true;\r
+                       }\r
+                       Lex();\r
+                       if(!IsEndOfStatement()) {\r
+                               int retexp = _fs->GetCurrentPos()+1;\r
+                               CommaExpr();\r
+                               if(op == _OP_RETURN && _fs->_traps > 0)\r
+                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);\r
+                               _fs->_returnexp = retexp;\r
+                               _fs->AddInstruction(op, 1, _fs->PopTarget());\r
+                       }\r
+                       else{ \r
+                               if(op == _OP_RETURN && _fs->_traps > 0)\r
+                                       _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);\r
+                               _fs->_returnexp = -1;\r
+                               _fs->AddInstruction(op, 0xFF); \r
+                       }\r
+                       break;}\r
+               case TK_BREAK:\r
+                       if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));\r
+                       if(_fs->_breaktargets.top() > 0){\r
+                               _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);\r
+                       }\r
+                       _fs->AddInstruction(_OP_JMP, 0, -1234);\r
+                       _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());\r
+                       Lex();\r
+                       break;\r
+               case TK_CONTINUE:\r
+                       if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));\r
+                       if(_fs->_continuetargets.top() > 0) {\r
+                               _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);\r
+                       }\r
+                       _fs->AddInstruction(_OP_JMP, 0, -1234);\r
+                       _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());\r
+                       Lex();\r
+                       break;\r
+               case TK_FUNCTION:\r
+                       FunctionStatement();\r
+                       break;\r
+               case TK_CLASS:\r
+                       ClassStatement();\r
+                       break;\r
+               case _SC('{'):{\r
+                               int stacksize = _fs->GetStackSize();\r
+                               Lex();\r
+                               Statements();\r
+                               Expect(_SC('}'));\r
+                               _fs->SetStackSize(stacksize);\r
+                       }\r
+                       break;\r
+               case TK_TRY:\r
+                       TryCatchStatement();\r
+                       break;\r
+               case TK_THROW:\r
+                       Lex();\r
+                       CommaExpr();\r
+                       _fs->AddInstruction(_OP_THROW, _fs->PopTarget());\r
+                       break;\r
+               default:\r
+                       CommaExpr();\r
+                       _fs->PopTarget();\r
+                       break;\r
+               }\r
+               _fs->SnoozeOpt();\r
+       }\r
+       void EmitDerefOp(SQOpcode op)\r
+       {\r
+               int val = _fs->PopTarget();\r
+               int key = _fs->PopTarget();\r
+               int src = _fs->PopTarget();\r
+        _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);\r
+       }\r
+       void Emit2ArgsOP(SQOpcode op, int p3 = 0)\r
+       {\r
+               int p2 = _fs->PopTarget(); //src in OP_GET\r
+               int p1 = _fs->PopTarget(); //key in OP_GET\r
+               _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);\r
+       }\r
+       void EmitCompoundArith(int tok,bool deref)\r
+       {\r
+               int oper;\r
+               switch(tok){\r
+               case TK_MINUSEQ: oper = '-'; break;\r
+               case TK_PLUSEQ: oper = '+'; break;\r
+               case TK_MULEQ: oper = '*'; break;\r
+               case TK_DIVEQ: oper = '/'; break;\r
+               case TK_MODEQ: oper = '%'; break;\r
+               default: assert(0); break;\r
+               };\r
+               if(deref) {\r
+                       int val = _fs->PopTarget();\r
+                       int key = _fs->PopTarget();\r
+                       int src = _fs->PopTarget();\r
+                       //mixes dest obj and source val in the arg1(hack?)\r
+                       _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);\r
+               }\r
+               else {\r
+                       Emit2ArgsOP(_OP_COMPARITHL, oper);\r
+               }\r
+       }\r
+       void CommaExpr()\r
+       {\r
+               for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());\r
+       }\r
+       ExpState Expression(bool funcarg = false)\r
+       {\r
+               PushExpState();\r
+               _exst._class_or_delete = false;\r
+               _exst._funcarg = funcarg;\r
+               LogicalOrExp();\r
+               switch(_token)  {\r
+               case _SC('='):\r
+               case TK_NEWSLOT:\r
+               case TK_MINUSEQ:\r
+               case TK_PLUSEQ:\r
+               case TK_MULEQ:\r
+               case TK_DIVEQ:\r
+               case TK_MODEQ:\r
+               {\r
+                               int op = _token;\r
+                               int ds = _exst._deref;\r
+                               bool freevar = _exst._freevar;\r
+                               if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));\r
+                               Lex(); Expression();\r
+\r
+                               switch(op){\r
+                               case TK_NEWSLOT:\r
+                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
+                                       if(ds == DEREF_FIELD)\r
+                                               EmitDerefOp(_OP_NEWSLOT);\r
+                                       else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
+                                               Error(_SC("can't 'create' a local slot"));\r
+                                       break;\r
+                               case _SC('='): //ASSIGN\r
+                                       if(freevar) Error(_SC("free variables cannot be modified"));\r
+                                       if(ds == DEREF_FIELD)\r
+                                               EmitDerefOp(_OP_SET);\r
+                                       else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
+                                               int p2 = _fs->PopTarget(); //src in OP_GET\r
+                                               int p1 = _fs->TopTarget(); //key in OP_GET\r
+                                               _fs->AddInstruction(_OP_MOVE, p1, p2);\r
+                                       }\r
+                                       break;\r
+                               case TK_MINUSEQ:\r
+                               case TK_PLUSEQ:\r
+                               case TK_MULEQ:\r
+                               case TK_DIVEQ:\r
+                               case TK_MODEQ:\r
+                                       EmitCompoundArith(op,ds == DEREF_FIELD);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       break;\r
+               case _SC('?'): {\r
+                       Lex();\r
+                       _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
+                       int jzpos = _fs->GetCurrentPos();\r
+                       int trg = _fs->PushTarget();\r
+                       Expression();\r
+                       int first_exp = _fs->PopTarget();\r
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+                       int endfirstexp = _fs->GetCurrentPos();\r
+                       _fs->AddInstruction(_OP_JMP, 0, 0);\r
+                       Expect(_SC(':'));\r
+                       int jmppos = _fs->GetCurrentPos();\r
+                       Expression();\r
+                       int second_exp = _fs->PopTarget();\r
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
+                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
+                       _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);\r
+                       _fs->SnoozeOpt();\r
+                       }\r
+                       break;\r
+               }\r
+               return PopExpState();\r
+       }\r
+       void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),int op3 = 0)\r
+       {\r
+               Lex(); (this->*f)();\r
+               int op1 = _fs->PopTarget();int op2 = _fs->PopTarget();\r
+               _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);\r
+       }\r
+       void LogicalOrExp()\r
+       {\r
+               LogicalAndExp();\r
+               for(;;) if(_token == TK_OR) {\r
+                       int first_exp = _fs->PopTarget();\r
+                       int trg = _fs->PushTarget();\r
+                       _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);\r
+                       int jpos = _fs->GetCurrentPos();\r
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+                       Lex(); LogicalOrExp();\r
+                       _fs->SnoozeOpt();\r
+                       int second_exp = _fs->PopTarget();\r
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
+                       _fs->SnoozeOpt();\r
+                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
+                       break;\r
+               }else return;\r
+       }\r
+       void LogicalAndExp()\r
+       {\r
+               BitwiseOrExp();\r
+               for(;;) switch(_token) {\r
+               case TK_AND: {\r
+                       int first_exp = _fs->PopTarget();\r
+                       int trg = _fs->PushTarget();\r
+                       _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);\r
+                       int jpos = _fs->GetCurrentPos();\r
+                       if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+                       Lex(); LogicalAndExp();\r
+                       _fs->SnoozeOpt();\r
+                       int second_exp = _fs->PopTarget();\r
+                       if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
+                       _fs->SnoozeOpt();\r
+                       _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
+                       break;\r
+                       }\r
+               case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;\r
+               case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;\r
+               default:\r
+                       return;\r
+               }\r
+       }\r
+       void BitwiseOrExp()\r
+       {\r
+               BitwiseXorExp();\r
+               for(;;) if(_token == _SC('|'))\r
+               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);\r
+               }else return;\r
+       }\r
+       void BitwiseXorExp()\r
+       {\r
+               BitwiseAndExp();\r
+               for(;;) if(_token == _SC('^'))\r
+               {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);\r
+               }else return;\r
+       }\r
+       void BitwiseAndExp()\r
+       {\r
+               CompExp();\r
+               for(;;) if(_token == _SC('&'))\r
+               {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);\r
+               }else return;\r
+       }\r
+       void CompExp()\r
+       {\r
+               ShiftExp();\r
+               for(;;) switch(_token) {\r
+               case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;\r
+               case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;\r
+               case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;\r
+               case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;\r
+               case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;\r
+               case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;\r
+               default: return;        \r
+               }\r
+       }\r
+       void ShiftExp()\r
+       {\r
+               PlusExp();\r
+               for(;;) switch(_token) {\r
+               case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;\r
+               case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;\r
+               case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;\r
+               default: return;        \r
+               }\r
+       }\r
+       void PlusExp()\r
+       {\r
+               MultExp();\r
+               for(;;) switch(_token) {\r
+               case _SC('+'): case _SC('-'):\r
+                       BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;\r
+               default: return;\r
+               }\r
+       }\r
+       \r
+       void MultExp()\r
+       {\r
+               PrefixedExpr();\r
+               for(;;) switch(_token) {\r
+               case _SC('*'): case _SC('/'): case _SC('%'):\r
+                       BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;\r
+               default: return;\r
+               }\r
+       }\r
+       //if 'pos' != -1 the previous variable is a local variable\r
+       void PrefixedExpr()\r
+       {\r
+               int pos = Factor();\r
+               for(;;) {\r
+                       switch(_token) {\r
+                       case _SC('.'): {\r
+                               pos = -1;\r
+                               SQObjectPtr idx;\r
+                               Lex(); \r
+                               if(_token == TK_PARENT) {\r
+                                       Lex();\r
+                                       if(!NeedGet())\r
+                                               Error(_SC("parent cannot be set"));\r
+                                       int src = _fs->PopTarget();\r
+                                       _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);\r
+                               }\r
+                               else {\r
+                                       idx = Expect(TK_IDENTIFIER); \r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(idx)));\r
+                                       if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
+                               }\r
+                               _exst._deref = DEREF_FIELD;\r
+                               _exst._freevar = false;\r
+                               }\r
+                               break;\r
+                       case _SC('['):\r
+                               if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));\r
+                               Lex(); Expression(); Expect(_SC(']')); \r
+                               pos = -1;\r
+                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
+                               _exst._deref = DEREF_FIELD;\r
+                               _exst._freevar = false;\r
+                               break;\r
+                       case TK_MINUSMINUS:\r
+                       case TK_PLUSPLUS:\r
+                       if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { \r
+                               int tok = _token; Lex();\r
+                               if(pos < 0)\r
+                                       Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);\r
+                               else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
+                                       int src = _fs->PopTarget();\r
+                                       _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);\r
+                               }\r
+                               \r
+                       }\r
+                       return;\r
+                       break;  \r
+                       case _SC('('): \r
+                               {\r
+                               if(_exst._deref != DEREF_NO_DEREF) {\r
+                                       if(pos<0) {\r
+                                               int key = _fs->PopTarget(); //key\r
+                                               int table = _fs->PopTarget(); //table etc...\r
+                                               int closure = _fs->PushTarget();\r
+                                               int ttarget = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);\r
+                                       }\r
+                                       else{\r
+                                               _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
+                                       }\r
+                               }\r
+                               else\r
+                                       _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
+                               _exst._deref = DEREF_NO_DEREF;\r
+                               Lex();\r
+                               FunctionCallArgs();\r
+                                }\r
+                               break;\r
+                       default: return;\r
+                       }\r
+               }\r
+       }\r
+       int Factor()\r
+       {\r
+               switch(_token)\r
+               {\r
+               case TK_STRING_LITERAL: {\r
+                               SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));\r
+                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
+                               Lex(); \r
+                       }\r
+                       break;\r
+               case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;\r
+               case TK_VARGV: { Lex();\r
+                       Expect(_SC('['));\r
+                       Expression();\r
+                       Expect(_SC(']'));\r
+                       int src = _fs->PopTarget();\r
+                       _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);\r
+                                          }\r
+                       break;\r
+               case TK_IDENTIFIER:\r
+               case TK_CONSTRUCTOR:\r
+               case TK_THIS:{\r
+                       _exst._freevar = false;\r
+                       SQObjectPtr id;\r
+                               switch(_token) {\r
+                                       case TK_IDENTIFIER: id = SQString::Create(_ss(_vm), _lex._svalue); break;\r
+                                       case TK_THIS: id = SQString::Create(_ss(_vm), _SC("this")); break;\r
+                                       case TK_CONSTRUCTOR: id = SQString::Create(_ss(_vm), _SC("constructor")); break;\r
+                               }\r
+                               int pos = -1;\r
+                               Lex();\r
+                               if((pos = _fs->GetLocalVariable(id)) == -1) {\r
+                                       //checks if is a free variable\r
+                                       if((pos = _fs->GetOuterVariable(id)) != -1) {\r
+                                               _exst._deref = _fs->PushTarget();\r
+                                               _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);        \r
+                                               _exst._freevar = true;\r
+                                       } else {\r
+                                               _fs->PushTarget(0);\r
+                                               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
+                                               if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
+                                               _exst._deref = DEREF_FIELD;\r
+                                       }\r
+                               }\r
+                               else{\r
+                                       _fs->PushTarget(pos);\r
+                                       _exst._deref = pos;\r
+                               }\r
+                               return _exst._deref;\r
+                       }\r
+                       break;\r
+               case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;\r
+               case TK_DOUBLE_COLON:  // "::"\r
+                       _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());\r
+                       _exst._deref = DEREF_FIELD;\r
+                       _token = _SC('.'); //hack\r
+                       return -1;\r
+                       break;\r
+               case TK_NULL: \r
+                       _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
+                       Lex();\r
+                       break;\r
+               case TK_INTEGER: \r
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));\r
+                       Lex();\r
+                       break;\r
+               case TK_FLOAT: \r
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
+                       Lex();\r
+                       break;\r
+               case TK_TRUE: case TK_FALSE:\r
+                       _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);\r
+                       Lex();\r
+                       break;\r
+               case _SC('['): {\r
+                               _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());\r
+                               int apos = _fs->GetCurrentPos(),key = 0;\r
+                               Lex();\r
+                               while(_token != _SC(']')) {\r
+                    Expression(); \r
+                                       if(_token == _SC(',')) Lex();\r
+                                       int val = _fs->PopTarget();\r
+                                       int array = _fs->TopTarget();\r
+                                       _fs->AddInstruction(_OP_APPENDARRAY, array, val);\r
+                                       key++;\r
+                               }\r
+                               _fs->SetIntructionParam(apos, 1, key);\r
+                               Lex();\r
+                       }\r
+                       break;\r
+               case _SC('{'):{\r
+                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
+                       Lex();ParseTableOrClass(_SC(','));\r
+                                }\r
+                       break;\r
+               case TK_FUNCTION: FunctionExp(_token);break;\r
+               case TK_CLASS: Lex(); ClassExp();break;\r
+               case _SC('-'): UnaryOP(_OP_NEG); break;\r
+               case _SC('!'): UnaryOP(_OP_NOT); break;\r
+               case _SC('~'): UnaryOP(_OP_BWNOT); break;\r
+               case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;\r
+               case TK_RESUME : UnaryOP(_OP_RESUME); break;\r
+               case TK_CLONE : UnaryOP(_OP_CLONE); break;\r
+               case TK_MINUSMINUS : \r
+               case TK_PLUSPLUS :PrefixIncDec(_token); break;\r
+               case TK_DELETE : DeleteExpr(); break;\r
+               case TK_DELEGATE : DelegateExpr(); break;\r
+               case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));\r
+                       break;\r
+               default: Error(_SC("expression expected"));\r
+               }\r
+               return -1;\r
+       }\r
+       void UnaryOP(SQOpcode op)\r
+       {\r
+               Lex(); PrefixedExpr();\r
+               int src = _fs->PopTarget();\r
+               _fs->AddInstruction(op, _fs->PushTarget(), src);\r
+       }\r
+       bool NeedGet()\r
+       {\r
+               switch(_token) {\r
+               case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
+               case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:\r
+                       return false;\r
+               }\r
+               return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));\r
+       }\r
+       \r
+       void FunctionCallArgs()\r
+       {\r
+               int nargs = 1;//this\r
+                while(_token != _SC(')')) {\r
+                        Expression(true);\r
+                        MoveIfCurrentTargetIsLocal();\r
+                        nargs++; \r
+                        if(_token == _SC(',')){ \r
+                                Lex(); \r
+                                if(_token == ')') Error(_SC("expression expected, found ')'"));\r
+                        }\r
+                }\r
+                Lex();\r
+                for(int i = 0; i < (nargs - 1); i++) _fs->PopTarget();\r
+                int stackbase = _fs->PopTarget();\r
+                int closure = _fs->PopTarget();\r
+         _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
+       }\r
+       void ParseTableOrClass(int separator,int terminator = '}')\r
+       {\r
+               int tpos = _fs->GetCurrentPos(),nkeys = 0;\r
+               \r
+               while(_token != terminator) {\r
+                       bool hasattrs = false;\r
+                       //check if is an attribute\r
+                       if(separator == ';' && _token == TK_ATTR_OPEN) {\r
+                               _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();\r
+                               ParseTableOrClass(',',TK_ATTR_CLOSE);\r
+                               hasattrs = true;\r
+                       }\r
+                       switch(_token) {\r
+                               case TK_FUNCTION:\r
+                               case TK_CONSTRUCTOR:{\r
+                                       int tk = _token;\r
+                                       Lex();\r
+                                       SQObjectPtr id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : SQString::Create(_ss(_vm),_SC("constructor"));\r
+                                       Expect(_SC('('));\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
+                                       CreateFunction(id);\r
+                                       _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
+                                                                 }\r
+                                                                 break;\r
+                               case _SC('['):\r
+                                       Lex(); CommaExpr(); Expect(_SC(']'));\r
+                                       Expect(_SC('=')); Expression();\r
+                                       break;\r
+                               default :\r
+                                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(Expect(TK_IDENTIFIER))));\r
+                                       Expect(_SC('=')); Expression();\r
+                       }\r
+\r
+                       if(_token == separator) Lex();//optional comma/semicolon\r
+                       nkeys++;\r
+                       int val = _fs->PopTarget();\r
+                       int key = _fs->PopTarget();\r
+                       int attrs = hasattrs ? _fs->PopTarget():-1;\r
+                       assert(hasattrs && attrs == key-1 || !hasattrs);\r
+                       int table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE\r
+                       _fs->AddInstruction(hasattrs?_OP_NEWSLOTA:_OP_NEWSLOT, _fs->PushTarget(), table, key, val);\r
+                       _fs->PopTarget();\r
+               }\r
+               if(separator == _SC(',')) //hack recognizes a table from the separator\r
+                       _fs->SetIntructionParam(tpos, 1, nkeys);\r
+               Lex();\r
+       }\r
+       void LocalDeclStatement()\r
+       {\r
+               SQObjectPtr varname;\r
+               do {\r
+                       Lex(); varname = Expect(TK_IDENTIFIER);\r
+                       if(_token == _SC('=')) {\r
+                               Lex(); Expression();\r
+                               int src = _fs->PopTarget();\r
+                               int dest = _fs->PushTarget();\r
+                               if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);\r
+                       }\r
+                       else{\r
+                               _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
+                       }\r
+                       _fs->PopTarget();\r
+                       _fs->PushLocalVariable(varname);\r
+               \r
+               } while(_token == _SC(','));\r
+       }\r
+       void IfStatement()\r
+       {\r
+               int jmppos;\r
+               bool haselse = false;\r
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
+               int jnepos = _fs->GetCurrentPos();\r
+               int stacksize = _fs->GetStackSize();\r
+               \r
+               Statement();\r
+               //\r
+               if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
+               \r
+               CleanStack(stacksize);\r
+               int endifblock = _fs->GetCurrentPos();\r
+               if(_token == TK_ELSE){\r
+                       haselse = true;\r
+                       stacksize = _fs->GetStackSize();\r
+                       _fs->AddInstruction(_OP_JMP);\r
+                       jmppos = _fs->GetCurrentPos();\r
+                       Lex();\r
+                       Statement(); OptionalSemicolon();\r
+                       CleanStack(stacksize);\r
+                       _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
+               }\r
+               _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
+       }\r
+       void WhileStatement()\r
+       {\r
+               int jzpos, jmppos;\r
+               int stacksize = _fs->GetStackSize();\r
+               jmppos = _fs->GetCurrentPos();\r
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+               \r
+               BEGIN_BREAKBLE_BLOCK();\r
+               _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
+               jzpos = _fs->GetCurrentPos();\r
+               stacksize = _fs->GetStackSize();\r
+               \r
+               Statement();\r
+               \r
+               CleanStack(stacksize);\r
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
+               _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
+               \r
+               END_BREAKBLE_BLOCK(jmppos);\r
+       }\r
+       void DoWhileStatement()\r
+       {\r
+               Lex();\r
+               int jzpos = _fs->GetCurrentPos();\r
+               int stacksize = _fs->GetStackSize();\r
+               BEGIN_BREAKBLE_BLOCK()\r
+               Statement();\r
+               CleanStack(stacksize);\r
+               Expect(TK_WHILE);\r
+               int continuetrg = _fs->GetCurrentPos();\r
+               Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+               _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);\r
+               END_BREAKBLE_BLOCK(continuetrg);\r
+       }\r
+       void ForStatement()\r
+       {\r
+               Lex();\r
+               int stacksize = _fs->GetStackSize();\r
+               Expect(_SC('('));\r
+               if(_token == TK_LOCAL) LocalDeclStatement();\r
+               else if(_token != _SC(';')){\r
+                       CommaExpr();\r
+                       _fs->PopTarget();\r
+               }\r
+               Expect(_SC(';'));\r
+               _fs->SnoozeOpt();\r
+               int jmppos = _fs->GetCurrentPos();\r
+               int jzpos = -1;\r
+               if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }\r
+               Expect(_SC(';'));\r
+               _fs->SnoozeOpt();\r
+               int expstart = _fs->GetCurrentPos() + 1;\r
+               if(_token != _SC(')')) {\r
+                       CommaExpr();\r
+                       _fs->PopTarget();\r
+               }\r
+               Expect(_SC(')'));\r
+               _fs->SnoozeOpt();\r
+               int expend = _fs->GetCurrentPos();\r
+               int expsize = (expend - expstart) + 1;\r
+               SQInstructionVec exp;\r
+               if(expsize > 0) {\r
+                       for(int i = 0; i < expsize; i++)\r
+                               exp.push_back(_fs->GetInstruction(expstart + i));\r
+                       _fs->PopInstructions(expsize);\r
+               }\r
+               BEGIN_BREAKBLE_BLOCK()\r
+               Statement();\r
+               int continuetrg = _fs->GetCurrentPos();\r
+               if(expsize > 0) {\r
+                       for(int i = 0; i < expsize; i++)\r
+                               _fs->AddInstruction(exp[i]);\r
+               }\r
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);\r
+               if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
+               CleanStack(stacksize);\r
+               \r
+               END_BREAKBLE_BLOCK(continuetrg);\r
+       }\r
+       void ForEachStatement()\r
+       {\r
+               SQObjectPtr idxname, valname;\r
+               Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);\r
+               if(_token == _SC(',')) {\r
+                       idxname = valname;\r
+                       Lex(); valname = Expect(TK_IDENTIFIER);\r
+               }\r
+               else{\r
+                       idxname = SQString::Create(_ss(_vm), _SC("@INDEX@"));\r
+               }\r
+               Expect(TK_IN);\r
+               \r
+               //save the stack size\r
+               int stacksize = _fs->GetStackSize();\r
+               //put the table in the stack(evaluate the table expression)\r
+               Expression(); Expect(_SC(')'));\r
+               int container = _fs->TopTarget();\r
+               //push the index local var\r
+               int indexpos = _fs->PushLocalVariable(idxname);\r
+               _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);\r
+               //push the value local var\r
+               int valuepos = _fs->PushLocalVariable(valname);\r
+               _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);\r
+               //push reference index\r
+               int itrpos = _fs->PushLocalVariable(SQString::Create(_ss(_vm), _SC("@ITERATOR@"))); //use invalid id to make it inaccessible\r
+               _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);\r
+               int jmppos = _fs->GetCurrentPos();\r
+               _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);\r
+               int foreachpos = _fs->GetCurrentPos();\r
+               //generate the statement code\r
+               BEGIN_BREAKBLE_BLOCK()\r
+               Statement();\r
+               _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
+               _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);\r
+               //restore the local variable stack(remove index,val and ref idx)\r
+               CleanStack(stacksize);\r
+               END_BREAKBLE_BLOCK(foreachpos - 1);\r
+       }\r
+       void SwitchStatement()\r
+       {\r
+               Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+               Expect(_SC('{'));\r
+               int expr = _fs->TopTarget();\r
+               bool bfirst = true;\r
+               int tonextcondjmp = -1;\r
+               int skipcondjmp = -1;\r
+               int __nbreaks__ = _fs->_unresolvedbreaks.size();\r
+               _fs->_breaktargets.push_back(0);\r
+               while(_token == TK_CASE) {\r
+                       if(!bfirst) {\r
+                               _fs->AddInstruction(_OP_JMP, 0, 0);\r
+                               skipcondjmp = _fs->GetCurrentPos();\r
+                               _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
+                       }\r
+                       //condition\r
+                       Lex(); Expression(); Expect(_SC(':'));\r
+                       int trg = _fs->PopTarget();\r
+                       _fs->AddInstruction(_OP_EQ, trg, trg, expr);\r
+                       _fs->AddInstruction(_OP_JZ, trg, 0);\r
+                       //end condition\r
+                       if(skipcondjmp != -1) {\r
+                               _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));\r
+                       }\r
+                       tonextcondjmp = _fs->GetCurrentPos();\r
+                       int stacksize = _fs->GetStackSize();\r
+                       Statements();\r
+                       _fs->SetStackSize(stacksize);\r
+                       bfirst = false;\r
+               }\r
+               if(tonextcondjmp != -1)\r
+                       _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
+               if(_token == TK_DEFAULT) {\r
+                       Lex(); Expect(_SC(':'));\r
+                       int stacksize = _fs->GetStackSize();\r
+                       Statements();\r
+                       _fs->SetStackSize(stacksize);\r
+               }\r
+               Expect(_SC('}'));\r
+               _fs->PopTarget();\r
+               __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;\r
+               if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);\r
+               _fs->_breaktargets.pop_back();\r
+               \r
+       }\r
+       void FunctionStatement()\r
+       {\r
+               SQObjectPtr id;\r
+               Lex(); id = Expect(TK_IDENTIFIER);\r
+               _fs->PushTarget(0);\r
+               _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
+               if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
+               \r
+               while(_token == TK_DOUBLE_COLON) {\r
+                       Lex();\r
+                       id = Expect(TK_IDENTIFIER);\r
+                       _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
+                       if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
+               }\r
+               Expect(_SC('('));\r
+               CreateFunction(id);\r
+               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
+               EmitDerefOp(_OP_NEWSLOT);\r
+               _fs->PopTarget();\r
+       }\r
+       void ClassStatement()\r
+       {\r
+               ExpState es;\r
+               Lex(); PushExpState();\r
+               _exst._class_or_delete = true;\r
+               _exst._funcarg = false;\r
+               PrefixedExpr();\r
+               es = PopExpState();\r
+               if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));\r
+               if(es._deref == DEREF_FIELD) {\r
+                       ClassExp();\r
+                       EmitDerefOp(_OP_NEWSLOT);\r
+                       _fs->PopTarget();\r
+               }\r
+               else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
+       }\r
+       void TryCatchStatement()\r
+       {\r
+               SQObjectPtr exid;\r
+               Lex();\r
+               _fs->AddInstruction(_OP_PUSHTRAP,0,0);\r
+               _fs->_traps++;\r
+               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;\r
+               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;\r
+               int trappos = _fs->GetCurrentPos();\r
+               Statement();\r
+               _fs->_traps--;\r
+               _fs->AddInstruction(_OP_POPTRAP, 1, 0);\r
+               if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;\r
+               if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;\r
+               _fs->AddInstruction(_OP_JMP, 0, 0);\r
+               int jmppos = _fs->GetCurrentPos();\r
+               _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));\r
+               Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));\r
+               int stacksize = _fs->GetStackSize();\r
+               int ex_target = _fs->PushLocalVariable(exid);\r
+               _fs->SetIntructionParam(trappos, 0, ex_target);\r
+               Statement();\r
+               _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);\r
+               CleanStack(stacksize);\r
+       }\r
+       void FunctionExp(int ftype)\r
+       {\r
+               Lex(); Expect(_SC('('));\r
+               CreateFunction(_null_);\r
+               _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);\r
+       }\r
+       void ClassExp()\r
+       {\r
+               int base = -1;\r
+               int attrs = -1;\r
+               if(_token == TK_EXTENDS) {\r
+                       Lex(); Expression();\r
+                       base = _fs->TopTarget();\r
+               }\r
+               if(_token == TK_ATTR_OPEN) {\r
+                       Lex();\r
+                       _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
+                       ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);\r
+                       attrs = _fs->TopTarget();\r
+               }\r
+               Expect(_SC('{'));\r
+               if(attrs != -1) _fs->PopTarget();\r
+               if(base != -1) _fs->PopTarget();\r
+               _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);\r
+               ParseTableOrClass(_SC(';'));\r
+       }\r
+       void DelegateExpr()\r
+       {\r
+               Lex(); CommaExpr();\r
+               Expect(_SC(':'));\r
+               CommaExpr();\r
+               int table = _fs->PopTarget(), delegate = _fs->PopTarget();\r
+               _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);\r
+       }\r
+       void DeleteExpr()\r
+       {\r
+               ExpState es;\r
+               Lex(); PushExpState();\r
+               _exst._class_or_delete = true;\r
+               _exst._funcarg = false;\r
+               PrefixedExpr();\r
+               es = PopExpState();\r
+               if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));\r
+               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);\r
+               else Error(_SC("cannot delete a local"));\r
+       }\r
+       void PrefixIncDec(int token)\r
+       {\r
+               ExpState es;\r
+               Lex(); PushExpState();\r
+               _exst._class_or_delete = true;\r
+               _exst._funcarg = false;\r
+               PrefixedExpr();\r
+               es = PopExpState();\r
+               if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);\r
+               else {\r
+                       int src = _fs->PopTarget();\r
+                       _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);\r
+               }\r
+       }\r
+       void CreateFunction(SQObjectPtr name)\r
+       {\r
+               SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), _fs);\r
+               _funcproto(funcstate._func)->_name = name;\r
+               SQObjectPtr paramname;\r
+               funcstate.AddParameter(SQString::Create(_ss(_vm), _SC("this")));\r
+               _funcproto(funcstate._func)->_sourcename = _sourcename;\r
+               while(_token!=_SC(')')) {\r
+                       if(_token == TK_VARPARAMS) {\r
+                               funcstate._varparams = true;\r
+                               Lex();\r
+                               if(_token != _SC(')')) Error(_SC("expected ')'"));\r
+                               break;\r
+                       }\r
+                       else {\r
+                               paramname = Expect(TK_IDENTIFIER);\r
+                               funcstate.AddParameter(paramname);\r
+                               if(_token == _SC(',')) Lex();\r
+                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
+                       }\r
+               }\r
+               Expect(_SC(')'));\r
+               //outer values\r
+               if(_token == _SC(':')) {\r
+                       Lex(); Expect(_SC('('));\r
+                       while(_token != _SC(')')) {\r
+                               paramname = Expect(TK_IDENTIFIER);\r
+                               //outers are treated as implicit local variables\r
+                               funcstate.AddOuterValue(paramname);\r
+                               if(_token == _SC(',')) Lex();\r
+                               else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
+                       }\r
+                       Lex();\r
+               }\r
+               \r
+               SQFuncState *currchunk = _fs;\r
+               _fs = &funcstate;\r
+               Statement();\r
+               funcstate.AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);\r
+        funcstate.AddInstruction(_OP_RETURN, -1);\r
+               funcstate.SetStackSize(0);\r
+               _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;\r
+               funcstate.Finalize();\r
+#ifdef _DEBUG_DUMP\r
+               funcstate.Dump();\r
+#endif\r
+               _fs = currchunk;\r
+               _fs->_functions.push_back(funcstate._func);\r
+       }\r
+       void CleanStack(int stacksize)\r
+       {\r
+               if(_fs->GetStackSize() != stacksize)\r
+                       _fs->SetStackSize(stacksize);\r
+       }\r
+       void ResolveBreaks(SQFuncState *funcstate, int ntoresolve)\r
+       {\r
+               while(ntoresolve > 0) {\r
+                       int pos = funcstate->_unresolvedbreaks.back();\r
+                       funcstate->_unresolvedbreaks.pop_back();\r
+                       //set the jmp instruction\r
+                       funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);\r
+                       ntoresolve--;\r
+               }\r
+       }\r
+       void ResolveContinues(SQFuncState *funcstate, int ntoresolve, int targetpos)\r
+       {\r
+               while(ntoresolve > 0) {\r
+                       int pos = funcstate->_unresolvedcontinues.back();\r
+                       funcstate->_unresolvedcontinues.pop_back();\r
+                       //set the jmp instruction\r
+                       funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);\r
+                       ntoresolve--;\r
+               }\r
+       }\r
+private:\r
+       int _token;\r
+       SQFuncState *_fs;\r
+       SQObjectPtr _sourcename;\r
+       SQLexer _lex;\r
+       bool _lineinfo;\r
+       bool _raiseerror;\r
+       int _debugline;\r
+       int _debugop;\r
+       ExpStateVec _expstates;\r
+       SQVM *_vm;\r
+};\r
+\r
+bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)\r
+{\r
+       SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);\r
+       return p.Compile(out);\r
+}\r
diff --git a/src/squirrel/squirrel/sqcompiler.h b/src/squirrel/squirrel/sqcompiler.h
new file mode 100644 (file)
index 0000000..1d29e96
--- /dev/null
@@ -0,0 +1,74 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQCOMPILER_H_\r
+#define _SQCOMPILER_H_\r
+\r
+struct SQVM;\r
+\r
+#define        TK_IDENTIFIER   258\r
+#define        TK_STRING_LITERAL       259\r
+#define        TK_INTEGER      260\r
+#define        TK_FLOAT        261\r
+#define        TK_DELEGATE     262\r
+#define        TK_DELETE       263\r
+#define        TK_EQ   264\r
+#define        TK_NE   265\r
+#define        TK_LE   266\r
+#define        TK_GE   267\r
+#define        TK_SWITCH       268\r
+#define        TK_ARROW        269\r
+#define        TK_AND  270\r
+#define        TK_OR   271\r
+#define        TK_IF   272\r
+#define        TK_ELSE 273\r
+#define        TK_WHILE        274\r
+#define        TK_BREAK        275\r
+#define        TK_FOR  276\r
+#define        TK_DO   277\r
+#define        TK_NULL 278\r
+#define        TK_FOREACH      279\r
+#define        TK_IN   280\r
+#define        TK_NEWSLOT      281\r
+#define        TK_MODULO       282\r
+#define        TK_LOCAL        283\r
+#define        TK_CLONE        284\r
+#define        TK_FUNCTION     285\r
+#define        TK_RETURN       286\r
+#define        TK_TYPEOF       287\r
+#define        TK_UMINUS       288\r
+#define        TK_PLUSEQ       289\r
+#define        TK_MINUSEQ      290\r
+#define        TK_CONTINUE     291\r
+#define TK_YIELD 292\r
+#define TK_TRY 293\r
+#define TK_CATCH 294\r
+#define TK_THROW 295\r
+#define TK_SHIFTL 296\r
+#define TK_SHIFTR 297\r
+#define TK_RESUME 298\r
+#define TK_DOUBLE_COLON 299\r
+#define TK_CASE 300\r
+#define TK_DEFAULT 301\r
+#define TK_THIS 302\r
+#define TK_PLUSPLUS 303\r
+#define TK_MINUSMINUS 304\r
+#define TK_PARENT 305\r
+#define TK_USHIFTR 306\r
+#define TK_CLASS 307\r
+#define TK_EXTENDS 308\r
+#define TK_CONSTRUCTOR 310\r
+#define TK_INSTANCEOF 311\r
+#define TK_VARPARAMS 312\r
+#define TK_VARGC 313\r
+#define TK_VARGV 314\r
+#define TK_TRUE 315\r
+#define TK_FALSE 316\r
+#define TK_MULEQ 317\r
+#define TK_DIVEQ 318\r
+#define TK_MODEQ 319\r
+#define TK_ATTR_OPEN 320\r
+#define TK_ATTR_CLOSE 321\r
+\r
+\r
+struct ParserException{ SQChar *desc; ParserException(SQChar *err):desc(err) {} };\r
+bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);\r
+#endif //_SQCOMPILER_H_\r
diff --git a/src/squirrel/squirrel/sqdebug.cpp b/src/squirrel/squirrel/sqdebug.cpp
new file mode 100644 (file)
index 0000000..89663ba
--- /dev/null
@@ -0,0 +1,98 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include <stdarg.h>\r
+#include "sqvm.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+#include "sqstring.h"\r
+\r
+SQRESULT sq_stackinfos(HSQUIRRELVM v, int level, SQStackInfos *si)\r
+{\r
+       int cssize = v->_callsstack.size();\r
+       if (cssize > level) {\r
+               memset(si, 0, sizeof(SQStackInfos));\r
+               SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];\r
+               switch (type(ci._closure)) {\r
+               case OT_CLOSURE:{\r
+                       SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function);\r
+                       if (type(func->_name) == OT_STRING)\r
+                               si->funcname = _stringval(func->_name);\r
+                       if (type(func->_sourcename) == OT_STRING)\r
+                               si->source = _stringval(func->_sourcename);\r
+                       si->line = func->GetLine(ci._ip);\r
+                                               }\r
+                       break;\r
+               case OT_NATIVECLOSURE:\r
+                       si->source = _SC("NATIVE");\r
+                       si->funcname = _SC("unknown");\r
+                       if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)\r
+                               si->funcname = _stringval(_nativeclosure(ci._closure)->_name);\r
+                       si->line = -1;\r
+                       break;\r
+               }\r
+               return SQ_OK;\r
+       }\r
+       return SQ_ERROR;\r
+}\r
+\r
+void SQVM::Raise_Error(const SQChar *s, ...)\r
+{\r
+       va_list vl;\r
+       va_start(vl, s);\r
+       scvsprintf(_sp(rsl(scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl);\r
+       va_end(vl);\r
+       _lasterror = SQString::Create(_ss(this),_spval,-1);\r
+}\r
+\r
+void SQVM::Raise_Error(SQObjectPtr &desc)\r
+{\r
+       _lasterror = desc;\r
+}\r
+\r
+SQString *SQVM::PrintObjVal(const SQObject &o)\r
+{\r
+       switch(type(o)) {\r
+       case OT_STRING: return _string(o);\r
+       case OT_INTEGER:\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o));\r
+               return SQString::Create(_ss(this), _spval);\r
+               break;\r
+       case OT_FLOAT:\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o));\r
+               return SQString::Create(_ss(this), _spval);\r
+               break;\r
+       default:\r
+               return SQString::Create(_ss(this), GetTypeName(o));\r
+       }\r
+}\r
+\r
+void SQVM::Raise_IdxError(SQObject &o)\r
+{\r
+       SQObjectPtr oval = PrintObjVal(o);\r
+       Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));\r
+}\r
+\r
+void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)\r
+{\r
+       SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);\r
+       Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));\r
+}\r
+\r
+\r
+void SQVM::Raise_ParamTypeError(int nparam,int typemask,int type)\r
+{\r
+       SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);\r
+       int found = 0;  \r
+       for(int i=0; i<16; i++)\r
+       {\r
+               int mask = 0x00000001 << i;\r
+               if(typemask & (mask)) {\r
+                       if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes);\r
+                       found ++;\r
+                       StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);\r
+               }\r
+       }\r
+       Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));\r
+}\r
diff --git a/src/squirrel/squirrel/sqfuncproto.h b/src/squirrel/squirrel/sqfuncproto.h
new file mode 100644 (file)
index 0000000..ab45ba2
--- /dev/null
@@ -0,0 +1,89 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQFUNCTION_H_\r
+#define _SQFUNCTION_H_\r
+\r
+#include "sqopcodes.h"\r
+\r
+enum SQOuterType {\r
+       otLOCAL = 0,\r
+       otSYMBOL = 1,\r
+       otOUTER = 2\r
+};\r
+\r
+struct SQOuterVar\r
+{\r
+       \r
+       SQOuterVar(){}\r
+       SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)\r
+       {\r
+               _name = name;\r
+               _src=src;\r
+               _type=t;\r
+       }\r
+       SQOuterVar(const SQOuterVar &ov)\r
+       {\r
+               _type=ov._type;\r
+               _src=ov._src;\r
+               _name=ov._name;\r
+       }\r
+       SQOuterType _type;\r
+       SQObjectPtr _name;\r
+       SQObjectPtr _src;\r
+};\r
+\r
+struct SQLocalVarInfo\r
+{\r
+       SQLocalVarInfo():_start_op(0),_end_op(0){}\r
+       SQLocalVarInfo(const SQLocalVarInfo &lvi)\r
+       {\r
+               _name=lvi._name;\r
+               _start_op=lvi._start_op;\r
+               _end_op=lvi._end_op;\r
+               _pos=lvi._pos;\r
+       }\r
+       SQObjectPtr _name;\r
+       unsigned int _start_op;\r
+       unsigned int _end_op;\r
+       unsigned int _pos;\r
+};\r
+\r
+struct SQLineInfo { int _line;int _op; };\r
+\r
+typedef sqvector<SQOuterVar> SQOuterVarVec;\r
+typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;\r
+typedef sqvector<SQLineInfo> SQLineInfoVec;\r
+\r
+struct SQFunctionProto : public SQRefCounted\r
+{\r
+private:\r
+       SQFunctionProto(){\r
+               _uiRef=0;\r
+       _stacksize=0;\r
+       _bgenerator=false;}\r
+public:\r
+       static SQFunctionProto *Create()\r
+       {\r
+               SQFunctionProto *f;\r
+               sq_new(f,SQFunctionProto);\r
+               return f;\r
+       }\r
+       void Release(){ sq_delete(this,SQFunctionProto);}\r
+       const SQChar* GetLocal(SQVM *v,unsigned int stackbase,unsigned int nseq,unsigned int nop);\r
+       int GetLine(SQInstruction *curr);\r
+       bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
+       bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);\r
+       SQObjectPtrVec _literals;\r
+       SQObjectPtrVec _functions;\r
+       SQObjectPtrVec _parameters;\r
+       SQOuterVarVec _outervalues;\r
+       SQInstructionVec _instructions;\r
+       SQObjectPtr _sourcename;\r
+       SQObjectPtr _name;\r
+       SQLocalVarInfoVec _localvarinfos;\r
+       SQLineInfoVec _lineinfos;\r
+    int _stacksize;\r
+       bool _bgenerator;\r
+       bool _varparams;\r
+};\r
+\r
+#endif //_SQFUNCTION_H_\r
diff --git a/src/squirrel/squirrel/sqfuncstate.cpp b/src/squirrel/squirrel/sqfuncstate.cpp
new file mode 100644 (file)
index 0000000..b070809
--- /dev/null
@@ -0,0 +1,482 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqcompiler.h"\r
+#include "sqfuncproto.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "sqopcodes.h"\r
+#include "sqfuncstate.h"\r
+\r
+#ifdef _DEBUG_DUMP\r
+SQInstructionDesc g_InstrDesc[]={\r
+       {_SC("_OP_LINE")},\r
+       {_SC("_OP_LOAD")},\r
+       {_SC("_OP_TAILCALL")},\r
+       {_SC("_OP_CALL")},\r
+       {_SC("_OP_PREPCALL")},\r
+       {_SC("_OP_PREPCALLK")},\r
+       {_SC("_OP_GETK")},\r
+       {_SC("_OP_MOVE")},\r
+       {_SC("_OP_NEWSLOT")},\r
+       {_SC("_OP_DELETE")},\r
+       {_SC("_OP_SET")},\r
+       {_SC("_OP_GET")},\r
+       {_SC("_OP_EQ")},\r
+       {_SC("_OP_NE")},\r
+       {_SC("_OP_ARITH")},\r
+       {_SC("_OP_BITW")},\r
+       {_SC("_OP_RETURN")},\r
+       {_SC("_OP_LOADNULLS")},\r
+       {_SC("_OP_LOADROOTTABLE")},\r
+       {_SC("_OP_DMOVE")},\r
+       {_SC("_OP_JMP")},\r
+       {_SC("_OP_JNZ")},\r
+       {_SC("_OP_JZ")},\r
+       {_SC("_OP_LOADFREEVAR")},\r
+       {_SC("_OP_VARGC")},\r
+       {_SC("_OP_GETVARGV")},\r
+       {_SC("_OP_NEWTABLE")},\r
+       {_SC("_OP_NEWARRAY")},\r
+       {_SC("_OP_APPENDARRAY")},\r
+       {_SC("_OP_GETPARENT")},\r
+       {_SC("_OP_COMPARITH")},\r
+       {_SC("_OP_COMPARITHL")},\r
+       {_SC("_OP_INC")},\r
+       {_SC("_OP_INCL")},\r
+       {_SC("_OP_PINC")},\r
+       {_SC("_OP_PINCL")},\r
+       {_SC("_OP_CMP")},\r
+       {_SC("_OP_EXISTS")},\r
+       {_SC("_OP_INSTANCEOF")},\r
+       {_SC("_OP_AND")},\r
+       {_SC("_OP_OR")},\r
+       {_SC("_OP_NEG")},\r
+       {_SC("_OP_NOT")},\r
+       {_SC("_OP_BWNOT")},\r
+       {_SC("_OP_CLOSURE")},\r
+       {_SC("_OP_YIELD")},\r
+       {_SC("_OP_RESUME")},\r
+       {_SC("_OP_FOREACH")},\r
+       {_SC("_OP_DELEGATE")},\r
+       {_SC("_OP_CLONE")},\r
+       {_SC("_OP_TYPEOF")},\r
+       {_SC("_OP_PUSHTRAP")},\r
+       {_SC("_OP_POPTRAP")},\r
+       {_SC("_OP_THROW")},\r
+       {_SC("_OP_CLASS")},\r
+       {_SC("_OP_NEWSLOTA")},\r
+       {_SC("_OP_LOADBOOL")}\r
+};\r
+#endif\r
+void DumpLiteral(SQObjectPtr &o)\r
+{\r
+       switch(type(o)){\r
+               case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;\r
+               case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;\r
+               case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;\r
+       }\r
+}\r
+\r
+SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)\r
+{\r
+               _nliterals = 0;\r
+               _literals = SQTable::Create(ss,0);\r
+               _sharedstate = ss;\r
+               _lastline = 0;\r
+               _optimization = true;\r
+               _func = func;\r
+               _parent = parent;\r
+               _stacksize = 0;\r
+               _traps = 0;\r
+               _returnexp = 0;\r
+               _varparams = false;\r
+}\r
+\r
+#ifdef _DEBUG_DUMP\r
+void SQFuncState::Dump()\r
+{\r
+       unsigned int n=0,i;\r
+       SQFunctionProto *func=_funcproto(_func);\r
+       scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));\r
+       scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));\r
+       scprintf(_SC("--------------------------------------------------------------------\n"));\r
+       scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));\r
+       scprintf(_SC("-----LITERALS\n"));\r
+       SQObjectPtr refidx,key,val;\r
+       SQInteger idx;\r
+       SQObjectPtrVec templiterals;\r
+       templiterals.resize(_nliterals);\r
+       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
+               refidx=idx;\r
+               templiterals[_integer(val)]=key;\r
+       }\r
+       for(i=0;i<templiterals.size();i++){\r
+               scprintf(_SC("[%d] "),n);\r
+               DumpLiteral(templiterals[i]);\r
+               scprintf(_SC("\n"));\r
+               n++;\r
+       }\r
+       scprintf(_SC("-----PARAMS\n"));\r
+       if(_varparams)\r
+               scprintf(_SC("<<VARPARAMS>>\n"));\r
+       n=0;\r
+       for(i=0;i<_parameters.size();i++){\r
+               scprintf(_SC("[%d] "),n);\r
+               DumpLiteral(_parameters[i]);\r
+               scprintf(_SC("\n"));\r
+               n++;\r
+       }\r
+       scprintf(_SC("-----LOCALS\n"));\r
+       for(i=0;i<func->_localvarinfos.size();i++){\r
+               SQLocalVarInfo lvi=func->_localvarinfos[i];\r
+               scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);\r
+               n++;\r
+       }\r
+       scprintf(_SC("-----LINE INFO\n"));\r
+       for(i=0;i<_lineinfos.size();i++){\r
+               SQLineInfo li=_lineinfos[i];\r
+               scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);\r
+               n++;\r
+       }\r
+       scprintf(_SC("-----dump\n"));\r
+       n=0;\r
+       for(i=0;i<_instructions.size();i++){\r
+               SQInstruction &inst=_instructions[i];\r
+               if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){\r
+                       \r
+                       int lidx = inst._arg1;\r
+                       scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);\r
+                       if(lidx >= 0xFFFFFFFF)\r
+                               scprintf(_SC("null"));\r
+                       else {\r
+                               int refidx;\r
+                               SQObjectPtr val,key,refo;\r
+                               while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
+                                       refo = refidx;  \r
+                               }\r
+                               DumpLiteral(key);\r
+                       }\r
+                       scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);\r
+               }\r
+               else if(inst.op==_OP_ARITH){\r
+                       scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
+               }\r
+               else \r
+                       scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
+               n++;\r
+       }\r
+       scprintf(_SC("-----\n"));\r
+       scprintf(_SC("stack size[%d]\n"),func->_stacksize);\r
+       scprintf(_SC("--------------------------------------------------------------------\n\n"));\r
+}\r
+#endif\r
+int SQFuncState::GetStringConstant(const SQChar *cons)\r
+{\r
+       return GetConstant(SQString::Create(_sharedstate,cons));\r
+}\r
+\r
+int SQFuncState::GetNumericConstant(const SQInteger cons)\r
+{\r
+       return GetConstant(cons);\r
+}\r
+\r
+int SQFuncState::GetNumericConstant(const SQFloat cons)\r
+{\r
+       return GetConstant(cons);\r
+}\r
+\r
+int SQFuncState::GetConstant(SQObjectPtr cons)\r
+{\r
+       int n=0;\r
+       SQObjectPtr val;\r
+       if(!_table(_literals)->Get(cons,val))\r
+       {\r
+               val = _nliterals;\r
+               _table(_literals)->NewSlot(cons,val);\r
+               _nliterals++;\r
+               if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));\r
+       }\r
+       return _integer(val);\r
+}\r
+\r
+void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)\r
+{\r
+       _instructions[pos]._arg0=*((unsigned int *)&arg0);\r
+       _instructions[pos]._arg1=*((unsigned int *)&arg1);\r
+       _instructions[pos]._arg2=*((unsigned int *)&arg2);\r
+       _instructions[pos]._arg3=*((unsigned int *)&arg3);\r
+}\r
+\r
+void SQFuncState::SetIntructionParam(int pos,int arg,int val)\r
+{\r
+       switch(arg){\r
+               case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;\r
+               case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
+               case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;\r
+               case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;\r
+               case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
+       };\r
+}\r
+\r
+int SQFuncState::AllocStackPos()\r
+{\r
+       int npos=_vlocals.size();\r
+       _vlocals.push_back(SQLocalVarInfo());\r
+       if(_vlocals.size()>((unsigned int)_stacksize)) {\r
+               if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));\r
+               _stacksize=_vlocals.size();\r
+       }\r
+       return npos;\r
+}\r
+\r
+int SQFuncState::PushTarget(int n)\r
+{\r
+       if(n!=-1){\r
+               _targetstack.push_back(n);\r
+               return n;\r
+       }\r
+       n=AllocStackPos();\r
+       _targetstack.push_back(n);\r
+       return n;\r
+}\r
+\r
+int SQFuncState::GetUpTarget(int n){\r
+       return _targetstack[((_targetstack.size()-1)-n)];\r
+}\r
+\r
+int SQFuncState::TopTarget(){\r
+       return _targetstack.back();\r
+}\r
+int SQFuncState::PopTarget()\r
+{\r
+       int npos=_targetstack.back();\r
+       SQLocalVarInfo t=_vlocals[_targetstack.back()];\r
+       if(type(t._name)==OT_NULL){\r
+               _vlocals.pop_back();\r
+       }\r
+       _targetstack.pop_back();\r
+       return npos;\r
+}\r
+\r
+int SQFuncState::GetStackSize()\r
+{\r
+       return _vlocals.size();\r
+}\r
+\r
+void SQFuncState::SetStackSize(int n)\r
+{\r
+       int size=_vlocals.size();\r
+       while(size>n){\r
+               size--;\r
+               SQLocalVarInfo lvi=_vlocals.back();\r
+               if(type(lvi._name)!=OT_NULL){\r
+                       lvi._end_op=GetCurrentPos();\r
+                       _localvarinfos.push_back(lvi);\r
+               }\r
+               _vlocals.pop_back();\r
+       }\r
+}\r
+\r
+bool SQFuncState::IsLocal(unsigned int stkpos)\r
+{\r
+       if(stkpos>=_vlocals.size())return false;\r
+       else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;\r
+       return false;\r
+}\r
+\r
+int SQFuncState::PushLocalVariable(const SQObjectPtr &name)\r
+{\r
+       int pos=_vlocals.size();\r
+       SQLocalVarInfo lvi;\r
+       lvi._name=name;\r
+       lvi._start_op=GetCurrentPos()+1;\r
+       lvi._pos=_vlocals.size();\r
+       _vlocals.push_back(lvi);\r
+       if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();\r
+       \r
+       return pos;\r
+}\r
+\r
+int SQFuncState::GetLocalVariable(const SQObjectPtr &name)\r
+{\r
+       int locals=_vlocals.size();\r
+       while(locals>=1){\r
+               if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){\r
+                       return locals-1;\r
+               }\r
+               locals--;\r
+       }\r
+       return -1;\r
+}\r
+\r
+int SQFuncState::GetOuterVariable(const SQObjectPtr &name)\r
+{\r
+       int outers = _outervalues.size();\r
+       for(int i = 0; i<outers; i++) {\r
+               if(_string(_outervalues[i]._name) == _string(name))\r
+                       return i;\r
+       }\r
+       return -1;\r
+}\r
+\r
+void SQFuncState::AddOuterValue(const SQObjectPtr &name)\r
+{\r
+       //AddParameter(name);\r
+       int pos=-1;\r
+       if(_parent) { \r
+               pos = _parent->GetLocalVariable(name);\r
+               if(pos == -1) {\r
+                       pos = _parent->GetOuterVariable(name);\r
+                       if(pos != -1) {\r
+                               _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local\r
+                               return;\r
+                       }\r
+               }\r
+               else {\r
+                       _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local\r
+                       return;\r
+               }\r
+       }       \r
+       _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global\r
+}\r
+\r
+void SQFuncState::AddParameter(const SQObjectPtr &name)\r
+{\r
+       PushLocalVariable(name);\r
+       _parameters.push_back(name);\r
+}\r
+\r
+void SQFuncState::AddLineInfos(int line,bool lineop,bool force)\r
+{\r
+       if(_lastline!=line || force){\r
+               SQLineInfo li;\r
+               li._line=line;li._op=(GetCurrentPos()+1);\r
+               if(lineop)AddInstruction(_OP_LINE,0,line);\r
+               _lineinfos.push_back(li);\r
+               _lastline=line;\r
+       }\r
+}\r
+\r
+void SQFuncState::AddInstruction(SQInstruction &i)\r
+{\r
+       int size = _instructions.size();\r
+       if(size > 0 && _optimization){ //simple optimizer\r
+               SQInstruction &pi = _instructions[size-1];//previous instruction\r
+               switch(i.op) {\r
+               case _OP_RETURN:\r
+                       if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {\r
+                               pi.op = _OP_TAILCALL;\r
+                       }\r
+               break;\r
+               case _OP_GET:\r
+                       if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){\r
+                               pi._arg1 = pi._arg1;\r
+                               pi._arg2 = (unsigned char)i._arg1;\r
+                               pi.op = _OP_GETK;\r
+                               pi._arg0 = i._arg0;\r
+                               \r
+                               return;\r
+                       }\r
+               break;\r
+               case _OP_PREPCALL:\r
+                       if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
+                               pi.op = _OP_PREPCALLK;\r
+                               pi._arg0 = i._arg0;\r
+                               pi._arg1 = pi._arg1;\r
+                               pi._arg2 = i._arg2;\r
+                               pi._arg3 = i._arg3;\r
+                               return;\r
+                       }\r
+                       break;\r
+               case _OP_APPENDARRAY:\r
+                       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
+                               pi.op = _OP_APPENDARRAY;\r
+                               pi._arg0 = i._arg0;\r
+                               pi._arg1 = pi._arg1;\r
+                               pi._arg2 = MAX_FUNC_STACKSIZE;\r
+                               pi._arg3 = MAX_FUNC_STACKSIZE;\r
+                               return;\r
+                       }\r
+                       break;\r
+               case _OP_MOVE: \r
+                       if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))\r
+                       {\r
+                               pi._arg0 = i._arg0;\r
+                               _optimization = false;\r
+                               return;\r
+                       }\r
+\r
+                       if(pi.op == _OP_MOVE)\r
+                       {\r
+                               pi.op = _OP_DMOVE;\r
+                               pi._arg2 = i._arg0;\r
+                               pi._arg3 = (unsigned char)i._arg1;\r
+                               return;\r
+                       }\r
+                       break;\r
+\r
+               case _OP_EQ:case _OP_NE:\r
+                       if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))\r
+                       {\r
+                               pi.op = i.op;\r
+                               pi._arg0 = i._arg0;\r
+                               pi._arg1 = pi._arg1;\r
+                               pi._arg2 = i._arg2;\r
+                               pi._arg3 = MAX_FUNC_STACKSIZE;\r
+                               return;\r
+                       }\r
+                       break;\r
+               case _OP_LOADNULLS:\r
+               //case _OP_LOADNULL:\r
+                       if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {\r
+                               \r
+                               pi._arg1 = pi._arg1 + 1;\r
+                               pi.op = _OP_LOADNULLS;\r
+                               return;\r
+                       }\r
+            break;\r
+               case _OP_LINE:\r
+                       if(pi.op == _OP_LINE) {\r
+                               _instructions.pop_back();\r
+                               _lineinfos.pop_back();\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+       _optimization = true;\r
+       _instructions.push_back(i);\r
+}\r
+\r
+SQObject SQFuncState::CreateString(const SQChar *s)\r
+{\r
+       SQObjectPtr ns(SQString::Create(_sharedstate,s));\r
+       _stringrefs.push_back(ns);\r
+       return ns;\r
+}\r
+\r
+void SQFuncState::Finalize()\r
+{\r
+       SQFunctionProto *f=_funcproto(_func);\r
+       f->_literals.resize(_nliterals);\r
+       SQObjectPtr refidx,key,val;\r
+       SQInteger idx;\r
+       while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
+               f->_literals[_integer(val)]=key;\r
+               refidx=idx;\r
+       }\r
+       f->_functions.resize(_functions.size());\r
+       f->_functions.copy(_functions);\r
+       f->_parameters.resize(_parameters.size());\r
+       f->_parameters.copy(_parameters);\r
+       f->_outervalues.resize(_outervalues.size());\r
+       f->_outervalues.copy(_outervalues);\r
+       f->_instructions.resize(_instructions.size());\r
+       f->_instructions.copy(_instructions);\r
+       f->_localvarinfos.resize(_localvarinfos.size());\r
+       f->_localvarinfos.copy(_localvarinfos);\r
+       f->_lineinfos.resize(_lineinfos.size());\r
+       f->_lineinfos.copy(_lineinfos);\r
+       f->_varparams = _varparams;\r
+}\r
diff --git a/src/squirrel/squirrel/sqfuncstate.h b/src/squirrel/squirrel/sqfuncstate.h
new file mode 100644 (file)
index 0000000..d35e963
--- /dev/null
@@ -0,0 +1,74 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQFUNCSTATE_H_\r
+#define _SQFUNCSTATE_H_\r
+///////////////////////////////////\r
+#include "squtils.h"\r
+\r
+\r
+\r
+struct SQFuncState\r
+{\r
+       SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent);\r
+#ifdef _DEBUG_DUMP\r
+       void Dump();\r
+#endif\r
+       void AddInstruction(SQOpcode _op,int arg0=0,int arg1=0,int arg2=0,int arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}\r
+       void AddInstruction(SQInstruction &i);\r
+       void SetIntructionParams(int pos,int arg0,int arg1,int arg2=0,int arg3=0);\r
+       void SetIntructionParam(int pos,int arg,int val);\r
+       SQInstruction &GetInstruction(int pos){return _instructions[pos];}\r
+       void PopInstructions(int size){for(int i=0;i<size;i++)_instructions.pop_back();}\r
+       void SetStackSize(int n);\r
+       void SnoozeOpt(){_optimization=false;}\r
+       int GetCurrentPos(){return _instructions.size()-1;}\r
+       int GetStringConstant(const SQChar *cons);\r
+       int GetNumericConstant(const SQInteger cons);\r
+       int GetNumericConstant(const SQFloat cons);\r
+       int PushLocalVariable(const SQObjectPtr &name);\r
+       void AddParameter(const SQObjectPtr &name);\r
+       void AddOuterValue(const SQObjectPtr &name);\r
+       int GetLocalVariable(const SQObjectPtr &name);\r
+       int GetOuterVariable(const SQObjectPtr &name);\r
+       int GenerateCode();\r
+       int GetStackSize();\r
+       int CalcStackFrameSize();\r
+       void AddLineInfos(int line,bool lineop,bool force=false);\r
+       void Finalize();\r
+       int AllocStackPos();\r
+       int PushTarget(int n=-1);\r
+       int PopTarget();\r
+       int TopTarget();\r
+       int GetUpTarget(int n);\r
+       bool IsLocal(unsigned int stkpos);\r
+       SQObject CreateString(const SQChar *s);\r
+       int _returnexp;\r
+       SQLocalVarInfoVec _vlocals;\r
+       SQIntVec _targetstack;\r
+       int _stacksize;\r
+       bool _varparams;\r
+       SQIntVec _unresolvedbreaks;\r
+       SQIntVec _unresolvedcontinues;\r
+       SQObjectPtrVec _functions;\r
+       SQObjectPtrVec _parameters;\r
+       SQObjectPtrVec _stringrefs;\r
+       SQOuterVarVec _outervalues;\r
+       SQInstructionVec _instructions;\r
+       SQLocalVarInfoVec _localvarinfos;\r
+       SQObjectPtr _literals;\r
+       SQInteger _nliterals;\r
+       SQLineInfoVec _lineinfos;\r
+       SQObjectPtr _func;\r
+       SQFuncState *_parent;\r
+       SQIntVec _breaktargets; //contains number of nested exception traps\r
+       SQIntVec _continuetargets;\r
+       int _lastline;\r
+       int _traps;\r
+       bool _optimization;\r
+       SQSharedState *_sharedstate;\r
+private:\r
+       int GetConstant(SQObjectPtr cons);\r
+};\r
+\r
+\r
+#endif //_SQFUNCSTATE_H_\r
+\r
diff --git a/src/squirrel/squirrel/sqlexer.cpp b/src/squirrel/squirrel/sqlexer.cpp
new file mode 100644 (file)
index 0000000..9dcd87f
--- /dev/null
@@ -0,0 +1,405 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+#include "sqtable.h"\r
+#include "sqstring.h"\r
+#include "sqcompiler.h"\r
+#include "sqlexer.h"\r
+\r
+#define CUR_CHAR (_currdata)\r
+#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}\r
+#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)\r
+#define NEXT() {Next();_currentcolumn++;}\r
+#define INIT_TEMP_STRING() { _longstr.resize(0);}\r
+#define APPEND_CHAR(c) { _longstr.push_back(c);}\r
+#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}\r
+#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))\r
+\r
+SQLexer::SQLexer(){}\r
+SQLexer::~SQLexer()\r
+{\r
+       _keywords->Release();\r
+}\r
+\r
+void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)\r
+{\r
+       _sharedstate = ss;\r
+       _keywords = SQTable::Create(ss, 26);\r
+       ADD_KEYWORD(while, TK_WHILE);\r
+       ADD_KEYWORD(do, TK_DO);\r
+       ADD_KEYWORD(if, TK_IF);\r
+       ADD_KEYWORD(else, TK_ELSE);\r
+       ADD_KEYWORD(break, TK_BREAK);\r
+       ADD_KEYWORD(continue, TK_CONTINUE);\r
+       ADD_KEYWORD(return, TK_RETURN);\r
+       ADD_KEYWORD(null, TK_NULL);\r
+       ADD_KEYWORD(function, TK_FUNCTION);\r
+       ADD_KEYWORD(local, TK_LOCAL);\r
+       ADD_KEYWORD(for, TK_FOR);\r
+       ADD_KEYWORD(foreach, TK_FOREACH);\r
+       ADD_KEYWORD(in, TK_IN);\r
+       ADD_KEYWORD(typeof, TK_TYPEOF);\r
+       ADD_KEYWORD(delegate, TK_DELEGATE);\r
+       ADD_KEYWORD(delete, TK_DELETE);\r
+       ADD_KEYWORD(try, TK_TRY);\r
+       ADD_KEYWORD(catch, TK_CATCH);\r
+       ADD_KEYWORD(throw, TK_THROW);\r
+       ADD_KEYWORD(clone, TK_CLONE);\r
+       ADD_KEYWORD(yield, TK_YIELD);\r
+       ADD_KEYWORD(resume, TK_RESUME);\r
+       ADD_KEYWORD(switch, TK_SWITCH);\r
+       ADD_KEYWORD(case, TK_CASE);\r
+       ADD_KEYWORD(default, TK_DEFAULT);\r
+       ADD_KEYWORD(this, TK_THIS);\r
+       ADD_KEYWORD(parent,TK_PARENT);\r
+       ADD_KEYWORD(class,TK_CLASS);\r
+       ADD_KEYWORD(extends,TK_EXTENDS);\r
+       ADD_KEYWORD(constructor,TK_CONSTRUCTOR);\r
+       ADD_KEYWORD(instanceof,TK_INSTANCEOF);\r
+       ADD_KEYWORD(vargc,TK_VARGC);\r
+       ADD_KEYWORD(vargv,TK_VARGV);\r
+       ADD_KEYWORD(true,TK_TRUE);\r
+       ADD_KEYWORD(false,TK_FALSE);\r
+\r
+       _readf = rg;\r
+       _up = up;\r
+       _lasttokenline = _currentline = 1;\r
+       _currentcolumn = 0;\r
+       _prevtoken = -1;\r
+       Next();\r
+}\r
+\r
+void SQLexer::Next()\r
+{\r
+       SQInteger t = _readf(_up);\r
+       if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));\r
+       if(t != 0) {\r
+               _currdata = t;\r
+               return;\r
+       }\r
+       _currdata = SQUIRREL_EOB;\r
+}\r
+\r
+SQObjectPtr SQLexer::Tok2Str(int tok)\r
+{\r
+       SQObjectPtr itr, key, val;\r
+       int nitr;\r
+       while((nitr = _keywords->Next(itr, key, val)) != -1) {\r
+               itr = (SQInteger)nitr;\r
+               if(((int)_integer(val)) == tok)\r
+                       return key;\r
+       }\r
+       return SQObjectPtr();\r
+}\r
+\r
+void SQLexer::LexBlockComment()\r
+{\r
+       bool done = false;\r
+       while(!done) {\r
+               switch(CUR_CHAR) {\r
+                       case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;\r
+                       //case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;\r
+                       case _SC('\n'): _currentline++; NEXT(); continue;\r
+                       case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));\r
+                       default: NEXT();\r
+               }\r
+       }\r
+}\r
+\r
+int SQLexer::Lex()\r
+{\r
+       _lasttokenline = _currentline;\r
+       while(CUR_CHAR != SQUIRREL_EOB) {\r
+               switch(CUR_CHAR){\r
+               case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;\r
+               case _SC('\n'):\r
+                       _currentline++;\r
+                       _prevtoken=_curtoken;\r
+                       _curtoken=_SC('\n');\r
+                       NEXT();\r
+                       _currentcolumn=1;\r
+                       continue;\r
+               case _SC('/'):\r
+                       NEXT();\r
+                       switch(CUR_CHAR){\r
+                       case _SC('*'):\r
+                               NEXT();\r
+                               LexBlockComment();\r
+                               continue;       \r
+                       case _SC('/'):\r
+                               do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));\r
+                               continue;\r
+                       case _SC('='):\r
+                               NEXT();\r
+                               RETURN_TOKEN(TK_DIVEQ);\r
+                               continue;\r
+                       case _SC('>'):\r
+                               NEXT();\r
+                               RETURN_TOKEN(TK_ATTR_CLOSE);\r
+                               continue;\r
+                       default:\r
+                               RETURN_TOKEN('/');\r
+                       }\r
+               case _SC('='):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }\r
+                       else { NEXT(); RETURN_TOKEN(TK_EQ); }\r
+               case _SC('<'):\r
+                       NEXT();\r
+                       if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }\r
+                       else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }\r
+                       else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }\r
+                       else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }\r
+                       //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }\r
+                       else { RETURN_TOKEN('<') }\r
+               case _SC('>'):\r
+                       NEXT();\r
+                       if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}\r
+                       else if(CUR_CHAR == _SC('>')){ \r
+                               NEXT(); \r
+                               if(CUR_CHAR == _SC('>')){\r
+                                       NEXT();\r
+                                       RETURN_TOKEN(TK_USHIFTR);\r
+                               }\r
+                               RETURN_TOKEN(TK_SHIFTR);\r
+                       }\r
+                       else { RETURN_TOKEN('>') }\r
+               case _SC('!'):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}\r
+                       else { NEXT(); RETURN_TOKEN(TK_NE); }\r
+               case _SC('@'): {\r
+                       int stype;\r
+                       NEXT(); \r
+                       if(CUR_CHAR != _SC('"'))\r
+                               throw ParserException(_SC("string expected"));\r
+                       if((stype=ReadString('"',true))!=-1) {\r
+                               RETURN_TOKEN(stype);\r
+                       }\r
+                       throw ParserException(_SC("error parsing the string"));\r
+                                          }\r
+               case _SC('"'):\r
+               case _SC('\''): {\r
+                       int stype;\r
+                       if((stype=ReadString(CUR_CHAR,false))!=-1){\r
+                               RETURN_TOKEN(stype);\r
+                       }\r
+                       throw ParserException(_SC("error parsing the string"));\r
+                       }\r
+               case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):\r
+               case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):\r
+                       {int ret = CUR_CHAR;\r
+                       NEXT(); RETURN_TOKEN(ret); }\r
+               case _SC('.'):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }\r
+                       NEXT();\r
+                       RETURN_TOKEN(TK_VARPARAMS);\r
+               case _SC('&'):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }\r
+                       else { NEXT(); RETURN_TOKEN(TK_AND); }\r
+               case _SC('|'):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }\r
+                       else { NEXT(); RETURN_TOKEN(TK_OR); }\r
+               case _SC(':'):\r
+                       NEXT();\r
+                       if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }\r
+                       else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }\r
+               case _SC('*'):\r
+                       NEXT();\r
+                       if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}\r
+                       else RETURN_TOKEN('*');\r
+               case _SC('%'):\r
+                       NEXT();\r
+                       if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}\r
+                       else RETURN_TOKEN('%');\r
+               case _SC('-'):\r
+                       NEXT();\r
+                       if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}\r
+                       else if  (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}\r
+                       else RETURN_TOKEN('-');\r
+               case _SC('+'):\r
+                       NEXT();\r
+                       if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}\r
+                       else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}\r
+                       else RETURN_TOKEN('+');\r
+               case SQUIRREL_EOB:\r
+                       return 0;\r
+               default:{\r
+                               if (scisdigit(CUR_CHAR)) {\r
+                                       int ret = ReadNumber();\r
+                                       RETURN_TOKEN(ret);\r
+                               }\r
+                               else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {\r
+                                       int t = ReadID();\r
+                                       RETURN_TOKEN(t);\r
+                               }\r
+                               else {\r
+                                       int c = CUR_CHAR;\r
+                                       if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));\r
+                                       NEXT();\r
+                                       RETURN_TOKEN(c);  \r
+                               }\r
+                               RETURN_TOKEN(0);\r
+                       }\r
+               }\r
+       }\r
+       return 0;    \r
+}\r
+       \r
+int SQLexer::GetIDType(SQChar *s)\r
+{\r
+       SQObjectPtr t;\r
+       if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {\r
+               return int(_integer(t));\r
+       }\r
+       return TK_IDENTIFIER;\r
+}\r
+\r
+\r
+int SQLexer::ReadString(int ndelim,bool verbatim)\r
+{\r
+       INIT_TEMP_STRING();\r
+       NEXT();\r
+       if(IS_EOB()) return -1;\r
+       for(;;) {\r
+               while(CUR_CHAR != ndelim) {\r
+                       switch(CUR_CHAR) {\r
+                       case SQUIRREL_EOB:\r
+                               throw ParserException(_SC("unfinished string"));\r
+                               return -1;\r
+                       case _SC('\n'): \r
+                               if(!verbatim) throw ParserException(_SC("newline in a constant")); \r
+                               APPEND_CHAR(CUR_CHAR); NEXT(); \r
+                               break;\r
+                       case _SC('\\'):\r
+                               if(verbatim) {\r
+                                       APPEND_CHAR('\\'); NEXT(); \r
+                               }\r
+                               else {\r
+\r
+                                       NEXT();\r
+                                       switch(CUR_CHAR) {\r
+                                       case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;\r
+                                       case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;\r
+                                       case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;\r
+                                       case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;\r
+                                       case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;\r
+                                       case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;\r
+                                       case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;\r
+                                       case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;\r
+                                       case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;\r
+                                       case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;\r
+                                       case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;\r
+                                       default:\r
+                                               throw ParserException(_SC("unrecognised escaper char"));\r
+                                       break;\r
+                                       }\r
+                               }\r
+                               break;\r
+                       default:\r
+                               APPEND_CHAR(CUR_CHAR);\r
+                               NEXT();\r
+                       }\r
+               }\r
+               NEXT();\r
+               if(verbatim && CUR_CHAR == '"') { //double quotation\r
+                       APPEND_CHAR(CUR_CHAR);\r
+                       NEXT();\r
+               }\r
+               else {\r
+                       break;\r
+               }\r
+       }\r
+       TERMINATE_BUFFER();\r
+       int len = _longstr.size()-1;\r
+       if(ndelim == _SC('\'')) {\r
+               if(len == 0) throw ParserException(_SC("empty constant"));\r
+               if(len > 1) throw ParserException(_SC("constant too long"));\r
+               _nvalue = _longstr[0];\r
+               return TK_INTEGER;\r
+       }\r
+       _svalue = &_longstr[0];\r
+       return TK_STRING_LITERAL;\r
+}\r
+\r
+int isexponent(int c) { return c == 'e' || c=='E'; }\r
+\r
+int SQLexer::ReadNumber()\r
+{\r
+#define TINT 1\r
+#define TFLOAT 2\r
+#define THEX 3\r
+#define TSCIENTIFIC 4\r
+       int type = TINT, firstchar = CUR_CHAR;\r
+       bool isfloat = false;\r
+       SQChar *sTemp;\r
+       INIT_TEMP_STRING();\r
+       NEXT();\r
+       if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {\r
+               NEXT();\r
+               type = THEX;\r
+               while(isxdigit(CUR_CHAR)) {\r
+                       APPEND_CHAR(CUR_CHAR);\r
+                       NEXT();\r
+               }\r
+               if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));\r
+       }\r
+       else {\r
+               APPEND_CHAR(firstchar);\r
+               while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {\r
+            if(CUR_CHAR == _SC('.')) type = TFLOAT;\r
+                       if(isexponent(CUR_CHAR)) {\r
+                               if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));\r
+                               type = TSCIENTIFIC;\r
+                               APPEND_CHAR(CUR_CHAR);\r
+                               NEXT();\r
+                               if(CUR_CHAR == '+' || CUR_CHAR == '-'){\r
+                                       APPEND_CHAR(CUR_CHAR);\r
+                                       NEXT();\r
+                               }\r
+                               if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));\r
+                       }\r
+                       \r
+                       APPEND_CHAR(CUR_CHAR);\r
+                       NEXT();\r
+               }\r
+       }\r
+       TERMINATE_BUFFER();\r
+       switch(type) {\r
+       case TSCIENTIFIC:\r
+       case TFLOAT:\r
+               _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);\r
+               return TK_FLOAT;\r
+       case TINT:\r
+               _nvalue = (SQInteger)scatoi(&_longstr[0]);\r
+               return TK_INTEGER;\r
+       case THEX:\r
+               *((unsigned long *)&_nvalue) = scstrtoul(&_longstr[0],&sTemp,16);\r
+               return TK_INTEGER;\r
+       }\r
+       return 0;\r
+}\r
+\r
+int SQLexer::ReadID()\r
+{\r
+       int res, size = 0;\r
+       INIT_TEMP_STRING();\r
+       do {\r
+               APPEND_CHAR(CUR_CHAR);\r
+               NEXT();\r
+       } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));\r
+       TERMINATE_BUFFER();\r
+       res = GetIDType(&_longstr[0]);\r
+       if(res == TK_IDENTIFIER) {\r
+               _svalue = &_longstr[0];\r
+       }\r
+       return res;\r
+}\r
diff --git a/src/squirrel/squirrel/sqlexer.h b/src/squirrel/squirrel/sqlexer.h
new file mode 100644 (file)
index 0000000..3f13c6b
--- /dev/null
@@ -0,0 +1,42 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQLEXER_H_\r
+#define _SQLEXER_H_\r
+\r
+#define MAX_STRING 2024\r
+\r
+struct SQLexer\r
+{\r
+       SQLexer();\r
+       ~SQLexer();\r
+       void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);\r
+       int Lex();\r
+       SQObjectPtr Tok2Str(int tok);\r
+private:\r
+       int GetIDType(SQChar *s);\r
+       int ReadString(int ndelim,bool verbatim);\r
+       int ReadNumber();\r
+       void LexBlockComment();\r
+       int ReadID();\r
+       void Next();\r
+       int _curtoken;\r
+       SQTable *_keywords;\r
+public:\r
+       int _prevtoken;\r
+       int _currentline;\r
+       int _lasttokenline;\r
+       int _currentcolumn;\r
+       const SQChar *_svalue;\r
+       SQInteger _nvalue;\r
+       SQFloat _fvalue;\r
+       SQLEXREADFUNC _readf;\r
+       SQUserPointer _up;\r
+#ifdef _UNICODE\r
+       SQChar _currdata;\r
+#else\r
+       unsigned char _currdata;\r
+#endif\r
+       SQSharedState *_sharedstate;\r
+       sqvector<SQChar> _longstr;\r
+};\r
+\r
+#endif\r
diff --git a/src/squirrel/squirrel/sqmem.cpp b/src/squirrel/squirrel/sqmem.cpp
new file mode 100644 (file)
index 0000000..f85c887
--- /dev/null
@@ -0,0 +1,9 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+void *sq_vm_malloc(unsigned int size){ return malloc(size); }\r
+\r
+void *sq_vm_realloc(void *p, unsigned int oldsize, unsigned int size){ return realloc(p, size); }\r
+\r
+void sq_vm_free(void *p, unsigned int size){   free(p); }\r
diff --git a/src/squirrel/squirrel/sqobject.cpp b/src/squirrel/squirrel/sqobject.cpp
new file mode 100644 (file)
index 0000000..cf5aa8e
--- /dev/null
@@ -0,0 +1,464 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqstring.h"\r
+#include "sqarray.h"\r
+#include "sqtable.h"\r
+#include "squserdata.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclass.h"\r
+#include "sqclosure.h"\r
+\r
+SQString *SQString::Create(SQSharedState *ss,const SQChar *s,int len)\r
+{\r
+       SQString *str=ADD_STRING(ss,s,len);\r
+       str->_sharedstate=ss;\r
+       return str;\r
+}\r
+\r
+void SQString::Release()\r
+{\r
+       REMOVE_STRING(_sharedstate,this);\r
+}\r
+\r
+unsigned int TranslateIndex(const SQObjectPtr &idx)\r
+{\r
+       switch(type(idx)){\r
+               case OT_NULL:\r
+                       return 0;\r
+               case OT_INTEGER:\r
+                       return (unsigned int)_integer(idx);\r
+       }\r
+       assert(0);\r
+       return 0;\r
+}\r
+\r
+bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {\r
+       if(_delegate) {\r
+               return _delegate->Get((*_ss(this)->_metamethods)[mm],res);\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQGenerator::Yield(SQVM *v)\r
+{\r
+       if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}\r
+       if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
+       int size = v->_top-v->_stackbase;\r
+       _ci=*v->ci;\r
+       _stack.resize(size);\r
+       for(int n =0; n<size; n++) {\r
+               _stack._vals[n] = v->_stack[v->_stackbase+n];\r
+               v->_stack[v->_stackbase+n] = _null_;\r
+       }\r
+       int nvargs = v->ci->_vargs.size;\r
+       int vargsbase = v->ci->_vargs.base;\r
+       for(int j = nvargs - 1; j >= 0; j--) {\r
+               _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
+       }\r
+       _ci._generator=_null_;\r
+       for(int i=0;i<_ci._etraps;i++) {\r
+               _etraps.push_back(v->_etraps.top());\r
+               v->_etraps.pop_back();\r
+       }\r
+       _state=eSuspended;\r
+       return true;\r
+}\r
+\r
+bool SQGenerator::Resume(SQVM *v,int target)\r
+{\r
+       int size=_stack.size();\r
+       if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
+       if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
+       int prevtop=v->_top-v->_stackbase;\r
+       PUSH_CALLINFO(v,_ci);\r
+       int oldstackbase=v->_stackbase;\r
+       v->_stackbase=v->_top;\r
+       v->ci->_target=target;\r
+       v->ci->_generator=SQObjectPtr(this);\r
+       v->ci->_vargs.size = _vargsstack.size();\r
+       \r
+       for(int i=0;i<_ci._etraps;i++) {\r
+               v->_etraps.push_back(_etraps.top());\r
+               _etraps.pop_back();\r
+       }\r
+       for(int n =0; n<size; n++) {\r
+               v->_stack[v->_stackbase+n] = _stack._vals[n];\r
+               _stack._vals[0] = _null_;\r
+       }\r
+       while(_vargsstack.size()) {\r
+               v->_vargsstack.push_back(_vargsstack.back());\r
+               _vargsstack.pop_back();\r
+       }\r
+       v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;\r
+       v->_top=v->_stackbase+size;\r
+       v->ci->_prevtop=prevtop;\r
+       v->ci->_prevstkbase=v->_stackbase-oldstackbase;\r
+       _state=eRunning;\r
+       return true;\r
+}\r
+\r
+void SQArray::Extend(const SQArray *a){\r
+       int xlen;\r
+       if((xlen=a->Size()))\r
+               for(int i=0;i<xlen;i++)\r
+                       Append(a->_values[i]);\r
+}\r
+\r
+const SQChar* SQFunctionProto::GetLocal(SQVM *vm,unsigned int stackbase,unsigned int nseq,unsigned int nop)\r
+{\r
+       unsigned int nvars=_localvarinfos.size();\r
+       const SQChar *res=NULL; \r
+       if(nvars>=nseq){\r
+               for(unsigned int i=0;i<nvars;i++){\r
+                       if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)\r
+                       {\r
+                               if(nseq==0){\r
+                                       vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);\r
+                                       res=_stringval(_localvarinfos[i]._name);\r
+                                       break;\r
+                               }\r
+                               nseq--;\r
+                       }\r
+               }\r
+       }\r
+       return res;\r
+}\r
+\r
+int SQFunctionProto::GetLine(SQInstruction *curr)\r
+{\r
+       int op=(curr-_instructions._vals);\r
+       int line=_lineinfos[0]._line;\r
+       for(unsigned int i=1;i<_lineinfos.size();i++){\r
+               if(_lineinfos[i]._op>=op)\r
+                       return line;\r
+               line=_lineinfos[i]._line;\r
+       }\r
+       return line;\r
+}\r
+\r
+//#define _ERROR_TRAP() error_trap:\r
+#define _CHECK_IO(exp)  { if(!exp)return false; }\r
+bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,int size)\r
+{\r
+       if(write(up,dest,size) != size) {\r
+               v->Raise_Error(_SC("io error (write function failure)"));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,int size)\r
+{\r
+       if(size && read(up,dest,size) != size) {\r
+               v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,int tag)\r
+{\r
+       return SafeWrite(v,write,up,&tag,sizeof(tag));\r
+}\r
+\r
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,int tag)\r
+{\r
+       int t;\r
+       _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
+       if(t != tag){\r
+               v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
+{\r
+       _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
+       switch(type(o)){\r
+       case OT_STRING:\r
+               _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
+               _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
+               break;\r
+       case OT_INTEGER:\r
+               _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
+       case OT_FLOAT:\r
+               _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;\r
+       case OT_NULL:\r
+               break;\r
+       default:\r
+               v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
+{\r
+       SQObjectType t;\r
+       _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
+       switch(t){\r
+       case OT_STRING:{\r
+               int len;\r
+               _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));\r
+               _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));\r
+               o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);\r
+                                  }\r
+               break;\r
+       case OT_INTEGER:{\r
+               SQInteger i;\r
+               _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
+                                       }\r
+       case OT_FLOAT:{\r
+               SQFloat f;\r
+               _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
+                                 }\r
+       case OT_NULL:\r
+               o=_null_;\r
+               break;\r
+       default:\r
+               v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
+{\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
+       _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
+       _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
+       return true;\r
+}\r
+\r
+bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
+{\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
+       _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
+       _CHECK_IO(_funcproto(_function)->Load(v,up,read));\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
+       return true;\r
+}\r
+\r
+bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
+{\r
+       int i,nsize=_literals.size();\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(WriteObject(v,up,write,_sourcename));\r
+       _CHECK_IO(WriteObject(v,up,write,_name));\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       for(i=0;i<nsize;i++){\r
+               _CHECK_IO(WriteObject(v,up,write,_literals[i]));\r
+       }\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_parameters.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       for(i=0;i<nsize;i++){\r
+               _CHECK_IO(WriteObject(v,up,write,_parameters[i]));\r
+       }\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_outervalues.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       for(i=0;i<nsize;i++){\r
+               _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(unsigned int)));\r
+               _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));\r
+               _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));\r
+       }\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_localvarinfos.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       for(i=0;i<nsize;i++){\r
+               SQLocalVarInfo &lvi=_localvarinfos[i];\r
+               _CHECK_IO(WriteObject(v,up,write,lvi._name));\r
+               _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(unsigned int)));\r
+               _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(unsigned int)));\r
+               _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(unsigned int)));\r
+       }\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_lineinfos.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_instructions.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));\r
+       _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+       nsize=_functions.size();\r
+       _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
+       for(i=0;i<nsize;i++){\r
+               _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));\r
+       }\r
+       _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));\r
+       _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));\r
+       _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));\r
+       return true;\r
+}\r
+\r
+bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
+{\r
+       int i, nsize = _literals.size();\r
+       SQObjectPtr o;\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(ReadObject(v, up, read, _sourcename));\r
+       _CHECK_IO(ReadObject(v, up, read, _name));\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
+       for(i = 0;i < nsize; i++){\r
+               _CHECK_IO(ReadObject(v, up, read, o));\r
+               _literals.push_back(o);\r
+       }\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
+       for(i = 0; i < nsize; i++){\r
+               _CHECK_IO(ReadObject(v, up, read, o));\r
+               _parameters.push_back(o);\r
+       }\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));\r
+       for(i = 0; i < nsize; i++){\r
+               unsigned int type;\r
+               SQObjectPtr name;\r
+               _CHECK_IO(SafeRead(v,read,up, &type, sizeof(unsigned int)));\r
+               _CHECK_IO(ReadObject(v, up, read, o));\r
+               _CHECK_IO(ReadObject(v, up, read, name));\r
+               _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));\r
+       }\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));\r
+       for(i = 0; i < nsize; i++){\r
+               SQLocalVarInfo lvi;\r
+               _CHECK_IO(ReadObject(v, up, read, lvi._name));\r
+               _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(unsigned int)));\r
+               _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(unsigned int)));\r
+               _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(unsigned int)));\r
+               _localvarinfos.push_back(lvi);\r
+       }\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));\r
+       _lineinfos.resize(nsize);\r
+       _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
+       _instructions.resize(nsize);\r
+       _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));\r
+       _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+       _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
+       for(i = 0; i < nsize; i++){\r
+               o = SQFunctionProto::Create();\r
+               _CHECK_IO(_funcproto(o)->Load(v, up, read));\r
+               _functions.push_back(o);\r
+       }\r
+       _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));\r
+       _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));\r
+       _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));\r
+       return true;\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+\r
+#define START_MARK()   if(!(_uiRef&MARK_FLAG)){ \\r
+               _uiRef|=MARK_FLAG;\r
+\r
+#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \\r
+               AddToChain(chain, this); }\r
+\r
+void SQVM::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               SQSharedState::MarkObject(_lasterror,chain);\r
+               SQSharedState::MarkObject(_errorhandler,chain);\r
+               SQSharedState::MarkObject(_debughook,chain);\r
+               SQSharedState::MarkObject(_roottable, chain);\r
+               SQSharedState::MarkObject(temp_reg, chain);\r
+               for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
+               for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQArray::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               int len = _values.size();\r
+               for(int i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);\r
+       END_MARK()\r
+}\r
+void SQTable::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               if(_delegate) _delegate->Mark(chain);\r
+               int len = _numofnodes;\r
+               for(int i = 0; i < len; i++){\r
+                       SQSharedState::MarkObject(_nodes[i].key, chain);\r
+                       SQSharedState::MarkObject(_nodes[i].val, chain);\r
+               }\r
+       END_MARK()\r
+}\r
+\r
+void SQClass::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               _members->Mark(chain);\r
+               if(_base) _base->Mark(chain);\r
+               SQSharedState::MarkObject(_attributes, chain);\r
+               for(unsigned int i =0; i< _defaultvalues.size(); i++) {\r
+                       SQSharedState::MarkObject(_defaultvalues[i].val, chain);\r
+                       SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);\r
+               }\r
+               for(unsigned int j =0; j< _methods.size(); j++) {\r
+                       SQSharedState::MarkObject(_methods[j].val, chain);\r
+                       SQSharedState::MarkObject(_methods[j].attrs, chain);\r
+               }\r
+               for(unsigned int k =0; k< _metamethods.size(); k++) {\r
+                       SQSharedState::MarkObject(_metamethods[k], chain);\r
+               }\r
+       END_MARK()\r
+}\r
+\r
+void SQInstance::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               _class->Mark(chain);\r
+               for(unsigned int i =0; i< _values.size(); i++) {\r
+                       SQSharedState::MarkObject(_values[i], chain);\r
+               }\r
+       END_MARK()\r
+}\r
+\r
+void SQGenerator::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
+               for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
+               SQSharedState::MarkObject(_closure, chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQClosure::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQNativeClosure::Mark(SQCollectable **chain)\r
+{\r
+       START_MARK()\r
+               for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQUserData::Mark(SQCollectable **chain){\r
+       START_MARK()\r
+               if(_delegate) _delegate->Mark(chain);\r
+       END_MARK()\r
+}\r
+\r
+void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }\r
+\r
+#endif\r
+\r
diff --git a/src/squirrel/squirrel/sqobject.h b/src/squirrel/squirrel/sqobject.h
new file mode 100644 (file)
index 0000000..8c900b7
--- /dev/null
@@ -0,0 +1,304 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQOBJECT_H_\r
+#define _SQOBJECT_H_\r
+\r
+#include "squtils.h"\r
+\r
+#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))\r
+#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))\r
+#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))\r
+\r
+#define SQ_TRY try\r
+#define SQ_CATCH(type, ex) catch(type &ex)\r
+\r
+struct SQSharedState;\r
+\r
+enum SQMetaMethod{\r
+       MT_ADD=0,\r
+       MT_SUB=1,\r
+       MT_MUL=2,\r
+       MT_DIV=3,\r
+       MT_UNM=4,\r
+       MT_MODULO=5,\r
+       MT_SET=6,\r
+       MT_GET=7,\r
+       MT_TYPEOF=8,\r
+       MT_NEXTI=9,\r
+       MT_CMP=10,\r
+       MT_CALL=11,\r
+       MT_CLONED=12,\r
+       MT_NEWSLOT=13,\r
+       MT_DELSLOT=14,\r
+       MT_LAST = 15,\r
+};\r
+\r
+#define MM_ADD         _SC("_add")\r
+#define MM_SUB         _SC("_sub")\r
+#define MM_MUL         _SC("_mul")\r
+#define MM_DIV         _SC("_div")\r
+#define MM_UNM         _SC("_unm")\r
+#define MM_MODULO      _SC("_modulo")\r
+#define MM_SET         _SC("_set")\r
+#define MM_GET         _SC("_get")\r
+#define MM_TYPEOF      _SC("_typeof")\r
+#define MM_NEXTI       _SC("_nexti")\r
+#define MM_CMP         _SC("_cmp")\r
+#define MM_CALL                _SC("_call")\r
+#define MM_CLONED      _SC("_cloned")\r
+#define MM_NEWSLOT     _SC("_newslot")\r
+#define MM_DELSLOT     _SC("_delslot")\r
+\r
+#define MINPOWER2 4\r
+\r
+struct SQRefCounted\r
+{\r
+        virtual ~SQRefCounted() {}\r
+\r
+       unsigned int _uiRef;\r
+       virtual void Release()=0;\r
+};\r
+\r
+struct SQObjectPtr;\r
+\r
+#define __AddRef(type,unval) if(ISREFCOUNTED(type))    \\r
+               { \\r
+                       unval.pRefCounted->_uiRef++; \\r
+               }  \r
+\r
+#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0))     \\r
+               {       \\r
+                       unval.pRefCounted->Release();   \\r
+               }\r
+\r
+#define __ObjRelease(obj) { \\r
+       if((obj)) {     \\r
+               (obj)->_uiRef--; \\r
+               if((obj)->_uiRef == 0) \\r
+                       (obj)->Release(); \\r
+               (obj) = NULL;   \\r
+       } \\r
+}\r
+\r
+#define __ObjAddRef(obj) { \\r
+       (obj)->_uiRef++; \\r
+}\r
+\r
+#define type(obj) ((obj)._type)\r
+#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)\r
+#define raw_type(obj) _RAW_TYPE((obj)._type)\r
+\r
+#define _integer(obj) ((obj)._unVal.nInteger)\r
+#define _float(obj) ((obj)._unVal.fFloat)\r
+#define _string(obj) ((obj)._unVal.pString)\r
+#define _table(obj) ((obj)._unVal.pTable)\r
+#define _array(obj) ((obj)._unVal.pArray)\r
+#define _closure(obj) ((obj)._unVal.pClosure)\r
+#define _generator(obj) ((obj)._unVal.pGenerator)\r
+#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)\r
+#define _userdata(obj) ((obj)._unVal.pUserData)\r
+#define _userpointer(obj) ((obj)._unVal.pUserPointer)\r
+#define _thread(obj) ((obj)._unVal.pThread)\r
+#define _funcproto(obj) ((obj)._unVal.pFunctionProto)\r
+#define _class(obj) ((obj)._unVal.pClass)\r
+#define _instance(obj) ((obj)._unVal.pInstance)\r
+#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)\r
+#define _rawval(obj) ((obj)._unVal.pRefCounted)\r
+\r
+#define _stringval(obj) (obj)._unVal.pString->_val\r
+#define _userdataval(obj) (obj)._unVal.pUserData->_val\r
+\r
+#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))\r
+#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))\r
+/////////////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////////////\r
+struct SQObjectPtr : public SQObject\r
+{\r
+       SQObjectPtr()\r
+       {\r
+               _type=OT_NULL;\r
+               _unVal.pUserPointer=NULL;\r
+       }\r
+       SQObjectPtr(const SQObjectPtr &o)\r
+       {\r
+               _type=o._type;\r
+               _unVal=o._unVal;\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(const SQObject &o)\r
+       {\r
+               _type=o._type;\r
+               _unVal=o._unVal;\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQTable *pTable)\r
+       {\r
+               _type=OT_TABLE;\r
+               _unVal.pTable=pTable;\r
+               assert(_unVal.pTable);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQClass *pClass)\r
+       {\r
+               _type=OT_CLASS;\r
+               _unVal.pClass=pClass;\r
+               assert(_unVal.pClass);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQInstance *pInstance)\r
+       {\r
+               _type=OT_INSTANCE;\r
+               _unVal.pInstance=pInstance;\r
+               assert(_unVal.pInstance);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQArray *pArray)\r
+       {\r
+               _type=OT_ARRAY;\r
+               _unVal.pArray=pArray;\r
+               assert(_unVal.pArray);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQClosure *pClosure)\r
+       {\r
+               _type=OT_CLOSURE;\r
+               _unVal.pClosure=pClosure;\r
+               assert(_unVal.pClosure);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQGenerator *pGenerator)\r
+       {\r
+               _type=OT_GENERATOR;\r
+               _unVal.pGenerator=pGenerator;\r
+               assert(_unVal.pGenerator);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQNativeClosure *pNativeClosure)\r
+       {\r
+               _type=OT_NATIVECLOSURE;\r
+               _unVal.pNativeClosure=pNativeClosure;\r
+               assert(_unVal.pNativeClosure);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQString *pString)\r
+       {\r
+               _type=OT_STRING;\r
+               _unVal.pString=pString;\r
+               assert(_unVal.pString);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQUserData *pUserData)\r
+       {\r
+               _type=OT_USERDATA;\r
+               _unVal.pUserData=pUserData;\r
+               assert(_unVal.pUserData);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQVM *pThread)\r
+       {\r
+               _type=OT_THREAD;\r
+               _unVal.pThread=pThread;\r
+               assert(_unVal.pThread);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQFunctionProto *pFunctionProto)\r
+       {\r
+               _type=OT_FUNCPROTO;\r
+               _unVal.pFunctionProto=pFunctionProto;\r
+               assert(_unVal.pFunctionProto);\r
+               __AddRef(_type,_unVal);\r
+       }\r
+       SQObjectPtr(SQInteger nInteger)\r
+       {\r
+               _type=OT_INTEGER;\r
+               _unVal.nInteger=nInteger;\r
+       }\r
+       SQObjectPtr(SQFloat fFloat)\r
+       {\r
+               _type=OT_FLOAT;\r
+               _unVal.fFloat=fFloat;\r
+       }\r
+       SQObjectPtr(bool bBool)\r
+       {\r
+               _type = OT_BOOL;\r
+               _unVal.nInteger = bBool?1:0;\r
+       }\r
+       SQObjectPtr(SQUserPointer pUserPointer)\r
+       {\r
+               _type=OT_USERPOINTER;\r
+               _unVal.pUserPointer=pUserPointer;\r
+       }\r
+       ~SQObjectPtr()\r
+       {\r
+               __Release(_type,_unVal);\r
+       }\r
+       void Null()\r
+       {\r
+               __Release(_type,_unVal);\r
+               _type=OT_NULL;\r
+               _unVal.pUserPointer=NULL;\r
+       }\r
+       SQObjectPtr& operator=(const SQObjectPtr& obj)\r
+       { \r
+               SQObjectType tOldType;\r
+               SQObjectValue unOldVal;\r
+               tOldType=_type;\r
+               unOldVal=_unVal;\r
+               _unVal = obj._unVal;\r
+               _type = obj._type;\r
+               __AddRef(_type,_unVal);\r
+               __Release(tOldType,unOldVal);\r
+               return *this;\r
+       }\r
+       SQObjectPtr& operator=(const SQObject& obj)\r
+       { \r
+               SQObjectType tOldType;\r
+               SQObjectValue unOldVal;\r
+               tOldType=_type;\r
+               unOldVal=_unVal;\r
+               _unVal = obj._unVal;\r
+               _type = obj._type;\r
+               __AddRef(_type,_unVal);\r
+               __Release(tOldType,unOldVal);\r
+               return *this;\r
+       }\r
+       private:\r
+               SQObjectPtr(const SQChar *){} //safety\r
+};\r
+/////////////////////////////////////////////////////////////////////////////////////\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+#define MARK_FLAG 0x80000000\r
+struct SQCollectable : public SQRefCounted {\r
+       SQCollectable *_next;\r
+       SQCollectable *_prev;\r
+       SQSharedState *_sharedstate;\r
+       virtual void Release()=0;\r
+       virtual void Mark(SQCollectable **chain)=0;\r
+       void UnMark();\r
+       virtual void Finalize()=0;\r
+       static void AddToChain(SQCollectable **chain,SQCollectable *c);\r
+       static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);\r
+};\r
+\r
+\r
+#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)\r
+#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}\r
+#define CHAINABLE_OBJ SQCollectable\r
+#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}\r
+#else\r
+\r
+#define ADD_TO_CHAIN(chain,obj) ((void)0)\r
+#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)\r
+#define CHAINABLE_OBJ SQRefCounted\r
+#define INIT_CHAIN() ((void)0)\r
+#endif\r
+\r
+struct SQDelegable : public CHAINABLE_OBJ {\r
+       virtual bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);\r
+       SQTable *_delegate;\r
+};\r
+\r
+unsigned int TranslateIndex(const SQObjectPtr &idx);\r
+typedef sqvector<SQObjectPtr> SQObjectPtrVec;\r
+typedef sqvector<int> SQIntVec;\r
+\r
+#endif //_SQOBJECT_H_\r
diff --git a/src/squirrel/squirrel/sqopcodes.h b/src/squirrel/squirrel/sqopcodes.h
new file mode 100644 (file)
index 0000000..81abae0
--- /dev/null
@@ -0,0 +1,107 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQOPCODES_H_\r
+#define _SQOPCODES_H_\r
+\r
+#define MAX_FUNC_STACKSIZE 0xFF\r
+#define MAX_LITERALS 0xFFFFFFFF\r
+\r
+enum BitWiseOP {\r
+       BW_AND = 0,\r
+       BW_OR = 2,      //like ADD\r
+       BW_XOR = 3,\r
+       BW_SHIFTL = 4,\r
+       BW_SHIFTR = 5,\r
+       BW_USHIFTR = 6\r
+};\r
+\r
+enum CmpOP {\r
+       CMP_G = 0,\r
+       CMP_GE = 2,     //like ADD\r
+       CMP_L = 3,\r
+       CMP_LE = 4\r
+};\r
+enum SQOpcode\r
+{\r
+       _OP_LINE=                               0x00,   \r
+       _OP_LOAD=                               0x01,   \r
+       _OP_TAILCALL=                   0x02,   \r
+       _OP_CALL=                               0x03,   \r
+       _OP_PREPCALL=                   0x04,   \r
+       _OP_PREPCALLK=                  0x05,   \r
+       _OP_GETK=                               0x06,   \r
+       _OP_MOVE=                               0x07,   \r
+       _OP_NEWSLOT=                    0x08,   \r
+       _OP_DELETE=                             0x09,   \r
+       _OP_SET=                                0x0A,   \r
+       _OP_GET=                                0x0B,\r
+       _OP_EQ=                                 0x0C,\r
+       _OP_NE=                                 0x0D,\r
+       _OP_ARITH=                              0x0E,\r
+       _OP_BITW=                               0x0F,\r
+       _OP_RETURN=                             0x10,   \r
+       _OP_LOADNULLS=                  0x11,   \r
+       _OP_LOADROOTTABLE=              0x12,   \r
+       _OP_DMOVE=                              0x13,   \r
+       _OP_JMP=                                0x14,   \r
+       _OP_JNZ=                                0x15,   \r
+       _OP_JZ=                                 0x16,   \r
+       _OP_LOADFREEVAR=                0x17,   \r
+       _OP_VARGC=                              0x18,   \r
+       _OP_GETVARGV=                   0x19,   \r
+       _OP_NEWTABLE=                   0x1A,   \r
+       _OP_NEWARRAY=                   0x1B,   \r
+       _OP_APPENDARRAY=                0x1C,   \r
+       _OP_GETPARENT=                  0x1D,   \r
+       _OP_COMPARITH=                  0x1E,   \r
+       _OP_COMPARITHL=                 0x1F,   \r
+       _OP_INC=                                0x20,   \r
+       _OP_INCL=                               0x21,   \r
+       _OP_PINC=                               0x22,   \r
+       _OP_PINCL=                              0x23,   \r
+       _OP_CMP=                                0x24,\r
+       _OP_EXISTS=                             0x25,   \r
+       _OP_INSTANCEOF=                 0x26,\r
+       _OP_AND=                                0x27,\r
+       _OP_OR=                                 0x28,\r
+       _OP_NEG=                                0x29,\r
+       _OP_NOT=                                0x2A,\r
+       _OP_BWNOT=                              0x2B,   \r
+       _OP_CLOSURE=                    0x2C,   \r
+       _OP_YIELD=                              0x2D,   \r
+       _OP_RESUME=                             0x2E,\r
+       _OP_FOREACH=                    0x2F,\r
+       _OP_DELEGATE=                   0x30,\r
+       _OP_CLONE=                              0x31,\r
+       _OP_TYPEOF=                             0x32,\r
+       _OP_PUSHTRAP=                   0x33,\r
+       _OP_POPTRAP=                    0x34,\r
+       _OP_THROW=                              0x35,\r
+       _OP_CLASS=                              0x36,\r
+       _OP_NEWSLOTA=                   0x37,\r
+       _OP_LOADBOOL=                   0x38\r
+};                                                       \r
+struct SQInstructionDesc {       \r
+       const SQChar *name;               \r
+};                                                       \r
+\r
+struct SQInstruction \r
+{\r
+       SQInstruction(){};\r
+       SQInstruction(SQOpcode _op,int a0=0,int a1=0,int a2=0,int a3=0)\r
+       {       op = _op;\r
+               _arg0 = a0;_arg1 = a1;\r
+               _arg2 = a2;_arg3 = a3;\r
+       }\r
+    \r
+       \r
+       unsigned int _arg1;\r
+       unsigned char op;\r
+       unsigned char _arg0;\r
+       unsigned char _arg2;\r
+       unsigned char _arg3;\r
+};\r
+\r
+#include "squtils.h"\r
+typedef sqvector<SQInstruction> SQInstructionVec;\r
+\r
+#endif // _SQOPCODES_H_\r
diff --git a/src/squirrel/squirrel/sqpcheader.h b/src/squirrel/squirrel/sqpcheader.h
new file mode 100644 (file)
index 0000000..f0e5cf2
--- /dev/null
@@ -0,0 +1,19 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQPCHEADER_H_\r
+#define _SQPCHEADER_H_\r
+\r
+#if defined(_MSC_VER) && defined(_DEBUG)\r
+#include <crtdbg.h>\r
+#endif \r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+#include <new>\r
+//squirrel stuff\r
+#include <squirrel.h>\r
+#include "sqobject.h"\r
+#include "sqstate.h"\r
+\r
+#endif //_SQPCHEADER_H_\r
diff --git a/src/squirrel/squirrel/sqstate.cpp b/src/squirrel/squirrel/sqstate.cpp
new file mode 100644 (file)
index 0000000..e352e25
--- /dev/null
@@ -0,0 +1,426 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqopcodes.h"\r
+#include "sqvm.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "sqarray.h"\r
+#include "squserdata.h"\r
+#include "sqclass.h"\r
+\r
+SQObjectPtr _null_;\r
+SQObjectPtr _true_(true);\r
+SQObjectPtr _false_(false);\r
+SQObjectPtr _one_(1);\r
+SQObjectPtr _minusone_(-1);\r
+\r
+SQSharedState::SQSharedState()\r
+{\r
+       _compilererrorhandler = NULL;\r
+       _printfunc = NULL;\r
+       _debuginfo = false;\r
+}\r
+\r
+#define newsysstring(s) {      \\r
+       _systemstrings->push_back(SQString::Create(this,s));    \\r
+       }\r
+\r
+#define newmetamethod(s) {     \\r
+       _metamethods->push_back(SQString::Create(this,s));      \\r
+       _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \\r
+       }\r
+\r
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask)\r
+{\r
+       int i = 0;\r
+       \r
+       int mask = 0;\r
+       while(typemask[i] != 0) {\r
+               \r
+               switch(typemask[i]){\r
+                               case 'i': mask |= _RT_INTEGER; break;\r
+                               case 'f': mask |= _RT_FLOAT; break;\r
+                               case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;\r
+                               case 's': mask |= _RT_STRING; break;\r
+                               case 't': mask |= _RT_TABLE; break;\r
+                               case 'a': mask |= _RT_ARRAY; break;\r
+                               case 'u': mask |= _RT_USERDATA; break;\r
+                               case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;\r
+                               case 'b': mask |= _RT_BOOL; break;\r
+                               case 'g': mask |= _RT_GENERATOR; break;\r
+                               case 'p': mask |= _RT_USERPOINTER; break;\r
+                               case 'v': mask |= _RT_THREAD; break;\r
+                               case 'x': mask |= _RT_INSTANCE; break;\r
+                               case 'y': mask |= _RT_CLASS; break;\r
+                               case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;\r
+                               case ' ': i++; continue; //ignores spaces\r
+                               default:\r
+                                       return false;\r
+               }\r
+               i++;\r
+               if(typemask[i] == '|') { \r
+                       i++; \r
+                       if(typemask[i] == 0)\r
+                               return false;\r
+                       continue; \r
+               }\r
+               res.push_back(mask);\r
+               mask = 0;\r
+               \r
+       }\r
+       return true;\r
+}\r
+\r
+SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)\r
+{\r
+       int i=0;\r
+       SQTable *t=SQTable::Create(ss,0);\r
+       while(funcz[i].name!=0){\r
+               SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);\r
+               nc->_nparamscheck = funcz[i].nparamscheck;\r
+               nc->_name = SQString::Create(ss,funcz[i].name);\r
+               if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))\r
+                       return NULL;\r
+               t->NewSlot(SQString::Create(ss,funcz[i].name),nc);\r
+               i++;\r
+       }\r
+       return t;\r
+}\r
+\r
+void SQSharedState::Init()\r
+{      \r
+       _scratchpad=NULL;\r
+       _scratchpadsize=0;\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       _gc_chain=NULL;\r
+#endif\r
+       sq_new(_stringtable,StringTable);\r
+       sq_new(_metamethods,SQObjectPtrVec);\r
+       sq_new(_systemstrings,SQObjectPtrVec);\r
+       sq_new(_types,SQObjectPtrVec);\r
+       _metamethodsmap = SQTable::Create(this,MT_LAST-1);\r
+       //adding type strings to avoid memory trashing\r
+       //types names\r
+       newsysstring(_SC("null"));\r
+       newsysstring(_SC("table"));\r
+       newsysstring(_SC("array"));\r
+       newsysstring(_SC("closure"));\r
+       newsysstring(_SC("string"));\r
+       newsysstring(_SC("userdata"));\r
+       newsysstring(_SC("integer"));\r
+       newsysstring(_SC("float"));\r
+       newsysstring(_SC("userpointer"));\r
+       newsysstring(_SC("function"));\r
+       newsysstring(_SC("generator"));\r
+       newsysstring(_SC("thread"));\r
+       newsysstring(_SC("class"));\r
+       newsysstring(_SC("instance"));\r
+       newsysstring(_SC("bool"));\r
+       //meta methods\r
+       newmetamethod(MM_ADD);\r
+       newmetamethod(MM_SUB);\r
+       newmetamethod(MM_MUL);\r
+       newmetamethod(MM_DIV);\r
+       newmetamethod(MM_UNM);\r
+       newmetamethod(MM_MODULO);\r
+       newmetamethod(MM_SET);\r
+       newmetamethod(MM_GET);\r
+       newmetamethod(MM_TYPEOF);\r
+       newmetamethod(MM_NEXTI);\r
+       newmetamethod(MM_CMP);\r
+       newmetamethod(MM_CALL);\r
+       newmetamethod(MM_CLONED);\r
+       newmetamethod(MM_NEWSLOT);\r
+       newmetamethod(MM_DELSLOT);\r
+\r
+       _constructoridx = SQString::Create(this,_SC("constructor"));\r
+       _refs_table = SQTable::Create(this,0);\r
+       _registry = SQTable::Create(this,0);\r
+       _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);\r
+       _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);\r
+       _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz);\r
+       _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz);\r
+       _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz);\r
+       _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz);\r
+       _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);\r
+       _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);\r
+       _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);\r
+\r
+}\r
+\r
+SQSharedState::~SQSharedState()\r
+{\r
+       _constructoridx = _null_;\r
+       _table(_refs_table)->Finalize();\r
+       _table(_registry)->Finalize();\r
+       _table(_metamethodsmap)->Finalize();\r
+       _refs_table = _null_;\r
+       _registry = _null_;\r
+       _metamethodsmap = _null_;\r
+       while(!_systemstrings->empty()){\r
+               _systemstrings->back()=_null_;\r
+               _systemstrings->pop_back();\r
+       }\r
+       _thread(_root_vm)->Finalize();\r
+       _root_vm = _null_;\r
+       _table_default_delegate=_null_;\r
+       _array_default_delegate=_null_;\r
+       _string_default_delegate=_null_;\r
+       _number_default_delegate=_null_;\r
+       _closure_default_delegate=_null_;\r
+       _generator_default_delegate=_null_;\r
+       _thread_default_delegate=_null_;\r
+       _class_default_delegate=_null_;\r
+       _instance_default_delegate=_null_;\r
+       \r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       \r
+       \r
+       SQCollectable *t=_gc_chain;\r
+       SQCollectable *nx=NULL;\r
+       while(t){\r
+               t->_uiRef++;\r
+               t->Finalize();\r
+               nx=t->_next;\r
+               if(--t->_uiRef==0)\r
+                       t->Release();\r
+               t=nx;\r
+       }\r
+       assert(_gc_chain==NULL); //just to proove a theory\r
+       while(_gc_chain){\r
+               _gc_chain->_uiRef++;\r
+               _gc_chain->Release();\r
+       }\r
+#endif\r
+       sq_delete(_types,SQObjectPtrVec);\r
+       sq_delete(_systemstrings,SQObjectPtrVec);\r
+       sq_delete(_metamethods,SQObjectPtrVec);\r
+       sq_delete(_stringtable,StringTable);\r
+       if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);\r
+}\r
+\r
+\r
+SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)\r
+{\r
+       if(type(name) != OT_STRING)\r
+               return -1;\r
+       SQObjectPtr ret;\r
+       if(_table(_metamethodsmap)->Get(name,ret)) {\r
+               return _integer(ret);\r
+       }\r
+       return -1;\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+\r
+void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)\r
+{\r
+       switch(type(o)){\r
+       case OT_TABLE:_table(o)->Mark(chain);break;\r
+       case OT_ARRAY:_array(o)->Mark(chain);break;\r
+       case OT_USERDATA:_userdata(o)->Mark(chain);break;\r
+       case OT_CLOSURE:_closure(o)->Mark(chain);break;\r
+       case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;\r
+       case OT_GENERATOR:_generator(o)->Mark(chain);break;\r
+       case OT_THREAD:_thread(o)->Mark(chain);break;\r
+       case OT_CLASS:_class(o)->Mark(chain);break;\r
+       case OT_INSTANCE:_instance(o)->Mark(chain);break;\r
+       }\r
+}\r
+\r
+\r
+int SQSharedState::CollectGarbage(SQVM *vm)\r
+{\r
+       int n=0;\r
+       SQCollectable *tchain=NULL;\r
+       SQVM *vms=_thread(_root_vm);\r
+       \r
+       vms->Mark(&tchain);\r
+       int x = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
+       MarkObject(_refs_table,&tchain);\r
+       MarkObject(_registry,&tchain);\r
+       MarkObject(_metamethodsmap,&tchain);\r
+       MarkObject(_table_default_delegate,&tchain);\r
+       MarkObject(_array_default_delegate,&tchain);\r
+       MarkObject(_string_default_delegate,&tchain);\r
+       MarkObject(_number_default_delegate,&tchain);\r
+       MarkObject(_generator_default_delegate,&tchain);\r
+       MarkObject(_thread_default_delegate,&tchain);\r
+       MarkObject(_closure_default_delegate,&tchain);\r
+       MarkObject(_class_default_delegate,&tchain);\r
+       MarkObject(_instance_default_delegate,&tchain);\r
+       \r
+       SQCollectable *t=_gc_chain;\r
+       SQCollectable *nx=NULL;\r
+       while(t){\r
+               t->_uiRef++;\r
+               t->Finalize();\r
+               nx=t->_next;\r
+               if(--t->_uiRef==0)\r
+                       t->Release();\r
+               t=nx;\r
+               n++;\r
+       }\r
+\r
+       t=tchain;\r
+       while(t){\r
+               t->UnMark();\r
+               t=t->_next;\r
+       }\r
+       _gc_chain=tchain;\r
+       int z = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
+       assert(z == x);\r
+       return n;\r
+}\r
+#endif\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)\r
+{\r
+    c->_prev=NULL;\r
+       c->_next=*chain;\r
+       if(*chain) (*chain)->_prev=c;\r
+       *chain=c;\r
+}\r
+\r
+void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)\r
+{\r
+       if(c->_prev) c->_prev->_next=c->_next;\r
+       else *chain=c->_next;\r
+       if(c->_next)\r
+               c->_next->_prev=c->_prev;\r
+       c->_next=NULL;\r
+       c->_prev=NULL;\r
+}\r
+#endif\r
+\r
+SQChar* SQSharedState::GetScratchPad(int size)\r
+{\r
+       int newsize;\r
+       if(size>0){\r
+               if(_scratchpadsize<size){\r
+                       newsize=size+(size>>1);\r
+                       _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
+                       _scratchpadsize=newsize;\r
+\r
+               }else if(_scratchpadsize>=(size<<5)){\r
+                       newsize=_scratchpadsize>>1;\r
+                       _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
+                       _scratchpadsize=newsize;\r
+               }\r
+       }\r
+       return _scratchpad;\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+//StringTable\r
+/*\r
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)\r
+* http://www.lua.org/copyright.html#4\r
+* http://www.lua.org/source/4.0.1/src_lstring.c.html\r
+*/\r
+\r
+int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+       int idx = (int)TranslateIndex(refpos);\r
+       while(idx < _len){\r
+               outkey = (SQInteger)idx;\r
+               outval = SQInteger(_val[idx]);\r
+               //return idx for the next iteration\r
+               return ++idx;\r
+       }\r
+       //nothing to iterate anymore\r
+       return -1;\r
+}\r
+\r
+StringTable::StringTable()\r
+{\r
+       AllocNodes(4);\r
+       _slotused = 0;\r
+}\r
+\r
+StringTable::~StringTable()\r
+{\r
+       SQ_FREE(_strings,sizeof(SQString*)*_numofslots);\r
+       _strings=NULL;\r
+}\r
+\r
+void StringTable::AllocNodes(int size)\r
+{\r
+       _numofslots=size;\r
+       //_slotused=0;\r
+       _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);\r
+       memset(_strings,0,sizeof(SQString*)*_numofslots);\r
+}\r
+\r
+SQString *StringTable::Add(const SQChar *news,int len)\r
+{\r
+       if(len<0)\r
+               len=scstrlen(news);\r
+       unsigned int h=::_hashstr(news,len)&(_numofslots-1);\r
+       SQString *s;\r
+       for (s = _strings[h]; s; s = s->_next){\r
+               if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))\r
+                       return s; //found\r
+       }\r
+\r
+       SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));\r
+       new (t) SQString;\r
+       memcpy(t->_val,news,rsl(len));\r
+       t->_val[len]=_SC('\0');\r
+       t->_len=len;\r
+       t->_hash=::_hashstr(news,len);\r
+       t->_next=_strings[h];\r
+       t->_uiRef=0;\r
+       _strings[h]=t;\r
+       _slotused++;\r
+       if (_slotused > _numofslots)  /* too crowded? */\r
+               Resize(_numofslots*2);\r
+       return t;\r
+}\r
+\r
+void StringTable::Resize(int size)\r
+{\r
+       int oldsize=_numofslots;\r
+       SQString **oldtable=_strings;\r
+       AllocNodes(size);\r
+       for (int i=0; i<oldsize; i++){\r
+               SQString *p = oldtable[i];\r
+               while(p){\r
+                       SQString *next = p->_next;\r
+                       unsigned int h=p->_hash&(_numofslots-1);\r
+                       p->_next=_strings[h];\r
+                       _strings[h] = p;\r
+                       p=next;\r
+               }\r
+       }\r
+       SQ_FREE(oldtable,oldsize*sizeof(SQString*));\r
+}\r
+\r
+void StringTable::Remove(SQString *bs)\r
+{\r
+       SQString *s;\r
+       SQString *prev=NULL;\r
+       unsigned int h=bs->_hash&(_numofslots-1);\r
+       \r
+       for (s = _strings[h]; s; ){\r
+               if(s == bs){\r
+                       if(prev)\r
+                               prev->_next = s->_next;\r
+                       else\r
+                               _strings[h] = s->_next;\r
+                       _slotused--;\r
+                       int slen=s->_len;\r
+                       s->~SQString();\r
+                       SQ_FREE(s,sizeof(SQString)+rsl(slen));\r
+                       return;\r
+               }\r
+               prev = s;\r
+               s = s->_next;\r
+       }\r
+       assert(0);//if this fail something is wrong\r
+}\r
diff --git a/src/squirrel/squirrel/sqstate.h b/src/squirrel/squirrel/sqstate.h
new file mode 100644 (file)
index 0000000..96acca8
--- /dev/null
@@ -0,0 +1,116 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTATE_H_\r
+#define _SQSTATE_H_\r
+\r
+#include "squtils.h"\r
+#include "sqobject.h"\r
+struct SQString;\r
+struct SQTable;\r
+//max number of character for a printed number\r
+#define NUMBER_MAX_CHAR 50\r
+\r
+struct StringTable\r
+{\r
+       StringTable();\r
+       ~StringTable();\r
+       //return a string obj if exists\r
+       //so when there is a table query, if the string doesn't exists in the global state\r
+       //it cannot be in a table so the result will be always null\r
+       //SQString *get(const SQChar *news);\r
+       SQString *Add(const SQChar *,int len);\r
+       void Remove(SQString *);\r
+private:\r
+       void Resize(int size);\r
+       void AllocNodes(int size);\r
+       SQString **_strings;\r
+       unsigned int _numofslots;\r
+       unsigned int _slotused;\r
+};\r
+\r
+#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)\r
+#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)\r
+\r
+struct SQObjectPtr;\r
+\r
+struct SQSharedState\r
+{\r
+       SQSharedState();\r
+       ~SQSharedState();\r
+       void Init();\r
+public:\r
+       SQChar* GetScratchPad(int size);\r
+       SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       int CollectGarbage(SQVM *vm); \r
+       static void MarkObject(SQObjectPtr &o,SQCollectable **chain);\r
+#endif\r
+       SQObjectPtrVec *_metamethods;\r
+       SQObjectPtr _metamethodsmap;\r
+       SQObjectPtrVec *_systemstrings;\r
+       SQObjectPtrVec *_types;\r
+       StringTable *_stringtable;\r
+       SQObjectPtr _refs_table;\r
+       SQObjectPtr _registry;\r
+       SQObjectPtr _constructoridx;\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       SQCollectable *_gc_chain;\r
+#endif\r
+       SQObjectPtr _root_vm;\r
+       SQObjectPtr _table_default_delegate;\r
+       static SQRegFunction _table_default_delegate_funcz[];\r
+       SQObjectPtr _array_default_delegate;\r
+       static SQRegFunction _array_default_delegate_funcz[];\r
+       SQObjectPtr _string_default_delegate;\r
+       static SQRegFunction _string_default_delegate_funcz[];\r
+       SQObjectPtr _number_default_delegate;\r
+       static SQRegFunction _number_default_delegate_funcz[];\r
+       SQObjectPtr _generator_default_delegate;\r
+       static SQRegFunction _generator_default_delegate_funcz[];\r
+       SQObjectPtr _closure_default_delegate;\r
+       static SQRegFunction _closure_default_delegate_funcz[];\r
+       SQObjectPtr _thread_default_delegate;\r
+       static SQRegFunction _thread_default_delegate_funcz[];\r
+       SQObjectPtr _class_default_delegate;\r
+       static SQRegFunction _class_default_delegate_funcz[];\r
+       SQObjectPtr _instance_default_delegate;\r
+       static SQRegFunction _instance_default_delegate_funcz[];\r
+       \r
+       SQCOMPILERERROR _compilererrorhandler;\r
+       SQPRINTFUNCTION _printfunc;\r
+       bool _debuginfo;\r
+private:\r
+       SQChar *_scratchpad;\r
+       int _scratchpadsize;\r
+};\r
+\r
+#define _sp(s) (_sharedstate->GetScratchPad(s))\r
+#define _spval (_sharedstate->GetScratchPad(-1))\r
+\r
+#define _table_ddel            _table(_sharedstate->_table_default_delegate) \r
+#define _array_ddel            _table(_sharedstate->_array_default_delegate) \r
+#define _string_ddel   _table(_sharedstate->_string_default_delegate) \r
+#define _number_ddel   _table(_sharedstate->_number_default_delegate) \r
+#define _generator_ddel        _table(_sharedstate->_generator_default_delegate) \r
+#define _closure_ddel  _table(_sharedstate->_closure_default_delegate) \r
+#define _thread_ddel   _table(_sharedstate->_thread_default_delegate) \r
+#define _class_ddel            _table(_sharedstate->_class_default_delegate) \r
+#define _instance_ddel _table(_sharedstate->_instance_default_delegate) \r
+\r
+#ifdef SQUNICODE //rsl REAL STRING LEN\r
+#define rsl(l) ((l)<<1)\r
+#else\r
+#define rsl(l) (l)\r
+#endif\r
+\r
+extern SQObjectPtr _null_;\r
+extern SQObjectPtr _true_;\r
+extern SQObjectPtr _false_;\r
+extern SQObjectPtr _one_;\r
+extern SQObjectPtr _minusone_;\r
+\r
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask);\r
+\r
+void *sq_vm_malloc(unsigned int size);\r
+void *sq_vm_realloc(void *p,unsigned int oldsize,unsigned int size);\r
+void sq_vm_free(void *p,unsigned int size);\r
+#endif //_SQSTATE_H_\r
diff --git a/src/squirrel/squirrel/sqstring.h b/src/squirrel/squirrel/sqstring.h
new file mode 100644 (file)
index 0000000..dfb4017
--- /dev/null
@@ -0,0 +1,31 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQSTRING_H_\r
+#define _SQSTRING_H_\r
+\r
+inline unsigned int _hashstr (const SQChar *s, size_t l)\r
+{\r
+               unsigned int h = l;  /* seed */\r
+               size_t step = (l>>5)|1;  /* if string is too long, don't hash all its chars */\r
+               for (; l>=step; l-=step)\r
+                       h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++));\r
+               return h;\r
+}\r
+\r
+struct SQString : public SQRefCounted\r
+{\r
+       SQString(){}\r
+       ~SQString(){}\r
+public:\r
+       static SQString *Create(SQSharedState *ss, const SQChar *, int len = -1 );\r
+       int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+       void Release();\r
+       SQSharedState *_sharedstate;\r
+       SQString *_next; //chain for the string table\r
+       int _len;\r
+       int _hash;\r
+       SQChar _val[1];\r
+};\r
+\r
+\r
+\r
+#endif //_SQSTRING_H_\r
diff --git a/src/squirrel/squirrel/sqtable.cpp b/src/squirrel/squirrel/sqtable.cpp
new file mode 100644 (file)
index 0000000..04509ec
--- /dev/null
@@ -0,0 +1,193 @@
+/*\r
+see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqtable.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+\r
+SQTable::SQTable(SQSharedState *ss,int nInitialSize)\r
+{\r
+       int pow2size=MINPOWER2;\r
+       while(nInitialSize>pow2size)pow2size=pow2size<<1;\r
+       AllocNodes(pow2size);\r
+       _uiRef = 0;\r
+       _usednodes = 0;\r
+       _delegate = NULL;\r
+       INIT_CHAIN();\r
+       ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);\r
+}\r
+\r
+void SQTable::Remove(const SQObjectPtr &key)\r
+{\r
+       _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               n->val = n->key = _null_;\r
+               _usednodes--;\r
+               Rehash(false);\r
+       }\r
+}\r
+\r
+void SQTable::AllocNodes(int nSize)\r
+{\r
+       _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);\r
+       for(int i=0;i<nSize;i++){\r
+               new (&nodes[i]) _HashNode;\r
+               nodes[i].next=NULL;\r
+       }\r
+       _numofnodes=nSize;\r
+       _nodes=nodes;\r
+       _firstfree=&_nodes[_numofnodes-1];\r
+}\r
+\r
+int SQTable::CountUsed()\r
+{\r
+       /*int n=0;\r
+       for(int i=0;i<_numofnodes;i++){\r
+               if(type(_nodes[i].key)!=OT_NULL) n++;\r
+       }*/\r
+       return _usednodes;\r
+}\r
+\r
+void SQTable::Rehash(bool force)\r
+{\r
+       int oldsize=_numofnodes;\r
+       //prevent problems with the integer division\r
+       if(oldsize<4)oldsize=4;\r
+       _HashNode *nold=_nodes;\r
+       int nelems=CountUsed();\r
+       if (nelems >= oldsize-oldsize/4)  /* using more than 3/4? */\r
+               AllocNodes(oldsize*2);\r
+       else if (nelems <= oldsize/4 &&  /* less than 1/4? */\r
+               oldsize > MINPOWER2)\r
+               AllocNodes(oldsize/2);\r
+       else if(force)\r
+               AllocNodes(oldsize);\r
+       else\r
+               return;\r
+       _usednodes = 0;\r
+       for (int i=0; i<oldsize; i++) {\r
+               _HashNode *old = nold+i;\r
+               if (type(old->key) != OT_NULL)\r
+                       NewSlot(old->key,old->val);\r
+       }\r
+       for(int k=0;k<oldsize;k++) \r
+               nold[k].~_HashNode();\r
+       SQ_FREE(nold,oldsize*sizeof(_HashNode));\r
+}\r
+\r
+SQTable *SQTable::Clone()\r
+{\r
+       SQTable *nt=Create(_opt_ss(this),_numofnodes);\r
+       SQInteger ridx=0;\r
+       SQObjectPtr key,val;\r
+       while((ridx=Next(ridx,key,val))!=-1){\r
+               nt->NewSlot(key,val);\r
+       }\r
+       nt->SetDelegate(_delegate);\r
+       return nt;\r
+}\r
+\r
+bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)\r
+{\r
+       _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               val = n->val;\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       unsigned long h = HashKey(key) & (_numofnodes - 1);\r
+       _HashNode *n = _Get(key, h);\r
+       if (n) {\r
+               n->val = val;\r
+               return false;\r
+       }\r
+       _HashNode *mp = &_nodes[h];\r
+       n = mp;\r
+\r
+       //key not found I'll insert it\r
+       //main pos is not free\r
+\r
+       if(type(mp->key)!=OT_NULL) {\r
+\r
+               _HashNode *othern;  /* main position of colliding node */\r
+               n = _firstfree;  /* get a free place */\r
+               if (mp > n && (othern = &_nodes[h]) != mp){\r
+                       /* yes; move colliding node into free position */\r
+                       while (othern->next != mp)\r
+                               othern = othern->next;  /* find previous */\r
+                       othern->next = n;  /* redo the chain with `n' in place of `mp' */\r
+                       *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */\r
+                       mp->next = NULL;  /* now `mp' is free */\r
+               }\r
+               else{\r
+                       /* new node will go into free position */\r
+                       n->next = mp->next;  /* chain new position */\r
+                       mp->next = n;\r
+                       mp = n;\r
+               }\r
+       }\r
+       mp->key = key;\r
+\r
+       for (;;) {  /* correct `firstfree' */\r
+               if (type(_firstfree->key) == OT_NULL) {\r
+                       mp->val = val;\r
+                       _usednodes++;\r
+                       return true;  /* OK; table still has a free place */\r
+               }\r
+               else if (_firstfree == _nodes) break;  /* cannot decrement from here */\r
+               else (_firstfree)--;\r
+       }\r
+       Rehash(true);\r
+       return NewSlot(key, val);\r
+}\r
+\r
+int SQTable::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+       int idx = (int)TranslateIndex(refpos);\r
+       while (idx < _numofnodes) {\r
+               if(type(_nodes[idx].key) != OT_NULL) {\r
+                       //first found\r
+                       outkey = _nodes[idx].key;\r
+                       outval = _nodes[idx].val;\r
+                       //return idx for the next iteration\r
+                       return ++idx;\r
+               }\r
+               ++idx;\r
+       }\r
+       //nothing to iterate anymore\r
+       return -1;\r
+}\r
+\r
+bool SQTable::SetDelegate(SQTable *mt)\r
+{\r
+       SQTable *temp = mt;\r
+       while (temp) {\r
+               if (temp->_delegate == this) return false; //cycle detected\r
+               temp = temp->_delegate;\r
+       }\r
+       if (mt) __ObjAddRef(mt);\r
+       __ObjRelease(_delegate);\r
+       _delegate = mt;\r
+       return true;\r
+}\r
+\r
+bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)\r
+{\r
+       _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               n->val = val;\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void SQTable::Finalize()\r
+{\r
+       for(int i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }\r
+               SetDelegate(NULL);\r
+}\r
diff --git a/src/squirrel/squirrel/sqtable.h b/src/squirrel/squirrel/sqtable.h
new file mode 100644 (file)
index 0000000..b27b7d3
--- /dev/null
@@ -0,0 +1,88 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQTABLE_H_\r
+#define _SQTABLE_H_\r
+/*\r
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)\r
+* http://www.lua.org/copyright.html#4\r
+* http://www.lua.org/source/4.0.1/src_ltable.c.html\r
+*/\r
+\r
+#include "sqstring.h"\r
+\r
+#define hashptr(p)  (((unsigned long)(p)) >> 3)\r
+\r
+struct SQTable : public SQDelegable \r
+{\r
+private:\r
+       struct _HashNode\r
+       {\r
+               SQObjectPtr val;\r
+               SQObjectPtr key;\r
+               _HashNode *next;\r
+       };\r
+       _HashNode *_firstfree;\r
+       _HashNode *_nodes;\r
+       int _numofnodes;\r
+       int _usednodes;\r
+       \r
+///////////////////////////\r
+       void AllocNodes(int nSize);\r
+       void Rehash(bool force);\r
+       SQTable(SQSharedState *ss, int nInitialSize);\r
+public:\r
+       static SQTable* Create(SQSharedState *ss,int nInitialSize)\r
+       {\r
+               SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));\r
+               new (newtable) SQTable(ss, nInitialSize);\r
+               newtable->_delegate = NULL;\r
+               return newtable;\r
+       }\r
+       void Finalize();\r
+       SQTable *Clone();\r
+       ~SQTable()\r
+       {\r
+               SetDelegate(NULL);\r
+               REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
+               for (int i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();\r
+               SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));\r
+       }\r
+#ifndef NO_GARBAGE_COLLECTOR \r
+       void Mark(SQCollectable **chain);\r
+#endif\r
+       inline unsigned long HashKey(const SQObjectPtr &key)\r
+       {\r
+               switch(type(key)){\r
+                       case OT_STRING:         return _string(key)->_hash;\r
+                       case OT_FLOAT:          return (unsigned long)((long)_float(key));\r
+                       case OT_INTEGER:        return (unsigned long)((long)_integer(key));\r
+                       default:                        return hashptr(key._unVal.pRefCounted);\r
+               }\r
+       }\r
+       _HashNode *_Get(const SQObjectPtr &key,unsigned long hash)\r
+       {\r
+               _HashNode *n = &_nodes[hash];\r
+               do{\r
+                       if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){\r
+                               return n;\r
+                       }\r
+               }while(n = n->next);\r
+               return NULL;\r
+       }\r
+       bool Get(const SQObjectPtr &key,SQObjectPtr &val);\r
+       void Remove(const SQObjectPtr &key);\r
+       bool Set(const SQObjectPtr &key, const SQObjectPtr &val);\r
+       //returns true if a new slot has been created false if it was already present\r
+       bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);\r
+       int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+       \r
+       int CountUsed();\r
+       void Release()\r
+       {\r
+               sq_delete(this, SQTable);\r
+       }\r
+       bool SetDelegate(SQTable *mt);\r
+       \r
+\r
+};\r
+\r
+#endif //_SQTABLE_H_\r
diff --git a/src/squirrel/squirrel/squirrel.dsp b/src/squirrel/squirrel/squirrel.dsp
new file mode 100644 (file)
index 0000000..1b8cd40
--- /dev/null
@@ -0,0 +1,302 @@
+# Microsoft Developer Studio Project File - Name="squirrel" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
+\r
+CFG=squirrel - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "squirrel.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "squirrel.mak" CFG="squirrel - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "squirrel - Win32 Release" (based on "Win32 (x86) Static Library")\r
+!MESSAGE "squirrel - Win32 Debug" (based on "Win32 (x86) Static Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_LocalPath ".."\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /c\r
+# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
+# ADD RSC /l 0x410 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
+# ADD RSC /l 0x410 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "squirrel - Win32 Release"\r
+# Name "squirrel - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\sqapi.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqbaselib.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqcompiler.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqdebug.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqfuncstate.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqlexer.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqmem.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqobject.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstate.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqtable.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqclass.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqvm.cpp\r
+\r
+!IF  "$(CFG)" == "squirrel - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "squirrel - Win32 Debug"\r
+\r
+# ADD CPP /YX"stdafx.h"\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\sqarray.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqclosure.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqcompiler.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqfuncproto.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqfuncstate.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqlexer.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqobject.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqopcodes.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqpcheader.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstate.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqstring.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqtable.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\squserdata.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\squtils.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqclass.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sqvm.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/src/squirrel/squirrel/squserdata.h b/src/squirrel/squirrel/squserdata.h
new file mode 100644 (file)
index 0000000..7b85913
--- /dev/null
@@ -0,0 +1,45 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQUSERDATA_H_\r
+#define _SQUSERDATA_H_\r
+\r
+struct SQUserData : SQDelegable\r
+{\r
+       SQUserData(SQSharedState *ss){ _uiRef = 0; _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }\r
+       ~SQUserData()\r
+       {\r
+               REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);\r
+               SetDelegate(NULL);\r
+       }\r
+       static SQUserData* Create(SQSharedState *ss, int size)\r
+       {\r
+               SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));\r
+               new (ud) SQUserData(ss);\r
+               ud->_size = size;\r
+               ud->_typetag = 0;\r
+               return ud;\r
+       }\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+       void Finalize(){SetDelegate(NULL);}\r
+#endif\r
+       void Release() {\r
+               if (_hook) _hook(_val,_size);\r
+               int tsize = _size - 1;\r
+               this->~SQUserData();\r
+               SQ_FREE(this, sizeof(SQUserData) + tsize);\r
+       }\r
+       void SetDelegate(SQTable *mt)\r
+       {\r
+               if (mt) __ObjAddRef(mt);\r
+               __ObjRelease(_delegate);\r
+               _delegate = mt;\r
+       }\r
+\r
+       \r
+       int _size;\r
+       SQRELEASEHOOK _hook;\r
+       unsigned int _typetag;\r
+       SQChar _val[1];\r
+};\r
+\r
+#endif //_SQUSERDATA_H_\r
diff --git a/src/squirrel/squirrel/squtils.h b/src/squirrel/squirrel/squtils.h
new file mode 100644 (file)
index 0000000..d1abd54
--- /dev/null
@@ -0,0 +1,104 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQUTILS_H_\r
+#define _SQUTILS_H_\r
+\r
+#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}\r
+#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}\r
+#define SQ_MALLOC(__size) sq_vm_malloc(__size);\r
+#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size);\r
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size);\r
+\r
+//sqvector mini vector class, supports objects by value\r
+template<typename T> class sqvector\r
+{\r
+public:\r
+       sqvector()\r
+       {\r
+               _vals = NULL;\r
+               _size = 0;\r
+               _allocated = 0;\r
+       }\r
+       sqvector(const sqvector<T>& v)\r
+       {\r
+               copy(v);\r
+       }\r
+       void copy(const sqvector<T>& v)\r
+       {\r
+               resize(v._size);\r
+               for(unsigned int i = 0; i < v._size; i++) {\r
+                       new ((void *)&_vals[i]) T(v._vals[i]);\r
+               }\r
+               _size = v._size;\r
+       }\r
+       ~sqvector()\r
+       {\r
+               if(_allocated) {\r
+                       for(unsigned int i = 0; i < _size; i++)\r
+                               _vals[i].~T();\r
+                       SQ_FREE(_vals, (_allocated * sizeof(T)));\r
+               }\r
+       }\r
+       void reserve(unsigned int newsize) { _realloc(newsize); }\r
+       void resize(unsigned int newsize, const T& fill = T())\r
+       {\r
+               if(newsize > _allocated)\r
+                       _realloc(newsize);\r
+               if(newsize > _size) {\r
+                       while(_size < newsize) {\r
+                               new ((void *)&_vals[_size]) T(fill);\r
+                               _size++;\r
+                       }\r
+               }\r
+               else{\r
+                       for(unsigned int i = newsize; i < _size; i++) {\r
+                               _vals[i].~T();\r
+                       }\r
+                       _size = newsize;\r
+               }\r
+       }\r
+       void shrinktofit() { if(_size > 4) { _realloc(_size); } }\r
+       T& top() const { return _vals[_size - 1]; }\r
+       inline unsigned int size() const { return _size; }\r
+       bool empty() const { return (_size <= 0); }\r
+       inline void push_back(const T& val = T())\r
+       {\r
+               if(_allocated <= _size)\r
+                       _realloc(_size * 2);\r
+               new ((void *)&_vals[_size++]) T(val);\r
+       }\r
+       inline void pop_back()\r
+       {\r
+               _size--; _vals[_size].~T();\r
+       }\r
+       void insert(unsigned int idx, const T& val)\r
+       {\r
+               resize(_size + 1);\r
+               for(unsigned int i = _size - 1; i > idx; i--) {\r
+                       _vals[i] = _vals[i - 1];\r
+               }\r
+       _vals[idx] = val;\r
+       }\r
+       void remove(unsigned int idx)\r
+       {\r
+               _vals[idx].~T();\r
+               if(idx < (_size - 1)) {\r
+                       memcpy(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));\r
+               }\r
+               _size--;\r
+       }\r
+       unsigned int capacity() { return _allocated; }\r
+       inline T &back() const { return _vals[_size - 1]; }\r
+       T& operator[](unsigned int pos) const{ return _vals[pos]; }\r
+       T* _vals;\r
+private:\r
+       void _realloc(unsigned int newsize)\r
+       {\r
+               newsize = (newsize > 0)?newsize:4;\r
+               _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));\r
+               _allocated = newsize;\r
+       }\r
+       unsigned int _size;\r
+       unsigned int _allocated;\r
+};\r
+\r
+#endif //_SQUTILS_H_\r
diff --git a/src/squirrel/squirrel/sqvm.cpp b/src/squirrel/squirrel/sqvm.cpp
new file mode 100644 (file)
index 0000000..3244c65
--- /dev/null
@@ -0,0 +1,1391 @@
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include <math.h>\r
+#include <stdlib.h>\r
+#include "sqopcodes.h"\r
+#include "sqfuncproto.h"\r
+#include "sqvm.h"\r
+#include "sqclosure.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "squserdata.h"\r
+#include "sqarray.h"\r
+#include "sqclass.h"\r
+\r
+#define TOP() (_stack[_top-1])\r
+\r
+bool SQVM::BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
+{\r
+       SQInteger res;\r
+       SQInteger i1 = _integer(o1), i2 = _integer(o2);\r
+       if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER))\r
+       {\r
+               switch(op) {\r
+                       case BW_AND:    res = i1 & i2; break;\r
+                       case BW_OR:             res = i1 | i2; break;\r
+                       case BW_XOR:    res = i1 ^ i2; break;\r
+                       case BW_SHIFTL: res = i1 << i2; break;\r
+                       case BW_SHIFTR: res = i1 >> i2; break;\r
+                       case BW_USHIFTR:res = (SQInteger)(*((unsigned int*)&i1) >> i2); break;\r
+                       default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }\r
+               }\r
+       } \r
+       else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}\r
+       trg = res;\r
+       return true;\r
+}\r
+\r
+bool SQVM::ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
+{\r
+       if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
+                       if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {\r
+                               switch(op) {\r
+                               case '+': trg = _integer(o1) + _integer(o2); break;\r
+                               case '-': trg = _integer(o1) - _integer(o2); break;\r
+                               case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; }\r
+                                       trg = _integer(o1) / _integer(o2); \r
+                                       break;\r
+                               case '*': trg = _integer(o1) * _integer(o2); break;\r
+                               case '%': trg = _integer(o1) % _integer(o2); break;\r
+                               }\r
+                       }else{\r
+                               switch(op) {\r
+                               case '+': trg = tofloat(o1) + tofloat(o2); break;\r
+                               case '-': trg = tofloat(o1) - tofloat(o2); break;\r
+                               case '/': trg = tofloat(o1) / tofloat(o2); break;\r
+                               case '*': trg = tofloat(o1) * tofloat(o2); break;\r
+                               case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break;\r
+                               }\r
+                       }       \r
+               } else {\r
+                       if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){\r
+                                       if(!StringCat(o1, o2, trg)) return false;\r
+                       }\r
+                       else if(!ArithMetaMethod(op,o1,o2,trg)) { \r
+                               Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; \r
+                       }\r
+               }\r
+               return true;\r
+}\r
+\r
+SQObjectPtr &stack_get(HSQUIRRELVM v,int idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}\r
+\r
+SQVM::SQVM(SQSharedState *ss)\r
+{\r
+       _sharedstate=ss;\r
+       _suspended=false;\r
+       _suspended_target=-1;\r
+       _suspended_root=false;\r
+       _suspended_traps=-1;\r
+       _foreignptr=NULL;\r
+       _nnativecalls=0;\r
+       _uiRef=0;\r
+       _lasterror = _null_;\r
+       _errorhandler = _null_;\r
+       _debughook = _null_;\r
+       INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+void SQVM::Finalize()\r
+{\r
+       _roottable = _null_;\r
+       _lasterror = _null_;\r
+       _errorhandler = _null_;\r
+       _debughook = _null_;\r
+       temp_reg = _null_;\r
+       int size=_stack.size();\r
+       for(int i=0;i<size;i++)\r
+               _stack[i]=_null_;\r
+}\r
+\r
+SQVM::~SQVM()\r
+{\r
+       Finalize();\r
+       REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+bool SQVM::ArithMetaMethod(int op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)\r
+{\r
+       SQMetaMethod mm;\r
+       switch(op){\r
+               case _SC('+'): mm=MT_ADD; break;\r
+               case _SC('-'): mm=MT_SUB; break;\r
+               case _SC('/'): mm=MT_DIV; break;\r
+               case _SC('*'): mm=MT_MUL; break;\r
+               case _SC('%'): mm=MT_MODULO; break;\r
+       }\r
+       if(is_delegable(o1) && _delegable(o1)->_delegate) {\r
+               Push(o1);Push(o2);\r
+               return CallMetaMethod(_delegable(o1),mm,2,dest);\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)\r
+{\r
+       \r
+       switch(type(o)) {\r
+       case OT_INTEGER:\r
+               trg = -_integer(o);\r
+               return true;\r
+       case OT_FLOAT:\r
+               trg = -_float(o);\r
+               return true;\r
+       case OT_TABLE:\r
+       case OT_USERDATA:\r
+       case OT_INSTANCE:\r
+               if(_delegable(o)->_delegate) {\r
+                       Push(o);\r
+                       if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) {\r
+                               trg = temp_reg;\r
+                               return true;\r
+                       }\r
+               }\r
+               return true;\r
+\r
+       }\r
+       Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));\r
+       return false;\r
+}\r
+\r
+#define _RET_SUCCEED(exp) { result = (exp); return true; } \r
+bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,int &result)\r
+{\r
+       if(type(o1)==type(o2)){\r
+               if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0);\r
+               SQObjectPtr res;\r
+               switch(type(o1)){\r
+               case OT_STRING:\r
+                       _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));\r
+               case OT_INTEGER:\r
+                       _RET_SUCCEED(_integer(o1)-_integer(o2));\r
+               case OT_FLOAT:\r
+                       _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);\r
+               case OT_TABLE:\r
+               case OT_USERDATA:\r
+               case OT_INSTANCE:\r
+                       Push(o1);Push(o2);\r
+                       if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);\r
+                       break;\r
+               }\r
+               if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
+               _RET_SUCCEED(_integer(res));\r
+       }\r
+       else{\r
+               if(sq_isnumeric(o1) && sq_isnumeric(o2)){\r
+                       if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { \r
+                               if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }\r
+                               else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }\r
+                               _RET_SUCCEED(1);\r
+                       }\r
+                       else{\r
+                               if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }\r
+                               else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }\r
+                               _RET_SUCCEED(1);\r
+                       }\r
+               }\r
+               else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);}\r
+               else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);}\r
+               else { Raise_CompareError(o1,o2); return false; }\r
+               \r
+       }\r
+       assert(0);\r
+       _RET_SUCCEED(0); //cannot happen\r
+}\r
+\r
+bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)\r
+{\r
+       int r;\r
+       if(ObjCmp(o1,o2,r)) {\r
+               switch(op) {\r
+                       case CMP_G: res = (r > 0)?_true_:_false_; return true;\r
+                       case CMP_GE: res = (r >= 0)?_true_:_false_; return true;\r
+                       case CMP_L: res = (r < 0)?_true_:_false_; return true;\r
+                       case CMP_LE: res = (r <= 0)?_true_:_false_; return true;\r
+                       \r
+               }\r
+               assert(0);\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)\r
+{\r
+       switch(type(obj))\r
+       {\r
+       case OT_STRING:\r
+               switch(type(str)){\r
+               case OT_STRING: {\r
+                       int l=_string(str)->_len,ol=_string(obj)->_len;\r
+                       SQChar *s=_sp(rsl(l+ol+1));\r
+                       memcpy(s,_stringval(str),rsl(l));memcpy(s+l,_stringval(obj),rsl(ol));s[l+ol]=_SC('\0');\r
+                       break;\r
+               }\r
+               case OT_FLOAT:\r
+                       scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%g%s"),_float(str),_stringval(obj));\r
+                       break;\r
+               case OT_INTEGER:\r
+                       scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%d%s"),_integer(str),_stringval(obj));\r
+                       break;\r
+               default:\r
+                       Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
+                       return false;\r
+               }\r
+               dest=SQString::Create(_ss(this),_spval);\r
+               break;\r
+       case OT_FLOAT:\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%g"),_stringval(str),_float(obj));\r
+               dest=SQString::Create(_ss(this),_spval);\r
+               break;\r
+       case OT_INTEGER:\r
+               scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%d"),_stringval(str),_integer(obj));\r
+               dest=SQString::Create(_ss(this),_spval);\r
+               break;\r
+       default:\r
+               Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+const SQChar *IdType2Name(SQObjectType type)\r
+{\r
+       switch(_RAW_TYPE(type))\r
+       {\r
+       case _RT_NULL:return _SC("null");\r
+       case _RT_INTEGER:return _SC("integer");\r
+       case _RT_FLOAT:return _SC("float");\r
+       case _RT_BOOL:return _SC("bool");\r
+       case _RT_STRING:return _SC("string");\r
+       case _RT_TABLE:return _SC("table");\r
+       case _RT_ARRAY:return _SC("array");\r
+       case _RT_GENERATOR:return _SC("generator");\r
+       case _RT_CLOSURE:\r
+       case _RT_NATIVECLOSURE:\r
+               return _SC("function");\r
+       case _RT_USERDATA:\r
+       case _RT_USERPOINTER:\r
+               return _SC("userdata");\r
+       case _RT_THREAD: return _SC("thread");\r
+       case _RT_FUNCPROTO: return _SC("function");\r
+       case _RT_CLASS: return _SC("class");\r
+       case _RT_INSTANCE: return _SC("instance");\r
+       default:\r
+               return NULL;\r
+       }\r
+}\r
+\r
+const SQChar *GetTypeName(const SQObjectPtr &obj1)\r
+{\r
+       return IdType2Name(type(obj1)); \r
+}\r
+\r
+void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)\r
+{\r
+       if(is_delegable(obj1) && _delegable(obj1)->_delegate) {\r
+               Push(obj1);\r
+               if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest))\r
+                       return;\r
+       }\r
+       dest = SQString::Create(_ss(this),GetTypeName(obj1));\r
+}\r
+\r
+bool SQVM::Init(SQVM *friendvm, int stacksize)\r
+{\r
+       _stack.resize(stacksize);\r
+       _callsstack.reserve(4);\r
+       _stackbase = 0;\r
+       _top = 0;\r
+       if(!friendvm) \r
+               _roottable = SQTable::Create(_ss(this), 0);\r
+       else {\r
+               _roottable = friendvm->_roottable;\r
+               _errorhandler = friendvm->_errorhandler;\r
+               _debughook = friendvm->_debughook;\r
+       }\r
+       \r
+       sq_base_register(this);\r
+       return true;\r
+}\r
+\r
+extern SQInstructionDesc g_InstrDesc[];\r
+\r
+bool SQVM::StartCall(SQClosure *closure,int target,int nargs,int stackbase,bool tailcall)\r
+{\r
+       SQFunctionProto *func = _funcproto(closure->_function);\r
+       //const int outerssize = func->_outervalues.size();\r
+\r
+       const int paramssize = func->_parameters.size();\r
+       const int oldtop = _top;\r
+       const int newtop = stackbase + func->_stacksize;\r
+       \r
+       \r
+       if(func->_varparams)\r
+       {\r
+               if (nargs < paramssize) {\r
+                       Raise_Error(_SC("wrong number of parameters"));\r
+                       return false;\r
+               }\r
+               for(int n = 0; n < nargs - paramssize; n++) {\r
+                       _vargsstack.push_back(_stack[stackbase+paramssize+n]);\r
+                       _stack[stackbase+paramssize+n] = _null_;\r
+               }\r
+       }\r
+       else {\r
+               if (paramssize != nargs) {\r
+                       Raise_Error(_SC("wrong number of parameters"));\r
+                       return false;\r
+               }\r
+               \r
+       }\r
+       \r
+       if (!tailcall) {\r
+               PUSH_CALLINFO(this, CallInfo());\r
+               ci->_etraps = 0;\r
+               ci->_prevstkbase = stackbase - _stackbase;\r
+               ci->_target = target;\r
+               ci->_prevtop = _top - _stackbase;\r
+               ci->_ncalls = 1;\r
+               ci->_root = false;\r
+       }\r
+       else {\r
+               ci->_ncalls++;\r
+       }\r
+       ci->_vargs.size = (nargs - paramssize);\r
+       ci->_vargs.base = _vargsstack.size()-(nargs - paramssize);\r
+       ci->_closure._unVal.pClosure = closure;\r
+       ci->_closure._type = OT_CLOSURE;\r
+       ci->_iv = &func->_instructions;\r
+       ci->_literals = &func->_literals;\r
+       //grows the stack if needed\r
+       if (((unsigned int)newtop + (func->_stacksize<<1)) > _stack.size()) {\r
+               _stack.resize(_stack.size() + (func->_stacksize<<1));\r
+       }\r
+               \r
+       _top = newtop;\r
+       _stackbase = stackbase;\r
+       ci->_ip = ci->_iv->_vals;\r
+       return true;\r
+}\r
+\r
+bool SQVM::Return(int _arg0, int _arg1, SQObjectPtr &retval)\r
+{\r
+       if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+               for(int i=0;i<ci->_ncalls;i++)\r
+                       CallDebugHook(_SC('r'));\r
+                                               \r
+       bool broot = ci->_root;\r
+       int last_top = _top;\r
+       int target = ci->_target;\r
+       int oldstackbase = _stackbase;\r
+       _stackbase -= ci->_prevstkbase;\r
+       _top = _stackbase + ci->_prevtop;\r
+       PopVarArgs(ci->_vargs);\r
+       POP_CALLINFO(this);\r
+       if (broot) {\r
+               if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1];\r
+               else retval = _null_;\r
+       }\r
+       else {\r
+               if (_arg0 != MAX_FUNC_STACKSIZE)\r
+                       STK(target) = _stack[oldstackbase+_arg1];\r
+               else\r
+                       STK(target) = _null_;\r
+       }\r
+\r
+       while (last_top >= _top) _stack[last_top--].Null();\r
+       assert(oldstackbase >= _stackbase); \r
+       return broot;\r
+}\r
+\r
+#define _RET_ON_FAIL(exp) { if(!exp) return false; }\r
+\r
+bool SQVM::LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
+{\r
+       _RET_ON_FAIL(ARITH_OP( op , target, a, incr));\r
+       a = target;\r
+       return true;\r
+}\r
+\r
+bool SQVM::PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
+{\r
+       SQObjectPtr trg;\r
+       _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));\r
+       target = a;\r
+       a = trg;\r
+       return true;\r
+}\r
+\r
+bool SQVM::DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix)\r
+{\r
+       SQObjectPtr tmp, tself = self, tkey = key;\r
+       if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; }\r
+       _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))\r
+       Set(tself, tkey, target,true);\r
+       if (postfix) target = tmp;\r
+       return true;\r
+}\r
+\r
+#define arg0 (_i_._arg0)\r
+#define arg1 (_i_._arg1)\r
+#define sarg1 (*((int *)&_i_._arg1))\r
+#define arg2 (_i_._arg2)\r
+#define arg3 (_i_._arg3)\r
+#define sarg3 (*((char *)&_i_._arg3))\r
+\r
+SQRESULT SQVM::Suspend()\r
+{\r
+       if (_suspended)\r
+               return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));\r
+       if (_nnativecalls!=2)\r
+               return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));\r
+       return SQ_SUSPEND_FLAG;\r
+}\r
+\r
+void SQVM::PopVarArgs(VarArgs &vargs)\r
+{\r
+       for(int n = 0; n< vargs.size; n++)\r
+               _vargsstack.pop_back();\r
+}\r
+\r
+#define _FINISH(stoploop) {finished = stoploop; return true; }\r
+bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr \r
+&o3,SQObjectPtr &o4,int arg_2,bool &finished)\r
+{\r
+       int nrefidx;\r
+       switch(type(o1)) {\r
+       case OT_TABLE:\r
+               if((nrefidx = _table(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);\r
+               o4 = (SQInteger)nrefidx; _FINISH(false);\r
+       case OT_ARRAY:\r
+               if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);\r
+               o4 = (SQInteger) nrefidx; _FINISH(false);\r
+       case OT_STRING:\r
+               if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);\r
+               o4 = (SQInteger)nrefidx; _FINISH(false);\r
+       case OT_CLASS:\r
+               if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);\r
+               o4 = (SQInteger)nrefidx; _FINISH(false);\r
+       case OT_USERDATA:\r
+       case OT_INSTANCE:\r
+               if(_delegable(o1)->_delegate) {\r
+                       SQObjectPtr itr;\r
+                       Push(o1);\r
+                       Push(o4);\r
+                       if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){\r
+                               o4 = o2 = itr;\r
+                               if(type(itr) == OT_NULL) _FINISH(true);\r
+                               if(!Get(o1, itr, o3, false,false)) {\r
+                                       Raise_Error(_SC("_nexti returned an invalid idx"));\r
+                                       return false;\r
+                               }\r
+                               _FINISH(false);\r
+                       }\r
+                       Raise_Error(_SC("_nexti failed"));\r
+                       return false;\r
+               }\r
+               break;\r
+       case OT_GENERATOR:\r
+               if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true);\r
+               if(_generator(o1)->_state == SQGenerator::eSuspended) {\r
+                       SQInteger idx = 0;\r
+                       if(type(o4) == OT_INTEGER) {\r
+                               idx = _integer(o4) + 1;\r
+                       }\r
+                       o2 = idx;\r
+                       o4 = idx;\r
+                       _generator(o1)->Resume(this, arg_2+1);\r
+                       _FINISH(false);\r
+               }\r
+       }\r
+       Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));\r
+       return false; //cannot be hit(just to avoid warnings)\r
+}\r
+\r
+bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)\r
+{\r
+       if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; }\r
+       switch(type(o2)) {\r
+       case OT_TABLE:\r
+               if(!_table(o1)->SetDelegate(_table(o2))){\r
+                       Raise_Error(_SC("delegate cycle detected"));\r
+                       return false;\r
+               }\r
+               break;\r
+       case OT_NULL:\r
+               _table(o1)->SetDelegate(NULL);\r
+               break;\r
+       default:\r
+               Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2));\r
+               return false;\r
+               break;\r
+       }\r
+       trg = o1;\r
+       return true;\r
+}\r
+#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1))\r
+\r
+#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }\r
+\r
+#define SQ_THROW() { goto exception_trap; }\r
+\r
+bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)\r
+{\r
+       int nouters;\r
+       SQClosure *closure = SQClosure::Create(_ss(this), func);\r
+       if(nouters = func->_outervalues.size()) {\r
+               closure->_outervalues.reserve(nouters);\r
+               for(int i = 0; i<nouters; i++) {\r
+                       SQOuterVar &v = func->_outervalues[i];\r
+                       switch(v._type){\r
+                       case otSYMBOL:\r
+                               closure->_outervalues.push_back(_null_);\r
+                               if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true))\r
+                               {Raise_IdxError(v._src); return false; }\r
+                               break;\r
+                       case otLOCAL:\r
+                               closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]);\r
+                               break;\r
+                       case otOUTER:\r
+                               closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]);\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       target = closure;\r
+       return true;\r
+\r
+}\r
+\r
+bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci)\r
+{\r
+       if(ci->_vargs.size == 0) {\r
+               Raise_Error(_SC("the function doesn't have var args"));\r
+               return false;\r
+       }\r
+       if(!sq_isnumeric(index)){\r
+               Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index));\r
+               return false;\r
+       }\r
+       int idx = tointeger(index);\r
+       if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; }\r
+       target = _vargsstack[ci->_vargs.base+idx];\r
+       return true;\r
+}\r
+\r
+bool SQVM::CLASS_OP(SQObjectPtr &target,int baseclass,int attributes)\r
+{\r
+       SQClass *base = NULL;\r
+       SQObjectPtr attrs;\r
+       if(baseclass != MAX_LITERALS) {\r
+               if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }\r
+               base = _class(_stack._vals[_stackbase + baseclass]);\r
+       }\r
+       if(attributes != MAX_FUNC_STACKSIZE) {\r
+               attrs = _stack._vals[_stackbase+attributes];\r
+       }\r
+       target = SQClass::Create(_ss(this),base);\r
+       _class(target)->_attributes = attrs;\r
+       return true;\r
+}\r
+\r
+bool SQVM::IsFalse(SQObjectPtr &o)\r
+{\r
+       SQObjectType t = type(o);\r
+       if((t & SQOBJECT_CANBEFALSE)\r
+               && ((t == OT_NULL) || ((t == OT_INTEGER || t == OT_BOOL) && _integer(o) == 0)\r
+               || (t == OT_FLOAT && _float(o) == SQFloat(0.0)))) {\r
+                       return true;\r
+               }\r
+       return false;\r
+}\r
+\r
+bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)\r
+{\r
+       if(type(o1) == type(o2)) {\r
+               res = ((_userpointer(o1) == _userpointer(o2)?true:false));\r
+       }\r
+       else {\r
+               if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
+                       int cmpres;\r
+                       if(!ObjCmp(o1, o2,cmpres)) return false;\r
+                       res = (cmpres == 0);\r
+               }\r
+               else {\r
+                       res = false;\r
+               }\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQVM::Execute(SQObjectPtr &closure, int target, int nargs, int stackbase,SQObjectPtr &outres, ExecutionType et)\r
+{\r
+       if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
+       _nnativecalls++;\r
+       AutoDec ad(&_nnativecalls);\r
+       int traps = 0;\r
+       //temp_reg vars for OP_CALL\r
+       int ct_target;\r
+       bool ct_tailcall; \r
+\r
+       switch(et) {\r
+               case ET_CALL: \r
+                       if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) { \r
+                               //call the handler if there are no calls in the stack, if not relies on the previous node\r
+                               if(ci == NULL) CallErrorHandler(_lasterror);\r
+                               return false;\r
+                       }\r
+                       ci->_root = true;\r
+                       break;\r
+               case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = true; traps += ci->_etraps; break;\r
+               case ET_RESUME_VM:\r
+                       traps = _suspended_traps;\r
+                       ci->_root = _suspended_root;\r
+                       _suspended = false;\r
+                       break;\r
+       }\r
+       \r
+exception_restore:\r
+       //SQ_TRY \r
+       {\r
+               for(;;)\r
+               {\r
+                       const SQInstruction &_i_ = *ci->_ip++;\r
+                       //dumpstack(_stackbase);\r
+                       //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);\r
+                       switch(_i_.op)\r
+                       {\r
+                       case _OP_LINE:\r
+                               if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+                                       CallDebugHook(_SC('l'),arg1);\r
+                               continue;\r
+                       case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue;\r
+                       case _OP_TAILCALL:\r
+                               temp_reg = STK(arg1);\r
+                               if (type(temp_reg) == OT_CLOSURE){ \r
+                                       ct_tailcall = true;\r
+                                       PopVarArgs(ci->_vargs);\r
+                                       for (int i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);\r
+                                       ct_target = ci->_target;\r
+                                       goto common_call;\r
+                               }\r
+                       case _OP_CALL: {\r
+                                       ct_tailcall = false;\r
+                                       ct_target = arg0;\r
+                                       temp_reg = STK(arg1);\r
+common_call:\r
+                                       int last_top = _top;\r
+                                       switch (type(temp_reg)) {\r
+                                       case OT_CLOSURE:{\r
+                                               StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall);\r
+                                               if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {\r
+                                                       SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));\r
+                                                       _GUARD(gen->Yield(this));\r
+                                                       Return(1, ct_target, temp_reg);\r
+                                                       STK(ct_target) = gen;\r
+                                                       while (last_top >= _top) _stack[last_top--].Null();\r
+                                                       continue;\r
+                                               }\r
+                                               if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+                                                       CallDebugHook(_SC('c'));\r
+                                               }\r
+                                               break;\r
+                                       case OT_NATIVECLOSURE: {\r
+                                               bool suspend;\r
+                                               _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend));\r
+                                               if(suspend){\r
+                                                       _suspended = true;\r
+                                                       _suspended_target = ct_target;\r
+                                                       _suspended_root = ci->_root;\r
+                                                       _suspended_traps = traps;\r
+                                                       outres = temp_reg;\r
+                                                       return true;\r
+                                               }\r
+                                               STK(ct_target) = temp_reg;\r
+                                                                                  }\r
+                                               break;\r
+                                       case OT_CLASS:{\r
+                                               _GUARD(CreateClassInstance(_class(temp_reg),arg3,_stackbase+arg2,STK(ct_target)));\r
+                                               }\r
+                                               break;\r
+                                       case OT_TABLE:\r
+                                       case OT_USERDATA:\r
+                                       case OT_INSTANCE:\r
+                                               {\r
+                                               Push(temp_reg);\r
+                                               for (int i = 0; i < arg3; i++) Push(STK(arg2 + i));\r
+                                               if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){\r
+                                                       STK(ct_target) = temp_reg;\r
+                                                       break;\r
+                                               }\r
+                                               Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));\r
+                                               SQ_THROW();\r
+                                         }\r
+                                       default:\r
+                                               Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));\r
+                                               SQ_THROW();\r
+                                       }\r
+                               }\r
+                                 continue;\r
+                       case _OP_PREPCALL:\r
+                                       if (!Get(STK(arg2), STK(arg1), temp_reg, false,true))\r
+                                       { Raise_IdxError(STK(arg1)); SQ_THROW(); }\r
+                                       goto common_prepcall;\r
+                       case _OP_PREPCALLK:\r
+                                       if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) {\r
+                                               if(type(STK(arg2)) == OT_CLASS) { //hack?\r
+                                                       if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) {\r
+                                                               STK(arg3) = STK(arg2);\r
+                                                               TARGET = temp_reg;\r
+                                                               continue;\r
+                                                       }\r
+                                               }\r
+                                               { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}\r
+                                       }\r
+common_prepcall:\r
+                                       if(type(STK(arg2)) == OT_CLASS) {\r
+                                               STK(arg3) = STK(0); // this\r
+                                       }\r
+                                       else {\r
+                                               STK(arg3) = STK(arg2);\r
+                                       }\r
+                                       TARGET = temp_reg;\r
+                               continue;\r
+                       case _OP_GETK:\r
+                               if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}\r
+                               TARGET = temp_reg;\r
+                               continue;\r
+                       case _OP_MOVE: TARGET = STK(arg1); continue;\r
+                       case _OP_NEWSLOT:\r
+                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
+                               if(arg0 != arg3) TARGET = STK(arg3);\r
+                               continue;\r
+                       case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;\r
+                       case _OP_SET:\r
+                               if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
+                               if (arg0 != arg3) TARGET = STK(arg3);\r
+                               continue;\r
+                       case _OP_GET:\r
+                               if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
+                               TARGET = temp_reg;\r
+                               continue;\r
+                       case _OP_EQ:{\r
+                               bool res;\r
+                               if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
+                               TARGET = res?_true_:_false_;\r
+                               }continue;\r
+                       case _OP_NE:{ \r
+                               bool res;\r
+                               if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
+                               TARGET = (!res)?_true_:_false_;\r
+                               } continue;\r
+                       case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue;\r
+                       case _OP_BITW:  _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;\r
+                       case _OP_RETURN:\r
+                               if(type((ci)->_generator) == OT_GENERATOR) {\r
+                                       _generator((ci)->_generator)->Kill();\r
+                               }\r
+                               if(Return(arg0, arg1, temp_reg)){\r
+                                       assert(traps==0);\r
+                                       outres = temp_reg;\r
+                                       return true;\r
+                               }\r
+                               continue;\r
+                       case _OP_LOADNULLS:{ for(unsigned int n=0;n<arg1;n++) STK(arg0+n) = _null_; }continue;\r
+                       case _OP_LOADROOTTABLE: TARGET = _roottable; continue;\r
+                       case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue;\r
+                       case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;\r
+                       case _OP_JMP: ci->_ip += (sarg1); continue;\r
+                       case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
+                       case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
+                       case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue;\r
+                       case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue;\r
+                       case _OP_GETVARGV: \r
+                               if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } \r
+                               continue;\r
+                       case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;\r
+                       case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;\r
+                       case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL);  continue;\r
+                       case _OP_GETPARENT:\r
+                               switch(type(STK(arg1))) {\r
+                               case OT_TABLE: \r
+                       TARGET = _table(STK(arg1))->_delegate?SQObjectPtr(_table(STK(arg1))->_delegate):_null_;\r
+                                       continue;\r
+                               case OT_CLASS: TARGET = _class(STK(arg1))->_base?_class(STK(arg1))->_base:_null_;\r
+                                       continue;\r
+                               }\r
+                               Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(STK(arg1)));\r
+                               SQ_THROW();\r
+                               continue;\r
+                       case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((unsigned int)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue;\r
+                       case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue;\r
+                       case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue;\r
+                       case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
+                       case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue;\r
+                       case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
+                       case _OP_CMP:   _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))  continue;\r
+                       case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue;\r
+                       case _OP_INSTANCEOF: \r
+                               if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)\r
+                               {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}\r
+                               TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;\r
+                               continue;\r
+                       case _OP_AND: \r
+                               if(IsFalse(STK(arg2))) {\r
+                                       TARGET = STK(arg2);\r
+                                       ci->_ip += (sarg1);\r
+                               }\r
+                               continue;\r
+                       case _OP_OR:\r
+                               if(!IsFalse(STK(arg2))) {\r
+                                       TARGET = STK(arg2);\r
+                                       ci->_ip += (sarg1);\r
+                               }\r
+                               continue;\r
+                       case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;\r
+                       case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue;\r
+                       case _OP_BWNOT:\r
+                               if(type(STK(arg1)) == OT_INTEGER) {\r
+                                       TARGET = SQInteger(~_integer(STK(arg1)));\r
+                                       continue;\r
+                               }\r
+                               Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));\r
+                               SQ_THROW();\r
+                       case _OP_CLOSURE: {\r
+                               SQClosure *c = ci->_closure._unVal.pClosure;\r
+                               SQFunctionProto *fp = c->_function._unVal.pFunctionProto;\r
+                               if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }\r
+                               continue;\r
+                       }\r
+                       case _OP_YIELD:{\r
+                               if(type(ci->_generator) == OT_GENERATOR) {\r
+                                       if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);\r
+                                       _GUARD(_generator(ci->_generator)->Yield(this));\r
+                                       traps -= ci->_etraps;\r
+                                       if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;\r
+                               }\r
+                               else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}\r
+                               if(Return(arg0, arg1, temp_reg)){\r
+                                       assert(traps==0);\r
+                                       outres = temp_reg;\r
+                                       return true;\r
+                               }\r
+                                       \r
+                               }\r
+                               continue;\r
+                       case _OP_RESUME:\r
+                               if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}\r
+                               _GUARD(_generator(STK(arg1))->Resume(this, arg0));\r
+                               traps += ci->_etraps;\r
+                continue;\r
+                       case _OP_FOREACH:{ bool finished;\r
+                               _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished));\r
+                               if(finished) ci->_ip += sarg1; }\r
+                               continue;\r
+                       case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;\r
+                       case _OP_CLONE:\r
+                               if(!Clone(STK(arg1), TARGET))\r
+                               { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();}\r
+                               continue;\r
+                       case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;\r
+                       case _OP_PUSHTRAP:\r
+                               _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++;\r
+                               ci->_etraps++;\r
+                               continue;\r
+                       case _OP_POPTRAP:{\r
+                               for(int i=0; i<arg0; i++) {\r
+                                       _etraps.pop_back(); traps--;\r
+                                       ci->_etraps--;\r
+                               }}\r
+                               continue;\r
+                       case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;\r
+                       case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;\r
+                       case _OP_NEWSLOTA:\r
+                               _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
+                               _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
+                               if(arg0 != arg3) TARGET = STK(arg3);\r
+                               continue;\r
+                       }\r
+                       \r
+               }\r
+       }\r
+exception_trap:\r
+       {\r
+               SQObjectPtr currerror = _lasterror;\r
+//             dumpstack(_stackbase);\r
+               int n = 0;\r
+               int last_top = _top;\r
+               if(ci) {\r
+                       if(traps) {\r
+                               do {\r
+                                       if(ci->_etraps > 0) {\r
+                                               SQExceptionTrap &et = _etraps.top();\r
+                                               ci->_ip = et._ip;\r
+                                               _top = et._stacksize;\r
+                                               _stackbase = et._stackbase;\r
+                                               _stack[_stackbase+et._extarget] = currerror;\r
+                                               _etraps.pop_back(); traps--; ci->_etraps--;\r
+                                               while(last_top >= _top) _stack[last_top--].Null();\r
+                                               goto exception_restore;\r
+                                       }\r
+                                       //if is a native closure\r
+                                       if(type(ci->_closure) != OT_CLOSURE && n)\r
+                                               break;\r
+                                       if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();\r
+                                       PopVarArgs(ci->_vargs);\r
+                                       POP_CALLINFO(this);\r
+                                       n++;\r
+                               }while(_callsstack.size());\r
+                       }\r
+                       //call the hook\r
+                       CallErrorHandler(currerror);\r
+                       //remove call stack until a C function is found or the cstack is empty\r
+                       if(ci) do{\r
+                               bool exitafterthisone = ci->_root;\r
+                               if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();\r
+                               _stackbase -= ci->_prevstkbase;\r
+                               _top = _stackbase + ci->_prevtop;\r
+                               PopVarArgs(ci->_vargs);\r
+                               POP_CALLINFO(this);\r
+                               if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;\r
+                       }while(_callsstack.size());\r
+\r
+                       while(last_top >= _top) _stack[last_top--].Null();\r
+               }\r
+               _lasterror = currerror;\r
+               return false;\r
+       }\r
+       assert(0);\r
+}\r
+\r
+bool SQVM::CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval)\r
+{\r
+       SQObjectPtr constr;\r
+       SQObjectPtr inst = theclass->CreateInstance();\r
+       _stack[stackbase] = inst;\r
+       if(theclass->Get(_ss(this)->_constructoridx,constr)) {\r
+               if(!Call(constr,nargs,stackbase,constr))\r
+                       return false;\r
+       }\r
+       retval = inst;\r
+       return true;\r
+}\r
+\r
+void SQVM::CallErrorHandler(SQObjectPtr &error)\r
+{\r
+       if(type(_errorhandler) != OT_NULL) {\r
+               SQObjectPtr out;\r
+               Push(_roottable); Push(error);\r
+               Call(_errorhandler, 2, _top-2, out);\r
+               Pop(2);\r
+       }\r
+}\r
+\r
+void SQVM::CallDebugHook(int type,int forcedline)\r
+{\r
+       SQObjectPtr temp_reg;\r
+       int nparams=5;\r
+       SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);\r
+       Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);\r
+       Call(_debughook,nparams,_top-nparams,temp_reg);\r
+       Pop(nparams);\r
+}\r
+\r
+bool SQVM::CallNative(SQNativeClosure *nclosure,int nargs,int stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend)\r
+{\r
+       if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
+       int nparamscheck = nclosure->_nparamscheck;\r
+       if(((nparamscheck > 0) && (nparamscheck != nargs))\r
+               || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {\r
+               Raise_Error(_SC("wrong number of parameters"));\r
+               return false;\r
+               }\r
+\r
+       int tcs;\r
+       if(tcs = nclosure->_typecheck.size()) {\r
+               for(int i = 0; i < nargs && i < tcs; i++)\r
+                       if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) {\r
+                Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i]));\r
+                               return false;\r
+                       }\r
+       }\r
+       _nnativecalls++;\r
+       if ((_top + MIN_STACK_OVERHEAD) > (int)_stack.size()) {\r
+               _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));\r
+       }\r
+       int oldtop = _top;\r
+       int oldstackbase = _stackbase;\r
+       _top = stackbase + nargs;\r
+       PUSH_CALLINFO(this, CallInfo());\r
+       ci->_etraps = 0;\r
+       ci->_closure._unVal.pNativeClosure = nclosure;\r
+       ci->_closure._type = OT_NATIVECLOSURE;\r
+       ci->_prevstkbase = stackbase - _stackbase;\r
+       ci->_ncalls = 1;\r
+       _stackbase = stackbase;\r
+       //push free variables\r
+       int outers = nclosure->_outervalues.size();\r
+       for (int i = 0; i < outers; i++) {\r
+               Push(nclosure->_outervalues[i]);\r
+       }\r
+       ci->_prevtop = (oldtop - oldstackbase);\r
+       int ret = (nclosure->_function)(this);\r
+       _nnativecalls--;\r
+       suspend = false;\r
+       if( ret == SQ_SUSPEND_FLAG) suspend = true;\r
+       else if (ret < 0) { \r
+               _stackbase = oldstackbase;\r
+               _top = oldtop;\r
+               POP_CALLINFO(this);\r
+               Raise_Error(_lasterror);\r
+               return false;\r
+       }\r
+       \r
+       if (ret != 0){ retval = TOP(); }\r
+       else { retval = _null_; }\r
+       _stackbase = oldstackbase;\r
+       _top = oldtop;\r
+       POP_CALLINFO(this);\r
+       return true;\r
+}\r
+\r
+bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot)\r
+{\r
+       switch(type(self)){\r
+       case OT_TABLE:\r
+               if(_table(self)->Get(key,dest))return true;\r
+               break;\r
+       case OT_ARRAY:\r
+               if(sq_isnumeric(key)){\r
+                       return _array(self)->Get(tointeger(key),dest);\r
+               }\r
+               break;\r
+       case OT_INSTANCE:\r
+               if(_instance(self)->Get(key,dest)) return true;\r
+               break;\r
+       }\r
+       if(FallBackGet(self,key,dest,raw)) return true;\r
+\r
+       if(fetchroot) {\r
+               if(_rawval(STK(0)) == _rawval(self) &&\r
+                       type(STK(0)) == type(self)) {\r
+                               return _table(_roottable)->Get(key,dest);\r
+               }\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw)\r
+{\r
+       switch(type(self)){\r
+       case OT_CLASS: \r
+               return _class(self)->Get(key,dest);\r
+               break;\r
+       case OT_TABLE:\r
+       case OT_USERDATA:\r
+        //delegation\r
+               if(_delegable(self)->_delegate) {\r
+                       if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false))\r
+                               return true;    \r
+                       if(raw)return false;\r
+                       Push(self);Push(key);\r
+                       if(CallMetaMethod(_delegable(self),MT_GET,2,dest))\r
+                               return true;\r
+               }\r
+               if(type(self) == OT_TABLE) {\r
+                       if(raw) return false;\r
+                       return _table_ddel->Get(key,dest);\r
+               }\r
+               return false;\r
+               break;\r
+       case OT_ARRAY:\r
+               if(raw)return false;\r
+               return _array_ddel->Get(key,dest);\r
+       case OT_STRING:\r
+               if(sq_isnumeric(key)){\r
+                       SQInteger n=tointeger(key);\r
+                       if(abs(n)<_string(self)->_len){\r
+                               if(n<0)n=_string(self)->_len-n;\r
+                               dest=SQInteger(_stringval(self)[n]);\r
+                               return true;\r
+                       }\r
+                       return false;\r
+               }\r
+               else {\r
+                       if(raw)return false;\r
+                       return _string_ddel->Get(key,dest);\r
+               }\r
+               break;\r
+       case OT_INSTANCE:\r
+               if(raw)return false;\r
+               Push(self);Push(key);\r
+               if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) {\r
+                       return _instance_ddel->Get(key,dest);\r
+               }\r
+               return true;\r
+       case OT_INTEGER:case OT_FLOAT:case OT_BOOL: \r
+               if(raw)return false;\r
+               return _number_ddel->Get(key,dest);\r
+       case OT_GENERATOR: \r
+               if(raw)return false;\r
+               return _generator_ddel->Get(key,dest);\r
+       case OT_CLOSURE: case OT_NATIVECLOSURE: \r
+               if(raw)return false;\r
+               return _closure_ddel->Get(key,dest);\r
+       case OT_THREAD:\r
+               if(raw)return false;\r
+               return  _thread_ddel->Get(key,dest);\r
+       default:return false;\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot)\r
+{\r
+       switch(type(self)){\r
+       case OT_TABLE:\r
+               if(_table(self)->Set(key,val))\r
+                       return true;\r
+               if(_table(self)->_delegate) {\r
+                       if(Set(_table(self)->_delegate,key,val,false)) {\r
+                               return true;\r
+                       }\r
+               }\r
+               //keeps going\r
+       case OT_USERDATA:\r
+               if(_delegable(self)->_delegate) {\r
+                       SQObjectPtr t;\r
+                       Push(self);Push(key);Push(val);\r
+                       if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
+               }\r
+               break;\r
+       case OT_INSTANCE:{\r
+               if(_instance(self)->Set(key,val))\r
+                       return true;\r
+               SQObjectPtr t;\r
+               Push(self);Push(key);Push(val);\r
+               if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
+               }\r
+               break;\r
+       case OT_ARRAY:\r
+               if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }\r
+               return _array(self)->Set(tointeger(key),val);\r
+       default:\r
+               Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));\r
+               return false;\r
+       }\r
+       if(fetchroot) {\r
+               if(_rawval(STK(0)) == _rawval(self) &&\r
+                       type(STK(0)) == type(self)) {\r
+                               return _table(_roottable)->Set(key,val);\r
+                       }\r
+       }\r
+       return false;\r
+}\r
+\r
+bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)\r
+{\r
+       SQObjectPtr temp_reg;\r
+       switch(type(self)){\r
+       case OT_TABLE:\r
+               target = _table(self)->Clone();\r
+               goto cloned_mt;\r
+       case OT_INSTANCE:\r
+               target = _instance(self)->Clone(_ss(this));\r
+cloned_mt:\r
+               if(_delegable(target)->_delegate){\r
+                       Push(target);\r
+                       Push(self);\r
+                       CallMetaMethod(_delegable(target),MT_CLONED,2,temp_reg);\r
+               }\r
+               return true;\r
+       case OT_ARRAY: \r
+               target=_array(self)->Clone();\r
+               return true;\r
+       default: return false;\r
+       }\r
+}\r
+\r
+bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }\r
+       switch(type(self)) {\r
+       case OT_TABLE: {\r
+               bool rawcall = true;\r
+               if(_table(self)->_delegate) {\r
+                       SQObjectPtr res;\r
+                       if(!_table(self)->Get(key,res)) {\r
+                               Push(self);Push(key);Push(val);\r
+                               rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res);\r
+                       }\r
+               }\r
+               if(rawcall) _table(self)->NewSlot(key,val); //cannot fail\r
+               \r
+               break;}\r
+       case OT_CLASS: \r
+               if(!_class(self)->NewSlot(key,val)) {\r
+                       if(_class(self)->_locked) {\r
+                               Raise_Error(_SC("trying to modify a class that has already been instantiated"));\r
+                               return false;\r
+                       }\r
+                       else {\r
+                               SQObjectPtr oval = PrintObjVal(key);\r
+                               Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));\r
+                               return false;\r
+                       }\r
+               }\r
+               break;\r
+       default:\r
+               Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));\r
+               return false;\r
+               break;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)\r
+{\r
+       switch(type(self)) {\r
+       case OT_TABLE:\r
+       case OT_INSTANCE:\r
+       case OT_USERDATA: {\r
+               SQObjectPtr t;\r
+               bool handled = false;\r
+               if(_delegable(self)->_delegate) {\r
+                       Push(self);Push(key);\r
+                       handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t);\r
+               }\r
+\r
+               if(!handled) {\r
+                       if(type(self) == OT_TABLE) {\r
+                               if(_table(self)->Get(key,t)) {\r
+                                       _table(self)->Remove(key);\r
+                               }\r
+                               else {\r
+                                       Raise_IdxError((SQObject &)key);\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       else {\r
+                               Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));\r
+                               return false;\r
+                       }\r
+               }\r
+               res = t;\r
+                               }\r
+               break;\r
+       default:\r
+               Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool SQVM::Call(SQObjectPtr &closure,int nparams,int stackbase,SQObjectPtr &outres)\r
+{\r
+#ifdef _DEBUG\r
+int prevstackbase = _stackbase;\r
+#endif\r
+       switch(type(closure)) {\r
+       case OT_CLOSURE:\r
+               return Execute(closure, _top - nparams, nparams, stackbase,outres);\r
+               break;\r
+       case OT_NATIVECLOSURE:{\r
+               bool suspend;\r
+               return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend);\r
+               \r
+                                                 }\r
+               break;\r
+       case OT_CLASS:\r
+               return CreateClassInstance(_class(closure),nparams,stackbase,outres);\r
+               break;\r
+       default:\r
+               return false;\r
+       }\r
+#ifdef _DEBUG\r
+       if(!_suspended) {\r
+               assert(_stackbase == prevstackbase);\r
+       }\r
+#endif\r
+       return true;\r
+}\r
+\r
+bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,int nparams,SQObjectPtr &outres)\r
+{\r
+       SQObjectPtr closure;\r
+       if(del->GetMetaMethod(mm, closure)) {\r
+               if(Call(closure, nparams, _top - nparams, outres)) {\r
+                       Pop(nparams);\r
+                       return true;\r
+               }\r
+       }\r
+       Pop(nparams);\r
+       return false;\r
+}\r
+\r
+void SQVM::Pop() {\r
+       _stack[--_top] = _null_;\r
+}\r
+void SQVM::Pop(int n) {\r
+       for(int i = 0; i < n; i++){\r
+               _stack[--_top] = _null_;\r
+       }\r
+}\r
+\r
+void SQVM::Remove(int n) {\r
+       n = (n >= 0)?n + _stackbase - 1:_top + n;\r
+       for(int i = n; i < _top; i++){\r
+               _stack[i] = _stack[i+1];\r
+       }\r
+       _stack[_top] = _null_;\r
+       _top--;\r
+}\r
+\r
+void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }\r
+SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }\r
+SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }\r
+SQObjectPtr &SQVM::GetUp(int n) { return _stack[_top+n]; }\r
+SQObjectPtr &SQVM::GetAt(int n) { return _stack[n]; }\r
+\r
+#ifdef _DEBUG_DUMP\r
+void SQVM::dumpstack(int stackbase,bool dumpall)\r
+{\r
+       int size=dumpall?_stack.size():_top;\r
+       int n=0;\r
+       scprintf(_SC("\n>>>>stack dump<<<<\n"));\r
+       CallInfo &ci=_callsstack.back();\r
+       scprintf(_SC("IP: %d\n"),ci._ip);\r
+       scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);\r
+       scprintf(_SC("prev top: %d\n"),ci._prevtop);\r
+       for(int i=0;i<size;i++){\r
+               SQObjectPtr &obj=_stack[i];     \r
+               if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));\r
+               scprintf(_SC("[%d]:"),n);\r
+               switch(type(obj)){\r
+               case OT_FLOAT:                  scprintf(_SC("FLOAT %.3f"),_float(obj));break;\r
+               case OT_INTEGER:                scprintf(_SC("INTEGER %d"),_integer(obj));break;\r
+               case OT_BOOL:                   scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;\r
+               case OT_STRING:                 scprintf(_SC("STRING %s"),_stringval(obj));break;\r
+               case OT_NULL:                   scprintf(_SC("NULL"));  break;\r
+               case OT_TABLE:                  scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;\r
+               case OT_ARRAY:                  scprintf(_SC("ARRAY %p"),_array(obj));break;\r
+               case OT_CLOSURE:                scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;\r
+               case OT_NATIVECLOSURE:  scprintf(_SC("NATIVECLOSURE"));break;\r
+               case OT_USERDATA:               scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;\r
+               case OT_GENERATOR:              scprintf(_SC("GENERATOR"));break;\r
+               case OT_THREAD:                 scprintf(_SC("THREAD [%p]"),_thread(obj));break;\r
+               case OT_USERPOINTER:    scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;\r
+               case OT_CLASS:                  scprintf(_SC("CLASS %p"),_class(obj));break;\r
+               case OT_INSTANCE:               scprintf(_SC("INSTANCE %p"),_instance(obj));break;\r
+               default:\r
+                       assert(0);\r
+                       break;\r
+               };\r
+               scprintf(_SC("\n"));\r
+               ++n;\r
+       }\r
+}\r
+\r
+#endif\r
diff --git a/src/squirrel/squirrel/sqvm.h b/src/squirrel/squirrel/sqvm.h
new file mode 100644 (file)
index 0000000..7ba178c
--- /dev/null
@@ -0,0 +1,189 @@
+/*     see copyright notice in squirrel.h */\r
+#ifndef _SQVM_H_\r
+#define _SQVM_H_\r
+\r
+#include "sqopcodes.h"\r
+#include "sqobject.h"\r
+#define MAX_NATIVE_CALLS 100\r
+#define MIN_STACK_OVERHEAD 10\r
+\r
+#define SQ_SUSPEND_FLAG -666\r
+//base lib\r
+void sq_base_register(HSQUIRRELVM v);\r
+\r
+struct SQExceptionTrap{\r
+       SQExceptionTrap() {}\r
+       SQExceptionTrap(int ss, int stackbase,SQInstruction *ip, int ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}\r
+       SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;      }\r
+       int _stackbase;\r
+       int _stacksize;\r
+       SQInstruction *_ip;\r
+       int _extarget;\r
+};\r
+\r
+\r
+#define STK(a) _stack._vals[_stackbase+(a)]\r
+#define TARGET _stack._vals[_stackbase+arg0]\r
+\r
+typedef sqvector<SQExceptionTrap> ExceptionsTraps;\r
+\r
+struct SQVM : public CHAINABLE_OBJ\r
+{\r
+       struct VarArgs {\r
+               VarArgs() { size = 0; base = 0; }\r
+               int size;\r
+               int base;\r
+       };\r
+\r
+       struct CallInfo{\r
+               //CallInfo() {}\r
+               //CallInfo(const CallInfo& ci) {  }\r
+               SQInstructionVec *_iv;\r
+               SQObjectPtrVec *_literals;\r
+               SQObject _closure;\r
+               SQObject _generator;\r
+               int _etraps;\r
+               int _prevstkbase;\r
+               int _prevtop;\r
+               int _target;\r
+               SQInstruction *_ip;\r
+               int _ncalls;\r
+               bool _root;\r
+               VarArgs _vargs;\r
+       };\r
+\r
+typedef sqvector<CallInfo> CallInfoVec;\r
+public:\r
+       enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };\r
+       SQVM(SQSharedState *ss);\r
+       ~SQVM();\r
+       bool Init(SQVM *friendvm, int stacksize);\r
+       bool Execute(SQObjectPtr &func, int target, int nargs, int stackbase, SQObjectPtr &outres, ExecutionType et = ET_CALL);\r
+       //start a native call return when the NATIVE closure returns(returns true if the vm has been suspended)\r
+       bool CallNative(SQNativeClosure *nclosure, int nargs, int stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);\r
+       //start a SQUIRREL call in the same "Execution loop"\r
+       bool StartCall(SQClosure *closure, int target, int nargs, int stackbase, bool tailcall);\r
+       bool CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval);\r
+       //call a generic closure pure SQUIRREL or NATIVE\r
+       bool Call(SQObjectPtr &closure, int nparams, int stackbase, SQObjectPtr &outres);\r
+       SQRESULT Suspend();\r
+\r
+       void CallDebugHook(int type,int forcedline=0);\r
+       void CallErrorHandler(SQObjectPtr &e);\r
+       bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);\r
+       bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);\r
+       bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);\r
+       bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val);\r
+       bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);\r
+       bool Clone(const SQObjectPtr &self, SQObjectPtr &target);\r
+       bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,int &res);\r
+       bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);\r
+       bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);\r
+       bool IsFalse(SQObjectPtr &o);\r
+       SQString *PrintObjVal(const SQObject &o);\r
+\r
\r
+       void Raise_Error(const SQChar *s, ...);\r
+       void Raise_Error(SQObjectPtr &desc);\r
+       void Raise_IdxError(SQObject &o);\r
+       void Raise_CompareError(const SQObject &o1, const SQObject &o2);\r
+       void Raise_ParamTypeError(int nparam,int typemask,int type);\r
+\r
+       void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
+       bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, int nparams, SQObjectPtr &outres);\r
+       bool ArithMetaMethod(int op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
+       //void Modulo(const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
+       bool Return(int _arg0, int _arg1, SQObjectPtr &retval);\r
+       //new stuff\r
+       bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
+       bool BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
+       bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);\r
+       bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);\r
+       bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);\r
+       bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);\r
+       bool CLASS_OP(SQObjectPtr &target,int base,int attrs);\r
+       //return true if the loop is finished\r
+       bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,int arg_2,bool &finished);\r
+       bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);\r
+       bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
+       bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
+       bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);\r
+       void PopVarArgs(VarArgs &vargs);\r
+#ifdef _DEBUG_DUMP\r
+       void dumpstack(int stackbase=-1, bool dumpall = false);\r
+#endif\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       void Mark(SQCollectable **chain);\r
+#endif\r
+       void Finalize();\r
+\r
+       void Release(){ sq_delete(this,SQVM); } //does nothing\r
+////////////////////////////////////////////////////////////////////////////\r
+       //stack functions for the api\r
+       void Pop();\r
+       void Pop(int n);\r
+       void Remove(int n);\r
+\r
+       void Push(const SQObjectPtr &o);\r
+       SQObjectPtr &Top();\r
+       SQObjectPtr &PopGet();\r
+       SQObjectPtr &GetUp(int n);\r
+       SQObjectPtr &GetAt(int n);\r
+\r
+       SQObjectPtrVec _stack;\r
+       SQObjectPtrVec _vargsstack;\r
+       int _top;\r
+       int _stackbase;\r
+       SQObjectPtr _roottable;\r
+       //SQObjectPtr _thrownerror;\r
+       SQObjectPtr _lasterror;\r
+       SQObjectPtr _errorhandler;\r
+       SQObjectPtr _debughook;\r
+\r
+       SQObjectPtr temp_reg;\r
+       CallInfoVec _callsstack;\r
+       ExceptionsTraps _etraps;\r
+       CallInfo *ci;\r
+       void *_foreignptr;\r
+       //VMs sharing the same state\r
+       SQSharedState *_sharedstate;\r
+       int _nnativecalls;\r
+       //suspend infos\r
+       bool _suspended;\r
+       bool _suspended_root;\r
+       int _suspended_target;\r
+       int _suspended_traps;\r
+};\r
+\r
+struct AutoDec{\r
+       AutoDec(int *n) { _n = n; }\r
+       ~AutoDec() { (*_n)--; }\r
+       int *_n;\r
+};\r
+\r
+SQObjectPtr &stack_get(HSQUIRRELVM v, int idx);\r
+const SQChar *GetTypeName(const SQObjectPtr &obj1);\r
+const SQChar *IdType2Name(SQObjectType type);\r
+\r
+#define _ss(_vm_) (_vm_)->_sharedstate\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+#define _opt_ss(_vm_) (_vm_)->_sharedstate\r
+#else\r
+#define _opt_ss(_vm_) NULL\r
+#endif\r
+\r
+#define PUSH_CALLINFO(v,nci){ \\r
+       v->_callsstack.push_back(nci); \\r
+       v->ci = &v->_callsstack.back(); \\r
+}\r
+\r
+#define POP_CALLINFO(v){ \\r
+       v->_callsstack.pop_back(); \\r
+       if(v->_callsstack.size())       \\r
+               v->ci = &v->_callsstack.back() ; \\r
+       else    \\r
+               v->ci = NULL; \\r
+}\r
+#endif //_SQVM_H_\r
index 2ea2e49..beff2c2 100644 (file)
 #include <config.h>
 
 #include "video/drawing_context.h"
-#include "app/gettext.h"
-#include "app/globals.h"
+#include "gettext.h"
 #include "lisp/lisp.h"
 #include "resources.h"
+#include "main.h"
 #include "statistics.h"
 
 Statistics global_stats;
index 218c027..2030b28 100644 (file)
@@ -24,8 +24,6 @@
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 
-using namespace SuperTux;
-
 class DrawingContext;
 
 #define SPLAYER 0
index 9f7a5dd..859ca30 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include "textscroller.h"
@@ -26,7 +25,6 @@
 #include "resources.h"
 #include "video/font.h"
 #include "video/drawing_context.h"
-#include "app/globals.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "main.h"
index 901dfcd..20835fb 100644 (file)
@@ -24,7 +24,6 @@
 #include <iostream>
 #include <stdexcept>
 
-#include "app/globals.h"
 #include "lisp/lisp.h"
 #include "tile.h"
 #include "resources.h"
index a5f5856..a9ea335 100644 (file)
@@ -25,8 +25,6 @@
 #include "math/rectangle.h"
 #include "lisp/lisp.h"
 
-using namespace SuperTux;
-
 /**
 Tile Class
 */
index e3a5b59..37cf79a 100644 (file)
@@ -23,8 +23,6 @@
 #include <stdexcept>
 #include <assert.h>
 #include "video/drawing_context.h"
-#include "app/setup.h"
-#include "app/globals.h"
 #include "lisp/lisp.h"
 #include "lisp/parser.h"
 #include "lisp/list_iterator.h"
index 7b2854c..8166e85 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include <math.h>
index 8844183..d7f0373 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __SUPERTUX_TIMER_H__
 #define __SUPERTUX_TIMER_H__
 
diff --git a/src/tinygettext/tinygettext.cpp b/src/tinygettext/tinygettext.cpp
new file mode 100644 (file)
index 0000000..dd73e80
--- /dev/null
@@ -0,0 +1,701 @@
+//  $Id$
+// 
+//  TinyGetText - A small flexible gettext() replacement
+//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include <sys/types.h>
+#include <iconv.h>
+#include <dirent.h>
+#include <fstream>
+#include <iostream>
+#include <ctype.h>
+#include <errno.h>
+#include "tinygettext.h"
+
+//#define TRANSLATION_DEBUG
+
+namespace TinyGetText {
+
+/** Convert \a which is in \a from_charset to \a to_charset and return it */
+std::string convert(const std::string& text,
+                    const std::string& from_charset,
+                    const std::string& to_charset)           
+{
+  if (from_charset == to_charset)
+    return text;
+
+  iconv_t cd = iconv_open(to_charset.c_str(), from_charset.c_str());
+  
+  size_t in_len = text.length();
+  size_t out_len = text.length()*3; // FIXME: cross fingers that this is enough        
+
+  char*  out_orig = new char[out_len];
+  char*  in_orig  = new char[in_len+1];
+  strcpy(in_orig, text.c_str());
+
+  char* out = out_orig;
+  char* in  = in_orig;
+  size_t out_len_temp = out_len; // iconv is counting down the bytes it has
+                                 // written from this...
+
+  size_t retval = iconv(cd, &in, &in_len, &out, &out_len_temp);
+  out_len -= out_len_temp; // see above
+  if (retval == (size_t) -1)
+    {
+      std::cerr << strerror(errno) << std::endl;
+      std::cerr << "Error: conversion from " << from_charset
+                << " to " << to_charset << " went wrong: " << retval << std::endl;
+      return "";
+    }
+  iconv_close(cd);
+
+  std::string ret(out_orig, out_len);
+  delete[] out_orig;
+  delete[] in_orig;
+  return ret;
+}
+
+bool has_suffix(const std::string& lhs, const std::string rhs)
+{
+  if (lhs.length() < rhs.length())
+    return false;
+  else
+    return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
+}
+
+bool has_prefix(const std::string& lhs, const std::string rhs)
+{
+  if (lhs.length() < rhs.length())
+    return false;
+  else
+    return lhs.compare(0, rhs.length(), rhs) == 0;
+}
+
+int plural1(int )     { return 0; }
+int plural2_1(int n)  { return (n != 1); }
+int plural2_2(int n)  { return (n > 1); }
+int plural3_lv(int n) { return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); }
+int plural3_ga(int n) { return n==1 ? 0 : n==2 ? 1 : 2; }
+int plural3_lt(int n) { return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2); }
+int plural3_1(int n)  { return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
+int plural3_sk(int n) { return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; }
+int plural3_pl(int n) { return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
+int plural3_sl(int n) { return (n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3); }
+
+/** Language Definitions */
+//*{
+LanguageDef lang_hu("hu", "Hungarian",         1, plural1); // "nplurals=1; plural=0;"
+LanguageDef lang_ja("ja", "Japanese",          1, plural1); // "nplurals=1; plural=0;"
+LanguageDef lang_ko("ko", "Korean",            1, plural1); // "nplurals=1; plural=0;"
+LanguageDef lang_tr("tr", "Turkish",           1, plural1); // "nplurals=1; plural=0;"
+LanguageDef lang_da("da", "Danish",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_nl("nl", "Dutch",             2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_en("en", "English",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_fo("fo", "Faroese",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_de("de", "German",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_nb("nb", "Norwegian Bokmal",  2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_no("no", "Norwegian",         2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_nn("nn", "Norwegian Nynorsk", 2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_sv("sv", "Swedish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_et("et", "Estonian",          2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_fi("fi", "Finnish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_el("el", "Greek",             2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_he("he", "Hebrew",            2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_it("it", "Italian",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_pt("pt", "Portuguese",        2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_es("es", "Spanish",           2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_eo("eo", "Esperanto",         2, plural2_1); // "nplurals=2; plural=(n != 1);"
+LanguageDef lang_fr("fr", "French",            2, plural2_2); // "nplurals=2; plural=(n > 1);"
+LanguageDef lang_pt_BR("pt_BR", "Brazilian",   2, plural2_2); // "nplurals=2; plural=(n > 1);"
+LanguageDef lang_lv("lv", "Latvian",           3, plural3_lv); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
+LanguageDef lang_ga("ga", "Irish",             3, plural3_ga); // "nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"
+LanguageDef lang_lt("lt", "Lithuanian",        3, plural3_lt); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"
+LanguageDef lang_hr("hr", "Croatian",          3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
+LanguageDef lang_cs("cs", "Czech",             3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
+LanguageDef lang_ru("ru", "Russian",           3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
+LanguageDef lang_uk("uk", "Ukrainian",         3, plural3_1); // "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
+LanguageDef lang_sk("sk", "Slovak",            3, plural3_sk); // "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
+LanguageDef lang_pl("pl", "Polish",            3, plural3_pl); // "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
+LanguageDef lang_sl("sl", "Slovenian",         3, plural3_sl); // "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
+//*}
+
+LanguageDef&
+get_language_def(const std::string& name)
+{
+  if (name == "hu") return lang_hu;
+  else if (name == "ja") return lang_ja;
+  else if (name == "ko") return lang_ko;
+  else if (name == "tr") return lang_tr;
+  else if (name == "da") return lang_da;
+  else if (name == "nl") return lang_nl;
+  else if (name == "en") return lang_en;
+  else if (name == "fo") return lang_fo;
+  else if (name == "de") return lang_de;
+  else if (name == "nb") return lang_nb;
+  else if (name == "no") return lang_no;
+  else if (name == "nn") return lang_nn;
+  else if (name == "sv") return lang_sv;
+  else if (name == "et") return lang_et;
+  else if (name == "fi") return lang_fi;
+  else if (name == "el") return lang_el;
+  else if (name == "he") return lang_he;
+  else if (name == "it") return lang_it;
+  else if (name == "pt") return lang_pt;
+  else if (name == "es") return lang_es;
+  else if (name == "eo") return lang_eo;
+  else if (name == "fr") return lang_fr;
+  else if (name == "pt_BR") return lang_pt_BR;
+  else if (name == "lv") return lang_lv;
+  else if (name == "ga") return lang_ga;
+  else if (name == "lt") return lang_lt;
+  else if (name == "hr") return lang_hr;
+  else if (name == "cs") return lang_cs;
+  else if (name == "ru") return lang_ru;
+  else if (name == "uk") return lang_uk;
+  else if (name == "sk") return lang_sk;
+  else if (name == "pl") return lang_pl;
+  else if (name == "sl") return lang_sl;
+  else return lang_en; 
+}
+
+DictionaryManager::DictionaryManager()
+  : current_dict(&empty_dict)
+{
+  parseLocaleAliases();
+  // setup language from environment vars
+  const char* lang = getenv("LC_ALL");
+  if(!lang)
+    lang = getenv("LC_MESSAGES");
+  if(!lang)
+    lang = getenv("LANG");
+  
+  if(lang)
+    set_language(lang);
+}
+
+void
+DictionaryManager::parseLocaleAliases()
+{
+  // try to parse language alias list
+  std::ifstream in("/usr/share/locale/locale.alias");
+  
+  char c = ' ';
+  while(in.good() && !in.eof()) {
+    while(isspace(c) && !in.eof())
+      in.get(c);
+    
+    if(c == '#') { // skip comments
+      while(c != '\n' && !in.eof())
+        in.get(c);
+      continue;
+    }
+    
+    std::string alias;
+    while(!isspace(c) && !in.eof()) {
+      alias += c;
+      in.get(c);
+    }
+    while(isspace(c) && !in.eof())
+      in.get(c);
+    std::string language;
+    while(!isspace(c) && !in.eof()) {
+      language += c;
+      in.get(c);
+    }
+
+    if(in.eof())
+      break;
+    set_language_alias(alias, language);
+  }
+}
+  
+Dictionary&
+DictionaryManager::get_dictionary(const std::string& spec)
+{
+  std::string lang = get_language_from_spec(spec);
+  Dictionaries::iterator i = dictionaries.find(get_language_from_spec(lang));
+  if (i != dictionaries.end())
+    {
+      return i->second;
+    }
+  else // Dictionary for languages lang isn't loaded, so we load it
+    {
+      //std::cout << "get_dictionary: " << lang << std::endl;
+      Dictionary& dict = dictionaries[lang];
+
+      dict.set_language(get_language_def(lang));
+      if(charset != "")
+        dict.set_charset(charset);
+
+      for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
+        {
+          DIR* dir = opendir(p->c_str());
+          if (!dir)
+            {
+              std::cerr << "Error: opendir() failed on " << *p << std::endl;
+            }
+          else
+            {
+              struct dirent* ent;
+              while((ent = readdir(dir)))
+                {
+                  if (std::string(ent->d_name) == lang + ".po")
+                    {
+                      std::string pofile = *p + "/" + ent->d_name;
+                      std::ifstream in(pofile.c_str());
+                      if (!in)
+                        {
+                          std::cerr << "Error: Failure file opening: " << pofile << std::endl;
+                        }
+                      else
+                        {
+                          read_po_file(dict, in);
+                        }
+                    }
+                }
+              closedir(dir);
+            }
+        }
+
+      return dict;
+    }
+}
+
+std::set<std::string>
+DictionaryManager::get_languages()
+{
+  std::set<std::string> languages;
+
+  for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
+    {
+      DIR* dir = opendir(p->c_str());
+      if (!dir)
+        {
+          std::cerr << "Error: opendir() failed on " << *p << std::endl;
+        }
+      else
+        {
+          struct dirent* ent;
+          while((ent = readdir(dir)))
+            {
+              if (has_suffix(ent->d_name, ".po"))
+                {
+                  std::string filename = ent->d_name;
+                  languages.insert(filename.substr(0, filename.length()-3));
+                }
+            }
+          closedir(dir);
+        }
+    }  
+  return languages;
+}
+
+void
+DictionaryManager::set_language(const std::string& lang)
+{
+  language = get_language_from_spec(lang);
+  current_dict = & (get_dictionary(language));
+}
+
+void
+DictionaryManager::set_charset(const std::string& charset)
+{
+  dictionaries.clear(); // changing charset invalidates cache
+  this->charset = charset;
+  set_language(language);
+}
+
+void
+DictionaryManager::set_language_alias(const std::string& alias,
+    const std::string& language)
+{
+  language_aliases.insert(std::make_pair(alias, language));
+}
+
+std::string
+DictionaryManager::get_language_from_spec(const std::string& spec)
+{
+  std::string lang = spec;
+  Aliases::iterator i = language_aliases.find(lang);
+  if(i != language_aliases.end()) {
+    lang = i->second;
+  }
+  
+  std::string::size_type s = lang.find_first_of("_.");
+  if(s == std::string::npos)
+    return lang;
+
+  return std::string(lang, 0, s);  
+}
+
+void
+DictionaryManager::add_directory(const std::string& pathname)
+{
+  dictionaries.clear(); // adding directories invalidates cache
+  search_path.push_back(pathname);
+  set_language(language);
+}
+
+//---------------------------------------------------------------------------
+
+Dictionary::Dictionary(const LanguageDef& language_, const std::string& charset_)
+  : language(language_), charset(charset_)
+{
+}
+
+Dictionary::Dictionary()
+  : language(lang_en)
+{
+}
+
+std::string
+Dictionary::get_charset() const
+{
+  return charset;
+}
+
+void
+Dictionary::set_charset(const std::string& charset_)
+{
+  charset = charset_;
+}
+
+void
+Dictionary::set_language(const LanguageDef& lang)
+{
+  language = lang;
+}
+
+std::string
+Dictionary::translate(const std::string& msgid, const std::string& msgid2, int num) 
+{
+  PluralEntries::iterator i = plural_entries.find(msgid);
+  std::map<int, std::string>& msgstrs = i->second;
+
+  if (i != plural_entries.end() && !msgstrs.empty())
+    {
+      int g = language.plural(num);
+      std::map<int, std::string>::iterator j = msgstrs.find(g);
+      if (j != msgstrs.end())
+        {
+          return j->second;
+        }
+      else
+        {
+          // Return the first translation, in case we can't translate the specific number
+          return msgstrs.begin()->second;
+        }
+    }
+  else
+    {
+#ifdef TRANSLATION_DEBUG
+      std::cerr << "Warning: Couldn't translate: " << msgid << std::endl;
+      std::cerr << "Candidates: " << std::endl;
+      for (PluralEntries::iterator i = plural_entries.begin(); i != plural_entries.end(); ++i)
+        std::cout << "'" << i->first << "'" << std::endl;
+#endif
+
+      if (plural2_1(num)) // default to english rules
+        return msgid2;
+      else
+        return msgid;
+    }
+}
+
+std::string
+Dictionary::translate(const std::string& msgid) 
+{
+  Entries::iterator i = entries.find(msgid);
+  if (i != entries.end() && !i->second.empty())
+    {
+      return i->second;
+    }
+  else
+    {
+#ifdef TRANSLATION_DBEUG
+      std::cout << "Error: Couldn't translate: " << msgid << std::endl;
+#endif
+      return msgid;
+    }
+}
+  
+void
+Dictionary::add_translation(const std::string& msgid, const std::string& ,
+                            const std::map<int, std::string>& msgstrs)
+{
+  // Do we need msgid2 for anything? its after all supplied to the
+  // translate call, so we just throw it away
+  plural_entries[msgid] = msgstrs;
+}
+
+void 
+Dictionary::add_translation(const std::string& msgid, const std::string& msgstr) 
+{
+  entries[msgid] = msgstr;
+}
+
+class POFileReader
+{
+private:
+  struct Token
+  {
+    std::string keyword;
+    std::string content;
+  };
+
+  Dictionary& dict;
+
+  std::string from_charset;
+  std::string to_charset;
+
+  std::string current_msgid;
+  std::string current_msgid_plural;
+  std::map<int, std::string> msgstr_plural;
+
+  int line_num;
+
+  enum { WANT_MSGID, WANT_MSGSTR, WANT_MSGSTR_PLURAL, WANT_MSGID_PLURAL } state;
+
+public:
+  POFileReader(std::istream& in, Dictionary& dict_)
+    : dict(dict_)
+  {
+    state = WANT_MSGID;
+    line_num = 0;
+    tokenize_po(in);
+  }
+
+  void parse_header(const std::string& header)
+  {
+    // Seperate the header in lines
+    typedef std::vector<std::string> Lines;
+    Lines lines;
+    
+    std::string::size_type start = 0;
+    for(std::string::size_type i = 0; i < header.length(); ++i)
+      {
+        if (header[i] == '\n')
+          {
+            lines.push_back(header.substr(start, i - start));
+            start = i+1;
+          }
+      }
+
+    for(Lines::iterator i = lines.begin(); i != lines.end(); ++i)
+      {
+        if (has_prefix(*i, "Content-Type: text/plain; charset=")) {
+          from_charset = i->substr(strlen("Content-Type: text/plain; charset="));
+        }
+      }
+
+    if (from_charset.empty() || from_charset == "CHARSET")
+      {
+        std::cerr << "Error: Charset not specified for .po, fallback to ISO-8859-1" << std::endl;
+        from_charset = "ISO-8859-1";
+      }
+
+    to_charset = dict.get_charset();
+    if (to_charset.empty())
+      { // No charset requested from the dict, so we use the one from the .po 
+        to_charset = from_charset;
+        dict.set_charset(from_charset);
+      }
+  }
+
+  void add_token(const Token& token)
+  {
+    switch(state) 
+      {
+      case WANT_MSGID:
+        if (token.keyword == "msgid") 
+          {
+            current_msgid = token.content;
+            state = WANT_MSGID_PLURAL;
+          }
+        else if (token.keyword.empty())
+          {
+            //std::cerr << "Got EOF, everything looks ok." << std::endl;
+          }
+        else
+          {
+            std::cerr << "tinygettext: expected 'msgid' keyword, got " << token.keyword 
+                      << " at line " << line_num << std::endl;
+          }
+        break;
+    
+      case WANT_MSGID_PLURAL:
+        if (token.keyword == "msgid_plural") 
+          {
+            current_msgid_plural = token.content;
+            state = WANT_MSGSTR_PLURAL;
+          } 
+        else
+          {
+            state = WANT_MSGSTR;
+            add_token(token);
+          }
+        break;
+
+      case WANT_MSGSTR:
+        if (token.keyword == "msgstr") 
+          {
+            if (current_msgid == "") 
+              { // .po Header is hidden in the msgid with the empty string
+                parse_header(token.content);
+              }
+            else
+              {
+                dict.add_translation(current_msgid, convert(token.content, from_charset, to_charset));
+              }
+            state = WANT_MSGID;
+          } 
+        else
+          {
+            std::cerr << "tinygettext: expected 'msgstr' keyword, got " << token.keyword 
+                      << " at line " << line_num << std::endl;
+          }
+        break;
+
+      case WANT_MSGSTR_PLURAL:
+        if (has_prefix(token.keyword, "msgstr[")) 
+          {
+            int num;
+            if (sscanf(token.keyword.c_str(), "msgstr[%d]", &num) != 1) 
+              {
+                std::cerr << "Error: Couldn't parse: " << token.keyword << std::endl;
+              } 
+            else 
+              {
+                msgstr_plural[num] = convert(token.content, from_charset, to_charset);
+              }
+          }
+        else 
+          {
+            dict.add_translation(current_msgid, current_msgid_plural, msgstr_plural);
+
+            state = WANT_MSGID;
+            add_token(token);
+          }
+        break;
+      }
+  }
+  
+  inline int getchar(std::istream& in) 
+  {
+    int c = in.get();
+    if (c == '\n')
+      line_num += 1;
+    return c;
+  }
+  
+  void tokenize_po(std::istream& in)
+  {
+    enum State { READ_KEYWORD, 
+                 READ_CONTENT,
+                 READ_CONTENT_IN_STRING,
+                 SKIP_COMMENT };
+
+    State state = READ_KEYWORD;
+    int c;
+    Token token;
+
+    while((c = getchar(in)) != EOF)
+      {
+        //std::cout << "Lexing char: " << char(c) << " " << state << std::endl;
+        switch(state)
+          {
+          case READ_KEYWORD:
+            if (c == '#')
+              {
+                state = SKIP_COMMENT;
+              }
+            else
+              {
+                // Read a new token
+                token = Token();
+                
+                do { // Read keyword 
+                  token.keyword += c;
+                } while((c = getchar(in)) != EOF && !isspace(c));
+                in.unget();
+
+                state = READ_CONTENT;
+              }
+            break;
+
+          case READ_CONTENT:
+            while((c = getchar(in)) != EOF)
+              {
+                if (c == '"') { 
+                  // Found start of content
+                  state = READ_CONTENT_IN_STRING;
+                  break;
+                } else if (isspace(c)) {
+                  // skip
+                } else { // Read something that may be a keyword
+                  in.unget();
+                  state = READ_KEYWORD;
+                  add_token(token);
+                  break;
+                }
+              }
+            break;
+
+          case READ_CONTENT_IN_STRING:
+            if (c == '\\') {
+              c = getchar(in);
+              if (c != EOF)
+                {
+                  if (c == 'n') token.content += '\n';
+                  else if (c == 't') token.content += '\t';
+                  else if (c == 'r') token.content += '\r';
+                  else if (c == '"') token.content += '"';
+                  else
+                    {
+                      std::cout << "Unhandled escape character: " << char(c) << std::endl;
+                    }
+                }
+              else
+                {
+                  std::cout << "Unterminated string" << std::endl;
+                }
+            } else if (c == '"') { // Content string is terminated
+              state = READ_CONTENT;
+            } else {
+              token.content += c;
+            }
+            break;
+
+          case SKIP_COMMENT:
+            if (c == '\n')
+              state = READ_KEYWORD;
+            break;
+          }
+      }
+    add_token(token);
+  }
+};
+
+void read_po_file(Dictionary& dict_, std::istream& in) 
+{
+  POFileReader reader(in, dict_);
+}
+
+} // namespace TinyGetText
+
+/* EOF */
diff --git a/src/tinygettext/tinygettext.h b/src/tinygettext/tinygettext.h
new file mode 100644 (file)
index 0000000..207ce28
--- /dev/null
@@ -0,0 +1,153 @@
+//  $Id$
+// 
+//  TinyGetText - A small flexible gettext() replacement
+//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef HEADER_TINYGETTEXT_H
+#define HEADER_TINYGETTEXT_H
+
+#include <map>
+#include <vector>
+#include <set>
+#include <string>
+
+namespace TinyGetText {
+
+typedef int (*PluralFunc)(int n);
+
+struct LanguageDef {
+  const char* code;
+  const char* name;
+  int         nplural;
+  PluralFunc  plural;
+
+  LanguageDef(const char* code_, const char* name_,  int nplural_, PluralFunc plural_)
+    : code(code_), name(name_), nplural(nplural_), plural(plural_)
+  {}
+};
+
+/** A simple dictionary class that mimics gettext() behaviour. Each
+    Dictionary only works for a single language, for managing multiple
+    languages and .po files at once use the DictionaryManager. */
+class Dictionary
+{
+private:
+  typedef std::map<std::string, std::string> Entries;
+  Entries entries;
+
+  typedef std::map<std::string, std::map<int, std::string> > PluralEntries;
+  PluralEntries plural_entries;
+
+  LanguageDef language;
+  std::string charset;
+public:
+  /** */
+  Dictionary(const LanguageDef& language_, const std::string& charset = "");
+
+  Dictionary();
+
+  /** Return the charset used for this dictionary */
+  std::string get_charset() const;
+
+  /** Set a charset for this dictionary, this will NOT convert stuff,
+      it is for information only, you have to convert stuff yourself
+      when you add it with \a add_translation() */
+  void set_charset(const std::string& charset);
+
+  /** Set the language that is used for this dictionary, this is
+      mainly needed to evaluate plural forms */
+  void set_language(const LanguageDef& lang);
+
+  /** Translate the string \a msgid to its correct plural form, based
+      on the number of items given by \a num. \a msgid2 is \a msgid in
+      plural form. */
+  std::string translate(const std::string& msgid, const std::string& msgid2, int num);
+
+  /** Translate the string \a msgid. */
+  std::string translate(const std::string& msgid);
+    
+  /** Add a translation from \a msgid to \a msgstr to the dictionary,
+      where \a msgid is the singular form of the message, msgid2 the
+      plural form and msgstrs a table of translations. The right
+      translation will be calculated based on the \a num argument to
+      translate(). */
+  void add_translation(const std::string& msgid, const std::string& msgid2,
+                       const std::map<int, std::string>& msgstrs);
+
+  /** Add a translation from \a msgid to \a msgstr to the
+      dictionary */
+  void add_translation(const std::string& msgid, const std::string& msgstr);
+};
+
+/** Manager class for dictionaries, you give it a bunch of directories
+    with .po files and it will then automatically load the right file
+    on demand depending on which language was set. */
+class DictionaryManager
+{
+private:
+  typedef std::map<std::string, Dictionary> Dictionaries;
+  Dictionaries dictionaries;
+  typedef std::vector<std::string> SearchPath;
+  SearchPath search_path;
+  typedef std::map<std::string, std::string> Aliases;
+  Aliases language_aliases;
+  std::string charset;
+  std::string language;
+  Dictionary* current_dict;
+  Dictionary empty_dict;
+
+public:
+  DictionaryManager();
+
+  /** Return the currently active dictionary, if none is set, an empty
+      dictionary is returned. */
+  Dictionary& get_dictionary()
+  { return *current_dict; }
+
+  /** Get dictionary for lang */
+  Dictionary& get_dictionary(const std::string& langspec);
+
+  /** Set a language based on a four? letter country code */
+  void set_language(const std::string& langspec);
+
+  /** Set a charset that will be set on the returned dictionaries */
+  void set_charset(const std::string& charset);
+
+  /** Define an alias for a language */
+  void set_language_alias(const std::string& alias, const std::string& lang);
+
+  /** Add a directory to the search path for dictionaries */
+  void add_directory(const std::string& pathname);
+  
+  /** Return a set of the available languages in their country code */
+  std::set<std::string> get_languages();
+
+private:
+  void parseLocaleAliases();
+  /// returns the language part in a language spec (like de_DE.UTF-8 -> de)
+  std::string get_language_from_spec(const std::string& spec);
+};
+
+/** Read the content of the .po file given as \a in into the
+    dictionary given as \a dict */
+void read_po_file(Dictionary& dict, std::istream& in);
+LanguageDef& get_language_def(const std::string& name);
+
+} // namespace TinyGetText
+
+#endif
+
+/* EOF */
index 7b3b89d..3ae54f6 100644 (file)
 #include <ctype.h>
 #endif
 
-#include "app/globals.h"
 #include "title.h"
 #include "video/screen.h"
 #include "video/surface.h"
 #include "gui/menu.h"
 #include "timer.h"
-#include "special/frame_rate.h"
-#include "app/setup.h"
 #include "lisp/lisp.h"
 #include "lisp/parser.h"
 #include "level.h"
 #include "object/camera.h"
 #include "object/player.h"
 #include "resources.h"
-#include "app/gettext.h"
+#include "gettext.h"
 #include "misc.h"
 #include "textscroller.h"
+#include "file_system.h"
 #include "control/joystickkeyboardcontroller.h"
 #include "control/codecontroller.h"
 #include "main.h"
@@ -81,8 +79,6 @@ static CodeController* controller;
 static std::vector<LevelSubset*> contrib_subsets;
 static LevelSubset* current_contrib_subset = 0;
 
-static FrameRate frame_rate(100);
-
 /* If the demo was stopped - because game started, level
    editor was excuted, etc - call this when you get back
    to the title code.
@@ -93,7 +89,7 @@ void resume_demo()
   titlesession->get_current_sector()->activate("main");
   titlesession->set_current();
 
-  frame_rate.update();
+  //frame_rate.update();
 }
 
 void update_load_save_game_menu(Menu* menu)
@@ -225,20 +221,16 @@ void check_levels_contrib_menu()
 void check_contrib_subset_menu()
 {
   int index = contrib_subset_menu->check();
-  if (index != -1)
-    {
-      if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
-        {
-          std::cout << "Starting level: " << index << std::endl;
-          
-          GameSession session(
-              current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
-          session.run();
-          player_status.reset();
-          Menu::set_current(main_menu);
-          resume_demo();
-        }
-    }  
+  if (index != -1) {
+    if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION) {
+      GameSession session(
+          current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
+      session.run();
+      player_status.reset();
+      Menu::set_current(main_menu);
+      resume_demo();
+    }
+  }  
 }
 
 void draw_demo(float elapsed_time)
@@ -256,12 +248,10 @@ void draw_demo(float elapsed_time)
   if(random_timer.check() || 
       (walking && (int) last_tux_x_pos == (int) tux->get_pos().x)) {
     walking = false;
-    printf("Walking: %d.\n", walking);
   } else {
       if(!walking && (int) tux->get_pos().y == (int) last_tux_y_pos) {
         random_timer.start(float(rand() % 3000 + 3000) / 1000.);
         walking = true;
-        printf("Walking: %d.\n", walking);
       }
   }
   if(!walking)
@@ -287,8 +277,6 @@ void title()
   MusicRef credits_music;
   controller = new CodeController();
 
-  Ticks::pause_init();
-
   titlesession = new GameSession(get_resource_filename("levels/misc/menu.stl"),
       ST_GL_DEMO_GAME);
 
@@ -374,7 +362,6 @@ void title()
                   break;
                 case MNID_LEVELS_CONTRIB:
                   // Contrib Menu
-                  puts("Entering contrib menu");
                   generate_contrib_menu();
                   break;
 #if 0
@@ -450,7 +437,7 @@ void title()
      
       context.do_drawing();
 
-      frame_rate.update();
+      //frame_rate.update();
 
       /* Pause: */
       frame++;
index efe8004..760d3d0 100644 (file)
 #include "sprite/sprite.h"
 #include "sprite/sprite_manager.h"
 #include "video/drawing_context.h"
-#include "app/globals.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 
-using namespace SuperTux;
-
 Door::Door(const lisp::Lisp& reader)
 {
   reader.get("x", bbox.p1.x);
index a599c33..8e264df 100644 (file)
 #include "sprite/sprite.h"
 #include "sprite/sprite_manager.h"
 #include "video/drawing_context.h"
-#include "app/globals.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 
-using namespace SuperTux;
-
 Hatch::Hatch(const lisp::Lisp& reader)
 {
   reader.get("x", bbox.p1.x);
index 66a7f2e..72c88f8 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include "secretarea_trigger.h"
@@ -25,8 +24,9 @@
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
 #include "object_factory.h"
+#include "main.h"
 
-#define MESSAGE_TIME 3.5
+static const float MESSAGE_TIME=3.5;
 
 //TODO: Count numbers of triggered/total secret areas
 SecretAreaTrigger::SecretAreaTrigger(const lisp::Lisp& reader)
index 60318bf..bbc3641 100644 (file)
@@ -17,7 +17,6 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #ifndef __SECRETAREA_TRIGGER_H__
 #define __SECRETAREA_TRIGGER_H__
 
@@ -25,7 +24,6 @@
 #include "serializable.h"
 #include "resources.h"
 #include "video/drawing_context.h"
-#include "app/globals.h"
 #include "timer.h"
 
 class SecretAreaTrigger : public TriggerBase, public Serializable
index 5ccc9ea..3f8fdc4 100644 (file)
@@ -24,7 +24,6 @@
 #include "sprite/sprite.h"
 
 class Player;
-using namespace SuperTux;
 
 /** This class is the base class for all objects you can interact with in some
  * way. There are several interaction types defined like touch and activate
index 66c1fa1..15e8863 100644 (file)
 
 #include "drawing_context.h"
 #include "surface.h"
-#include "app/globals.h"
 #include "font.h"
+#include "main.h"
 #include "gameconfig.h"
 
-using namespace SuperTux;
-
 DrawingContext::DrawingContext(SDL_Surface* targetsurface)
 {
   if(targetsurface) {
index 0aa7cec..e396659 100644 (file)
@@ -30,8 +30,6 @@
 #include "video/surface.h"
 #include "video/font.h"
 
-using namespace SuperTux;
-
 class Surface;
 
 // some constants for predefined layer values
index 3d2c8ca..bdcd541 100644 (file)
 #include <cstring>
 #include <stdexcept>
 
-#include "app/globals.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "screen.h"
 #include "font.h"
 #include "drawing_context.h"
 
-using namespace SuperTux;
-
 Font::Font(const std::string& file, FontType ntype, int nw, int nh,
         int nshadowsize)
     : chars(0), shadow_chars(0), type(ntype), w(nw), h(nh),
index 8bc28c8..7ceb28e 100644 (file)
 
 #include "gameconfig.h"
 #include "screen.h"
-#include "app/globals.h"
+#include "main.h"
 #include "video/drawing_context.h"
 #include "math/vector.h"
 
 static const float LOOP_DELAY = 20.0;
 extern SDL_Surface* screen;
 
-using namespace SuperTux;
-
 /* 'Stolen' from the SDL documentation.
  * Return the pixel value at (x, y)
  * NOTE: The surface must be locked before calling this!
index 1da2432..48c5180 100644 (file)
@@ -26,8 +26,6 @@
 #include <vector>
 #include "math/vector.h"
 
-using namespace SuperTux;
-
 /** Stores 8bit RGBA values. */
 class Color
 {
index fb3e8a0..9987482 100644 (file)
 #include "gameconfig.h"
 #include "video/surface.h"
 #include "video/screen.h"
-#include "app/globals.h"
-#include "app/setup.h"
-
-using namespace SuperTux;
 
 Surface::Surfaces Surface::surfaces;
 
index a2f8d3b..173e936 100644 (file)
 #include <sstream>
 #include <unistd.h>
 
-#include "app/globals.h"
-#include "app/gettext.h"
-#include "app/setup.h"
+#include "gettext.h"
 #include "video/surface.h"
 #include "video/screen.h"
 #include "video/drawing_context.h"
-#include "special/frame_rate.h"
 #include "sprite/sprite_manager.h"
 #include "audio/sound_manager.h"
 #include "lisp/parser.h"
@@ -47,6 +44,9 @@
 #include "player_status.h"
 #include "textscroller.h"
 #include "main.h"
+#include "file_system.h"
+#include "gui/menu.h"
+#include "gui/mousecursor.h"
 #include "control/joystickkeyboardcontroller.h"
 
 Menu* worldmap_menu  = 0;
@@ -688,7 +688,6 @@ WorldMap::update(float delta)
         {
           PlayerStatus old_player_status = player_status;
 
-          std::cout << "Enter the current level: " << level->name << std::endl;
           // do a shriking fade to the level
           shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),
                              (level->pos.y*32 + 16 + offset.y)), 500);
@@ -732,8 +731,6 @@ WorldMap::update(float delta)
                         tux->set_direction(dir);
                         //tux->update(delta);
                       }
-
-                    std::cout << "Walk to dir: " << dir << std::endl;
                   }
               }
 
@@ -772,8 +769,7 @@ WorldMap::update(float delta)
 
               context.do_drawing();
 
-              SDL_Event event;
-              wait_for_event(event,2000,6000,true);
+              wait_for_event(2.0, 6.0);
 
               quit = true;
               player_status.reset();
diff --git a/tools/Jamfile b/tools/Jamfile
new file mode 100644 (file)
index 0000000..9273914
--- /dev/null
@@ -0,0 +1,3 @@
+SubDir TOP tools ;
+
+SubInclude TOP tools miniswig ;
index a806de4..fc83acd 100644 (file)
@@ -6,7 +6,7 @@
 #include "globals.h"
 
 void
-WrapperCreator::create_wrapper(CompilationUnit* unit)
+WrapperCreator::create_wrapper(Namespace* ns)
 {
     // hpp file
     hppout
@@ -14,10 +14,10 @@ WrapperCreator::create_wrapper(CompilationUnit* unit)
         << " * WARNING: This file is automatically generated from '"
         << inputfile << "' - do not change\n"
         << " */\n"
-        << "#ifndef __" << modulename << "_WRAPPER_HPP__\n"
-        << "#define __" << modulename << "_WRAPPER_HPP__\n"
+        << "#ifndef __" << modulename << "_WRAPPER_H__\n"
+        << "#define __" << modulename << "_WRAPPER_H__\n"
         << "\n"
-        << "#include \"WrapperUtil.hpp\"\n"
+        << "#include \"wrapper_util.h\"\n"
         << "\n"
         << "extern WrappedFunction " << modulename << "_global_functions[];\n"
         << "extern WrappedClass " << modulename << "_classes[];\n"
@@ -34,26 +34,30 @@ WrapperCreator::create_wrapper(CompilationUnit* unit)
         << "#include <new>\n"
         << "#include <string>\n"
         << "#include <squirrel.h>\n"
-        << "#include \"WrapperUtil.hpp\"\n"
-        << "#include \"" << inputfile << "\"\n"
+        << "#include \"wrapper_util.h\"\n"
+        << "#include \"wrapper.interface.h\"\n"
         << "\n";
+    if(selected_namespace != "") {
+        out << "using namespace " << selected_namespace << ";\n";
+        out << "\n";
+    }
     
-    for(std::vector<AtomicType*>::iterator i = unit->types.begin();
-            i != unit->types.end(); ++i) {
+    for(std::vector<AtomicType*>::iterator i = ns->types.begin();
+            i != ns->types.end(); ++i) {
         AtomicType* type = *i;
         Class* _class = dynamic_cast<Class*> (type);
         if(_class != 0)
             create_class_wrapper(_class);
     }
-    for(std::vector<Function*>::iterator i = unit->functions.begin();
-            i != unit->functions.end(); ++i) {
+    for(std::vector<Function*>::iterator i = ns->functions.begin();
+            i != ns->functions.end(); ++i) {
         create_function_wrapper(0, *i);
     }
 
     // create function list...
     out << "WrappedFunction " << modulename << "_global_functions[] = {\n";
-    for(std::vector<Function*>::iterator i = unit->functions.begin();
-            i != unit->functions.end(); ++i) {
+    for(std::vector<Function*>::iterator i = ns->functions.begin();
+            i != ns->functions.end(); ++i) {
         Function* function = *i;
         out << ind << "{ \"" << function->name << "\", &"
             << function->name << "_wrapper },\n";
@@ -66,8 +70,8 @@ WrapperCreator::create_wrapper(CompilationUnit* unit)
     std::ostringstream classlist;
     classlist << "WrappedClass " << modulename << "_classes[] = {\n";
 
-    for(std::vector<AtomicType*>::iterator i = unit->types.begin();
-            i != unit->types.end(); ++i) {
+    for(std::vector<AtomicType*>::iterator i = ns->types.begin();
+            i != ns->types.end(); ++i) {
         AtomicType* type = *i;
         Class* _class = dynamic_cast<Class*> (type);
         if(_class == 0)
@@ -93,10 +97,10 @@ WrapperCreator::create_wrapper(CompilationUnit* unit)
             out << ind << "{ \"" << function->name << "\", &"
                 << _class->name << "_" << function->name << "_wrapper },\n";
         }
-        classlist << ind << "{ 0, 0 }\n";
         out << "};\n"
             << "\n";
     }
+    classlist << ind << "{ 0, 0 }\n";
     classlist << "};\n";
     out << classlist.str();
     out << "\n";
@@ -148,6 +152,8 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
     }
     if(_class != 0) {
         out << "_this->";
+    } else if(selected_namespace != "") {
+        out << selected_namespace << "::";
     }
     out << function->name << "(";
     for(size_t i = 0; i < function->parameters.size(); ++i) {
@@ -262,7 +268,7 @@ WrapperCreator::create_class_destruct_function(Class* _class)
         << "{\n"
         << ind << _class->name 
         << "* _this = reinterpret_cast<" << _class->name << "*> (ptr);\n"
-        << ind << "_this->~" << _class->name << "();\n"
+        << ind << "delete _this;\n"
         << ind << "return 0;\n"
         << "}\n"
         << "\n";
index 7b51a18..0b546eb 100644 (file)
@@ -18,7 +18,7 @@ public:
         ind = "  ";
     }
 
-    void create_wrapper(CompilationUnit* unit);
+    void create_wrapper(Namespace* ns);
     void create_class_wrapper(Class* _class);
     void create_class_construct_function(Class* _class);
     void create_class_destruct_function(Class* _class);
index 652f688..362559b 100644 (file)
@@ -4,10 +4,17 @@
 #include "tree.h"
 #include <iostream>
 
+// parsing
 extern CompilationUnit* unit;
+extern bool search_down;
+extern Namespace* search_namespace;
+extern Namespace* current_namespace;
+
+// config/output
 extern std::istream* input;
 extern std::string inputfile;
 extern std::string modulename;
+extern std::string selected_namespace;
 
 #endif
 
index dc019e8..3285ec4 100644 (file)
@@ -21,6 +21,7 @@
 
 %%
 
+#.*                                     /* ignore preprocessor directives */
 [[:space:]]+                            /* eat spaces */
 \/\*.*\*\/                              /* eat comment */
 \/\/[^\n]*\n                            /* eat comment */        
@@ -41,10 +42,14 @@ double                                  { return T_DOUBLE; }
 public                                  { return T_PUBLIC; }
 protected                               { return T_PROTECTED; }
 private                                 { return T_PRIVATE; }
+namespace                               { return T_NAMESPACE; }
 [a-zA-Z_][a-zA-Z_0-9]*                  {
+        Namespace* ns = search_namespace;
+        if(ns == 0)
+            ns = current_namespace;          
         // is it a type?
-        for(std::vector<AtomicType*>::iterator i = unit->types.begin();
-                i != unit->types.end(); ++i) {
+        for(std::vector<AtomicType*>::iterator i = ns->types.begin();
+                i != ns->types.end(); ++i) {
             AtomicType* type = *i;
             if(type->name == yytext) {
                 yylval->atomic_type = type;
@@ -52,10 +57,11 @@ private                                 { return T_PRIVATE; }
             }
         }
         // or a namespace? (hack for now...)
-        if(strcmp(yytext, "std") == 0) {
-            yylval->_namespace = unit->namespaces[0];
-            return T_NAMESPACE;
+        yylval->_namespace = ns->_findNamespace(yytext, search_down);
+        if(yylval->_namespace) {
+            return T_NAMESPACEREF;
         }
+        // a new ID
         yylval->str = strdup(yytext);
         return T_ID;
 }
index 94393df..2417198 100644 (file)
@@ -12,11 +12,12 @@ extern int yylex();
 CompilationUnit* unit = 0;
 std::istream* input = 0;
 std::string inputfile;
+std::string selected_namespace;
 std::string modulename = "wrapper";
 
 void usage()
 {
-    std::cout << "Usage: miniswig --input FILE --output-cpp FILE --output-hpp FILE [--module NAME]\n";
+    std::cout << "Usage: miniswig --input FILE --output-cpp FILE --output-hpp FILE [--module NAME] [--select-namespace NAME]\n";
     std::cout << "\n";
 }
 
@@ -53,6 +54,13 @@ int main(int argc, char** argv)
                 return 1;
             }
             outputhpp = argv[++i];
+        } else if(strcmp(argv[i], "--select-namespace") == 0) {
+            if(i+1 >= argc) {
+                std::cerr << "Need to specify a namespace.\n";
+                usage();
+                return 1;
+            }
+            selected_namespace = argv[++i];
         } else if(argv[i][0] == '-') {
             std::cerr << "Unknown option '" << argv[i] << "'.\n";
             usage();
@@ -73,11 +81,13 @@ int main(int argc, char** argv)
             return 1;
         }
         unit = new CompilationUnit();
-        unit->types.push_back(new StringType());
         Namespace* std_namespace = new Namespace();
         std_namespace->name = "std";
+        std_namespace->types.push_back(new StringType());
         unit->namespaces.push_back(std_namespace);
+        
         yyparse();
+
         std::ofstream cppout(outputcpp.c_str());
         if(!cppout.good()) {
             std::cerr << "Couldn't open file '" << outputcpp << "' for writing.\n";
@@ -88,8 +98,14 @@ int main(int argc, char** argv)
             std::cerr << "Couldn't open file '" << outputhpp << "' for writing.\n";
             return 1;
         }
+
+        Namespace* ns = unit;
+        if(selected_namespace != "") {
+            ns = ns->findNamespace(selected_namespace);
+        }
+
         WrapperCreator creator(cppout, hppout);
-        creator.create_wrapper(unit);
+        creator.create_wrapper(ns);
     } catch(std::exception& e) {
         std::cerr << e.what() << "\n";
         return 1;
index f7865cc..e66b58c 100644 (file)
@@ -26,10 +26,13 @@ extern int yylex(YYSTYPE* yylval);
 void yyerror(const char* s);
 extern int yylineno;
 
-static Class* currentClass = 0;
+bool search_down = true;
+Namespace* search_namespace = 0;
+Namespace* current_namespace = 0;
+static Class* current_class = 0;
 static Function* currentFunction = 0;
-static Type* currentType = 0;
-static ClassMember::Visbility currentVisibility;
+static Type* current_type = 0;
+static ClassMember::Visbility current_visibility;
 
 class ParseError : public std::exception
 {
@@ -59,7 +62,7 @@ private:
 %token <str>  T_STRING
 %token <str>  T_ID
 %token <atomic_type> T_ATOMIC_TYPE
-%token <_namespace> T_NAMESPACE;
+%token <_namespace> T_NAMESPACEREF;
 %token T_CLASS
 %token T_STRUCT
 %token T_STATIC
@@ -77,6 +80,7 @@ private:
 %token T_PUBLIC
 %token T_PROTECTED
 %token T_PRIVATE
+%token T_NAMESPACE
 %token T_DDCOL "::"
 
 %type <_class> class_declaration
@@ -88,77 +92,110 @@ private:
 
 %%
 
-input:  /* empty */
-    | compilation_unit
+input:
+        {
+            current_namespace = unit;
+        }
+    namespace_members
+;
+
+namespace_members: /* empty */
+    | namespace_members namespace_member
 ;
 
-compilation_unit: compilation_unit_part
-    | compilation_unit compilation_unit_part
+namespace_declaration:
+    T_NAMESPACE T_ID '{' 
+        {
+            Namespace* newNamespace = new Namespace();
+            newNamespace->name = $2;
+            free($2);
+            current_namespace->add_namespace(newNamespace);
+            current_namespace = newNamespace;
+        }
+    namespace_members '}'
+        {
+            current_namespace = current_namespace->parent;
+        }
+    | T_NAMESPACE T_NAMESPACEREF '{'
+        {
+            current_namespace = $2;
+        }
+    namespace_members '}'
+        {
+            current_namespace = current_namespace->parent;
+        }
 ;
 
-compilation_unit_part: class_declaration
-        { unit->types.push_back($1); }  
+namespace_member:
+    class_declaration
+        { current_namespace->add_type($1); }
     | function_declaration
-        { unit->functions.push_back($1); }
+        { current_namespace->functions.push_back($1); }
+    | namespace_declaration
 ;  
 
-class_declaration: T_CLASS T_ID '{' 
-            {
-                currentClass = new Class();
-                currentClass->name = $2;
-                free($2);
-                currentVisibility = ClassMember::PROTECTED;
-            }
-        class_body '}' ';'
-            {
-                $$ = currentClass;
-            }
+class_declaration:
+    T_CLASS T_ID '{' 
+        {
+            current_class = new Class();
+            current_class->name = $2;
+            free($2);
+            current_visibility = ClassMember::PROTECTED;
+        }
+    class_body '}' ';'
+        {
+            $$ = current_class;
+        }
 ;
 
 class_body: /* empty */
-        | visibility_change class_body
+        | class_body class_body_element
+;
+
+class_body_element:
+        visibility_change
         | constructor_declaration
             { 
-                $1->visibility = currentVisibility;
-                currentClass->members.push_back($1);
+                $1->visibility = current_visibility;
+                current_class->members.push_back($1);
             }
-          class_body
         | destructor_declaration
             {
-                $1->visibility = currentVisibility;
-                currentClass->members.push_back($1);
+                $1->visibility = current_visibility;
+                current_class->members.push_back($1);
             }
-          class_body
         | function_declaration
             {
-                $1->visibility = currentVisibility;
-                currentClass->members.push_back($1);
+                $1->visibility = current_visibility;
+                current_class->members.push_back($1);
             }
-          class_body
-        | variable_declaration class_body
+        | variable_declaration
 ;
 
-visibility_change:  T_PUBLIC ':'
-            { currentVisibility = ClassMember::PUBLIC; }
-        |   T_PROTECTED ':'
-            { currentVisibility = ClassMember::PROTECTED; }
-        |   T_PRIVATE ':'
-            { currentVisibility = ClassMember::PRIVATE; }
+visibility_change:
+    T_PUBLIC ':'
+        { current_visibility = ClassMember::PUBLIC; }
+    |   T_PROTECTED ':'
+        { current_visibility = ClassMember::PROTECTED; }
+    |   T_PRIVATE ':'
+        { current_visibility = ClassMember::PRIVATE; }
 ;
 
-constructor_declaration:    T_ID '('
+constructor_declaration:    
+    T_ID '('
         {
             currentFunction = new Function();
             currentFunction->type = Function::CONSTRUCTOR;
             free($1);
         }
-    param_list ')' ';'
+    parameter_list ')' ';'
         {
             $$ = currentFunction;
         }
 ;
 
-destructor_declaration:     '~' T_ID '(' ')' ';'
+destructor_declaration:
+    '~' T_ID '(' ')' ';'
         {
             currentFunction = new Function();
             currentFunction->type = Function::DESTRUCTOR;
@@ -167,9 +204,12 @@ destructor_declaration:     '~' T_ID '(' ')' ';'
         }
 ;
 
-variable_declaration:   type T_ID ';'
+variable_declaration:
+    type T_ID ';'
+;
 
-function_declaration:       type T_ID '(' 
+function_declaration:
+    type T_ID '(' 
         {
             currentFunction = new Function();
             currentFunction->type = Function::FUNCTION;
@@ -178,83 +218,121 @@ function_declaration:       type T_ID '('
             currentFunction->name = $2;
             free($2);
         }                           
-    param_list ')' ';'
+    parameter_list ')' ';'
         {
             $$ = currentFunction;
         }
 ;
 
-param_list: /* empty */
-        | param_list2
+parameter_list:
+    /* empty */
+    | parameters
 ;
 
-param_list2: parameter
-        | parameter ',' param_list2
+parameters:
+    parameter
+    | parameters ',' parameter
 ;
 
-parameter: type
-            {
-                Parameter parameter;
-                parameter.type = *($1);
-                delete $1;
-                currentFunction->parameters.push_back(parameter);
-            }
-        | type T_ID
-            {
-                Parameter parameter;
-                parameter.type = *($1);
-                delete $1;
-                parameter.name = *($2);
-                free($2);
-                currentFunction->parameters.push_back(parameter);
-            }
+parameter:
+    type
+        {
+            Parameter parameter;
+            parameter.type = *($1);
+            delete $1;
+            currentFunction->parameters.push_back(parameter);
+        }
+    | type T_ID
+        {
+            Parameter parameter;
+            parameter.type = *($1);
+            delete $1;
+            parameter.name = *($2);
+            free($2);
+            currentFunction->parameters.push_back(parameter);
+        }
 ;
 
-type: {
-          currentType = new Type();
-      }
-      prefix_type_modifiers atomic_type postfix_type_modifiers 
-      {
-          $$ = currentType;
-      }
+type:
+        {
+            current_type = new Type();
+        }
+    prefix_type_modifiers atomic_type postfix_type_modifiers 
+        {
+            $$ = current_type;
+        }
+;
+
+prefix_type_modifiers:
+    /* empty */
+    | prefix_type_modifiers prefix_type_modifier
+;
+
+prefix_type_modifier:
+    T_UNSIGNED
+    | T_SIGNED
+    | T_STATIC
+    | T_CONST
 ;
 
-prefix_type_modifiers: /* empty */
-            | T_UNSIGNED prefix_type_modifiers
-            | T_SIGNED prefix_type_modifiers
-            | T_STATIC prefix_type_modifiers
-            | T_CONST prefix_type_modifiers
+postfix_type_modifiers:
+    /* empty */
+    | postfix_type_modifiers postfix_type_modifier
 ;
 
-postfix_type_modifiers: /* empty */
-            | T_CONST postfix_type_modifiers
-                { currentType->_const = true; }
-            |   '*' postfix_type_modifiers
-                { currentType->pointer++; }
-            |   '&' postfix_type_modifiers
-                { currentType->ref++; }
+postfix_type_modifier:
+    T_CONST
+        { current_type->_const = true; }
+    |   '*'
+        { current_type->pointer++; }
+    |   '&'
+        { current_type->ref++; }
 ;
 
-atomic_type:    T_VOID      { currentType->atomic_type = &BasicType::VOID; }
-            |   T_BOOL      { currentType->atomic_type = &BasicType::BOOL; }
-            |   T_CHAR      { currentType->atomic_type = &BasicType::CHAR; }
-            |   T_SHORT     { currentType->atomic_type = &BasicType::SHORT; }
-            |   T_INT       { currentType->atomic_type = &BasicType::INT; }
-            |   T_LONG      { currentType->atomic_type = &BasicType::LONG; }
-            |   T_FLOAT     { currentType->atomic_type = &BasicType::FLOAT; }
-            |   T_DOUBLE    { currentType->atomic_type = &BasicType::DOUBLE; }
-            |   type_identifier  { currentType->atomic_type = $1; }
+atomic_type:
+    T_VOID
+        { current_type->atomic_type = &BasicType::VOID; }
+    | T_BOOL
+        { current_type->atomic_type = &BasicType::BOOL; }
+    | T_CHAR
+        { current_type->atomic_type = &BasicType::CHAR; }
+    | T_SHORT
+        { current_type->atomic_type = &BasicType::SHORT; }
+    | T_INT
+        { current_type->atomic_type = &BasicType::INT; }
+    | T_LONG
+        { current_type->atomic_type = &BasicType::LONG; }
+    | T_FLOAT
+        { current_type->atomic_type = &BasicType::FLOAT; }
+    | T_DOUBLE
+        { current_type->atomic_type = &BasicType::DOUBLE; }
+    | type_identifier
+        { current_type->atomic_type = $1; }
 ;
 
-type_identifier: T_ATOMIC_TYPE
+type_identifier:
+    T_ATOMIC_TYPE
         {
             // search for type in current compilation unit...
             $$ = $1;
         }
-        |   T_NAMESPACE "::" type_identifier
+    | namespace_refs "::" T_ATOMIC_TYPE
         {
-            // hack...
             $$ = $3;
+            search_namespace = 0;
+            search_down = true;
+        }
+;
+
+namespace_refs:
+    T_NAMESPACEREF
+        {
+            search_namespace = $1;
+            search_down = false;
+        }
+    | namespace_refs "::" T_NAMESPACEREF
+        {
+            search_namespace = $3;
         }
 ;
 
index 4b9485c..f1149af 100644 (file)
@@ -4,10 +4,16 @@
 #include <vector>
 #include <string>
 #include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+class Namespace;
 
 class AtomicType {
 public:
-    std::string name;
+    AtomicType()
+        : parent(0)
+    { }
     virtual ~AtomicType()
     { }
 
@@ -15,6 +21,9 @@ public:
     {
         out << name;
     }
+
+    std::string name;
+    Namespace* parent;
 };
 
 class BasicType : public AtomicType {
@@ -143,12 +152,10 @@ public:
 
 class Namespace {
 public:
-    std::string name;
-};
-
-class CompilationUnit {
-public:
-    ~CompilationUnit() {
+    Namespace() {
+        parent = 0;
+    }
+    virtual ~Namespace() {
         for(std::vector<Function*>::iterator i = functions.begin();
                 i != functions.end(); ++i)
             delete *i;
@@ -159,10 +166,50 @@ public:
                 i != namespaces.end(); ++i)
             delete *i;
     }
+    void add_type(AtomicType* type)
+    {
+        types.push_back(type);
+        type->parent = this;
+    }
+    void add_namespace(Namespace* ns)
+    {
+        namespaces.push_back(ns);
+        ns->parent = this;
+    }
+    Namespace* _findNamespace(const std::string& name, bool godown = false) {
+        for(std::vector<Namespace*>::iterator i = namespaces.begin();
+                i != namespaces.end(); ++i) {
+            Namespace* ns = *i;
+            if(ns->name == name)
+                return ns;
+        }
+        if(godown && parent)
+            return parent->_findNamespace(name, true);
+
+        return 0;
+    }
+
+    Namespace* findNamespace(const std::string& name, bool godown = false) {
+        Namespace* ret = _findNamespace(name, godown);
+        if(!ret) {
+            std::ostringstream msg;
+            msg << "Couldn't find namespace '" << name << "'.";
+            throw std::runtime_error(msg.str());
+        }
+
+        return ret;
+    }
+                                                                             
     std::vector<Function*> functions;
     std::vector<AtomicType*> types;
     std::vector<Namespace*> namespaces;
+
+    Namespace* parent;
+    std::string name;
+};
+
+class CompilationUnit : public Namespace {
+public:
 };
 
 #endif