(name "Forest Theme Test")
(author "Marek Moeckel")
(time 300)
- (end-sequence-animation "none")
(sector
(name "main")
(gravity 10)
(name "Nolok Test")
(author "Marek")
(time 500)
- (end-sequence-animation "none")
(sector
(name "main")
(gravity 10)
+++ /dev/null
-/*
- 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 */
+++ /dev/null
-// $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
+++ /dev/null
-// $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 */
+++ /dev/null
-// $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;
-}
+++ /dev/null
-// $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*/
-
+++ /dev/null
-// $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 */
+++ /dev/null
-// $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 */
+++ /dev/null
-#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
-
+++ /dev/null
-// $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;
-}
-
+++ /dev/null
-// $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*/
+++ /dev/null
-#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
-
+++ /dev/null
-// $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);
-}
+++ /dev/null
-// $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*/
-
+++ /dev/null
-//
-// 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();
-}
+++ /dev/null
-//
-// 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*/
-
+++ /dev/null
-// $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 */
+++ /dev/null
-// $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: */
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 ]
;
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 ;
// 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)
{
#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)
// 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;
#include "SDL_mixer.h"
#include "math/vector.h"
-using namespace SuperTux;
-
class MusicRef;
class MovingObject;
physic.enable_gravity(true);
set_state(STATE_FALLING);
}
- std::cout << "KILL_FALL - HITPOINTS: " << hitpoints << ", BULLET HP: " << bullet_hitpoints << std::endl;
}
void
// 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__
#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"
#include "video/drawing_context.h"
#include "sprite/sprite_manager.h"
-using namespace SuperTux;
-
class BadGuy : public MovingObject, public Serializable
{
public:
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");
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
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;
}
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")
physic.enable_gravity(true);
set_state(STATE_FALLING);
}
- std::cout << "KILL_FALL - HITPOINTS: " << hitpoints << ", BULLET HP: " << bullet_hitpoints << std::endl;
}
IMPLEMENT_FACTORY(Yeti, "yeti")
#ifndef __COLLISION_H__
#define __COLLISION_H__
-namespace SuperTux {
class Vector;
class Rectangle;
class AATriangle;
-}
-
-using namespace SuperTux;
-
class CollisionHit;
class Collision
// 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;
/**
// 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
#include "math/vector.h"
-using namespace SuperTux;
-
/**
* Used as return value for the collision functions, to indicate how the
* collision should be handled
#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"
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;
}
if(!good) {
SDL_JoystickClose(joystick);
- joysticks.push_back(0);
- joystick_names.push_back("");
continue;
}
max_joybuttons = SDL_JoystickNumButtons(joystick);
}
- joystick_names.push_back(SDL_JoystickName(i));
joysticks.push_back(joystick);
}
{
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();
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)));
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;
--- /dev/null
+#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;
+}
+
+}
+
--- /dev/null
+#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
+
#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"
#include "lisp/lisp.h"
#include "lisp/parser.h"
#include "resources.h"
-#include "app/gettext.h"
#include "worldmap.h"
#include "misc.h"
#include "statistics.h"
#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"
context.do_drawing();
- SDL_Event event;
- wait_for_event(event,1000,3000,true);
+ wait_for_event(1.0, 3.0);
}
/* Reset Timers */
GameSession::start_timers()
{
time_left.start(level->timelimit);
- Ticks::pause_init();
}
void
} 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;
}
}
// end of pause mode?
if(!Menu::current() && game_pause) {
game_pause = false;
- Ticks::pause_stop();
}
if (end_sequence != NO_ENDSEQUENCE) {
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)
{
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;
}
#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,
#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()
--- /dev/null
+/*
+ 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 */
// 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;
// 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
class Surface;
-namespace SuperTux
- {
class ButtonGroup;
enum {
int buttons_pair_nb;
};
-} //namespace SuperTux
-
#endif
#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;
last_menus.push_back(current_);
current_ = pmenu;
- current_->effect.start(500);
+ current_->effect_ticks = SDL_GetTicks();
}
void
{
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;
last_menus.clear();
if (menu)
- menu->effect.start(500);
+ menu->effect_ticks = SDL_GetTicks();
current_ = menu;
// just to be sure...
toggled = false;
selected = false;
target_menu = 0;
- input_flickering = false;
- input_flickering_timer.init(true);
- input_flickering_timer.start(FLICK_CURSOR_TIME);
}
void
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)
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)
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)
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;
void
Menu::event(const SDL_Event& event)
{
- if(effect.started())
+ if(effect_ticks != 0)
return;
switch(event.type) {
#include "video/surface.h"
#include "video/font.h"
-#include "special/timer.h"
#include "mousecursor.h"
bool confirm_dialog(Surface* background, std::string text);
/// keyboard key or joystick button
bool input_flickering;
- Timer input_flickering_timer;
};
class Menu
/* input implementation variables */
int delete_character;
char mn_input_char;
- Timer repeat_timer;
+ Uint32 menu_repeat_ticks;
public:
static Font* default_font;
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;
};
// 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);
}
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);
}
// 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*/
#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"
// 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())
// 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
#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"
// 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>
};
#endif
+
+#endif
#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
{
}
if(dictionary_manager) {
- dictionary_manager->add_directory(SuperTux::FileSystem::dirname(filename));
+ dictionary_manager->add_directory(FileSystem::dirname(filename));
dictionary = & (dictionary_manager->get_dictionary());
}
#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()
{
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);
}
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()
}
}
+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
// 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
--- /dev/null
+#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
+
--- /dev/null
+#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
+
--- /dev/null
+// $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);
+}
--- /dev/null
+// $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
+
#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;
#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,
// 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)
// 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
#include "game_object.h"
#include "serializable.h"
-using namespace SuperTux;
-
class DisplayManager;
namespace lisp {
// 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__
#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.
// 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__
class Sprite;
class Player;
-using namespace SuperTux;
-
class Block : public MovingObject
{
public:
// 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>
#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;
// 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
// 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)
// 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
#include "serializable.h"
#include "timer.h"
-using namespace SuperTux;
namespace lisp {
class Lisp;
}
// 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__
class Sprite;
-using namespace SuperTux;
-
class Coin : public MovingObject
{
public:
// 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);
// 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>
#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)
// 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
{
#include <iostream>
#include <cmath>
-#include "app/globals.h"
#include "tile.h"
#include "tile_manager.h"
#include "game_session.h"
#include "tilemap.h"
#include "video/drawing_context.h"
#include "camera.h"
+#include "main.h"
BouncyCoin::BouncyCoin(const Vector& pos)
: position(pos)
#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"
// 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>
#include "camera.h"
#include "sector.h"
#include "player.h"
-#include "app/globals.h"
#include "sprite/sprite_manager.h"
GrowUp::GrowUp(const Vector& pos)
// 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
{
// 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
{
// 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()
{
// 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
#include "game_object.h"
#include "serializable.h"
-using namespace SuperTux;
-
namespace lisp {
class Lisp;
}
// 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
*/
#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"
#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;
// 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.
#define __ROCK_H__
#include "moving_object.h"
-#include "math/physic.h"
+#include "physic.h"
#include "lisp/lisp.h"
#include "portable.h"
#include "serializable.h"
// 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>
#include "resources.h"
#include "camera.h"
#include "sector.h"
-#include "app/globals.h"
#include "sprite/sprite_manager.h"
SpecialRiser::SpecialRiser(MovingObject* _child)
// 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.
// 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
{
#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),
// 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
class Lisp;
}
-using namespace SuperTux;
-
class Level;
class TileManager;
class Tile;
// 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
{
#include "game_object.h"
#include "math/vector.h"
-using namespace SuperTux;
-
class Factory
{
public:
--- /dev/null
+// $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;
+}
+
--- /dev/null
+// $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
// 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;
TileManager* tile_manager = 0;
SoundManager* sound_manager = 0;
+MouseCursor* mouse_cursor = 0;
+
Font* gold_text;
Font* blue_text;
Font* gray_text;
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: */
#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;
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;
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
--- /dev/null
+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 ] ;
+}
+
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
+
--- /dev/null
+#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& )
+ {}
+}
+
--- /dev/null
+#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
+
--- /dev/null
+#include <stdio.h>
+#include "functions.h"
+
+namespace Scripting
+{
+
+void wait(float secs)
+{
+ (void) secs;
+ printf("Wait not implemented.\n");
+}
+
+}
+
--- /dev/null
+#ifndef __FUNCTIONS_H__
+#define __FUNCTIONS_H__
+
+namespace Scripting
+{
+
+void wait(float secs);
+
+}
+
+#endif
+
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
+
--- /dev/null
+#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
+
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
+
--- /dev/null
+;; 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]))
+ )
+ )
+ )
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
+
--- /dev/null
+/**
+ * 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 }
+};
+
--- /dev/null
+/**
+ * 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
+
--- /dev/null
+/** 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"
--- /dev/null
+#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);
+}
+
--- /dev/null
+#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
#include <fstream>
#include <stdexcept>
-#include "app/globals.h"
#include "sector.h"
#include "player_status.h"
#include "object/gameobjs.h"
#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;
#include <cassert>
#include <stdexcept>
-#include "app/globals.h"
-#include "app/setup.h"
#include "sprite.h"
#include "video/drawing_context.h"
#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"
--- /dev/null
+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 ;
--- /dev/null
+This directory contains the SQUIRREL programming language version 2.0.1 from
+http://squirrel.sourceforge.net
+Originally on zlib/png license.
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+# 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+# 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
#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;
#include "lisp/lisp.h"
#include "lisp/writer.h"
-using namespace SuperTux;
-
class DrawingContext;
#define SPLAYER 0
// 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"
#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"
#include <iostream>
#include <stdexcept>
-#include "app/globals.h"
#include "lisp/lisp.h"
#include "tile.h"
#include "resources.h"
#include "math/rectangle.h"
#include "lisp/lisp.h"
-using namespace SuperTux;
-
/**
Tile Class
*/
#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"
// 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>
// 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__
--- /dev/null
+// $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 */
--- /dev/null
+// $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 */
#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"
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.
titlesession->get_current_sector()->activate("main");
titlesession->set_current();
- frame_rate.update();
+ //frame_rate.update();
}
void update_load_save_game_menu(Menu* 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)
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)
MusicRef credits_music;
controller = new CodeController();
- Ticks::pause_init();
-
titlesession = new GameSession(get_resource_filename("levels/misc/menu.stl"),
ST_GL_DEMO_GAME);
break;
case MNID_LEVELS_CONTRIB:
// Contrib Menu
- puts("Entering contrib menu");
generate_contrib_menu();
break;
#if 0
context.do_drawing();
- frame_rate.update();
+ //frame_rate.update();
/* Pause: */
frame++;
#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);
#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);
// 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"
#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)
// 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__
#include "serializable.h"
#include "resources.h"
#include "video/drawing_context.h"
-#include "app/globals.h"
#include "timer.h"
class SecretAreaTrigger : public TriggerBase, public Serializable
#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
#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) {
#include "video/surface.h"
#include "video/font.h"
-using namespace SuperTux;
-
class Surface;
// some constants for predefined layer values
#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),
#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!
#include <vector>
#include "math/vector.h"
-using namespace SuperTux;
-
/** Stores 8bit RGBA values. */
class Color
{
#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;
#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"
#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;
{
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);
tux->set_direction(dir);
//tux->update(delta);
}
-
- std::cout << "Walk to dir: " << dir << std::endl;
}
}
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();
--- /dev/null
+SubDir TOP tools ;
+
+SubInclude TOP tools miniswig ;
#include "globals.h"
void
-WrapperCreator::create_wrapper(CompilationUnit* unit)
+WrapperCreator::create_wrapper(Namespace* ns)
{
// hpp file
hppout
<< " * 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"
<< "#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";
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)
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";
}
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) {
<< "{\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";
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);
#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
%%
+#.* /* ignore preprocessor directives */
[[:space:]]+ /* eat spaces */
\/\*.*\*\/ /* eat comment */
\/\/[^\n]*\n /* eat comment */
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;
}
}
// 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;
}
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";
}
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();
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";
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;
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
{
%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
%token T_PUBLIC
%token T_PROTECTED
%token T_PRIVATE
+%token T_NAMESPACE
%token T_DDCOL "::"
%type <_class> class_declaration
%%
-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;
}
;
-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;
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;
}
;
#include <vector>
#include <string>
#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+class Namespace;
class AtomicType {
public:
- std::string name;
+ AtomicType()
+ : parent(0)
+ { }
virtual ~AtomicType()
{ }
{
out << name;
}
+
+ std::string name;
+ Namespace* parent;
};
class BasicType : public AtomicType {
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;
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