From: Matthias Braun Date: Fri, 21 Jul 2006 11:45:14 +0000 (+0000) Subject: fix cr/lfs and remove trailing whitespaces... X-Git-Url: https://git.octo.it/?p=supertux.git;a=commitdiff_plain;h=a113d3bd1feddd510e3b2852b0d42522735eee40 fix cr/lfs and remove trailing whitespaces... SVN-Revision: 4059 --- diff --git a/data/levels/bonus1/extro.txt b/data/levels/bonus1/extro.txt index 45b1f9cc6..97fa464fc 100644 --- a/data/levels/bonus1/extro.txt +++ b/data/levels/bonus1/extro.txt @@ -11,17 +11,16 @@ Abednego Matr1x - + #If you didn't clear all levels yet, -#find your way back home and take +#find your way back home and take #another path. There is still more #challenge waiting for you! #And there is a secret level to be #found as well... - + #A big \"Thank you\" goes out to #everyone who contributed to this #release. We hope you enjoyed it!")) ) - diff --git a/data/levels/world1/extro.txt b/data/levels/world1/extro.txt index b0a6a683d..725af4dda 100644 --- a/data/levels/world1/extro.txt +++ b/data/levels/world1/extro.txt @@ -37,4 +37,3 @@ #hand. No, he decided, he would not give #up. Penny was counting on him.")) ) - diff --git a/data/levels/world1/intro.txt b/data/levels/world1/intro.txt index 57490589a..495149b30 100644 --- a/data/levels/world1/intro.txt +++ b/data/levels/world1/intro.txt @@ -24,4 +24,3 @@ #the distance. Determined to save his #beloved Penny, he begins his journey.")) ) - diff --git a/src/audio/dummy_sound_source.cpp b/src/audio/dummy_sound_source.cpp index 0ca6392ff..1a9c274e0 100644 --- a/src/audio/dummy_sound_source.cpp +++ b/src/audio/dummy_sound_source.cpp @@ -32,12 +32,12 @@ public: { is_playing = true; } - + virtual void stop() { is_playing = false; } - + virtual bool playing() { return is_playing; @@ -79,4 +79,3 @@ SoundSource* create_dummy_sound_source() { return new DummySoundSource(); } - diff --git a/src/audio/dummy_sound_source.hpp b/src/audio/dummy_sound_source.hpp index 53a3e911d..458c1e834 100644 --- a/src/audio/dummy_sound_source.hpp +++ b/src/audio/dummy_sound_source.hpp @@ -1,4 +1,4 @@ -// $Id: sound_source.hpp 3462 2006-04-28 19:38:41Z sommer $ +// $Id$ // // SuperTux // Copyright (C) 2006 Matthias Braun @@ -24,4 +24,3 @@ SoundSource* create_dummy_sound_source(); #endif - diff --git a/src/audio/openal_sound_source.hpp b/src/audio/openal_sound_source.hpp index 75b6ef680..f70dd0ff9 100644 --- a/src/audio/openal_sound_source.hpp +++ b/src/audio/openal_sound_source.hpp @@ -1,4 +1,4 @@ -// $Id: sound_source.hpp 3462 2006-04-28 19:38:41Z sommer $ +// $Id$ // // SuperTux // Copyright (C) 2006 Matthias Braun @@ -45,9 +45,8 @@ public: protected: friend class SoundManager; - + ALuint source; }; #endif - diff --git a/src/audio/sound_file.cpp b/src/audio/sound_file.cpp index 01a4032c3..48c2e9ed8 100644 --- a/src/audio/sound_file.cpp +++ b/src/audio/sound_file.cpp @@ -44,7 +44,7 @@ public: private: PHYSFS_file* file; - + PHYSFS_sint64 datastart; }; @@ -80,7 +80,7 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) uint32_t wavelen = read32LE(file); (void) wavelen; - + if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1) throw std::runtime_error("Couldn't read chunk header (not a wav file?)"); if(strncmp(magic, "WAVE", 4) != 0) @@ -92,9 +92,9 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) // search audio data format chunk do { if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1) - throw std::runtime_error("EOF while searching format chunk"); + throw std::runtime_error("EOF while searching format chunk"); chunklen = read32LE(file); - + if(strncmp(chunkmagic, "fmt ", 4) == 0) break; @@ -106,11 +106,11 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) } else { throw std::runtime_error("complex WAVE files not supported"); } - } while(true); + } while(true); if(chunklen < 16) throw std::runtime_error("Format chunk too short"); - + // parse format uint16_t encoding = read16LE(file); if(encoding != 1) @@ -131,7 +131,7 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) // set file offset to DATA chunk data do { if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1) - throw std::runtime_error("EOF while searching data chunk"); + throw std::runtime_error("EOF while searching data chunk"); chunklen = read32LE(file); if(strncmp(chunkmagic, "data", 4) == 0) @@ -165,7 +165,7 @@ WavSoundFile::read(void* buffer, size_t buffer_size) PHYSFS_sint64 cur = PHYSFS_tell(file); if(cur >= end) return 0; - + size_t readsize = std::min(static_cast (end - cur), buffer_size); if(PHYSFS_read(file, buffer, readsize, 1) != 1) throw std::runtime_error("read error while reading samples"); @@ -206,7 +206,7 @@ private: static int cb_seek(void* source, ogg_int64_t offset, int whence); static int cb_close(void* source); static long cb_tell(void* source); - + PHYSFS_file* file; OggVorbis_File vorbis_file; }; @@ -238,7 +238,7 @@ OggSoundFile::read(void* _buffer, size_t buffer_size) size_t totalBytesRead= 0; while(buffer_size>0){ - long bytesRead + long bytesRead = ov_read(&vorbis_file, buffer, static_cast (buffer_size), #ifdef WORDS_BIGENDIAN 1, @@ -253,7 +253,7 @@ OggSoundFile::read(void* _buffer, size_t buffer_size) buffer += bytesRead; totalBytesRead += bytesRead; } - + return totalBytesRead; } @@ -267,8 +267,8 @@ size_t OggSoundFile::cb_read(void* ptr, size_t size, size_t nmemb, void* source) { PHYSFS_file* file = reinterpret_cast (source); - - PHYSFS_sint64 res + + PHYSFS_sint64 res = PHYSFS_read(file, ptr, static_cast (size), static_cast (nmemb)); if(res <= 0) @@ -304,7 +304,7 @@ OggSoundFile::cb_seek(void* source, ogg_int64_t offset, int whence) } return 0; } - + int OggSoundFile::cb_close(void* source) { @@ -331,7 +331,7 @@ SoundFile* load_sound_file(const std::string& filename) msg << "Couldn't open '" << filename << "': " << PHYSFS_getLastError(); throw std::runtime_error(msg.str()); } - + try { char magic[4]; if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1) @@ -349,4 +349,3 @@ SoundFile* load_sound_file(const std::string& filename) throw std::runtime_error(msg.str()); } } - diff --git a/src/audio/sound_file.hpp b/src/audio/sound_file.hpp index f10e22a37..fd777b22a 100644 --- a/src/audio/sound_file.hpp +++ b/src/audio/sound_file.hpp @@ -42,4 +42,3 @@ public: SoundFile* load_sound_file(const std::string& filename); #endif - diff --git a/src/audio/sound_manager.cpp b/src/audio/sound_manager.cpp index 3976eb6b5..cc9dc40ea 100644 --- a/src/audio/sound_manager.cpp +++ b/src/audio/sound_manager.cpp @@ -118,8 +118,8 @@ SoundManager::create_sound_source(const std::string& filename) return create_dummy_sound_source(); ALuint buffer; - - // reuse an existing static sound buffer + + // reuse an existing static sound buffer SoundBuffers::iterator i = buffers.find(filename); if(i != buffers.end()) { buffer = i->second; @@ -141,10 +141,10 @@ SoundManager::create_sound_source(const std::string& filename) return create_dummy_sound_source(); } } - + OpenALSoundSource* source = new OpenALSoundSource(); alSourcei(source->source, AL_BUFFER, buffer); - return source; + return source; } void @@ -152,7 +152,7 @@ SoundManager::preload(const std::string& filename) { if(!sound_enabled) return; - + SoundBuffers::iterator i = buffers.find(filename); // already loaded? if(i != buffers.end()) @@ -172,11 +172,11 @@ SoundManager::play(const std::string& filename, const Vector& pos) { if(!sound_enabled) return; - + try { - std::auto_ptr source + std::auto_ptr source (static_cast (create_sound_source(filename))); - + if(pos == Vector(-1, -1)) { source->set_rollof_factor(0); } else { @@ -193,18 +193,18 @@ void SoundManager::manage_source(SoundSource* source) { assert(source != NULL); - + OpenALSoundSource* openal_source = dynamic_cast (source); if(openal_source != NULL) { sources.push_back(openal_source); } } -void +void SoundManager::register_for_update( StreamSoundSource* sss ){ if( sss != NULL ){ update_list.push_back( sss ); - } + } } void @@ -218,7 +218,7 @@ SoundManager::remove_from_update( StreamSoundSource* sss ){ i++; } } - } + } } void @@ -300,7 +300,7 @@ SoundManager::set_listener_position(const Vector& pos) Uint32 current_ticks = SDL_GetTicks(); if(current_ticks - lastticks < 300) return; - lastticks = current_ticks; + lastticks = current_ticks; alListener3f(AL_POSITION, pos.x, pos.y, 0); } @@ -325,7 +325,7 @@ SoundManager::update() OpenALSoundSource* source = *i; source->update(); - + if(!source->playing()) { delete source; i = sources.erase(i); @@ -343,7 +343,7 @@ SoundManager::update() alcProcessContext(context); check_alc_error("Error while processing audio context: "); } - + //run update() for stream_sound_source StreamSoundSources::iterator s = update_list.begin(); while( s != update_list.end() ){ @@ -372,7 +372,7 @@ SoundManager::get_sample_format(SoundFile* file) throw std::runtime_error("Only 16 and 8 bit samples supported"); } } - + throw std::runtime_error("Only 1 and 2 channel samples supported"); } @@ -393,7 +393,7 @@ SoundManager::check_alc_error(const char* message) std::stringstream msg; msg << message << alcGetString(device, err); throw std::runtime_error(msg.str()); - } + } } void @@ -404,6 +404,5 @@ SoundManager::check_al_error(const char* message) std::stringstream msg; msg << message << alGetString(err); throw std::runtime_error(msg.str()); - } + } } - diff --git a/src/audio/sound_manager.hpp b/src/audio/sound_manager.hpp index 153bf3643..657ca06a3 100644 --- a/src/audio/sound_manager.hpp +++ b/src/audio/sound_manager.hpp @@ -66,7 +66,7 @@ public: void play_music(const std::string& filename, bool fade = false); void stop_music(float fadetime = 0); - bool is_music_enabled() { return music_enabled; } + bool is_music_enabled() { return music_enabled; } bool is_sound_enabled() { return sound_enabled; } bool is_audio_enabled() { @@ -74,7 +74,7 @@ public: } void update(); - + /* * Tell soundmanager to call update() for stream_sound_source. */ @@ -116,4 +116,3 @@ private: extern SoundManager* sound_manager; #endif - diff --git a/src/audio/sound_source.hpp b/src/audio/sound_source.hpp index 3824c3c1d..48c3f287a 100644 --- a/src/audio/sound_source.hpp +++ b/src/audio/sound_source.hpp @@ -47,4 +47,3 @@ public: }; #endif - diff --git a/src/audio/stream_sound_source.cpp b/src/audio/stream_sound_source.cpp index 3569ecdee..958ef6f58 100644 --- a/src/audio/stream_sound_source.cpp +++ b/src/audio/stream_sound_source.cpp @@ -78,8 +78,8 @@ StreamSoundSource::update() if(!playing()) { if(processed == 0 || !looping) return; - - // we might have to restart the source if we had a buffer underrun + + // we might have to restart the source if we had a buffer underrun log_info << "Restarting audio source because of buffer underrun" << std::endl; play(); } @@ -142,4 +142,3 @@ StreamSoundSource::fillBufferAndQueue(ALuint buffer) // return false if there aren't more buffers to fill return bytesread >= STREAMFRAGMENTSIZE; } - diff --git a/src/audio/stream_sound_source.hpp b/src/audio/stream_sound_source.hpp index de1dbc05c..aa621b39f 100644 --- a/src/audio/stream_sound_source.hpp +++ b/src/audio/stream_sound_source.hpp @@ -51,11 +51,11 @@ public: { return looping; } - + private: static const size_t STREAMBUFFERSIZE = 1024 * 500; static const size_t STREAMFRAGMENTS = 5; - static const size_t STREAMFRAGMENTSIZE + static const size_t STREAMFRAGMENTSIZE = STREAMBUFFERSIZE / STREAMFRAGMENTS; bool fillBufferAndQueue(ALuint buffer); @@ -69,4 +69,3 @@ private: }; #endif - diff --git a/src/badguy/angrystone.cpp b/src/badguy/angrystone.cpp index bcf6d90f8..865e43061 100644 --- a/src/badguy/angrystone.cpp +++ b/src/badguy/angrystone.cpp @@ -59,7 +59,7 @@ AngryStone::collision_solid(const CollisionHit& hit) // TODO (void) hit; #if 0 - if ((state == ATTACKING) && + if ((state == ATTACKING) && (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) { state = IDLE; sprite->set_action("idle"); @@ -89,7 +89,7 @@ AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& ) return FORCE_MOVE; } -void +void AngryStone::active_update(float elapsed_time) { BadGuy::active_update(elapsed_time); diff --git a/src/badguy/angrystone.hpp b/src/badguy/angrystone.hpp index 3b1c97467..7abd8f18f 100644 --- a/src/badguy/angrystone.hpp +++ b/src/badguy/angrystone.hpp @@ -50,7 +50,7 @@ protected: RECOVERING }; AngryStoneState state; - + }; #endif diff --git a/src/badguy/badguy.cpp b/src/badguy/badguy.cpp index a74cce2c2..f0d5eacf5 100644 --- a/src/badguy/badguy.cpp +++ b/src/badguy/badguy.cpp @@ -34,7 +34,7 @@ static const float X_OFFSCREEN_DISTANCE = 1600; static const float Y_OFFSCREEN_DISTANCE = 1200; BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer) - : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false) + : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false) { start_position = bbox.p1; @@ -93,7 +93,7 @@ BadGuy::update(float elapsed_time) if (state == STATE_ACTIVE) deactivate(); set_state(STATE_INACTIVE); } - + switch(state) { case STATE_ACTIVE: active_update(elapsed_time); @@ -125,11 +125,11 @@ BadGuy::str2dir( std::string dir_str ) return AUTO; if( dir_str == "left" ) return LEFT; - if( dir_str == "right" ) + if( dir_str == "right" ) return RIGHT; //default to "auto" - log_warning << "Badguy::str2dir: unknown direction \"" << dir_str << "\"" << std::endl;; + log_warning << "Badguy::str2dir: unknown direction \"" << dir_str << "\"" << std::endl;; return AUTO; } @@ -305,7 +305,7 @@ BadGuy::is_offscreen() { float scroll_x = Sector::current()->camera->get_translation().x; float scroll_y = Sector::current()->camera->get_translation().y; - + if(bbox.p2.x < scroll_x - X_OFFSCREEN_DISTANCE || bbox.p1.x > scroll_x + X_OFFSCREEN_DISTANCE || bbox.p2.y < scroll_y - Y_OFFSCREEN_DISTANCE @@ -325,7 +325,7 @@ BadGuy::try_activate() * the effect of having badguys suddenly popping up from nowhere. */ //Badguy left of screen - if (start_position.x > scroll_x - X_OFFSCREEN_DISTANCE && + if (start_position.x > scroll_x - X_OFFSCREEN_DISTANCE && start_position.x < scroll_x - bbox.get_width() && start_position.y > scroll_y - Y_OFFSCREEN_DISTANCE && start_position.y < scroll_y + Y_OFFSCREEN_DISTANCE) { @@ -377,7 +377,7 @@ BadGuy::try_activate() } set_state(STATE_ACTIVE); activate(); - } + } } bool @@ -400,7 +400,7 @@ BadGuy::might_fall(int height) return Sector::current()->is_free_space(Rect(x1, y1, x2, y2)); } -Player* +Player* BadGuy::get_nearest_player() { // FIXME: does not really return nearest player @@ -414,7 +414,7 @@ BadGuy::get_nearest_player() return 0; } -void +void BadGuy::update_on_ground_flag(const CollisionHit& hit) { if (hit.bottom) on_ground_flag = true; @@ -425,4 +425,3 @@ BadGuy::on_ground() { return on_ground_flag; } - diff --git a/src/badguy/badguy.hpp b/src/badguy/badguy.hpp index 51521397a..d5cf8739e 100644 --- a/src/badguy/badguy.hpp +++ b/src/badguy/badguy.hpp @@ -88,7 +88,7 @@ public: { start_position = vec; } - + /** Count this badguy to the statistics? This value should not be changed * during runtime. */ bool countMe; @@ -101,14 +101,14 @@ protected: STATE_SQUISHED, STATE_FALLING }; - + /** Called when the badguy collided with a player */ virtual HitResponse collision_player(Player& player, const CollisionHit& hit); /** Called when the badguy collided with solid ground */ virtual void collision_solid(const CollisionHit& hit); /** Called when the badguy collided with another badguy */ virtual HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit); - + /** Called when the player hit the badguy from above. You should return true * if the badguy was squished, false if squishing wasn't possible */ @@ -135,12 +135,12 @@ protected: void set_state(State state); State get_state() const { return state; } - + /** * returns a pointer to the nearest player or 0 if no player is available */ Player* get_nearest_player(); - + Physic physic; /// is the enemy activated @@ -170,7 +170,7 @@ protected: /** * Get Direction from String. - */ + */ Direction str2dir( std::string dir_str ); /** @@ -187,11 +187,10 @@ protected: private: void try_activate(); - + State state; Timer state_timer; bool on_ground_flag; }; #endif - diff --git a/src/badguy/bomb.cpp b/src/badguy/bomb.cpp index c9e2c8a61..c26fe15b1 100644 --- a/src/badguy/bomb.cpp +++ b/src/badguy/bomb.cpp @@ -96,7 +96,7 @@ Bomb::active_update(float ) remove_me(); } break; - } + } } void @@ -129,4 +129,3 @@ Bomb::kill_fall() if (state != STATE_EXPLODING) // we don't want it exploding again explode(); } - diff --git a/src/badguy/bomb.hpp b/src/badguy/bomb.hpp index 40b29d08d..430c270d0 100644 --- a/src/badguy/bomb.hpp +++ b/src/badguy/bomb.hpp @@ -41,11 +41,10 @@ private: STATE_TICKING, STATE_EXPLODING }; - + State state; std::auto_ptr ticking; }; #endif - diff --git a/src/badguy/bouncing_snowball.cpp b/src/badguy/bouncing_snowball.cpp index 616d63e5d..72d1acffc 100644 --- a/src/badguy/bouncing_snowball.cpp +++ b/src/badguy/bouncing_snowball.cpp @@ -26,7 +26,7 @@ static const float WALKSPEED = 80; BouncingSnowball::BouncingSnowball(const lisp::Lisp& reader) : BadGuy(reader, "images/creatures/bouncing_snowball/bouncing_snowball.sprite") -{ +{ } BouncingSnowball::BouncingSnowball(const Vector& pos, Direction d) @@ -72,7 +72,7 @@ BouncingSnowball::collision_solid(const CollisionHit& hit) } else if(hit.top) { physic.set_velocity_y(0); } - + if(hit.left || hit.right) { // left or right collision dir = dir == LEFT ? RIGHT : LEFT; sprite->set_action(dir == LEFT ? "left" : "right"); @@ -88,4 +88,3 @@ BouncingSnowball::collision_badguy(BadGuy& , const CollisionHit& hit) } IMPLEMENT_FACTORY(BouncingSnowball, "bouncingsnowball") - diff --git a/src/badguy/bouncing_snowball.hpp b/src/badguy/bouncing_snowball.hpp index b2265909c..371d60abc 100644 --- a/src/badguy/bouncing_snowball.hpp +++ b/src/badguy/bouncing_snowball.hpp @@ -40,4 +40,3 @@ protected: }; #endif - diff --git a/src/badguy/dart.cpp b/src/badguy/dart.cpp index 992d7749c..393474e31 100644 --- a/src/badguy/dart.cpp +++ b/src/badguy/dart.cpp @@ -28,7 +28,7 @@ namespace { static const std::string SOUNDFILE = "sounds/flame.wav"; -Dart::Dart(const lisp::Lisp& reader) +Dart::Dart(const lisp::Lisp& reader) : BadGuy(reader, "images/creatures/dart/dart.sprite"), parent(0) { physic.enable_gravity(false); @@ -58,7 +58,7 @@ Dart::~Dart() { } -bool +bool Dart::updatePointers(const GameObject* from_object, GameObject* to_object) { if (from_object == parent) { @@ -79,7 +79,7 @@ Dart::write(lisp::Writer& writer) void Dart::activate() -{ +{ physic.set_velocity_x(dir == LEFT ? -::SPEED : ::SPEED); sprite->set_action(dir == LEFT ? "flying-left" : "flying-right"); @@ -93,12 +93,12 @@ Dart::activate() void Dart::deactivate() -{ +{ sound_source.reset(); remove_me(); } -void +void Dart::active_update(float elapsed_time) { BadGuy::active_update(elapsed_time); @@ -112,7 +112,7 @@ Dart::collision_solid(const CollisionHit& ) remove_me(); } -HitResponse +HitResponse Dart::collision_badguy(BadGuy& badguy, const CollisionHit& ) { // ignore collisions with parent @@ -125,7 +125,7 @@ Dart::collision_badguy(BadGuy& badguy, const CollisionHit& ) return ABORT_MOVE; } -HitResponse +HitResponse Dart::collision_player(Player& player, const CollisionHit& hit) { sound_manager->play("sounds/stomp.wav", get_pos()); @@ -134,4 +134,3 @@ Dart::collision_player(Player& player, const CollisionHit& hit) } IMPLEMENT_FACTORY(Dart, "dart") - diff --git a/src/badguy/dart.hpp b/src/badguy/dart.hpp index bfed41fe2..bbab1df0f 100644 --- a/src/badguy/dart.hpp +++ b/src/badguy/dart.hpp @@ -54,4 +54,3 @@ protected: }; #endif - diff --git a/src/badguy/darttrap.cpp b/src/badguy/darttrap.cpp index abada3ba3..9bb2eaa3a 100644 --- a/src/badguy/darttrap.cpp +++ b/src/badguy/darttrap.cpp @@ -26,7 +26,7 @@ namespace { const float MUZZLE_Y = 28; /**< [px] muzzle y-offset from top */ } -DartTrap::DartTrap(const lisp::Lisp& reader) +DartTrap::DartTrap(const lisp::Lisp& reader) : BadGuy(reader, "images/creatures/darttrap/darttrap.sprite", LAYER_TILES-1), initial_delay(0), fire_delay(2), ammo(-1), state(IDLE) { reader.get("initial-delay", initial_delay); @@ -60,7 +60,7 @@ DartTrap::activate() fire_timer.start(initial_delay); } -HitResponse +HitResponse DartTrap::collision_player(Player& , const CollisionHit& ) { return ABORT_MOVE; @@ -105,4 +105,3 @@ DartTrap::fire() } IMPLEMENT_FACTORY(DartTrap, "darttrap") - diff --git a/src/badguy/darttrap.hpp b/src/badguy/darttrap.hpp index b891de432..7f2b80ebc 100644 --- a/src/badguy/darttrap.hpp +++ b/src/badguy/darttrap.hpp @@ -45,7 +45,7 @@ protected: void load(); /**< load a shot */ void fire(); /**< fire a shot */ - + float initial_delay; /**< time to wait before firing first shot */ float fire_delay; /**< reload time */ int ammo; /**< ammo left (-1 means unlimited) */ @@ -55,4 +55,3 @@ protected: }; #endif - diff --git a/src/badguy/dispenser.cpp b/src/badguy/dispenser.cpp index 1bcf021da..0483bb12e 100644 --- a/src/badguy/dispenser.cpp +++ b/src/badguy/dispenser.cpp @@ -58,7 +58,7 @@ Dispenser::write(lisp::Writer& writer) void Dispenser::activate() -{ +{ dispense_timer.start(cycle, true); launch_badguy(); } diff --git a/src/badguy/dispenser.hpp b/src/badguy/dispenser.hpp index f79e8e6d0..c01e19e1d 100644 --- a/src/badguy/dispenser.hpp +++ b/src/badguy/dispenser.hpp @@ -43,4 +43,3 @@ protected: }; #endif - diff --git a/src/badguy/fish.cpp b/src/badguy/fish.cpp index 4f2377843..b60312509 100644 --- a/src/badguy/fish.cpp +++ b/src/badguy/fish.cpp @@ -107,10 +107,10 @@ Fish::active_update(float elapsed_time) if(waiting.check()) { jump(); } - + // set sprite sprite->set_action(physic.get_velocity_y() < 0 ? "normal" : "down"); - + // we can't afford flying out of the tilemap, 'cause the engine would remove us. if ((get_pos().y - 31.8) < 0) // too high, let us fall { diff --git a/src/badguy/fish.hpp b/src/badguy/fish.hpp index 117d1d513..413b5c27e 100644 --- a/src/badguy/fish.hpp +++ b/src/badguy/fish.hpp @@ -43,7 +43,7 @@ private: HitResponse hit(const CollisionHit& ); void start_waiting(); void jump(); - + Timer waiting; float stop_y; /**< y-coordinate to stop at */ }; diff --git a/src/badguy/flame.cpp b/src/badguy/flame.cpp index 9acd1c64a..85e470cf9 100644 --- a/src/badguy/flame.cpp +++ b/src/badguy/flame.cpp @@ -84,4 +84,3 @@ Flame::kill_fall() } IMPLEMENT_FACTORY(Flame, "flame") - diff --git a/src/badguy/flame.hpp b/src/badguy/flame.hpp index b099eae5d..ac8a8fc7b 100644 --- a/src/badguy/flame.hpp +++ b/src/badguy/flame.hpp @@ -43,4 +43,3 @@ private: }; #endif - diff --git a/src/badguy/flyingsnowball.cpp b/src/badguy/flyingsnowball.cpp index 66a2db504..517f6b90a 100644 --- a/src/badguy/flyingsnowball.cpp +++ b/src/badguy/flyingsnowball.cpp @@ -57,7 +57,7 @@ FlyingSnowBall::write(lisp::Writer& writer) writer.end_list("flyingsnowball"); } -void +void FlyingSnowBall::activate() { sprite->set_action(dir == LEFT ? "left" : "right"); @@ -84,7 +84,7 @@ FlyingSnowBall::collision_solid(const CollisionHit& hit) } void -FlyingSnowBall::active_update(float elapsed_time) +FlyingSnowBall::active_update(float elapsed_time) { if(timer.check()) { if(mode == FLY_UP) { @@ -93,7 +93,7 @@ FlyingSnowBall::active_update(float elapsed_time) // stop puffing puff_timer.stop(); - + } else if(mode == FLY_DOWN) { mode = FLY_UP; physic.set_velocity_y(FLYSPEED); diff --git a/src/badguy/flyingsnowball.hpp b/src/badguy/flyingsnowball.hpp index 7e78c5266..9b244347c 100644 --- a/src/badguy/flyingsnowball.hpp +++ b/src/badguy/flyingsnowball.hpp @@ -48,4 +48,3 @@ private: }; #endif - diff --git a/src/badguy/igel.cpp b/src/badguy/igel.cpp index f43aea297..245106586 100644 --- a/src/badguy/igel.cpp +++ b/src/badguy/igel.cpp @@ -98,7 +98,7 @@ Igel::active_update(float elapsed_time) BadGuy::active_update(elapsed_time); return; } - + // else adhere to default behaviour WalkingBadguy::active_update(elapsed_time); } diff --git a/src/badguy/igel.hpp b/src/badguy/igel.hpp index 6da2df1ff..0c83cef38 100644 --- a/src/badguy/igel.hpp +++ b/src/badguy/igel.hpp @@ -51,4 +51,3 @@ private: }; #endif - diff --git a/src/badguy/jumpy.cpp b/src/badguy/jumpy.cpp index 233a672ac..012adaa5c 100644 --- a/src/badguy/jumpy.cpp +++ b/src/badguy/jumpy.cpp @@ -62,7 +62,7 @@ Jumpy::hit(const CollisionHit& chit) pos_groundhit = get_pos(); groundhit_pos_set = true; } - + physic.set_velocity_y(JUMPSPEED); // TODO create a nice sound for this... //sound_manager->play("sounds/skid.wav"); @@ -77,19 +77,19 @@ void Jumpy::active_update(float elapsed_time) { BadGuy::active_update(elapsed_time); - + Player* player = this->get_nearest_player(); if (player) { dir = (player->get_pos().x > get_pos().x) ? RIGHT : LEFT; } - + if (!groundhit_pos_set) { sprite->set_action(dir == LEFT ? "left-middle" : "right-middle"); return; } - + if ( get_pos().y < (pos_groundhit.y - JUMPY_MID_TOLERANCE ) ) sprite->set_action(dir == LEFT ? "left-up" : "right-up"); else if ( get_pos().y >= (pos_groundhit.y - JUMPY_MID_TOLERANCE) && diff --git a/src/badguy/jumpy.hpp b/src/badguy/jumpy.hpp index 494559b4a..fa39085d6 100644 --- a/src/badguy/jumpy.hpp +++ b/src/badguy/jumpy.hpp @@ -42,4 +42,3 @@ private: }; #endif - diff --git a/src/badguy/kugelblitz.cpp b/src/badguy/kugelblitz.cpp index e9fac1519..c6242e6ad 100644 --- a/src/badguy/kugelblitz.cpp +++ b/src/badguy/kugelblitz.cpp @@ -150,7 +150,7 @@ Kugelblitz::active_update(float elapsed_time) } */ } - BadGuy::active_update(elapsed_time); + BadGuy::active_update(elapsed_time); } void diff --git a/src/badguy/kugelblitz.hpp b/src/badguy/kugelblitz.hpp index 2e7b3ee71..5f327f29e 100644 --- a/src/badguy/kugelblitz.hpp +++ b/src/badguy/kugelblitz.hpp @@ -54,4 +54,3 @@ private: }; #endif - diff --git a/src/badguy/mrbomb.cpp b/src/badguy/mrbomb.cpp index 90db30f06..0cbb71ea4 100644 --- a/src/badguy/mrbomb.cpp +++ b/src/badguy/mrbomb.cpp @@ -37,7 +37,7 @@ MrBomb::MrBomb(const lisp::Lisp& reader) sprite_name = "images/creatures/mr_cherry/juicebox.sprite"; return; } - //Replace sprite + //Replace sprite sprite = sprite_manager->create( sprite_name ); } diff --git a/src/badguy/mrbomb.hpp b/src/badguy/mrbomb.hpp index 63c436493..845c063a3 100644 --- a/src/badguy/mrbomb.hpp +++ b/src/badguy/mrbomb.hpp @@ -38,4 +38,3 @@ protected: }; #endif - diff --git a/src/badguy/mriceblock.cpp b/src/badguy/mriceblock.cpp index 472aa1757..0e46ba619 100644 --- a/src/badguy/mriceblock.cpp +++ b/src/badguy/mriceblock.cpp @@ -31,7 +31,7 @@ MrIceBlock::MrIceBlock(const lisp::Lisp& reader) : WalkingBadguy(reader, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"), ice_state(ICESTATE_NORMAL), squishcount(0) { walk_speed = 80; - max_drop_height = 600; + max_drop_height = 600; sound_manager->preload("sounds/iceblock_bump.wav"); sound_manager->preload("sounds/stomp.wav"); sound_manager->preload("sounds/kick.wav"); @@ -40,8 +40,8 @@ MrIceBlock::MrIceBlock(const lisp::Lisp& reader) MrIceBlock::MrIceBlock(const Vector& pos, Direction d) : WalkingBadguy(pos, d, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"), ice_state(ICESTATE_NORMAL), squishcount(0) { - walk_speed = 80; - max_drop_height = 600; + walk_speed = 80; + max_drop_height = 600; sound_manager->preload("sounds/iceblock_bump.wav"); sound_manager->preload("sounds/stomp.wav"); sound_manager->preload("sounds/kick.wav"); @@ -151,7 +151,7 @@ MrIceBlock::collision_player(Player& player, const CollisionHit& hit) return FORCE_MOVE; } } - + return BadGuy::collision_player(player, hit); } @@ -209,7 +209,7 @@ MrIceBlock::set_state(IceState state) { if(ice_state == state) return; - + if(state == ICESTATE_FLAT) flags |= FLAG_PORTABLE; else @@ -222,8 +222,8 @@ MrIceBlock::set_state(IceState state) case ICESTATE_FLAT: sound_manager->play("sounds/stomp.wav", get_pos()); physic.set_velocity_x(0); - physic.set_velocity_y(0); - + physic.set_velocity_y(0); + sprite->set_action(dir == LEFT ? "flat-left" : "flat-right"); flat_timer.start(4); break; diff --git a/src/badguy/mriceblock.hpp b/src/badguy/mriceblock.hpp index 98c4225d1..26546c4e8 100644 --- a/src/badguy/mriceblock.hpp +++ b/src/badguy/mriceblock.hpp @@ -37,7 +37,7 @@ public: HitResponse collision_player(Player& player, const CollisionHit& hit); void active_update(float elapsed_time); - + void grab(MovingObject& object, const Vector& pos, Direction dir); void ungrab(MovingObject& object, Direction dir); bool can_break(); @@ -56,11 +56,10 @@ private: }; void set_state(IceState state); - + IceState ice_state; Timer flat_timer; int squishcount; }; #endif - diff --git a/src/badguy/mrrocket.hpp b/src/badguy/mrrocket.hpp index 77a7634c4..11ae037a5 100644 --- a/src/badguy/mrrocket.hpp +++ b/src/badguy/mrrocket.hpp @@ -43,4 +43,3 @@ protected: }; #endif - diff --git a/src/badguy/mrtree.cpp b/src/badguy/mrtree.cpp index 7b8763f25..775c82102 100644 --- a/src/badguy/mrtree.cpp +++ b/src/badguy/mrtree.cpp @@ -63,7 +63,7 @@ MrTree::collision_squished(Player& player) // give Feedback sound_manager->play("sounds/mr_tree.ogg", get_pos()); player.bounce(*this); - + // spawn some particles // TODO: provide convenience function in MovingSprite or MovingObject? for (int px = (int)stumpy->get_bbox().p1.x; px < (int)stumpy->get_bbox().p2.x; px+=10) { @@ -85,7 +85,7 @@ MrTree::collision_squished(Player& player) leaf1 = leaf1; Sector::current()->add_object(leaf1); } - + // spawn PoisonIvy Vector leaf2_pos = Vector(stumpy_pos.x + sprite->get_current_hitbox_width() + 1, stumpy_pos.y - POISONIVY_Y_OFFSET); Rect leaf2_bbox = Rect(leaf2_pos.x, leaf2_pos.y, leaf2_pos.x + POISONIVY_WIDTH, leaf2_pos.y + POISONIVY_HEIGHT); @@ -99,4 +99,3 @@ MrTree::collision_squished(Player& player) } IMPLEMENT_FACTORY(MrTree, "mrtree") - diff --git a/src/badguy/plant.cpp b/src/badguy/plant.cpp index 91cb1c92b..5830d2b01 100644 --- a/src/badguy/plant.cpp +++ b/src/badguy/plant.cpp @@ -78,7 +78,7 @@ Plant::collision_badguy(BadGuy& , const CollisionHit& hit) return CONTINUE; } -void +void Plant::active_update(float elapsed_time) { BadGuy::active_update(elapsed_time); diff --git a/src/badguy/plant.hpp b/src/badguy/plant.hpp index 75d77e300..7216514e6 100644 --- a/src/badguy/plant.hpp +++ b/src/badguy/plant.hpp @@ -44,7 +44,7 @@ protected: PLANT_WALKING }; PlantState state; - + }; #endif diff --git a/src/badguy/rocketexplosion.cpp b/src/badguy/rocketexplosion.cpp index 4e0520c2f..2c24ccb34 100644 --- a/src/badguy/rocketexplosion.cpp +++ b/src/badguy/rocketexplosion.cpp @@ -70,4 +70,3 @@ void RocketExplosion::kill_fall() { } - diff --git a/src/badguy/rocketexplosion.hpp b/src/badguy/rocketexplosion.hpp index 873d83b31..e334dc830 100644 --- a/src/badguy/rocketexplosion.hpp +++ b/src/badguy/rocketexplosion.hpp @@ -41,4 +41,3 @@ private: }; #endif - diff --git a/src/badguy/skullyhop.cpp b/src/badguy/skullyhop.cpp index 63e6435de..a1fab8462 100644 --- a/src/badguy/skullyhop.cpp +++ b/src/badguy/skullyhop.cpp @@ -103,7 +103,7 @@ SkullyHop::collision_solid(const CollisionHit& hit) set_state(STANDING); } // check if we hit the roof while climbing - if(hit.top) { + if(hit.top) { physic.set_velocity_y(0); } @@ -139,7 +139,7 @@ SkullyHop::active_update(float elapsed_time) if ((state == CHARGING) && (sprite->animation_done())) { set_state(JUMPING); return; - } + } } IMPLEMENT_FACTORY(SkullyHop, "skullyhop") diff --git a/src/badguy/skullyhop.hpp b/src/badguy/skullyhop.hpp index 805cf3541..1ceab05b0 100644 --- a/src/badguy/skullyhop.hpp +++ b/src/badguy/skullyhop.hpp @@ -55,4 +55,3 @@ protected: }; #endif - diff --git a/src/badguy/snail.cpp b/src/badguy/snail.cpp index cb34a8f1f..e40a24dae 100644 --- a/src/badguy/snail.cpp +++ b/src/badguy/snail.cpp @@ -78,10 +78,10 @@ Snail::be_flat() state = STATE_FLAT; sprite->set_action(dir == LEFT ? "flat-left" : "flat-right"); sprite->set_fps(64); - + physic.set_velocity_x(0); - physic.set_velocity_y(0); - + physic.set_velocity_y(0); + flat_timer.start(4); } @@ -93,8 +93,8 @@ Snail::be_kicked() sprite->set_fps(64); physic.set_velocity_x(0); - physic.set_velocity_y(0); - + physic.set_velocity_y(0); + // start a timer to delay addition of upward movement until we are (hopefully) out from under the player kicked_delay_timer.start(0.05); } @@ -183,7 +183,7 @@ Snail::collision_solid(const CollisionHit& hit) } break; } - + } HitResponse @@ -221,7 +221,7 @@ Snail::collision_squished(Player& player) sound_manager->play("sounds/stomp.wav", get_pos()); be_flat(); break; - + case STATE_FLAT: sound_manager->play("sounds/kick.wav", get_pos()); @@ -235,7 +235,7 @@ Snail::collision_squished(Player& player) case STATE_KICKED_DELAY: break; - + } player.bounce(*this); diff --git a/src/badguy/snail.hpp b/src/badguy/snail.hpp index 7427f02cd..0e804090e 100644 --- a/src/badguy/snail.hpp +++ b/src/badguy/snail.hpp @@ -61,4 +61,3 @@ private: }; #endif - diff --git a/src/badguy/snowball.hpp b/src/badguy/snowball.hpp index bdb9b57ad..a68bc3eec 100644 --- a/src/badguy/snowball.hpp +++ b/src/badguy/snowball.hpp @@ -37,4 +37,3 @@ protected: }; #endif - diff --git a/src/badguy/spidermite.cpp b/src/badguy/spidermite.cpp index 70feda769..42210d2b2 100644 --- a/src/badguy/spidermite.cpp +++ b/src/badguy/spidermite.cpp @@ -48,7 +48,7 @@ SpiderMite::write(lisp::Writer& writer) writer.end_list("spidermite"); } -void +void SpiderMite::activate() { sprite->set_action(dir == LEFT ? "left" : "right"); @@ -74,7 +74,7 @@ SpiderMite::collision_solid(const CollisionHit& hit) } void -SpiderMite::active_update(float elapsed_time) +SpiderMite::active_update(float elapsed_time) { if(timer.check()) { if(mode == FLY_UP) { diff --git a/src/badguy/spidermite.hpp b/src/badguy/spidermite.hpp index 84f313d51..91333aa87 100644 --- a/src/badguy/spidermite.hpp +++ b/src/badguy/spidermite.hpp @@ -47,4 +47,3 @@ private: }; #endif - diff --git a/src/badguy/sspiky.cpp b/src/badguy/sspiky.cpp index 292767f3c..c81ea1d79 100644 --- a/src/badguy/sspiky.cpp +++ b/src/badguy/sspiky.cpp @@ -65,7 +65,7 @@ SSpiky::collision_badguy(BadGuy& badguy, const CollisionHit& hit) return WalkingBadguy::collision_badguy(badguy, hit); } -void +void SSpiky::active_update(float elapsed_time) { if(state == SSPIKY_WALKING) { @@ -91,7 +91,7 @@ SSpiky::active_update(float elapsed_time) { state = SSPIKY_WAKING; } } - + BadGuy::active_update(elapsed_time); } diff --git a/src/badguy/stalactite.cpp b/src/badguy/stalactite.cpp index 289135b60..c0fd7be98 100644 --- a/src/badguy/stalactite.cpp +++ b/src/badguy/stalactite.cpp @@ -73,7 +73,7 @@ Stalactite::collision_solid(const CollisionHit& hit) { if(state != STALACTITE_FALLING && state != STALACTITE_SQUISHED) return; - + if(hit.bottom) { // hit floor? state = STALACTITE_SQUISHED; set_group(COLGROUP_MOVING_ONLY_STATIC); @@ -104,7 +104,7 @@ Stalactite::draw(DrawingContext& context) { if(get_state() != STATE_ACTIVE) return; - + if(state == STALACTITE_SHAKING) { sprite->draw(context, get_pos() + Vector(systemRandom.rand(-3,3), 0), LAYER_OBJECTS); } else { diff --git a/src/badguy/stalactite.hpp b/src/badguy/stalactite.hpp index 74803c284..ef48ede79 100644 --- a/src/badguy/stalactite.hpp +++ b/src/badguy/stalactite.hpp @@ -26,7 +26,7 @@ class Stalactite : public BadGuy { public: Stalactite(const lisp::Lisp& reader); - + void active_update(float elapsed_time); void write(lisp::Writer& writer); void collision_solid(const CollisionHit& hit); @@ -51,4 +51,3 @@ protected: }; #endif - diff --git a/src/badguy/stumpy.cpp b/src/badguy/stumpy.cpp index 342879fd8..282b3a635 100644 --- a/src/badguy/stumpy.cpp +++ b/src/badguy/stumpy.cpp @@ -164,4 +164,3 @@ Stumpy::collision_badguy(BadGuy& badguy, const CollisionHit& hit) } IMPLEMENT_FACTORY(Stumpy, "stumpy") - diff --git a/src/badguy/stumpy.hpp b/src/badguy/stumpy.hpp index a3bd2038b..25ca246da 100644 --- a/src/badguy/stumpy.hpp +++ b/src/badguy/stumpy.hpp @@ -43,7 +43,7 @@ protected: MyState mystate; Timer invincible_timer; - + bool collision_squished(Player& player); }; diff --git a/src/badguy/totem.cpp b/src/badguy/totem.cpp index b20991496..279038ba7 100644 --- a/src/badguy/totem.cpp +++ b/src/badguy/totem.cpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux - "Totem" Badguy // Copyright (C) 2006 Christoph Sommer // @@ -12,7 +12,7 @@ // 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 @@ -42,13 +42,13 @@ Totem::Totem(const Totem& other) sound_manager->preload( LAND_ON_TOTEM_SOUND ); } -Totem::~Totem() +Totem::~Totem() { if (carrying) carrying->jump_off(); if (carried_by) jump_off(); } -bool +bool Totem::updatePointers(const GameObject* from_object, GameObject* to_object) { if (from_object == carrying) { @@ -101,14 +101,14 @@ Totem::active_update(float elapsed_time) Sector* s = Sector::current(); if (s) { - // jump a bit if we find a suitable totem + // jump a bit if we find a suitable totem for (std::vector::iterator i = s->moving_objects.begin(); i != s->moving_objects.end(); i++) { Totem* t = dynamic_cast(*i); if (!t) continue; - + // skip if we are not approaching each other if (!((this->dir == LEFT) && (t->dir == RIGHT))) continue; - + Vector p1 = this->get_pos(); Vector p2 = t->get_pos(); @@ -165,7 +165,7 @@ Totem::collision_solid(const CollisionHit& hit) return; } - // If we hit something from above or below: stop moving in this direction + // If we hit something from above or below: stop moving in this direction if (hit.top || hit.bottom) { physic.set_velocity_y(0); } @@ -189,7 +189,7 @@ Totem::collision_badguy(BadGuy& badguy, const CollisionHit& hit) carried_by->collision_badguy(badguy, hit); return CONTINUE; } - + // if we hit a Totem that is not from our stack: have our base jump on its top Totem* totem = dynamic_cast(&badguy); if (totem) { @@ -223,23 +223,23 @@ Totem::kill_fall() BadGuy::kill_fall(); } -void +void Totem::jump_on(Totem* target) { if (target->carrying) { log_warning << "target is already carrying someone" << std::endl; return; } - + target->carrying = this; this->carried_by = target; this->activate(); bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); - + sound_manager->play( LAND_ON_TOTEM_SOUND , get_pos()); - + this->synchronize_with(target); } @@ -261,7 +261,7 @@ Totem::jump_off() { physic.set_velocity_y(JUMP_OFF_SPEED_Y); } -void +void Totem::synchronize_with(Totem* base) { @@ -269,7 +269,7 @@ Totem::synchronize_with(Totem* base) dir = base->dir; sprite->set_action(dir == LEFT ? "stacked-left" : "stacked-right"); } - + Vector pos = base->get_pos(); pos.y -= sprite->get_current_hitbox_height(); set_pos(pos); @@ -280,4 +280,3 @@ Totem::synchronize_with(Totem* base) IMPLEMENT_FACTORY(Totem, "totem") - diff --git a/src/badguy/totem.hpp b/src/badguy/totem.hpp index 044c000c0..89ef732aa 100644 --- a/src/badguy/totem.hpp +++ b/src/badguy/totem.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux - "Totem" Badguy // Copyright (C) 2006 Christoph Sommer // @@ -12,7 +12,7 @@ // 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 @@ -56,4 +56,3 @@ protected: }; #endif - diff --git a/src/badguy/walking_badguy.cpp b/src/badguy/walking_badguy.cpp index 110511095..66cc3f99b 100644 --- a/src/badguy/walking_badguy.cpp +++ b/src/badguy/walking_badguy.cpp @@ -73,11 +73,11 @@ WalkingBadguy::collision_solid(const CollisionHit& hit) update_on_ground_flag(hit); - if (hit.top || hit.bottom) { + if (hit.top || hit.bottom) { physic.set_velocity_y(0); } - if ((hit.left && dir == LEFT) || (hit.right && dir == RIGHT)) { + if ((hit.left && dir == LEFT) || (hit.right && dir == RIGHT)) { turn_around(); } @@ -87,7 +87,7 @@ HitResponse WalkingBadguy::collision_badguy(BadGuy& , const CollisionHit& hit) { - if ((hit.left && (dir == LEFT)) || (hit.right && (dir == RIGHT))) { + if ((hit.left && (dir == LEFT)) || (hit.right && (dir == RIGHT))) { turn_around(); } @@ -101,4 +101,3 @@ WalkingBadguy::turn_around() sprite->set_action(dir == LEFT ? walk_left_action : walk_right_action); physic.set_velocity_x(dir == LEFT ? -walk_speed : walk_speed); } - diff --git a/src/badguy/walking_badguy.hpp b/src/badguy/walking_badguy.hpp index 98d694fb2..6f023a833 100644 --- a/src/badguy/walking_badguy.hpp +++ b/src/badguy/walking_badguy.hpp @@ -39,7 +39,7 @@ public: HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit); protected: - void turn_around(); + void turn_around(); std::string walk_left_action; std::string walk_right_action; diff --git a/src/badguy/willowisp.cpp b/src/badguy/willowisp.cpp index 6480c1675..6e069e8c3 100644 --- a/src/badguy/willowisp.cpp +++ b/src/badguy/willowisp.cpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux - "Will-O-Wisp" Badguy // Copyright (C) 2006 Christoph Sommer // @@ -12,7 +12,7 @@ // 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 @@ -55,12 +55,12 @@ void WillOWisp::draw(DrawingContext& context) { sprite->draw(context, get_pos(), layer); - + context.push_target(); context.set_target(DrawingContext::LIGHTMAP); sprite->draw(context, get_pos(), layer); - + context.pop_target(); } @@ -78,7 +78,7 @@ WillOWisp::active_update(float elapsed_time) mystate = STATE_TRACKING; } } - + if (mystate == STATE_TRACKING) { if (dist.norm() <= VANISH_RANGE) { Vector dir = dist.unit(); @@ -101,7 +101,7 @@ WillOWisp::active_update(float elapsed_time) remove_me(); } } - + } void @@ -156,4 +156,3 @@ WillOWisp::collision_player(Player& player, const CollisionHit& ) { } IMPLEMENT_FACTORY(WillOWisp, "willowisp") - diff --git a/src/badguy/willowisp.hpp b/src/badguy/willowisp.hpp index ced723088..51bdc1f77 100644 --- a/src/badguy/willowisp.hpp +++ b/src/badguy/willowisp.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux - "Will-O-Wisp" Badguy // Copyright (C) 2006 Christoph Sommer // @@ -12,7 +12,7 @@ // 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 @@ -53,4 +53,3 @@ private: }; #endif - diff --git a/src/badguy/yeti.cpp b/src/badguy/yeti.cpp index 909fbe22c..2b18b98ba 100644 --- a/src/badguy/yeti.cpp +++ b/src/badguy/yeti.cpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux - Boss "Yeti" // Copyright (C) 2005 Matthias Braun // Copyright (C) 2006 Christoph Sommer @@ -13,7 +13,7 @@ // 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 @@ -42,7 +42,7 @@ namespace { const float STOMP_VY = -250; /** vertical speed while stomping on the dais */ const float LEFT_STAND_X = 16; /**< x-coordinate of left dais' end position */ - const float RIGHT_STAND_X = 800-60-16; /**< x-coordinate of right dais' end position */ + const float RIGHT_STAND_X = 800-60-16; /**< x-coordinate of right dais' end position */ const float LEFT_JUMP_X = LEFT_STAND_X+224; /**< x-coordinate of from where to jump on the left dais */ const float RIGHT_JUMP_X = RIGHT_STAND_X-224; /**< x-coordinate of from where to jump on the right dais */ const float STOMP_WAIT = .5; /**< time we stay on the dais before jumping again */ @@ -191,7 +191,7 @@ void Yeti::take_hit(Player& ) physic.enable_gravity(true); physic.set_velocity_x(0); physic.set_velocity_y(0); - + state = SQUISHED; state_timer.start(SQUISH_TIME); set_group(COLGROUP_MOVING_ONLY_STATIC); @@ -249,7 +249,7 @@ Yeti::drop_stalactite() i != sector->gameobjects.end(); ++i) { YetiStalactite* stalactite = dynamic_cast (*i); if(stalactite && stalactite->is_hanging()) { - float sdist + float sdist = fabsf(stalactite->get_pos().x - player->get_pos().x); if(sdist < dist) { nearest = stalactite; @@ -265,7 +265,7 @@ Yeti::drop_stalactite() void Yeti::collision_solid(const CollisionHit& hit) { - if(hit.top || hit.bottom) { + if(hit.top || hit.bottom) { // hit floor or roof physic.set_velocity_y(0); switch (state) { diff --git a/src/badguy/yeti.hpp b/src/badguy/yeti.hpp index 74d8b1957..d7e16ce39 100644 --- a/src/badguy/yeti.hpp +++ b/src/badguy/yeti.hpp @@ -49,7 +49,7 @@ private: void jump_down(); void take_hit(Player& player); - + enum YetiState { JUMP_DOWN, RUN, @@ -66,4 +66,3 @@ private: }; #endif - diff --git a/src/badguy/yeti_stalactite.hpp b/src/badguy/yeti_stalactite.hpp index 40ead0d03..04897c0e8 100644 --- a/src/badguy/yeti_stalactite.hpp +++ b/src/badguy/yeti_stalactite.hpp @@ -38,4 +38,3 @@ public: }; #endif - diff --git a/src/badguy/zeekling.cpp b/src/badguy/zeekling.cpp index 4d7894331..85b2d471c 100644 --- a/src/badguy/zeekling.cpp +++ b/src/badguy/zeekling.cpp @@ -66,7 +66,7 @@ Zeekling::collision_squished(Player& player) return true; } -void +void Zeekling::onBumpHorizontal() { if (state == FLYING) { dir = (dir == LEFT ? RIGHT : LEFT); @@ -89,7 +89,7 @@ Zeekling::onBumpHorizontal() { } } -void +void Zeekling::onBumpVertical() { if (state == FLYING) { physic.set_velocity_y(0); @@ -109,7 +109,7 @@ void Zeekling::collision_solid(const CollisionHit& hit) { if(hit.top || hit.bottom) { - onBumpVertical(); + onBumpVertical(); } else if(hit.left || hit.right) { onBumpHorizontal(); } @@ -118,7 +118,7 @@ Zeekling::collision_solid(const CollisionHit& hit) /** * linear prediction of player and badguy positions to decide if we should enter the DIVING state */ -bool +bool Zeekling::should_we_dive() { const MovingObject* player = this->get_nearest_player(); if (!player) return false; @@ -144,7 +144,7 @@ Zeekling::should_we_dive() { // guess number of frames to descend to same height as player float estFrames = height / relSpeed; - + // guess where the player would be at this time float estPx = (playerPos.x + (estFrames * playerMov.x)); @@ -157,7 +157,7 @@ Zeekling::should_we_dive() { return false; } -void +void Zeekling::active_update(float elapsed_time) { if (state == FLYING) { if (should_we_dive()) { diff --git a/src/badguy/zeekling.hpp b/src/badguy/zeekling.hpp index 178423703..fd0f2871b 100644 --- a/src/badguy/zeekling.hpp +++ b/src/badguy/zeekling.hpp @@ -57,4 +57,3 @@ private: }; #endif - diff --git a/src/collision.cpp b/src/collision.cpp index 8ae5e91bf..e9c25fb38 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -52,7 +52,7 @@ namespace { { n = Vector(p2.y-p1.y, p1.x-p2.x); c = -(p2 * n); - float nval = n.norm(); + float nval = n.norm(); n /= nval; c /= nval; } @@ -93,8 +93,8 @@ bool rectangle_aatriangle(Constraints* constraints, const Rect& rect, break; default: assert(false); - } - + } + switch(triangle.dir & AATriangle::DIRECTION_MASK) { case AATriangle::SOUTHWEST: p1 = Vector(rect.p1.x, rect.p2.y); @@ -152,7 +152,7 @@ bool rectangle_aatriangle(Constraints* constraints, const Rect& rect, } constraints->hit.slope_normal = normal; } - + return true; } diff --git a/src/collision.hpp b/src/collision.hpp index cc5bcd0cc..73c966dc8 100644 --- a/src/collision.hpp +++ b/src/collision.hpp @@ -55,10 +55,10 @@ public: /** checks if 2 rectangle intersect each other */ bool intersects(const Rect& r1, const Rect& r2); - + /** does collision detection between a rectangle and an axis aligned triangle * Returns true in case of a collision and fills in the hit structure then. - */ + */ bool rectangle_aatriangle(Constraints* constraints, const Rect& rect, const AATriangle& triangle); @@ -68,4 +68,3 @@ void set_rectangle_rectangle_constraints(Constraints* constraints, } #endif - diff --git a/src/collision_hit.hpp b/src/collision_hit.hpp index ba29e9f82..02879039a 100644 --- a/src/collision_hit.hpp +++ b/src/collision_hit.hpp @@ -32,7 +32,7 @@ enum HitResponse /// don't move the object ABORT_MOVE = 0, /// move object out of collision and check for collisions again - /// if this happens to often then the move will just be aborted + /// if this happens to often then the move will just be aborted CONTINUE, /// do the move ignoring the collision FORCE_MOVE, @@ -67,4 +67,3 @@ public: }; #endif - diff --git a/src/console.cpp b/src/console.cpp index cc88905bc..d6b22388c 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -34,12 +34,12 @@ static const float FADE_SPEED = 1; Console::Console() - : history_position(history.end()), vm(NULL), backgroundOffset(0), + : history_position(history.end()), vm(NULL), backgroundOffset(0), height(0), alpha(1.0), offset(0), focused(false), stayOpen(0) { fontheight = 8; } -Console::~Console() +Console::~Console() { if(vm != NULL) { sq_release(Scripting::global_vm, &vm_object); @@ -56,8 +56,8 @@ Console::init_graphics() background2.reset(new Surface("images/engine/console2.png")); } -void -Console::flush(ConsoleStreamBuffer* buffer) +void +Console::flush(ConsoleStreamBuffer* buffer) { if (buffer == &outputBuffer) { std::string s = outputBuffer.str(); @@ -93,7 +93,7 @@ Console::ready_vm() throw Scripting::SquirrelError(vm, "Couldn't get vm object for console"); sq_addref(vm, &vm_object); sq_pop(vm, 1); - + // create new roottable for thread sq_newtable(new_vm); sq_pushroottable(new_vm); @@ -103,7 +103,7 @@ Console::ready_vm() sq_setroottable(new_vm); vm = new_vm; - + try { std::string filename = "scripts/console.nut"; IFileStream stream(filename); @@ -119,15 +119,15 @@ Console::execute_script(const std::string& command) { using namespace Scripting; - ready_vm(); + ready_vm(); - SQInteger oldtop = sq_gettop(vm); + SQInteger oldtop = sq_gettop(vm); try { if(SQ_FAILED(sq_compilebuffer(vm, command.c_str(), command.length(), "", SQTrue))) throw SquirrelError(vm, "Couldn't compile command"); - sq_pushroottable(vm); + sq_pushroottable(vm); if(SQ_FAILED(sq_call(vm, 1, SQTrue, SQTrue))) throw SquirrelError(vm, "Problem while executing command"); @@ -244,7 +244,7 @@ sq_insert_commands(std::list& cmds, HSQUIRRELVM vm, std::string tab } -} +} // End of Console::autocomplete helper functions void @@ -294,16 +294,16 @@ Console::autocomplete() } } -void -Console::addLines(std::string s) +void +Console::addLines(std::string s) { std::istringstream iss(s); std::string line; while (std::getline(iss, line, '\n')) addLine(line); } -void -Console::addLine(std::string s) +void +Console::addLine(std::string s) { // output line to stderr std::cerr << s << std::endl; @@ -318,7 +318,7 @@ Console::addLine(std::string s) // trim scrollback buffer while (lines.size() >= 1000) lines.pop_back(); - + // increase console height if necessary if (height < 64) { if(height < 4) @@ -335,7 +335,7 @@ Console::addLine(std::string s) } void -Console::parse(std::string s) +Console::parse(std::string s) { // make sure we actually have something to parse if (s.length() == 0) return; @@ -380,7 +380,7 @@ Console::parse(std::string s) } bool -Console::consoleCommand(std::string command, std::vector arguments) +Console::consoleCommand(std::string command, std::vector arguments) { if (command == "ccrs") { if (arguments.size() != 1) { @@ -409,7 +409,7 @@ Console::consoleCommand(std::string command, std::vector arguments) } bool -Console::hasFocus() +Console::hasFocus() { return focused; } @@ -423,7 +423,7 @@ Console::show() SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); } -void +void Console::hide() { focused = false; @@ -435,13 +435,13 @@ Console::hide() SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL); } -void +void Console::toggle() { if (Console::hasFocus()) { - Console::hide(); - } - else { + Console::hide(); + } + else { Console::show(); } } @@ -462,7 +462,7 @@ Console::update(float elapsed_time) } } -void +void Console::draw(DrawingContext& context) { if (height == 0) @@ -498,13 +498,13 @@ Console::draw(DrawingContext& context) context.pop_transform(); } -void +void Console::registerCommand(std::string command, ConsoleCommandReceiver* ccr) { commands[command].push_front(ccr); } -void +void Console::unregisterCommand(std::string command, ConsoleCommandReceiver* ccr) { std::map >::iterator i = commands.find(command); @@ -520,7 +520,7 @@ Console::unregisterCommand(std::string command, ConsoleCommandReceiver* ccr) i->second.erase(j); } -void +void Console::unregisterCommands(ConsoleCommandReceiver* ccr) { for (std::map >::iterator i = commands.begin(); i != commands.end(); i++) { @@ -537,4 +537,3 @@ ConsoleStreamBuffer Console::inputBuffer; ConsoleStreamBuffer Console::outputBuffer; std::ostream Console::input(&Console::inputBuffer); std::ostream Console::output(&Console::outputBuffer); - diff --git a/src/console.hpp b/src/console.hpp index a128d607d..15d9791cb 100644 --- a/src/console.hpp +++ b/src/console.hpp @@ -35,7 +35,7 @@ class DrawingContext; class Surface; class Font; -class Console +class Console { public: Console(); @@ -55,7 +55,7 @@ public: void draw(DrawingContext& context); /**< draw the console in a DrawingContext */ void update(float elapsed_time); - + void show(); /**< display the console */ void hide(); /**< hide the console */ void toggle(); /**< display the console if hidden, hide otherwise */ @@ -90,13 +90,13 @@ private: std::list::iterator history_position; /**< item of command history that is currently displayed */ std::list lines; /**< backbuffer of lines sent to the console. New lines get added to front. */ std::map > commands; /**< map of console commands and a list of associated ConsoleCommandReceivers */ - + std::auto_ptr background; /**< console background image */ std::auto_ptr background2; /**< second, moving console background image */ HSQUIRRELVM vm; /**< squirrel thread for the console (with custom roottable) */ HSQOBJECT vm_object; - + int backgroundOffset; /**< current offset of scrolling background image */ float height; /**< height of the console in px */ float alpha; @@ -113,23 +113,23 @@ private: void addLines(std::string s); /**< display a string of (potentially) multiple lines in the console */ void addLine(std::string s); /**< display a line in the console */ void parse(std::string s); /**< react to a given command */ - + /** ready a virtual machine instance, creating a new thread and loading default .nut files if needed */ void ready_vm(); /** execute squirrel script and output result */ void execute_script(const std::string& s); - + bool consoleCommand(std::string command, std::vector arguments); /**< process internal command; return false if command was unknown, true otherwise */ friend class ConsoleStreamBuffer; void flush(ConsoleStreamBuffer* buffer); /**< act upon changes in a ConsoleStreamBuffer */ }; -class ConsoleStreamBuffer : public std::stringbuf +class ConsoleStreamBuffer : public std::stringbuf { public: - int sync() + int sync() { int result = std::stringbuf::sync(); if(Console::instance != NULL) @@ -145,7 +145,7 @@ public: { Console::instance->unregisterCommands(this); } - + /** * callback from Console; return false if command was unknown, * true otherwise diff --git a/src/control/codecontroller.hpp b/src/control/codecontroller.hpp index 7cdb4c4ba..fdc089323 100644 --- a/src/control/codecontroller.hpp +++ b/src/control/codecontroller.hpp @@ -26,7 +26,7 @@ * This is a dummy controler that doesn't react to any user input but should * be controlled by code */ -class CodeController : public Controller +class CodeController : public Controller { public: CodeController(); diff --git a/src/control/controller.hpp b/src/control/controller.hpp index deeb8e639..9f3a07fdc 100644 --- a/src/control/controller.hpp +++ b/src/control/controller.hpp @@ -24,7 +24,7 @@ class Controller { public: static const char* controlNames[]; - + enum Control { LEFT = 0, RIGHT, @@ -37,7 +37,7 @@ public: CONSOLE, PEEK_LEFT, PEEK_RIGHT, - + CONTROLCOUNT }; @@ -48,7 +48,7 @@ public: bool hold(Control control); /** returns true if the control has just been pressed down this frame */ bool pressed(Control control); - /** returns true if the control has just been released this frame */ + /** returns true if the control has just been released this frame */ bool released(Control control); virtual void reset(); diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp index c62153dcf..7bd5961d9 100644 --- a/src/control/joystickkeyboardcontroller.cpp +++ b/src/control/joystickkeyboardcontroller.cpp @@ -52,7 +52,7 @@ public: virtual void menu_action(MenuItem* item); JoystickKeyboardController* controller; }; - + JoystickKeyboardController::JoystickKeyboardController() : wait_for_key(-1), wait_for_joybutton(-1), key_options_menu(0), joystick_options_menu(0) @@ -67,13 +67,13 @@ JoystickKeyboardController::JoystickKeyboardController() keymap.insert(std::make_pair(SDLK_LALT, ACTION)); keymap.insert(std::make_pair(SDLK_ESCAPE, PAUSE_MENU)); keymap.insert(std::make_pair(SDLK_p, PAUSE_MENU)); - keymap.insert(std::make_pair(SDLK_PAUSE, PAUSE_MENU)); + keymap.insert(std::make_pair(SDLK_PAUSE, PAUSE_MENU)); keymap.insert(std::make_pair(SDLK_RETURN, MENU_SELECT)); keymap.insert(std::make_pair(SDLK_KP_ENTER, MENU_SELECT)); keymap.insert(std::make_pair(SDLK_CARET, CONSOLE)); keymap.insert(std::make_pair(SDLK_DELETE, PEEK_LEFT)); keymap.insert(std::make_pair(SDLK_END, PEEK_RIGHT)); - + int joystick_count = SDL_NumJoysticks(); min_joybuttons = -1; max_joybuttons = -1; @@ -93,7 +93,7 @@ JoystickKeyboardController::JoystickKeyboardController() SDL_JoystickClose(joystick); continue; } - + if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons) min_joybuttons = SDL_JoystickNumButtons(joystick); if(SDL_JoystickNumButtons(joystick) > max_joybuttons) { @@ -108,7 +108,7 @@ JoystickKeyboardController::JoystickKeyboardController() joyaxis_y = 1; dead_zone_x = 1000; dead_zone_y = 1000; - + joy_button_map.insert(std::make_pair(0, JUMP)); joy_button_map.insert(std::make_pair(1, ACTION)); // 6 or more Buttons @@ -123,7 +123,7 @@ JoystickKeyboardController::JoystickKeyboardController() if( i != min_joybuttons-1 && i !=4 && i!= 5 ) joy_button_map.insert(std::make_pair(i, MENU_SELECT)); } - + } else { // map the last 2 buttons to menu and pause if(min_joybuttons > 2) @@ -209,12 +209,12 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp) log_warning << "Invalid button '" << button << "' in buttonmap" << std::endl; continue; } - + int i = 0; for(i = 0; controlNames[i] != 0; ++i) { if(control == controlNames[i]) break; - } + } if(controlNames[i] == 0) { log_warning << "Invalid control '" << control << "' in buttonmap" << std::endl; continue; @@ -249,7 +249,7 @@ JoystickKeyboardController::write(lisp::Writer& writer) writer.write_string("control", controlNames[i->second]); writer.end_list("map"); } - writer.end_list("joystick"); + writer.end_list("joystick"); } void @@ -296,7 +296,7 @@ JoystickKeyboardController::process_event(const SDL_Event& event) case SDL_JOYHATMOTION: if(!use_hat) break; - + if(event.jhat.value & SDL_HAT_UP) { controls[UP] = true; controls[DOWN] = false; @@ -341,7 +341,7 @@ JoystickKeyboardController::process_event(const SDL_Event& event) log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl; return; } - + controls[i->second] = event.type == SDL_JOYBUTTONDOWN ? true : false; break; @@ -368,10 +368,10 @@ JoystickKeyboardController::process_key_event(const SDL_Event& event) if (Console::instance->hasFocus()) { process_console_key_event(event); return; - } + } // if menu mode: send key there - if (Menu::current()) { + if (Menu::current()) { process_menu_key_event(event); return; } @@ -432,7 +432,7 @@ JoystickKeyboardController::process_menu_key_event(const SDL_Event& event) if(event.type == SDL_KEYUP) return; - if(event.key.keysym.sym != SDLK_ESCAPE + if(event.key.keysym.sym != SDLK_ESCAPE && event.key.keysym.sym != SDLK_PAUSE) { reset_key(event.key.keysym.sym, (Control) wait_for_key); } @@ -440,7 +440,7 @@ JoystickKeyboardController::process_menu_key_event(const SDL_Event& event) key_options_menu->update(); wait_for_key = -1; return; - } + } if(wait_for_joybutton >= 0) { if(event.key.keysym.sym == SDLK_ESCAPE) { reset(); @@ -449,7 +449,7 @@ JoystickKeyboardController::process_menu_key_event(const SDL_Event& event) } return; } - + Control control; /* we use default keys when the menu is open (to avoid problems when * redefining keys to invalid settings @@ -699,7 +699,7 @@ JoystickKeyboardController::JoystickMenu::get_button_name(int button) { if(button < 0) return _("None"); - + std::ostringstream name; name << "Button " << button; return name.str(); @@ -731,4 +731,3 @@ JoystickKeyboardController::JoystickMenu::update() get_item_by_id((int) Controller::PEEK_RIGHT).change_input(get_button_name( controller->reversemap_joybutton(Controller::PEEK_RIGHT))); } - diff --git a/src/control/joystickkeyboardcontroller.hpp b/src/control/joystickkeyboardcontroller.hpp index e113d4235..7d88932fc 100644 --- a/src/control/joystickkeyboardcontroller.hpp +++ b/src/control/joystickkeyboardcontroller.hpp @@ -50,12 +50,12 @@ private: void process_key_event(const SDL_Event& event); void process_console_key_event(const SDL_Event& event); void process_menu_key_event(const SDL_Event& event); - + typedef std::map KeyMap; KeyMap keymap; std::vector joysticks; - + typedef std::map ButtonMap; ButtonMap joy_button_map; std::string name; @@ -95,7 +95,7 @@ private: class KeyboardMenu; class JoystickMenu; - + KeyboardMenu* key_options_menu; JoystickMenu* joystick_options_menu; friend class KeyboardMenu; @@ -103,4 +103,3 @@ private: }; #endif - diff --git a/src/fadeout.cpp b/src/fadeout.cpp index 25165e2cd..283771ea1 100644 --- a/src/fadeout.cpp +++ b/src/fadeout.cpp @@ -54,4 +54,3 @@ FadeOut::done() { return accum_time >= fade_time; } - diff --git a/src/fadeout.hpp b/src/fadeout.hpp index 130cac072..b005b8c28 100644 --- a/src/fadeout.hpp +++ b/src/fadeout.hpp @@ -33,7 +33,7 @@ public: virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); - + /// returns true if the effect is completed virtual bool done(); @@ -44,4 +44,3 @@ private: }; #endif - diff --git a/src/file_system.cpp b/src/file_system.cpp index cb8f426d9..266da812f 100644 --- a/src/file_system.cpp +++ b/src/file_system.cpp @@ -32,9 +32,9 @@ namespace FileSystem std::string dirname(const std::string& filename) { std::string::size_type p = filename.find_last_of('/'); - if(p == std::string::npos) + if(p == std::string::npos) return ""; - + return filename.substr(0, p+1); } @@ -76,11 +76,11 @@ std::string normalize(const std::string& filename) size_t len = p - pstart; if(len == 0) break; - + std::string pathelem(pstart, p-pstart); if(pathelem == ".") continue; - + if(pathelem == "..") { if(path_stack.empty()) { @@ -108,4 +108,3 @@ std::string normalize(const std::string& filename) } } - diff --git a/src/file_system.hpp b/src/file_system.hpp index 9c14bac0a..b8211884c 100644 --- a/src/file_system.hpp +++ b/src/file_system.hpp @@ -41,4 +41,3 @@ namespace FileSystem } #endif - diff --git a/src/flip_level_transformer.cpp b/src/flip_level_transformer.cpp index 0baa38863..00d10046c 100644 --- a/src/flip_level_transformer.cpp +++ b/src/flip_level_transformer.cpp @@ -31,7 +31,7 @@ void FlipLevelTransformer::transform_sector(Sector* sector) { float height = sector->get_height(); - + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) { GameObject* object = *i; @@ -117,7 +117,7 @@ FlipLevelTransformer::transform_moving_object(float height, MovingObject*object) object->set_pos(pos); } -void +void FlipLevelTransformer::transform_platform(float height, Platform& platform) { Path& path = platform.get_path(); @@ -127,7 +127,7 @@ FlipLevelTransformer::transform_platform(float height, Platform& platform) } } -void +void FlipLevelTransformer::transform_block(float height, Block& block) { block.original_y = height - block.original_y - block.get_bbox().get_height(); diff --git a/src/flip_level_transformer.hpp b/src/flip_level_transformer.hpp index bfb0c6f0e..12459c4e9 100644 --- a/src/flip_level_transformer.hpp +++ b/src/flip_level_transformer.hpp @@ -46,4 +46,3 @@ private: }; #endif - diff --git a/src/game_object.hpp b/src/game_object.hpp index 7d4b05f71..d9541ed1d 100644 --- a/src/game_object.hpp +++ b/src/game_object.hpp @@ -59,14 +59,14 @@ public: { return !wants_to_die; } - + /** schedules this object to be removed at the end of the frame */ void remove_me() { wants_to_die = true; } - - /** registers a remove listener which will be called if the object + + /** registers a remove listener which will be called if the object * gets removed/destroyed */ void add_remove_listener(ObjectRemoveListener* listener) @@ -77,18 +77,18 @@ public: remove_listeners = entry; } - + // flags enum { /// the tile so you can stand on it FLAG_SOLID = (1 << 0), /// the object can be carried around (inherits from Portable) FLAG_PORTABLE = (1 << 1) - }; + }; int get_flags() const { - return flags; + return flags; } private: @@ -109,4 +109,3 @@ protected: }; #endif /*SUPERTUX_GAMEOBJECT_H*/ - diff --git a/src/game_session.cpp b/src/game_session.cpp index fe24f2596..c2aaebd1d 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -90,7 +90,7 @@ GameSession::GameSession(const std::string& levelfile_, Statistics* statistics) { current_ = this; currentsector = NULL; - + game_pause = false; statistics_backdrop.reset(new Surface("images/engine/menu/score-backdrop.png")); @@ -122,7 +122,8 @@ GameSession::restart_level(bool fromBeginning) level->stats.total_badguys = level->get_total_badguys(); level->stats.total_secrets = level->get_total_count(); level->stats.reset(); - if (!fromBeginning) level->stats.declare_invalid(); + if (!fromBeginning) + level->stats.declare_invalid(); if (fromBeginning) reset_sector=""; if(reset_sector != "") { @@ -139,7 +140,7 @@ GameSession::restart_level(bool fromBeginning) throw std::runtime_error("Couldn't find main sector"); currentsector->activate("main"); } - + //levelintro(); currentsector->play_music(LEVEL_MUSIC); @@ -169,8 +170,8 @@ void GameSession::record_demo(const std::string& filename) { delete capture_demo_stream; - - capture_demo_stream = new std::ofstream(filename.c_str()); + + capture_demo_stream = new std::ofstream(filename.c_str()); if(!capture_demo_stream->good()) { std::stringstream msg; msg << "Couldn't open demo file '" << filename << "' for writing."; @@ -208,7 +209,7 @@ GameSession::play_demo(const std::string& filename) { delete playback_demo_stream; delete demo_controller; - + playback_demo_stream = new std::ifstream(filename.c_str()); if(!playback_demo_stream->good()) { std::stringstream msg; @@ -259,7 +260,7 @@ GameSession::levelintro() if((level->get_author().size()) && (level->get_author() != "SuperTux Team")) context.draw_text(white_small_text, - std::string(_("contributed by ")) + level->get_author(), + std::string(_("contributed by ")) + level->get_author(), Vector(SCREEN_WIDTH/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); if(best_level_statistics != NULL) @@ -281,7 +282,7 @@ GameSession::on_escape_press() toggle_pause(); } } - + void GameSession::toggle_pause() { @@ -342,9 +343,9 @@ GameSession::process_events() } end_sequence_controller->press(Controller::RIGHT); - + if (int(last_x_pos) == int(tux.get_pos().x)) - end_sequence_controller->press(Controller::JUMP); + end_sequence_controller->press(Controller::JUMP); last_x_pos = tux.get_pos().x; } @@ -377,7 +378,7 @@ GameSession::process_events() capture_demo_stream ->put(main_controller->hold(Controller::RIGHT)); capture_demo_stream ->put(main_controller->hold(Controller::UP)); capture_demo_stream ->put(main_controller->hold(Controller::DOWN)); - capture_demo_stream ->put(main_controller->hold(Controller::JUMP)); + capture_demo_stream ->put(main_controller->hold(Controller::JUMP)); capture_demo_stream ->put(main_controller->hold(Controller::ACTION)); } } @@ -392,20 +393,20 @@ GameSession::check_end_conditions() finish(true); return; } else if (!end_sequence && tux->is_dead()) { - if (player_status->coins < 0) { + if (player_status->coins < 0) { // No more coins: restart level from beginning player_status->coins = 0; restart_level(true); - } else { + } else { // Still has coins: restart level from last reset point restart_level(false); } - + return; } } -void +void GameSession::draw(DrawingContext& context) { currentsector->draw(context); @@ -422,7 +423,7 @@ GameSession::draw_pause(DrawingContext& context) Vector(0,0), Vector(SCREEN_WIDTH, SCREEN_HEIGHT), Color(.2, .2, .2, .5), LAYER_FOREGROUND1); } - + void GameSession::process_menu() { @@ -462,7 +463,7 @@ GameSession::update(float elapsed_time) // handle controller if(main_controller->pressed(Controller::PAUSE_MENU)) on_escape_press(); - + process_events(); process_menu(); @@ -483,14 +484,9 @@ GameSession::update(float elapsed_time) // Update the world state and all objects in the world if(!game_pause) { - // Update the world - if (end_sequence == ENDSEQUENCE_RUNNING) { - currentsector->update(elapsed_time/2); - } else if(end_sequence == NO_ENDSEQUENCE) { - play_time += elapsed_time; //TODO: make sure we don't count cutscene time - level->stats.time = play_time; - currentsector->update(elapsed_time); - } + currentsector->update(elapsed_time * speed_factor); + play_time += elapsed_time; + currentsector->update(elapsed_time); } // update sounds @@ -499,7 +495,7 @@ GameSession::update(float elapsed_time) /* Handle music: */ if (end_sequence) return; - + if(currentsector->player->invincible_timer.started()) { if(currentsector->player->invincible_timer.get_timeleft() <= TUX_INVINCIBLE_TIME_WARNING) { @@ -521,7 +517,7 @@ GameSession::finish(bool win) if(WorldMap::current()) WorldMap::current()->finished_level(level.get()); } - + main_loop->exit_screen(); } @@ -552,7 +548,7 @@ GameSession::display_info_box(const std::string& text) bool running = true; DrawingContext context; - + while(running) { // TODO make a screen out of this, another mainloop is ugly @@ -589,6 +585,7 @@ GameSession::start_sequence(const std::string& sequencename) if(end_sequence) return; + speed_factor = 0.5; end_sequence = ENDSEQUENCE_RUNNING; endsequence_timer.start(7.3); last_x_pos = -1; @@ -631,4 +628,3 @@ GameSession::drawstatus(DrawingContext& context) level->stats.draw_endseq_panel(context, best_level_statistics, statistics_backdrop.get()); } } - diff --git a/src/game_session.hpp b/src/game_session.hpp index 59a464280..92a0b6987 100644 --- a/src/game_session.hpp +++ b/src/game_session.hpp @@ -63,7 +63,7 @@ public: void respawn(const std::string& sectorname, const std::string& spawnpointname); void set_reset_point(const std::string& sectorname, const Vector& pos); void display_info_box(const std::string& text); - + Sector* get_current_sector() { return currentsector; } @@ -82,6 +82,12 @@ public: void toggle_pause(); + /** + * Allows adjusting the game speed with a factor. 1.0 means normal speed + * 0.0 means the game is stopped. + */ + void adjust_game_speed(float factor); + private: void check_end_conditions(); void process_events(); @@ -127,6 +133,9 @@ private: std::string reset_sector; Vector reset_pos; + /// speed factos + float speed_factor; + // the sector and spawnpoint we should spawn after this frame std::string newsector; std::string newspawnpoint; @@ -146,4 +155,3 @@ private: }; #endif /*SUPERTUX_GAMELOOP_H*/ - diff --git a/src/gameconfig.cpp b/src/gameconfig.cpp index c2d143134..f4c28ca18 100644 --- a/src/gameconfig.cpp +++ b/src/gameconfig.cpp @@ -110,6 +110,6 @@ Config::save() main_controller->write(writer); writer.end_list("control"); } - + writer.end_list("supertux-config"); } diff --git a/src/gameconfig.hpp b/src/gameconfig.hpp index 160278799..7865c4d8d 100644 --- a/src/gameconfig.hpp +++ b/src/gameconfig.hpp @@ -26,7 +26,7 @@ class Config public: Config(); ~Config(); - + void load(); void save(); diff --git a/src/gettext.hpp b/src/gettext.hpp index a3353e12b..a2bd00349 100644 --- a/src/gettext.hpp +++ b/src/gettext.hpp @@ -1,4 +1,4 @@ -/* +/* 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) diff --git a/src/gui/button.cpp b/src/gui/button.cpp index 148ac84a6..05ef76c51 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -61,7 +61,7 @@ if(state == BT_SHOW_INFO) offset = Vector(size.x, - 10); else if(pos.x + tanslation.x < 100) offset = Vector(size.x, 0); - else + else offset = Vector(-30, -size.y/2); context.draw_text(info_font, info, pos + offset, LEFT_ALLIGN, LAYER_GUI+2); if(binding != 0) @@ -178,7 +178,7 @@ switch(event.type) if(mouse_left_button) { - pos.x += int(event.motion.xrel * float(SCREEN_WIDTH)/screen->w); + pos.x += int(event.motion.xrel * float(SCREEN_WIDTH)/screen->w); pos.y += int(event.motion.yrel * float(SCREEN_HEIGHT)/screen->h); caught_event = true; } diff --git a/src/gui/button.hpp b/src/gui/button.hpp index 6f086b9f8..b81f51dbf 100644 --- a/src/gui/button.hpp +++ b/src/gui/button.hpp @@ -42,7 +42,7 @@ class Button public: Button(Surface* image_, std::string info_, SDLKey binding_); ~Button(); - + void draw(DrawingContext& context, bool selected); int event(SDL_Event& event, int x_offset = 0, int y_offset = 0); @@ -72,7 +72,7 @@ public: void add_button(Button button, int id, bool select = false); void add_pair_of_buttons(Button button1, int id1, Button button2, int id2); - + int selected_id(); void set_unselected(); bool is_hover(); diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 1738a2684..1fb5ae67f 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -64,7 +64,7 @@ bool confirm_dialog(Surface *background, std::string text) dialog->add_entry(true, _("Yes")); dialog->add_entry(false, _("No")); dialog->add_hl(); - + Menu::set_current(dialog); DrawingContext context; @@ -234,7 +234,7 @@ Menu::additem(MenuItem* item) * selectable item added */ if (active_item == -1 - && item->kind != MN_HL + && item->kind != MN_HL && item->kind != MN_LABEL && item->kind != MN_DEACTIVE) { active_item = items.size() - 1; @@ -327,16 +327,16 @@ Menu::update() menuaction = MENU_ACTION_UP; menu_repeat_time = real_time + MENU_REPEAT_INITIAL; } - if(main_controller->hold(Controller::UP) && + if(main_controller->hold(Controller::UP) && menu_repeat_time != 0 && real_time > menu_repeat_time) { menuaction = MENU_ACTION_UP; menu_repeat_time = real_time + MENU_REPEAT_RATE; - } + } if(main_controller->pressed(Controller::DOWN)) { menuaction = MENU_ACTION_DOWN; menu_repeat_time = real_time + MENU_REPEAT_INITIAL; } - if(main_controller->hold(Controller::DOWN) && + if(main_controller->hold(Controller::DOWN) && menu_repeat_time != 0 && real_time > menu_repeat_time) { menuaction = MENU_ACTION_DOWN; menu_repeat_time = real_time + MENU_REPEAT_RATE; @@ -353,7 +353,7 @@ Menu::update() hit_item = -1; if(items.size() == 0) return; - + int last_active_item = active_item; switch(menuaction) { case MENU_ACTION_UP: @@ -362,13 +362,13 @@ Menu::update() --active_item; else active_item = int(items.size())-1; - } while ((items[active_item]->kind == MN_HL + } while ((items[active_item]->kind == MN_HL || items[active_item]->kind == MN_LABEL || items[active_item]->kind == MN_DEACTIVE) && (active_item != last_active_item)); - + break; - + case MENU_ACTION_DOWN: do { if(active_item < int(items.size())-1 ) @@ -379,9 +379,9 @@ Menu::update() || items[active_item]->kind == MN_LABEL || items[active_item]->kind == MN_DEACTIVE) && (active_item != last_active_item)); - + break; - + case MENU_ACTION_LEFT: if(items[active_item]->kind == MN_STRINGSELECT) { if(items[active_item]->selected > 0) @@ -390,7 +390,7 @@ Menu::update() items[active_item]->selected = items[active_item]->list.size()-1; } break; - + case MENU_ACTION_RIGHT: if(items[active_item]->kind == MN_STRINGSELECT) { if(items[active_item]->selected+1 < items[active_item]->list.size()) @@ -399,7 +399,7 @@ Menu::update() items[active_item]->selected = 0; } break; - + case MENU_ACTION_HIT: { hit_item = active_item; switch (items[active_item]->kind) { @@ -407,26 +407,26 @@ Menu::update() assert(items[active_item]->target_menu != 0); Menu::push_current(items[active_item]->target_menu); break; - + case MN_TOGGLE: items[active_item]->toggled = !items[active_item]->toggled; menu_action(items[active_item]); break; - + case MN_CONTROLFIELD: menu_action(items[active_item]); break; - + case MN_ACTION: menu_action(items[active_item]); break; - + case MN_TEXTFIELD: case MN_NUMFIELD: menuaction = MENU_ACTION_DOWN; update(); break; - + case MN_BACK: Menu::pop_current(); break; @@ -435,7 +435,7 @@ Menu::update() } break; } - + case MENU_ACTION_REMOVE: if(items[active_item]->kind == MN_TEXTFIELD || items[active_item]->kind == MN_NUMFIELD) @@ -443,7 +443,7 @@ Menu::update() if(!items[active_item]->input.empty()) { int i = items[active_item]->input.size(); - + while(delete_character > 0) /* remove charactes */ { items[active_item]->input.resize(i-1); @@ -452,16 +452,16 @@ Menu::update() } } break; - + case MENU_ACTION_INPUT: if(items[active_item]->kind == MN_TEXTFIELD - || (items[active_item]->kind == MN_NUMFIELD + || (items[active_item]->kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) { items[active_item]->input.push_back(mn_input_char); } break; - + case MENU_ACTION_BACK: Menu::pop_current(); break; @@ -491,7 +491,7 @@ void Menu::draw_item(DrawingContext& context, int index) { float menu_height = get_height(); - float menu_width = get_width(); + float menu_width = get_width(); MenuItem& pitem = *(items[index]); @@ -515,7 +515,7 @@ Menu::draw_item(DrawingContext& context, int index) if(pitem.list.size() > 0) { list_width = (int) text_font->get_text_width(pitem.list[pitem.selected]); } - + if (arrange_left) x_pos += 24 - menu_width/2 + (text_width + input_width + list_width)/2; @@ -684,11 +684,11 @@ float Menu::get_width() const label_font->get_text_width(items[i]->input) + 16; if(items[i]->kind == MN_TOGGLE) w += 32; - + if(w > menu_width) menu_width = w; } - + return menu_width + 24; } @@ -704,9 +704,9 @@ Menu::draw(DrawingContext& context) if(MouseCursor::current()) { MouseCursor::current()->draw(context); } - + float menu_height = get_height(); - float menu_width = get_width(); + float menu_width = get_width(); /* Draw a transparent background */ context.draw_filled_rect( @@ -726,7 +726,7 @@ Menu::get_item_by_id(int id) for(std::vector::iterator i = items.begin(); i != items.end(); ++i) { MenuItem& item = **i; - + if(item.id == id) return item; } @@ -740,7 +740,7 @@ Menu::get_item_by_id(int id) const for(std::vector::const_iterator i = items.begin(); i != items.end(); ++i) { const MenuItem& item = **i; - + if(item.id == id) return item; } @@ -792,15 +792,15 @@ Menu::event(const SDL_Event& event) y > pos_y - get_height()/2 && y < pos_y + get_height()/2) { - int new_active_item + int new_active_item = static_cast ((y - (pos_y - get_height()/2)) / 24); - + /* only change the mouse focus to a selectable item */ if ((items[new_active_item]->kind != MN_HL) && (items[new_active_item]->kind != MN_LABEL) && (items[new_active_item]->kind != MN_DEACTIVE)) active_item = new_active_item; - + if(MouseCursor::current()) MouseCursor::current()->set_state(MC_LINK); } diff --git a/src/gui/menu.hpp b/src/gui/menu.hpp index 55d97e216..5e85fa1ab 100644 --- a/src/gui/menu.hpp +++ b/src/gui/menu.hpp @@ -57,22 +57,22 @@ class MenuItem public: MenuItem(MenuItemKind kind, int id = -1); MenuItemKind kind; - int id; // item id + int id; // item id bool toggled; std::string text; std::string input; - + std::vector list; // list of values for a STRINGSELECT item size_t selected; // currently selected item - + Menu* target_menu; - + void change_text (const std::string& text); void change_input(const std::string& text); - + static MenuItem* create(MenuItemKind kind, const std::string& text, int init_toggle, Menu* target_menu, int id, int key); - + std::string get_input_with_symbol(bool active_item); // returns the text with an input symbol private: @@ -90,21 +90,21 @@ class Menu private: static std::vector last_menus; static Menu* current_; - + static void pop_current(); - + public: /** Set the current menu, if pmenu is NULL, hide the current menu */ static void set_current(Menu* pmenu); - static void push_current(Menu* pmenu); - + static void push_current(Menu* pmenu); + /** Return the current active menu or NULL if none is active */ static Menu* current() { return current_; } - + private: /* Action done on the menu */ enum MenuAction { @@ -118,18 +118,18 @@ private: MENU_ACTION_REMOVE, MENU_ACTION_BACK }; - + /** Number of the item that got 'hit' (ie. pressed) in the last event()/update() call, -1 if none */ int hit_item; - + // position of the menu (ie. center of the menu, not top/left) float pos_x; float pos_y; - + /** input event for the menu (up, down, left, right, etc.) */ MenuAction menuaction; - + /* input implementation variables */ int delete_character; char mn_input_char; @@ -143,10 +143,10 @@ public: static Font* field_font; std::vector items; - + Menu(); virtual ~Menu(); - + void add_hl(); void add_label(const std::string& text); void add_entry(int id, const std::string& text); @@ -158,40 +158,40 @@ public: const std::string& mapping = ""); virtual void menu_action(MenuItem* item); - + void update(); - + /** Remove all entries from the menu */ void clear(); - + /** Return the index of the menu item that was 'hit' (ie. the user clicked on it) in the last event() call */ int check (); - + MenuItem& get_item(int index) { return *(items[index]); } MenuItem& get_item_by_id(int id); const MenuItem& get_item_by_id(int id) const; - + int get_active_item_id(); void set_active_item(int id); - - void draw(DrawingContext& context); + + void draw(DrawingContext& context); void set_pos(float x, float y, float rw = 0, float rh = 0); - + void event(const SDL_Event& event); bool is_toggled(int id) const; protected: - void additem(MenuItem* pmenu_item); + void additem(MenuItem* pmenu_item); float get_width() const; float get_height() const; private: - void check_controlfield_change_event(const SDL_Event& event); + void check_controlfield_change_event(const SDL_Event& event); void draw_item(DrawingContext& context, int index); float effect_time; int arrange_left; diff --git a/src/gui/mousecursor.cpp b/src/gui/mousecursor.cpp index 902f86772..b2010c58d 100644 --- a/src/gui/mousecursor.cpp +++ b/src/gui/mousecursor.cpp @@ -29,7 +29,7 @@ extern SDL_Surface* screen; MouseCursor::MouseCursor(std::string cursor_file) : mid_x(0), mid_y(0) { cursor = new Surface(cursor_file); - + cur_state = MC_NORMAL; SDL_ShowCursor(SDL_DISABLE); diff --git a/src/gui/mousecursor.hpp b/src/gui/mousecursor.hpp index 49b9e8f2d..b3cb53b4b 100644 --- a/src/gui/mousecursor.hpp +++ b/src/gui/mousecursor.hpp @@ -25,7 +25,7 @@ #include "video/surface.hpp" #define MC_STATES_NB 3 - + enum { MC_NORMAL = 0, MC_CLICK, diff --git a/src/level.cpp b/src/level.cpp index dccfbd870..1a81bca08 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -93,7 +93,7 @@ Level::load(const std::string& filepath) continue; } } - + } catch(std::exception& e) { std::stringstream msg; msg << "Problem when reading level '" << filepath << "': " << e.what(); diff --git a/src/level_transformer.cpp b/src/level_transformer.cpp index 2b8b14bfa..a9366f5b5 100644 --- a/src/level_transformer.cpp +++ b/src/level_transformer.cpp @@ -34,4 +34,3 @@ LevelTransformer::transform(Level* level) transform_sector(level->get_sector(i)); } } - diff --git a/src/level_transformer.hpp b/src/level_transformer.hpp index b178ecd86..53f06b7b8 100644 --- a/src/level_transformer.hpp +++ b/src/level_transformer.hpp @@ -32,9 +32,9 @@ class LevelTransformer { public: virtual ~LevelTransformer(); - + /** transform a complete Level, the standard implementation just calls - * transformSector on each sector in the level. + * transformSector on each sector in the level. */ virtual void transform(Level* level); @@ -42,4 +42,3 @@ public: }; #endif - diff --git a/src/lisp/lexer.cpp b/src/lisp/lexer.cpp index 05d687b49..de3243e52 100644 --- a/src/lisp/lexer.cpp +++ b/src/lisp/lexer.cpp @@ -57,7 +57,7 @@ Lexer::nextChar() throw EOFException(); stream.read(buffer, BUFFER_SIZE); size_t bytes_read = stream.gcount(); - + c = buffer; bufend = buffer + bytes_read; @@ -83,9 +83,9 @@ Lexer::getNextToken() ++linenumber; nextChar(); }; - + token_length = 0; - + switch(*c) { case ';': // comment while(true) { @@ -138,7 +138,7 @@ Lexer::getNextToken() case '#': // constant try { nextChar(); - + while(isalnum(*c) || *c == '_') { if(token_length < MAX_TOKEN_LENGTH) token_string[token_length++] = *c; @@ -171,15 +171,15 @@ Lexer::getNextToken() bool have_nondigits = false; bool have_digits = false; int have_floating_point = 0; - + do { if(isdigit(*c)) have_digits = true; else if(*c == '.') ++have_floating_point; else if(isalnum(*c) || *c == '_') - have_nondigits = true; - + have_nondigits = true; + if(token_length < MAX_TOKEN_LENGTH) token_string[token_length++] = *c; @@ -187,7 +187,7 @@ Lexer::getNextToken() } while(!isspace(*c) && !strchr(delims, *c)); token_string[token_length] = 0; - + // no nextChar if(have_nondigits || !have_digits || have_floating_point > 1) @@ -203,11 +203,11 @@ Lexer::getNextToken() nextChar(); } while(!isspace(*c) && !strchr(delims, *c)); token_string[token_length] = 0; - + // no nextChar return TOKEN_SYMBOL; - } + } } } catch(EOFException& ) { return TOKEN_EOF; @@ -215,4 +215,3 @@ Lexer::getNextToken() } } // end of namespace lisp - diff --git a/src/lisp/lexer.hpp b/src/lisp/lexer.hpp index 8128b13d7..f541abdd1 100644 --- a/src/lisp/lexer.hpp +++ b/src/lisp/lexer.hpp @@ -37,7 +37,7 @@ public: TOKEN_TRUE, TOKEN_FALSE }; - + Lexer(std::istream& stream); ~Lexer(); @@ -46,15 +46,15 @@ public: { return token_string; } int getLineNumber() const { return linenumber; } - + private: enum { MAX_TOKEN_LENGTH = 16384, BUFFER_SIZE = 1024 }; - + inline void nextChar(); - + std::istream& stream; bool eof; int linenumber; @@ -68,4 +68,3 @@ private: } // end of namespace lisp #endif - diff --git a/src/lisp/lisp.cpp b/src/lisp/lisp.cpp index fcf5cee27..39313d21f 100644 --- a/src/lisp/lisp.cpp +++ b/src/lisp/lisp.cpp @@ -23,7 +23,7 @@ namespace lisp { - + Lisp::Lisp(LispType newtype) : type(newtype) { @@ -65,7 +65,7 @@ Lisp::print(int indent) const { for(int i = 0; i < indent; ++i) printf(" "); - + if(type == TYPE_CONS) { printf("(\n"); const Lisp* lisp = this; diff --git a/src/lisp/lisp.hpp b/src/lisp/lisp.hpp index 2f14625d8..c01170fc2 100644 --- a/src/lisp/lisp.hpp +++ b/src/lisp/lisp.hpp @@ -31,7 +31,7 @@ class Lisp { public: ~Lisp(); - + enum LispType { TYPE_CONS, TYPE_SYMBOL, @@ -42,27 +42,27 @@ public: }; LispType get_type() const - { return type; } + { return type; } Lisp* get_car() const { return v.cons.car; } Lisp* get_cdr() const { return v.cons.cdr; } - + bool get(std::string& val) const - { + { if(type != TYPE_STRING && type != TYPE_SYMBOL) return false; val = v.string; return true; } - + std::string get_string() const { assert(type == TYPE_STRING); return v.string; } - + bool get(unsigned int& val) const { if(type != TYPE_INTEGER) @@ -70,7 +70,7 @@ public: val = v.integer; return true; } - + bool get(int& val) const { if(type != TYPE_INTEGER) @@ -84,7 +84,7 @@ public: assert(type == TYPE_INTEGER); return v.integer; } - + bool get(float& val) const { if(type != TYPE_REAL) { @@ -145,11 +145,11 @@ public: bool get_vector(const char* name, std::vector& vec) const { vec.clear(); - + const Lisp* child = get_lisp(name); if(!child) return false; - + for( ; child != 0; child = child->get_cdr()) { T val; if(!child->get_car()) @@ -158,10 +158,10 @@ public: vec.push_back(val); } } - + return true; } - + Lisp* get_lisp(const char* name) const; Lisp* get_lisp(const std::string& name) const { return get_lisp(name.c_str()); } @@ -192,4 +192,3 @@ private: } // end of namespace lisp #endif - diff --git a/src/lisp/list_iterator.hpp b/src/lisp/list_iterator.hpp index c11594e9c..092b6728b 100644 --- a/src/lisp/list_iterator.hpp +++ b/src/lisp/list_iterator.hpp @@ -33,7 +33,7 @@ class ListIterator { public: ListIterator(const lisp::Lisp* cur); - + const std::string& item() const { return current_item; } lisp::Lisp* lisp() const @@ -51,4 +51,3 @@ private: } #endif - diff --git a/src/lisp/parser.cpp b/src/lisp/parser.cpp index dbed7ac2f..d108ba014 100644 --- a/src/lisp/parser.cpp +++ b/src/lisp/parser.cpp @@ -71,7 +71,7 @@ Parser::parse(const std::string& filename) dictionary_manager->add_directory(dirname(filename)); dictionary = & (dictionary_manager->get_dictionary()); } - + return parse(in); } @@ -85,11 +85,11 @@ Parser::parse(std::istream& stream) Lisp* result = new Lisp(Lisp::TYPE_CONS); result->v.cons.car = read(); result->v.cons.cdr = 0; - + delete lexer; lexer = 0; - return result; + return result; } Lisp* @@ -111,7 +111,7 @@ Parser::read() } case Lexer::TOKEN_OPEN_PAREN: { result = new Lisp(Lisp::TYPE_CONS); - + token = lexer->getNextToken(); if(token == Lexer::TOKEN_CLOSE_PAREN) { result->v.cons.car = 0; @@ -125,14 +125,14 @@ Parser::read() token = lexer->getNextToken(); if(token != Lexer::TOKEN_STRING) throw std::runtime_error("Expected string after '(_'"); - + result = new Lisp(Lisp::TYPE_STRING); if(dictionary) { std::string translation = dictionary->translate(lexer->getString()); result->v.string = new char[translation.size()+1]; memcpy(result->v.string, translation.c_str(), translation.size()+1); } else { - size_t len = strlen(lexer->getString()) + 1; + size_t len = strlen(lexer->getString()) + 1; result->v.string = new char[len]; memcpy(result->v.string, lexer->getString(), len); } diff --git a/src/lisp/parser.hpp b/src/lisp/parser.hpp index b6d02092b..fc808b18e 100644 --- a/src/lisp/parser.hpp +++ b/src/lisp/parser.hpp @@ -44,7 +44,7 @@ public: private: Lisp* read(); - + Lexer* lexer; TinyGetText::DictionaryManager* dictionary_manager; TinyGetText::Dictionary* dictionary; @@ -54,4 +54,3 @@ private: } // end of namespace lisp #endif - diff --git a/src/lisp/writer.cpp b/src/lisp/writer.cpp index 4126b7fad..5792c47dd 100644 --- a/src/lisp/writer.cpp +++ b/src/lisp/writer.cpp @@ -34,7 +34,7 @@ Writer::Writer(const std::string& filename) out_owned = true; indent_depth = 0; } - + Writer::Writer(std::ostream* newout) { out = newout; @@ -84,7 +84,7 @@ Writer::end_list(const std::string& listname) return; } lists.pop_back(); - + indent_depth -= 2; indent(); *out << ")\n"; diff --git a/src/lisp/writer.hpp b/src/lisp/writer.hpp index 758a70e7f..ba5d327ab 100644 --- a/src/lisp/writer.hpp +++ b/src/lisp/writer.hpp @@ -59,8 +59,7 @@ namespace lisp int indent_depth; std::vector lists; }; - + } //namespace lisp #endif //SUPERTUX_LISPWRITER_H - diff --git a/src/log.cpp b/src/log.cpp index 9b03ff834..ca54b1d77 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -35,4 +35,3 @@ std::ostream& operator<<(std::ostream& out, const Rect& rect) << rect.get_right() << "," << rect.get_bottom() << "]"; return out; } - diff --git a/src/log.hpp b/src/log.hpp index 4d4b74b98..7093dc079 100644 --- a/src/log.hpp +++ b/src/log.hpp @@ -85,4 +85,3 @@ class Rect; std::ostream& operator<< (std::ostream& str, const Rect& rect); #endif - diff --git a/src/main.cpp b/src/main.cpp index 1eadf1abf..fabccddff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,17 +99,17 @@ static void init_physfs(const char* argv0) sprintf(mkdir, ".%s", application); if(!PHYSFS_setWriteDir(userdir) || !PHYSFS_mkdir(mkdir)) { std::ostringstream msg; - msg << "Failed creating configuration directory '" + msg << "Failed creating configuration directory '" << writedir << "': " << PHYSFS_getLastError(); delete[] writedir; delete[] mkdir; throw std::runtime_error(msg.str()); } delete[] mkdir; - + if(!PHYSFS_setWriteDir(writedir)) { std::ostringstream msg; - msg << "Failed to use configuration directory '" + msg << "Failed to use configuration directory '" << writedir << "': " << PHYSFS_getLastError(); delete[] writedir; throw std::runtime_error(msg.str()); @@ -136,7 +136,7 @@ static void init_physfs(const char* argv0) } } } - + PHYSFS_freeList(rc); // when started from source dir... @@ -302,12 +302,12 @@ void init_video() { if(texture_manager != NULL) texture_manager->save_textures(); - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - + int flags = SDL_OPENGL; if(config->use_fullscreen) flags |= SDL_FULLSCREEN; @@ -365,7 +365,7 @@ void init_video() static void init_audio() { sound_manager = new SoundManager(); - + sound_manager->enable_sound(config->sound_enabled); sound_manager->enable_music(config->music_enabled); } @@ -381,7 +381,7 @@ static void quit_audio() void wait_for_event(float min_delay, float max_delay) { assert(min_delay <= max_delay); - + Uint32 min = (Uint32) (min_delay * 1000); Uint32 max = (Uint32) (max_delay * 1000); @@ -425,7 +425,7 @@ static const char* last_timelog_component = 0; static inline void timelog(const char* component) { Uint32 current_ticks = SDL_GetTicks(); - + if(last_timelog_component != 0) { log_info << "Component '" << last_timelog_component << "' finished after " << (current_ticks - last_timelog_ticks) / 1000.0 << " seconds" << std::endl; } @@ -439,17 +439,17 @@ static inline void timelog(const char* ) } #endif -int main(int argc, char** argv) +int main(int argc, char** argv) { int result = 0; - + try { Console::instance = new Console(); init_physfs(argv[0]); init_sdl(); - + timelog("controller"); - main_controller = new JoystickKeyboardController(); + main_controller = new JoystickKeyboardController(); timelog("config"); init_config(); timelog("tinygettext"); @@ -461,14 +461,14 @@ int main(int argc, char** argv) init_audio(); timelog("video"); init_video(); - Console::instance->init_graphics(); + Console::instance->init_graphics(); timelog("scripting"); Scripting::init_squirrel(config->enable_script_debugger); timelog("resources"); - load_shared(); + load_shared(); timelog(0); - main_loop = new MainLoop(); + main_loop = new MainLoop(); if(config->start_level != "") { // we have a normal path specified at commandline not physfs paths. // So we simply mount that path here... @@ -485,7 +485,7 @@ int main(int argc, char** argv) // rain particles before we do this: std::auto_ptr session ( new GameSession(FileSystem::basename(config->start_level))); - + config->random_seed =session->get_demo_random_seed(config->start_demo); init_rand();//initialise generator with seed from session @@ -532,6 +532,6 @@ int main(int argc, char** argv) texture_manager = NULL; SDL_Quit(); PHYSFS_deinit(); - + return result; } diff --git a/src/mainloop.cpp b/src/mainloop.cpp index f9a54f18d..9f8be24e8 100644 --- a/src/mainloop.cpp +++ b/src/mainloop.cpp @@ -115,21 +115,21 @@ MainLoop::draw_fps(DrawingContext& context, float fps_fps) snprintf(str, sizeof(str), "%3.1f", fps_fps); const char* fpstext = "FPS"; context.draw_text(white_text, fpstext, Vector(SCREEN_WIDTH - white_text->get_text_width(fpstext) - gold_text->get_text_width(" 99999") - BORDER_X, BORDER_Y + 20), LEFT_ALLIGN, LAYER_FOREGROUND1); - context.draw_text(gold_text, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), RIGHT_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), RIGHT_ALLIGN, LAYER_FOREGROUND1); } void MainLoop::run() { - DrawingContext context; - + DrawingContext context; + unsigned int frame_count = 0; float fps_fps = 0; Uint32 fps_ticks = SDL_GetTicks(); Uint32 fps_nextframe_ticks = SDL_GetTicks(); Uint32 ticks; bool skipdraw = false; - + running = true; while(running) { while( (next_screen.get() != NULL || nextpop == true) && @@ -149,7 +149,7 @@ MainLoop::run() if(nextpush && current_screen.get() != NULL) { screen_stack.push_back(current_screen.release()); } - + nextpush = false; nextpop = false; speed = 1.0; @@ -163,7 +163,7 @@ MainLoop::run() if(!running || current_screen.get() == NULL) break; - + float elapsed_time = 1.0 / LOGICAL_FPS; ticks = SDL_GetTicks(); if(ticks > fps_nextframe_ticks) { @@ -206,7 +206,7 @@ MainLoop::run() if(config->show_fps) { ++frame_count; - + if(SDL_GetTicks() - fps_ticks >= 500) { fps_fps = (float) frame_count / .5; @@ -219,14 +219,14 @@ MainLoop::run() real_time += elapsed_time; elapsed_time *= speed; game_time += elapsed_time; - + Scripting::update_debugger(); Scripting::TimeScheduler::instance->update(game_time); current_screen->update(elapsed_time); if(screen_fade.get() != NULL) screen_fade->update(elapsed_time); Console::instance->update(elapsed_time); - + main_controller->update(); SDL_Event event; while(SDL_PollEvent(&event)) { @@ -242,4 +242,3 @@ MainLoop::run() //log_info << "== periodic rand() = " << systemRandom.rand() << std::endl; } } - diff --git a/src/mainloop.hpp b/src/mainloop.hpp index 47621f348..a69baafb2 100644 --- a/src/mainloop.hpp +++ b/src/mainloop.hpp @@ -33,7 +33,7 @@ class MainLoop public: MainLoop(); ~MainLoop(); - + void run(); void exit_screen(ScreenFade* fade = NULL); void quit(ScreenFade* fade = NULL); @@ -48,7 +48,7 @@ public: private: void draw_fps(DrawingContext& context, float fps); - + bool running; float speed; bool nextpop; @@ -63,4 +63,3 @@ private: extern MainLoop* main_loop; #endif - diff --git a/src/math/aatriangle.hpp b/src/math/aatriangle.hpp index 06aa12dca..15a0db622 100644 --- a/src/math/aatriangle.hpp +++ b/src/math/aatriangle.hpp @@ -32,7 +32,7 @@ public: /** Directions: * * SOUTHEWEST NORTHEAST SOUTHEAST NORTHWEST - * * or *---* or * or *---* + * * or *---* or * or *---* * | \ \ | / | | / * | \ \ | / | | / * *---* * *---* * @@ -65,4 +65,3 @@ public: }; #endif - diff --git a/src/math/rect.hpp b/src/math/rect.hpp index 79e422af0..2c30258b7 100644 --- a/src/math/rect.hpp +++ b/src/math/rect.hpp @@ -83,7 +83,7 @@ public: { set_width(width); set_height(height); - } + } Vector get_size() { return Vector(get_width(), get_height()); @@ -108,7 +108,7 @@ public: return true; } - + // leave these 2 public to safe the headaches of set/get functions for such // simple things :) @@ -119,4 +119,3 @@ public: }; #endif - diff --git a/src/math/vector.hpp b/src/math/vector.hpp index a2aeb4400..817bb4d96 100644 --- a/src/math/vector.hpp +++ b/src/math/vector.hpp @@ -120,4 +120,3 @@ public: }; #endif - diff --git a/src/moving_object.hpp b/src/moving_object.hpp index 46abffbbe..22a8c3e9c 100644 --- a/src/moving_object.hpp +++ b/src/moving_object.hpp @@ -63,7 +63,7 @@ enum CollisionGroup { * coins */ COLGROUP_TOUCHABLE, - + /** * Should be used for tilemaps */ @@ -92,23 +92,23 @@ public: { (void) tile_attributes; } - + const Vector& get_pos() const { return bbox.p1; } - + /** returns the bounding box of the Object */ const Rect& get_bbox() const { return bbox; } - + const Vector& get_movement() const { return movement; } - + /** places the moving object at a specific position. Be carefull when * using this function. There are no collision detection checks performed * here so bad things could happen. @@ -150,12 +150,12 @@ public: { this->group = group; } - + protected: friend class Sector; friend class CollisionGrid; friend class Platform; - + /** The bounding box of the object (as used for collision detection, this * isn't necessarily the bounding box for graphics) */ diff --git a/src/object/ambient_light.hpp b/src/object/ambient_light.hpp index 65de646ba..0d5d9db66 100644 --- a/src/object/ambient_light.hpp +++ b/src/object/ambient_light.hpp @@ -36,4 +36,3 @@ public: }; #endif - diff --git a/src/object/ambient_sound.cpp b/src/object/ambient_sound.cpp index 8fad2a9c5..b4231863f 100644 --- a/src/object/ambient_sound.cpp +++ b/src/object/ambient_sound.cpp @@ -61,12 +61,12 @@ AmbientSound::AmbientSound(const lisp::Lisp& lisp) lisp.get("volume" ,maximumvolume ); // set dimension to zero if smaller than 64, which is default size in flexlay - + if ((dimension.x <= 64) || (dimension.y <= 64)) { dimension.x = 0; dimension.y = 0; } - + // square all distances (saves us a sqrt later) distance_bias*=distance_bias; @@ -78,7 +78,7 @@ AmbientSound::AmbientSound(const lisp::Lisp& lisp) silence_distance = 10e99; else silence_distance = 1/distance_factor; - + lisp.get("silence_distance",silence_distance); sound_source = 0; // not playing at the beginning @@ -97,7 +97,7 @@ AmbientSound::AmbientSound(Vector pos, float factor, float bias, float vol, std: distance_bias=bias*bias; maximumvolume=vol; sample=file; - + // set default silence_distance if (distance_factor == 0) @@ -131,7 +131,7 @@ AmbientSound::start_playing() sound_source = sound_manager->create_sound_source(sample); if(!sound_source) throw std::runtime_error("file not found"); - + sound_source->set_gain(0); sound_source->set_looping(true); currentvolume=targetvolume=1e-20; @@ -145,8 +145,8 @@ AmbientSound::start_playing() } void -AmbientSound::update(float deltat) -{ +AmbientSound::update(float deltat) +{ if (latency-- <= 0) { float px,py; float rx,ry; @@ -168,7 +168,7 @@ AmbientSound::update(float deltat) // inside the bias: full volume (distance 0) if (sqrdistance<0) sqrdistance=0; - + // calculate target volume - will never become 0 targetvolume=1/(1+sqrdistance*distance_factor); float rise=targetvolume/currentvolume; @@ -194,7 +194,7 @@ AmbientSound::update(float deltat) latency=(int)(0.001/distance_factor); //(int)(10*((sqrdistance-silence_distance)/silence_distance)); } - } + } // heuristically measured "good" latency maximum @@ -203,7 +203,7 @@ AmbientSound::update(float deltat) } void -AmbientSound::draw(DrawingContext &) +AmbientSound::draw(DrawingContext &) { } @@ -223,7 +223,7 @@ AmbientSound::unexpose(HSQUIRRELVM vm, SQInteger table_idx) void AmbientSound::set_pos(float x, float y){ position.x = x; - position.y = y; + position.y = y; } float diff --git a/src/object/ambient_sound.hpp b/src/object/ambient_sound.hpp index 2a587880e..fc349236f 100644 --- a/src/object/ambient_sound.hpp +++ b/src/object/ambient_sound.hpp @@ -21,13 +21,13 @@ /** * Ambient Sound Source, gamma version. Features: * - * - "rounded rectancle" geometry with position, dimension and - * "rounding radius" (extending in all directions) of a 100% - * volume area, adjustable maximum volume, inverse square + * - "rounded rectancle" geometry with position, dimension and + * "rounding radius" (extending in all directions) of a 100% + * volume area, adjustable maximum volume, inverse square * falloff outside area. - * + * * - degenerates gracefully to a disc for dimension=0 - * + * * - parameters: * * x, y position @@ -36,8 +36,8 @@ * distance_bias high = big "100% disc" * silence_distance defaults reasonably. * sample sample to be played back in loop mode - * - * basti_ + * + * basti_ */ #ifndef __AMBIENT_SOUND_H__ @@ -57,7 +57,7 @@ public: AmbientSound(const lisp::Lisp& lisp); AmbientSound(Vector pos, float factor, float bias, float vol, std::string file); ~AmbientSound(); - + void set_pos(Vector newpos) { position=newpos; @@ -92,7 +92,7 @@ private: float distance_factor; /// distance scaling float distance_bias; /// 100% volume disc radius - float silence_distance; /// not implemented yet + float silence_distance; /// not implemented yet float maximumvolume; /// maximum volume float targetvolume; /// how loud we want to be @@ -102,4 +102,3 @@ private: }; #endif - diff --git a/src/object/anchor_point.cpp b/src/object/anchor_point.cpp index 110fb4290..4c42edb06 100644 --- a/src/object/anchor_point.cpp +++ b/src/object/anchor_point.cpp @@ -71,7 +71,7 @@ AnchorPoint string_to_anchor_point(const std::string& str) return ANCHOR_BOTTOM; else if(str == "bottomright") return ANCHOR_BOTTOM_RIGHT; - + std::ostringstream msg; msg << "Unknown anchor '" << str << "'"; throw std::runtime_error(msg.str()); @@ -80,7 +80,7 @@ AnchorPoint string_to_anchor_point(const std::string& str) Vector get_anchor_pos(const Rect& rect, AnchorPoint point) { Vector result; - + switch(point & ANCHOR_V_MASK) { case ANCHOR_LEFT: result.x = rect.get_left(); @@ -118,7 +118,7 @@ Vector get_anchor_pos(const Rect& rect, AnchorPoint point) result.y = rect.get_top(); break; } - + return result; } @@ -126,7 +126,7 @@ Vector get_anchor_pos(const Rect& destrect, float width, float height, AnchorPoint point) { Vector result; - + switch(point & ANCHOR_V_MASK) { case ANCHOR_LEFT: result.x = destrect.get_left(); @@ -164,7 +164,6 @@ Vector get_anchor_pos(const Rect& destrect, float width, float height, result.y = destrect.get_top(); break; } - - return result; -} + return result; +} diff --git a/src/object/anchor_point.hpp b/src/object/anchor_point.hpp index 256c9fe84..5b8baee3b 100644 --- a/src/object/anchor_point.hpp +++ b/src/object/anchor_point.hpp @@ -33,7 +33,7 @@ enum AnchorPoint { ANCHOR_LEFT = 0x0001, ANCHOR_RIGHT = 0x0002, ANCHOR_MIDDLE = 0x0000, - + ANCHOR_TOP_LEFT = ANCHOR_TOP | ANCHOR_LEFT, ANCHOR_TOP_RIGHT = ANCHOR_TOP | ANCHOR_RIGHT, ANCHOR_BOTTOM_LEFT = ANCHOR_BOTTOM | ANCHOR_LEFT, @@ -47,4 +47,3 @@ Vector get_anchor_pos(const Rect& destrect, float width, float height, AnchorPoint point); #endif - diff --git a/src/object/background.cpp b/src/object/background.cpp index f42de1aca..f60f18435 100644 --- a/src/object/background.cpp +++ b/src/object/background.cpp @@ -51,7 +51,7 @@ Background::Background(const lisp::Lisp& reader) reader.get("layer", layer); if(!reader.get("image", imagefile) || !reader.get("speed", speed)) throw std::runtime_error("Must specify image and speed for background"); - + set_image(imagefile, speed); reader.get("speed-y", speed_y); if (reader.get("image-top", imagefile_top)) { @@ -73,7 +73,7 @@ Background::write(lisp::Writer& writer) if (image_top.get() != NULL) writer.write_string("image-top", imagefile_top); - + writer.write_string("image", imagefile); if (image_bottom.get() != NULL) writer.write_string("image-bottom", imagefile_bottom); @@ -81,7 +81,7 @@ Background::write(lisp::Writer& writer) writer.write_float("speed", speed); writer.write_float("speed-y", speed_y); writer.write_int("layer", layer); - + writer.end_list("background"); } @@ -104,7 +104,7 @@ Background::draw(DrawingContext& context) { if(image.get() == NULL) return; - + int w = (int) image->get_width(); int h = (int) image->get_height(); int sx = int(pos.x-context.get_translation().x * speed) % w - w; @@ -118,7 +118,7 @@ Background::draw(DrawingContext& context) if (image_top.get() != NULL && (y < center_image_py)) { context.draw_surface(image_top.get(), Vector(x, y), layer); continue; - } + } if (image_bottom.get() != NULL && (y >= bottom_image_py)) { context.draw_surface(image_bottom.get(), Vector(x, y), layer); continue; diff --git a/src/object/background.hpp b/src/object/background.hpp index 4310b4c43..6b4625e83 100644 --- a/src/object/background.hpp +++ b/src/object/background.hpp @@ -66,4 +66,3 @@ private: }; #endif /*SUPERTUX_BACKGROUND_H*/ - diff --git a/src/object/block.cpp b/src/object/block.cpp index 17cb7ad0d..4bd14094b 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -92,7 +92,7 @@ Block::update(float elapsed_time) { if(!bouncing) return; - + float offset = original_y - get_pos().y; if(offset > BOUNCY_BRICK_MAX_OFFSET) { bounce_dir = BOUNCY_BRICK_SPEED; @@ -138,7 +138,7 @@ BonusBlock::BonusBlock(const Vector& pos, int data) log_warning << "Invalid box contents" << std::endl; contents = CONTENT_COIN; break; - } + } } BonusBlock::BonusBlock(const lisp::Lisp& lisp) @@ -182,12 +182,12 @@ BonusBlock::BonusBlock(const lisp::Lisp& lisp) } else { log_warning << "Invalid element '" << token << "' in bonusblock" << std::endl; } - } + } } if(contents == CONTENT_CUSTOM && object == 0) throw std::runtime_error("Need to specify content object for custom block"); - + bbox.set_pos(pos); } @@ -205,7 +205,7 @@ BonusBlock::hit(Player& ) HitResponse BonusBlock::collision(GameObject& other, const CollisionHit& hit){ BadGuy* badguy = dynamic_cast (&other); - if(badguy) { + if(badguy) { // hit contains no information for collisions with blocks. // Badguy's bottom has to be below the top of the bonusblock // +7 is required to slide over one tile gaps. @@ -223,7 +223,7 @@ BonusBlock::try_open() sound_manager->play("sounds/brick.wav"); return; } - + Sector* sector = Sector::current(); assert(sector); assert(sector->player); @@ -251,12 +251,12 @@ BonusBlock::try_open() case CONTENT_ICEGROW: if(player.get_status()->bonus == NO_BONUS) { SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp(direction)); - sector->add_object(riser); + sector->add_object(riser); } else { SpecialRiser* riser = new SpecialRiser( get_pos(), new Flower(ICE_BONUS)); sector->add_object(riser); - } + } sound_manager->play("sounds/upgrade.wav"); break; @@ -300,7 +300,7 @@ Brick::hit(Player& ) { if(sprite->get_action() == "empty") return; - + try_break(true); } @@ -323,7 +323,7 @@ Brick::try_break(bool playerhit) { if(sprite->get_action() == "empty") return; - + sound_manager->play("sounds/brick.wav"); Sector* sector = Sector::current(); Player& player = *(sector->player); @@ -356,4 +356,3 @@ Brick::try_break(bool playerhit) } //IMPLEMENT_FACTORY(Brick, "brick"); - diff --git a/src/object/block.hpp b/src/object/block.hpp index 462e8ff63..c00cce787 100644 --- a/src/object/block.hpp +++ b/src/object/block.hpp @@ -94,4 +94,3 @@ private: }; #endif - diff --git a/src/object/bullet.cpp b/src/object/bullet.cpp index ef7b52f17..7f0e49194 100644 --- a/src/object/bullet.cpp +++ b/src/object/bullet.cpp @@ -37,7 +37,7 @@ Bullet::Bullet(const Vector& pos, float xm, int dir) : life_count(3) { sprite.reset(sprite_manager->create("images/objects/bullets/firebullet.sprite")); - + bbox.set_pos(pos); bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); @@ -99,5 +99,3 @@ Bullet::collision(GameObject& , const CollisionHit& ) { return FORCE_MOVE; } - - diff --git a/src/object/bullet.hpp b/src/object/bullet.hpp index 3664f33aa..c5eb76dc7 100644 --- a/src/object/bullet.hpp +++ b/src/object/bullet.hpp @@ -29,7 +29,7 @@ class Bullet : public MovingObject public: Bullet(const Vector& pos, float xm, int dir); ~Bullet(); - + void update(float elapsed_time); void draw(DrawingContext& context); void collision_solid(const CollisionHit& hit); diff --git a/src/object/camera.cpp b/src/object/camera.cpp index 7f836b57a..ef22b8f11 100644 --- a/src/object/camera.cpp +++ b/src/object/camera.cpp @@ -72,7 +72,7 @@ void Camera::parse(const lisp::Lisp& reader) { std::string modename; - + reader.get("mode", modename); if(modename == "normal") { mode = NORMAL; @@ -102,7 +102,7 @@ void Camera::write(lisp::Writer& writer) { writer.start_list("camera"); - + if(mode == NORMAL) { writer.write_string("mode", "normal"); writer.write_bool("backscrolling", do_backscrolling); @@ -112,7 +112,7 @@ Camera::write(lisp::Writer& writer) } else if(mode == MANUAL) { writer.write_string("mode", "manual"); } - + writer.end_list("camera"); } @@ -177,12 +177,12 @@ Camera::keep_in_bounds(Vector& translation) // don't scroll before the start or after the level's end if(translation.y > height - SCREEN_HEIGHT) translation.y = height - SCREEN_HEIGHT; - if(translation.y < 0) - translation.y = 0; + if(translation.y < 0) + translation.y = 0; if(translation.x > width - SCREEN_WIDTH) translation.x = width - SCREEN_WIDTH; if(translation.x < 0) - translation.x = 0; + translation.x = 0; } void @@ -199,7 +199,7 @@ Camera::update_scroll_normal(float elapsed_time) { assert(sector != 0); Player* player = sector->player; - + // check that we don't have division by zero later if(elapsed_time < EPSILON) return; @@ -227,7 +227,7 @@ Camera::update_scroll_normal(float elapsed_time) float speed_y = delta_y / elapsed_time; // limit the camera speed when jumping upwards - if(player->fall_mode != Player::FALLING + if(player->fall_mode != Player::FALLING && player->fall_mode != Player::TRAMPOLINE_JUMP) { if(speed_y > max_speed_y) speed_y = max_speed_y; @@ -246,7 +246,7 @@ Camera::update_scroll_normal(float elapsed_time) /****** Horizontal scrolling part *******/ // our camera is either in leftscrolling, rightscrolling or nonscrollingmode. - + // when suddenly changing directions while scrolling into the other direction. // abort scrolling, since tux might be going left/right at a relatively small // part of the map (like when jumping upwards) @@ -289,7 +289,7 @@ Camera::update_scroll_normal(float elapsed_time) if( player->peeking_direction() == ::RIGHT ){ speed_x = -maxv; } - + // apply scrolling translation.x -= speed_x * elapsed_time; @@ -304,7 +304,7 @@ Camera::update_scroll_normal(float elapsed_time) void Camera::update_scroll_autoscroll(float elapsed_time) { - Player* player = sector->player; + Player* player = sector->player; if(player->is_dying()) return; @@ -326,4 +326,3 @@ Camera::update_scroll_to(float elapsed_time) translation = scroll_from + (scroll_goal - scroll_from) * scroll_to_pos; } - diff --git a/src/object/camera.hpp b/src/object/camera.hpp index 07a92d001..de6c43dae 100644 --- a/src/object/camera.hpp +++ b/src/object/camera.hpp @@ -124,4 +124,3 @@ private: }; #endif /*SUPERTUX_CAMERA_H*/ - diff --git a/src/object/candle.hpp b/src/object/candle.hpp index 38ea32589..9c3547a6f 100644 --- a/src/object/candle.hpp +++ b/src/object/candle.hpp @@ -34,7 +34,7 @@ class Candle : public MovingSprite, public ScriptInterface public: Candle(const lisp::Lisp& lisp); virtual Candle* clone() const { return new Candle(*this); } - + HitResponse collision(GameObject& other, const CollisionHit& hit); virtual void expose(HSQUIRRELVM vm, SQInteger table_idx); @@ -52,4 +52,3 @@ private: }; #endif - diff --git a/src/object/coin.cpp b/src/object/coin.cpp index e9e0a0d2c..c75312fb9 100644 --- a/src/object/coin.cpp +++ b/src/object/coin.cpp @@ -52,7 +52,7 @@ Coin::collect() { // TODO: commented out musical code. Maybe fork this for a special "MusicalCoin" object? /* - static Timer sound_timer; + static Timer sound_timer; static int pitch_one = 128; static float last_pitch = 1; float pitch = 1; @@ -63,11 +63,11 @@ Coin::collect() pitch_one = tile; pitch = 1; last_pitch = 1; - } + } else if (sound_timer.get_timegone() < 0.02) { pitch = last_pitch; - } - else + } + else { switch ((pitch_one - tile) % 7) { case -6: diff --git a/src/object/coin.hpp b/src/object/coin.hpp index 9c3106f0c..16d04c94e 100644 --- a/src/object/coin.hpp +++ b/src/object/coin.hpp @@ -35,4 +35,3 @@ public: }; #endif - diff --git a/src/object/display_effect.cpp b/src/object/display_effect.cpp index 88a17d11c..ca3125d6e 100644 --- a/src/object/display_effect.cpp +++ b/src/object/display_effect.cpp @@ -94,12 +94,12 @@ DisplayEffect::update(float elapsed_time) borders = false; border_fade = NO_FADE; } - border_size = (border_fadetime - border_fading) + border_size = (border_fadetime - border_fading) / border_fadetime * BORDER_SIZE; break; default: assert(false); - } + } } void @@ -108,7 +108,7 @@ DisplayEffect::draw(DrawingContext& context) context.push_transform(); context.set_translation(Vector(0, 0)); - if(black || screen_fade != NO_FADE) { + if(black || screen_fade != NO_FADE) { float alpha; if(black) { alpha = 1.0f; @@ -196,4 +196,3 @@ DisplayEffect::four_to_three(float fadetime) border_fading = border_fadetime; } } - diff --git a/src/object/display_effect.hpp b/src/object/display_effect.hpp index 017daff41..40510cc00 100644 --- a/src/object/display_effect.hpp +++ b/src/object/display_effect.hpp @@ -55,10 +55,9 @@ private: float border_fadetime; float border_fading; float border_size; - + bool black; bool borders; }; #endif - diff --git a/src/object/electrifier.cpp b/src/object/electrifier.cpp index 0a7feca5f..f1b8c1ccd 100644 --- a/src/object/electrifier.cpp +++ b/src/object/electrifier.cpp @@ -31,12 +31,12 @@ Electrifier::Electrifier(uint32_t oldtile, uint32_t newtile, float seconds) change_to = newtile; Sector::current()->change_solid_tiles(change_from,change_to); } - + Electrifier::~Electrifier() { } void -Electrifier::update(float ) +Electrifier::update(float ) { if (duration.check()) { Sector::current()->change_solid_tiles(change_to,change_from); @@ -45,6 +45,6 @@ Electrifier::update(float ) } void -Electrifier::draw(DrawingContext& ) +Electrifier::draw(DrawingContext& ) { } diff --git a/src/object/electrifier.hpp b/src/object/electrifier.hpp index 46ce291ce..3ad746c2a 100644 --- a/src/object/electrifier.hpp +++ b/src/object/electrifier.hpp @@ -32,7 +32,7 @@ class Electrifier : public GameObject public: Electrifier(uint32_t oldtile, uint32_t newtile, float seconds); ~Electrifier(); -protected: +protected: virtual void update(float time); virtual void draw(DrawingContext& context); private: @@ -42,4 +42,3 @@ private: }; #endif - diff --git a/src/object/firefly.cpp b/src/object/firefly.cpp index ae98d7574..49299fb94 100644 --- a/src/object/firefly.cpp +++ b/src/object/firefly.cpp @@ -33,7 +33,7 @@ Firefly::Firefly(const lisp::Lisp& lisp) : MovingSprite(lisp, "images/objects/resetpoints/default-resetpoint.sprite", LAYER_TILES, COLGROUP_TOUCHABLE), activated(false) { - + if( !lisp.get( "sprite", sprite_name ) ){ return; } @@ -41,7 +41,7 @@ Firefly::Firefly(const lisp::Lisp& lisp) sprite_name = "images/objects/resetpoints/default-resetpoint.sprite"; return; } - //Replace sprite + //Replace sprite sprite = sprite_manager->create( sprite_name ); bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); } @@ -60,7 +60,7 @@ Firefly::collision(GameObject& other, const CollisionHit& ) { if(activated) return ABORT_MOVE; - + Player* player = dynamic_cast (&other); if(player) { activated = true; @@ -81,7 +81,7 @@ Firefly::collision(GameObject& other, const CollisionHit& ) GameSession::current()->set_reset_point(Sector::current()->get_name(), get_pos()); } - + return ABORT_MOVE; } diff --git a/src/object/firefly.hpp b/src/object/firefly.hpp index 89a3882aa..f77a5745b 100644 --- a/src/object/firefly.hpp +++ b/src/object/firefly.hpp @@ -43,4 +43,3 @@ private: }; #endif - diff --git a/src/object/fireworks.hpp b/src/object/fireworks.hpp index 882ef5faa..4128c8362 100644 --- a/src/object/fireworks.hpp +++ b/src/object/fireworks.hpp @@ -29,7 +29,7 @@ class Fireworks : public GameObject public: Fireworks(); ~Fireworks(); - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); @@ -38,4 +38,3 @@ private: }; #endif - diff --git a/src/object/floating_image.cpp b/src/object/floating_image.cpp index 6041baec2..579878471 100644 --- a/src/object/floating_image.cpp +++ b/src/object/floating_image.cpp @@ -29,7 +29,7 @@ #include "lisp/lisp.hpp" #include "floating_image.hpp" -FloatingImage::FloatingImage(const std::string& spritefile) +FloatingImage::FloatingImage(const std::string& spritefile) : layer(LAYER_FOREGROUND1 + 1), visible(false), anchor(ANCHOR_MIDDLE) { sprite.reset(sprite_manager->create(spritefile)); diff --git a/src/object/floating_image.hpp b/src/object/floating_image.hpp index 7e7ddc3a2..db37066d9 100644 --- a/src/object/floating_image.hpp +++ b/src/object/floating_image.hpp @@ -36,7 +36,7 @@ public: void set_layer(int layer) { this->layer = layer; } - + int get_layer() const { return layer; } @@ -47,7 +47,7 @@ public: const Vector& get_pos() const { return pos; } - + void set_anchor_point(AnchorPoint anchor) { this->anchor = anchor; } @@ -77,4 +77,3 @@ private: }; #endif - diff --git a/src/object/flower.cpp b/src/object/flower.cpp index b5830e0a9..71cacf2f8 100644 --- a/src/object/flower.cpp +++ b/src/object/flower.cpp @@ -39,7 +39,7 @@ Flower::Flower(BonusType _type) sound_manager->preload("sounds/fire-flower.wav"); } else if(type == ICE_BONUS) { - sprite = sprite_manager->create("images/powerups/iceflower/iceflower.sprite"); + sprite = sprite_manager->create("images/powerups/iceflower/iceflower.sprite"); } else { assert(false); } @@ -72,9 +72,8 @@ Flower::collision(GameObject& other, const CollisionHit& ) if(!player->add_bonus(type, true)) return FORCE_MOVE; - + sound_manager->play("sounds/fire-flower.wav"); remove_me(); return ABORT_MOVE; } - diff --git a/src/object/flower.hpp b/src/object/flower.hpp index 4411ef9db..46a2e6c22 100644 --- a/src/object/flower.hpp +++ b/src/object/flower.hpp @@ -41,4 +41,3 @@ private: }; #endif - diff --git a/src/object/gameobjs.cpp b/src/object/gameobjs.cpp index caf93ed7c..bcbbdd503 100644 --- a/src/object/gameobjs.cpp +++ b/src/object/gameobjs.cpp @@ -175,4 +175,3 @@ SmokeCloud::draw(DrawingContext& context) { sprite->draw(context, position, LAYER_OBJECTS+1); } - diff --git a/src/object/gameobjs.hpp b/src/object/gameobjs.hpp index 2fa10da1e..d15ed27d4 100644 --- a/src/object/gameobjs.hpp +++ b/src/object/gameobjs.hpp @@ -69,14 +69,14 @@ class FloatingText : public GameObject public: FloatingText(const Vector& pos, const std::string& text_); FloatingText(const Vector& pos, int s); // use this for score, for instance - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); private: Vector position; std::string text; - Timer timer; + Timer timer; }; class SmokeCloud : public GameObject @@ -84,7 +84,7 @@ class SmokeCloud : public GameObject public: SmokeCloud(const Vector& pos); ~SmokeCloud(); - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); @@ -94,7 +94,7 @@ private: Vector position; }; -#endif +#endif /* Local Variables: */ /* mode:c++ */ diff --git a/src/object/gradient.cpp b/src/object/gradient.cpp index c383895c6..d89996bb2 100644 --- a/src/object/gradient.cpp +++ b/src/object/gradient.cpp @@ -68,7 +68,7 @@ Gradient::write(lisp::Writer& writer) writer.write_float_vector("bottom_color", bkgd_bottom_color); writer.write_int("layer", layer); - + writer.end_list("gradient"); } @@ -82,7 +82,7 @@ Gradient::set_gradient(Color top, Color bottom) { gradient_top = top; gradient_bottom = bottom; - + if (gradient_top.red > 1.0 || gradient_top.green > 1.0 || gradient_top.blue > 1.0 || gradient_top.alpha > 1.0) log_warning << "top gradient color has values above 1.0" << std::endl; diff --git a/src/object/gradient.hpp b/src/object/gradient.hpp index a0037fd74..6feba3180 100644 --- a/src/object/gradient.hpp +++ b/src/object/gradient.hpp @@ -45,7 +45,7 @@ public: Color get_gradient_top() const { return gradient_top; } - + Color get_gradient_bottom() const { return gradient_bottom; } @@ -59,4 +59,3 @@ private: }; #endif /*SUPERTUX_BACKGROUND_H*/ - diff --git a/src/object/growup.cpp b/src/object/growup.cpp index 6af5b5b3c..1d256dbb7 100644 --- a/src/object/growup.cpp +++ b/src/object/growup.cpp @@ -60,10 +60,9 @@ GrowUp::collision(GameObject& other, const CollisionHit& ) sound_manager->play("sounds/grow.wav"); remove_me(); - + return ABORT_MOVE; } return FORCE_MOVE; } - diff --git a/src/object/growup.hpp b/src/object/growup.hpp index df21d60f4..315740de3 100644 --- a/src/object/growup.hpp +++ b/src/object/growup.hpp @@ -33,10 +33,9 @@ public: virtual void update(float elapsed_time); virtual void collision_solid(const CollisionHit& hit); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); - + private: Physic physic; }; #endif - diff --git a/src/object/hurting_platform.hpp b/src/object/hurting_platform.hpp index 04c48fed9..71cbf84df 100644 --- a/src/object/hurting_platform.hpp +++ b/src/object/hurting_platform.hpp @@ -1,4 +1,4 @@ -// $Id: hurting_platform.hpp 3506 2006-05-12 01:41:09Z sommer $ +// $Id$ // // SuperTux - Hurting Platform // Copyright (C) 2006 Christoph Sommer @@ -39,4 +39,3 @@ private: }; #endif - diff --git a/src/object/infoblock.cpp b/src/object/infoblock.cpp index aff82ac53..c332f3acd 100644 --- a/src/object/infoblock.cpp +++ b/src/object/infoblock.cpp @@ -41,7 +41,7 @@ InfoBlock::InfoBlock(const lisp::Lisp& lisp) } //stopped = false; //ringing = new AmbientSound(get_pos(), 0.5, 300, 1, "sounds/phone.wav"); - //Sector::current()->add_object(ringing); + //Sector::current()->add_object(ringing); } InfoBlock::~InfoBlock() diff --git a/src/object/infoblock.hpp b/src/object/infoblock.hpp index 4aa6d4e41..7f9b051bf 100644 --- a/src/object/infoblock.hpp +++ b/src/object/infoblock.hpp @@ -28,7 +28,7 @@ class InfoBlock : public Block public: InfoBlock(const lisp::Lisp& lisp); virtual ~InfoBlock(); - + protected: virtual void hit(Player& player); std::string message; @@ -37,4 +37,3 @@ protected: }; #endif - diff --git a/src/object/invisible_block.cpp b/src/object/invisible_block.cpp index fe17ba651..73ccf5612 100644 --- a/src/object/invisible_block.cpp +++ b/src/object/invisible_block.cpp @@ -62,7 +62,7 @@ InvisibleBlock::collision(GameObject& other, const CollisionHit& hit) void InvisibleBlock::hit(Player& ) { - sound_manager->play("sounds/brick.wav"); + sound_manager->play("sounds/brick.wav"); if(visible) return; diff --git a/src/object/invisible_block.hpp b/src/object/invisible_block.hpp index 560730208..7b32be384 100644 --- a/src/object/invisible_block.hpp +++ b/src/object/invisible_block.hpp @@ -38,4 +38,3 @@ private: }; #endif - diff --git a/src/object/level_time.cpp b/src/object/level_time.cpp index 0b7f09c0a..1f1034b7c 100644 --- a/src/object/level_time.cpp +++ b/src/object/level_time.cpp @@ -72,7 +72,7 @@ LevelTime::draw(DrawingContext& context) context.set_translation(Vector(0, 0)); char str[60]; - + if(get_remaining_time() < 0) { context.draw_text(white_text, _("TIME's UP"), Vector(SCREEN_WIDTH/2, BORDER_Y), CENTER_ALLIGN, LAYER_FOREGROUND1); diff --git a/src/object/level_time.hpp b/src/object/level_time.hpp index 928fee8f9..b4741ec99 100644 --- a/src/object/level_time.hpp +++ b/src/object/level_time.hpp @@ -43,4 +43,3 @@ private: }; #endif - diff --git a/src/object/light.cpp b/src/object/light.cpp index 8b3983f9e..ba08bc68f 100644 --- a/src/object/light.cpp +++ b/src/object/light.cpp @@ -47,9 +47,9 @@ Light::draw(DrawingContext& context) { context.push_target(); context.set_target(DrawingContext::LIGHTMAP); - + sprite->draw(context, Sector::current()->player->get_pos(), 0); - + context.pop_target(); } diff --git a/src/object/light.hpp b/src/object/light.hpp index cac9a714b..b24891fb3 100644 --- a/src/object/light.hpp +++ b/src/object/light.hpp @@ -39,4 +39,3 @@ private: }; #endif - diff --git a/src/object/moving_sprite.cpp b/src/object/moving_sprite.cpp index 853de73ff..953d55691 100644 --- a/src/object/moving_sprite.cpp +++ b/src/object/moving_sprite.cpp @@ -81,7 +81,7 @@ MovingSprite::MovingSprite(const MovingSprite& other) sprite = new Sprite(*other.sprite); } -MovingSprite& +MovingSprite& MovingSprite::operator=(const MovingSprite& other) { if (this == &other) return *this; @@ -105,19 +105,19 @@ MovingSprite::draw(DrawingContext& context) sprite->draw(context, get_pos(), layer); } -void +void MovingSprite::update(float ) { } -void +void MovingSprite::set_action(const std::string& action, int loops) { sprite->set_action(action, loops); set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); } -void +void MovingSprite::set_action_centered(const std::string& action, int loops) { Vector old_size = bbox.get_size(); @@ -125,4 +125,3 @@ MovingSprite::set_action_centered(const std::string& action, int loops) set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); set_pos(get_pos() - (bbox.get_size() - old_size) / 2); } - diff --git a/src/object/moving_sprite.hpp b/src/object/moving_sprite.hpp index 503f9491c..868c62223 100644 --- a/src/object/moving_sprite.hpp +++ b/src/object/moving_sprite.hpp @@ -61,4 +61,3 @@ protected: }; #endif - diff --git a/src/object/oneup.cpp b/src/object/oneup.cpp index 3ce81fa84..bdbaa5e9a 100644 --- a/src/object/oneup.cpp +++ b/src/object/oneup.cpp @@ -38,7 +38,7 @@ OneUp::update(float elapsed_time) if(!Sector::current()->inside(bbox)) remove_me(); - movement = physic.get_movement(elapsed_time); + movement = physic.get_movement(elapsed_time); } HitResponse @@ -52,4 +52,3 @@ OneUp::collision(GameObject& other, const CollisionHit& ) } return FORCE_MOVE; } - diff --git a/src/object/particles.cpp b/src/object/particles.cpp index cea6c82f8..f6f066b36 100644 --- a/src/object/particles.cpp +++ b/src/object/particles.cpp @@ -102,4 +102,3 @@ Particles::draw(DrawingContext& context) context.draw_filled_rect((*i)->pos, Vector(size,size), color,drawing_layer); } } - diff --git a/src/object/particles.hpp b/src/object/particles.hpp index 4e4d3a27a..9c353ee2d 100644 --- a/src/object/particles.hpp +++ b/src/object/particles.hpp @@ -33,7 +33,7 @@ public: int number, Color color, int size, float life_time, int drawing_layer); ~Particles(); - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); diff --git a/src/object/particlesystem.cpp b/src/object/particlesystem.cpp index a58a7d4d1..a63afa0e5 100644 --- a/src/object/particlesystem.cpp +++ b/src/object/particlesystem.cpp @@ -138,7 +138,7 @@ void SnowParticleSystem::update(float elapsed_time) particle->pos.y += particle->speed * elapsed_time; particle->pos.x += particle->wobble * elapsed_time /* * particle->speed * 0.125*/; - + anchor_delta = (particle->anchorx - particle->pos.x); particle->wobble += (4 * anchor_delta * 0.05) + systemRandom.randf(-0.5, 0.5); particle->wobble *= 0.99; diff --git a/src/object/particlesystem.hpp b/src/object/particlesystem.hpp index dd356f82c..b3f49a5ad 100644 --- a/src/object/particlesystem.hpp +++ b/src/object/particlesystem.hpp @@ -54,7 +54,7 @@ class ParticleSystem : public GameObject public: ParticleSystem(float max_particle_size = 60); virtual ~ParticleSystem(); - + virtual void draw(DrawingContext& context); protected: @@ -70,7 +70,7 @@ protected: Vector pos; Surface* texture; }; - + std::vector particles; float virtual_width, virtual_height; }; @@ -88,7 +88,7 @@ public: std::string type() const { return "SnowParticleSystem"; } - + private: class SnowParticle : public Particle { @@ -98,7 +98,7 @@ private: float anchorx; float drift_speed; }; - + Surface* snowimages[3]; }; @@ -115,14 +115,14 @@ public: std::string type() const { return "GhostParticleSystem"; } - + private: class GhostParticle : public Particle { public: float speed; }; - + Surface* ghosts[2]; }; @@ -138,17 +138,16 @@ public: virtual void update(float elapsed_time); std::string type() const - { return "CloudParticleSystem"; } - + { return "CloudParticleSystem"; } + private: class CloudParticle : public Particle { public: float speed; }; - + Surface* cloudimage; }; #endif - diff --git a/src/object/particlesystem_interactive.cpp b/src/object/particlesystem_interactive.cpp index 0a45cb53c..2d4a3c2ee 100644 --- a/src/object/particlesystem_interactive.cpp +++ b/src/object/particlesystem_interactive.cpp @@ -61,7 +61,7 @@ ParticleSystem_Interactive::~ParticleSystem_Interactive() void ParticleSystem_Interactive::draw(DrawingContext& context) { context.push_transform(); - + std::vector::iterator i; for(i = particles.begin(); i != particles.end(); ++i) { Particle* particle = *i; @@ -121,7 +121,7 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement) if(intersects(dest, rect)) { if(tile->getAttributes() & Tile::WATER) water = true; - set_rectangle_rectangle_constraints(&constraints, dest, rect); + set_rectangle_rectangle_constraints(&constraints, dest, rect); } } } diff --git a/src/object/particlesystem_interactive.hpp b/src/object/particlesystem_interactive.hpp index 3bb7313bf..55bf3c5c0 100644 --- a/src/object/particlesystem_interactive.hpp +++ b/src/object/particlesystem_interactive.hpp @@ -50,7 +50,7 @@ class ParticleSystem_Interactive : public GameObject public: ParticleSystem_Interactive(); virtual ~ParticleSystem_Interactive(); - + virtual void draw(DrawingContext& context); protected: @@ -65,7 +65,7 @@ protected: Vector pos; Surface* texture; }; - + std::vector particles; float virtual_width, virtual_height; int collision(Particle* particle, Vector movement); @@ -84,14 +84,14 @@ public: std::string type() const { return "RainParticleSystem"; } - + private: class RainParticle : public Particle { public: float speed; }; - + Surface* rainimages[2]; }; @@ -108,16 +108,15 @@ public: std::string type() const { return "CometParticleSystem"; } - + private: class CometParticle : public Particle { public: float speed; }; - + Surface* cometimages[2]; }; #endif - diff --git a/src/object/path.cpp b/src/object/path.cpp index 5f7cc0947..6529cf338 100644 --- a/src/object/path.cpp +++ b/src/object/path.cpp @@ -66,7 +66,7 @@ Path::read(const lisp::Lisp& reader) } continue; } - + if(iter.item() != "node") { log_warning << "unknown token '" << iter.item() << "' in Path nodes list. Ignored." << std::endl; continue; @@ -130,7 +130,6 @@ Path::get_base() const { if(nodes.empty()) return Vector(0, 0); - + return nodes[0].position; } - diff --git a/src/object/path.hpp b/src/object/path.hpp index 5ac0fe032..f599c760f 100644 --- a/src/object/path.hpp +++ b/src/object/path.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux Path // Copyright (C) 2005 Philipp // Copyright (C) 2006 Christoph Sommer @@ -14,7 +14,7 @@ // 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 @@ -66,4 +66,3 @@ private: }; #endif - diff --git a/src/object/path_walker.cpp b/src/object/path_walker.cpp index 29ee6fcec..0c8ae2599 100644 --- a/src/object/path_walker.cpp +++ b/src/object/path_walker.cpp @@ -43,7 +43,7 @@ PathWalker::advance(float elapsed_time) assert(elapsed_time >= 0); elapsed_time *= fabsf(walking_speed); - + const Path::Node* current_node = & (path->nodes[current_node_nr]); while(node_time + elapsed_time * node_mult >= 1) { elapsed_time -= (1 - node_time) / node_mult; @@ -62,17 +62,17 @@ PathWalker::advance(float elapsed_time) node_mult = 1 / path->nodes[next_node_nr].time; } } - + const Path::Node* next_node = & (path->nodes[next_node_nr]); node_time += elapsed_time * node_mult; - - Vector new_pos = current_node->position + + + Vector new_pos = current_node->position + (next_node->position - current_node->position) * node_time; - + return new_pos; } -void +void PathWalker::goto_node(int node_no) { if (node_no == stop_at_node_nr) return; @@ -80,14 +80,14 @@ PathWalker::goto_node(int node_no) stop_at_node_nr = node_no; } -void +void PathWalker::start_moving() { running = true; stop_at_node_nr = -1; } -void +void PathWalker::stop_moving() { stop_at_node_nr = next_node_nr; diff --git a/src/object/path_walker.hpp b/src/object/path_walker.hpp index 5bb330092..f3bdf9e6e 100644 --- a/src/object/path_walker.hpp +++ b/src/object/path_walker.hpp @@ -55,7 +55,7 @@ public: private: void advance_node(); void goback_node(); - + /** * set to false to immediately stop advancing */ diff --git a/src/object/platform.cpp b/src/object/platform.cpp index 08469b655..6d04777be 100644 --- a/src/object/platform.cpp +++ b/src/object/platform.cpp @@ -47,7 +47,7 @@ Platform::Platform(const lisp::Lisp& reader) path->read(*pathLisp); walker.reset(new PathWalker(path.get(), running)); bbox.set_pos(path->get_base()); - + flags |= FLAG_SOLID; } diff --git a/src/object/platform.hpp b/src/object/platform.hpp index f5e1d245e..ad1d999d7 100644 --- a/src/object/platform.hpp +++ b/src/object/platform.hpp @@ -69,4 +69,3 @@ private: }; #endif - diff --git a/src/object/player.cpp b/src/object/player.cpp index 093e12e41..48f90358b 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -160,7 +160,7 @@ Player::init() backflip_direction = 0; visible = true; swimming = false; - + on_ground_flag = false; grabbed_object = NULL; @@ -192,8 +192,13 @@ Player::adjust_height(float new_height) Rect bbox2 = bbox; bbox2.move(Vector(0, bbox.get_height() - new_height)); bbox2.set_height(new_height); - if (!Sector::current()->is_free_space(bbox2)) - return false; + + if(new_height > bbox.get_height()) { + Rect additional_space = bbox2; + additional_space.set_height(new_height - bbox.get_height()); + if(!Sector::current()->is_free_space(additional_space)) + return false; + } // adjust bbox accordingly // note that we use members of moving_object for this, so we can run this during CD, too @@ -209,7 +214,7 @@ Player::update(float elapsed_time) swimming = false; } no_water = true; - + if(dying && dying_timer.check()) { dead = true; return; @@ -240,8 +245,8 @@ Player::update(float elapsed_time) // handle backflipping if (backflipping) { - //prevent player from changing direction when backflipping - dir = (backflip_direction == 1) ? LEFT : RIGHT; + //prevent player from changing direction when backflipping + dir = (backflip_direction == 1) ? LEFT : RIGHT; if (backflip_timer.started()) physic.set_velocity_x(100 * backflip_direction); } @@ -257,66 +262,27 @@ Player::update(float elapsed_time) } // check if we landed - if(on_ground()) { + if(on_ground()) { jumping = false; if (backflipping && (!backflip_timer.started())) { backflipping = false; backflip_direction = 0; // if controls are currently deactivated, we take care of standing up ourselves - if (deactivated) do_standup(); + if (deactivated) + do_standup(); } } - -#if 0 - // Do butt jump - if (butt_jump && on_ground() && is_big()) { - // Add a smoke cloud - if (duck) - Sector::current()->add_smoke_cloud(Vector(get_pos().x - 32, get_pos().y)); - else - Sector::current()->add_smoke_cloud( - Vector(get_pos().x - 32, get_pos().y + 32)); - - butt_jump = false; - - // Break bricks beneath Tux - if(Sector::current()->trybreakbrick( - Vector(base.x + 1, base.y + base.height), false) - || Sector::current()->trybreakbrick( - Vector(base.x + base.width - 1, base.y + base.height), false)) { - physic.set_velocity_y(-2); - butt_jump = true; - } - - // Kill nearby badguys - std::vector gameobjects = Sector::current()->gameobjects; - for (std::vector::iterator i = gameobjects.begin(); - i != gameobjects.end(); - i++) { - BadGuy* badguy = dynamic_cast (*i); - if(badguy) { - // don't kill when badguys are already dying or in a certain mode - if(badguy->dying == DYING_NOT && badguy->mode != BadGuy::BOMB_TICKING && - badguy->mode != BadGuy::BOMB_EXPLODE) { - if (fabsf(base.x - badguy->base.x) < 96 && - fabsf(base.y - badguy->base.y) < 64) - badguy->kill_me(25); - } - } - } - } -#endif // calculate movement for this frame movement = physic.get_movement(elapsed_time); if(grabbed_object != NULL && !dying) { - Vector pos = get_pos() + + Vector pos = get_pos() + Vector(dir == LEFT ? -16 : 16, get_bbox().get_height()*0.66666 - 32); grabbed_object->grab(*this, pos, dir); } - + if(grabbed_object != NULL && dying){ grabbed_object->ungrab(*this, dir); grabbed_object = NULL; @@ -345,7 +311,7 @@ Player::update(float elapsed_time) Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "dark", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5)); } } - } + } } @@ -375,22 +341,6 @@ Player::apply_friction() } else { physic.set_acceleration_x(WALK_ACCELERATION_X * -1.5); } - -#if 0 - // if we're on ice slow down acceleration or deceleration - if (isice(base.x, base.y + base.height)) - { - /* the acceleration/deceleration rate on ice is inversely proportional to - * the current velocity. - */ - - // increasing 1 will increase acceleration/deceleration rate - // decreasing 1 will decrease acceleration/deceleration rate - // must stay above zero, though - if (ax != 0) ax *= 1 / fabs(vx); - } -#endif - } void @@ -456,7 +406,7 @@ Player::handle_horizontal_input() dir == RIGHT ? 270+20 : 90-40, dir == RIGHT ? 270+40 : 90-20, Vector(280, -260), Vector(0, 300), 3, Color(.4, .4, .4), 3, .8, LAYER_OBJECTS+1)); - + ax *= 2.5; } else { ax *= 2; @@ -483,11 +433,15 @@ Player::do_cheer() void Player::do_duck() { - if (duck) return; - if (!is_big()) return; + if (duck) + return; + if (!is_big()) + return; - if (physic.get_velocity_y() != 0) return; - if (!on_ground()) return; + if (physic.get_velocity_y() != 0) + return; + if (!on_ground()) + return; if (adjust_height(31.8)) { duck = true; @@ -497,11 +451,14 @@ Player::do_duck() { } } -void +void Player::do_standup() { - if (!duck) return; - if (!is_big()) return; - if (backflipping) return; + if (!duck) + return; + if (!is_big()) + return; + if (backflipping) + return; if (adjust_height(63.8)) { duck = false; @@ -510,7 +467,7 @@ Player::do_standup() { // if timer is not already running, start it. if (unduck_hurt_timer.get_period() == 0) { unduck_hurt_timer.start(UNDUCK_HURT_TIME); - } + } else if (unduck_hurt_timer.check()) { kill(false); } @@ -520,8 +477,10 @@ Player::do_standup() { void Player::do_backflip() { - if (!duck) return; - if (!on_ground()) return; + if (!duck) + return; + if (!on_ground()) + return; // TODO: we don't have an animation for firetux backflipping, so let's revert to bigtux set_bonus(GROWUP_BONUS, true); @@ -535,7 +494,8 @@ Player::do_backflip() { void Player::do_jump(float yspeed) { - if (!on_ground()) return; + if (!on_ground()) + return; physic.set_velocity_y(yspeed); //bbox.move(Vector(0, -1)); @@ -557,16 +517,16 @@ Player::handle_vertical_input() // Press jump key if(controller->pressed(Controller::JUMP) && (can_jump)) { - if (duck) { + if (duck) { // when running, only jump a little bit; else do a backflip if (physic.get_velocity_x() != 0) do_jump(-300); else do_backflip(); } else { // jump a bit higher if we are running; else do a normal jump if (fabs(physic.get_velocity_x()) > MAX_WALK_XM) do_jump(-580); else do_jump(-520); } - } + } // Let go of jump key - else if(!controller->hold(Controller::JUMP)) { + else if(!controller->hold(Controller::JUMP)) { if (!backflipping && jumping && physic.get_velocity_y() < 0) { jumping = false; physic.set_velocity_y(0); @@ -578,7 +538,7 @@ Player::handle_vertical_input() if (controller->hold(Controller::DOWN) && !butt_jump && !duck && is_big() && jumping) { butt_jump = true; } - + /* When Down is not held anymore, disable butt jump */ if(butt_jump && !controller->hold(Controller::DOWN)) butt_jump = false; @@ -594,7 +554,7 @@ Player::handle_input() if(!controller->hold(Controller::ACTION) && grabbed_object) { // move the grabbed object a bit away from tux - Vector pos = get_pos() + + Vector pos = get_pos() + Vector(dir == LEFT ? -bbox.get_width()-1 : bbox.get_width()+1, bbox.get_height()*0.66666 - 32); Rect dest(pos, pos + Vector(32, 32)); @@ -613,20 +573,20 @@ Player::handle_input() /* Peeking */ if( controller->released( Controller::PEEK_LEFT ) ) { peeking = AUTO; - } + } if( controller->released( Controller::PEEK_RIGHT ) ) { peeking = AUTO; } if( controller->pressed( Controller::PEEK_LEFT ) ) { peeking = LEFT; - } + } if( controller->pressed( Controller::PEEK_RIGHT ) ) { peeking = RIGHT; } - + /* Handle horizontal movement: */ if (!backflipping) handle_horizontal_input(); - + /* Jump/jumping? */ if (on_ground() && !controller->hold(Controller::JUMP)) can_jump = true; @@ -637,12 +597,12 @@ Player::handle_input() /* Shoot! */ if (controller->pressed(Controller::ACTION) && player_status->bonus == FIRE_BONUS) { if(Sector::current()->add_bullet( - get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2) + get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2) : Vector(32, bbox.get_height()/2)), physic.get_velocity_x(), dir)) shooting_timer.start(SHOOTING_TIME); } - + /* Duck or Standup! */ if (controller->hold(Controller::DOWN)) do_duck(); else do_standup(); @@ -653,13 +613,13 @@ Player::handle_input_ghost() { float vx = 0; float vy = 0; - if (controller->hold(Controller::LEFT)) { - dir = LEFT; - vx -= MAX_RUN_XM * 2; + if (controller->hold(Controller::LEFT)) { + dir = LEFT; + vx -= MAX_RUN_XM * 2; } - if (controller->hold(Controller::RIGHT)) { - dir = RIGHT; - vx += MAX_RUN_XM * 2; + if (controller->hold(Controller::RIGHT)) { + dir = RIGHT; + vx += MAX_RUN_XM * 2; } if ((controller->hold(Controller::UP)) || (controller->hold(Controller::JUMP))) { vy -= MAX_RUN_XM * 2; @@ -684,7 +644,7 @@ bool Player::add_bonus(const std::string& bonustype) { BonusType type = NO_BONUS; - + if(bonustype == "grow") { type = GROWUP_BONUS; } else if(bonustype == "fireflower") { @@ -698,7 +658,7 @@ Player::add_bonus(const std::string& bonustype) msg << "Unknown bonus type " << bonustype; throw std::runtime_error(msg.str()); } - + return add_bonus(type); } @@ -713,7 +673,7 @@ Player::add_bonus(BonusType type, bool animate) // ignore GROWUP_BONUS if we're already big if (type == GROWUP_BONUS) { if (player_status->bonus == GROWUP_BONUS) - return true; + return true; if (player_status->bonus == FIRE_BONUS) return true; if (player_status->bonus == ICE_BONUS) @@ -758,7 +718,7 @@ void Player::set_visible(bool visible) { this->visible = visible; - if( visible ) + if( visible ) set_group(COLGROUP_MOVING); else set_group(COLGROUP_DISABLED); @@ -783,7 +743,7 @@ Player::draw(DrawingContext& context) return; TuxBodyParts* tux_body; - + if (player_status->bonus == GROWUP_BONUS) tux_body = big_tux; else if (player_status->bonus == FIRE_BONUS) @@ -891,7 +851,7 @@ Player::draw(DrawingContext& context) /* Draw Tux */ if(dying) { smalltux_gameover->draw(context, get_pos(), LAYER_FLOATINGOBJECTS + 1); - } + } else if ((growing_timer.get_timeleft() > 0) && (!duck)) { if (dir == RIGHT) { context.draw_surface(growingtux_right[int((growing_timer.get_timegone() * @@ -913,8 +873,8 @@ Player::collision_tile(uint32_t tile_attributes) { if(tile_attributes & Tile::HURTS) kill(false); - - if( swimming ){ + + if( swimming ){ if( tile_attributes & Tile::WATER ){ no_water = false; } else { @@ -979,7 +939,7 @@ Player::collision(GameObject& other, const CollisionHit& hit) #ifdef DEBUG assert(dynamic_cast (&other) != NULL); #endif - MovingObject* moving_object = static_cast (&other); + MovingObject* moving_object = static_cast (&other); if(moving_object->get_group() == COLGROUP_TOUCHABLE) { TriggerBase* trigger = dynamic_cast (&other); if(trigger) { @@ -1006,7 +966,7 @@ Player::make_invincible() { sound_manager->play("sounds/invincible.wav"); invincible_timer.start(TUX_INVINCIBLE_TIME); - Sector::current()->play_music(HERRING_MUSIC); + Sector::current()->play_music(HERRING_MUSIC); } /* Kill Player! */ @@ -1017,8 +977,8 @@ Player::kill(bool completely) return; if(!completely && (safe_timer.started() || invincible_timer.started())) - return; - + return; + sound_manager->play("sounds/hurt.wav"); physic.set_velocity_x(0); @@ -1039,8 +999,8 @@ Player::kill(bool completely) for (int i = 0; (i < 5) && (i < player_status->coins); i++) { // the numbers: starting x, starting y, velocity y - Sector::current()->add_object(new FallingCoin(get_pos() + - Vector(systemRandom.rand(5), systemRandom.rand(-32,18)), + Sector::current()->add_object(new FallingCoin(get_pos() + + Vector(systemRandom.rand(5), systemRandom.rand(-32,18)), systemRandom.rand(-100,100))); } physic.enable_gravity(true); @@ -1085,35 +1045,21 @@ Player::check_bounds(Camera* camera) set_pos(Vector(0, get_pos().y)); } - /* Keep in-bounds, vertically: */ + /* fallen out of the level? */ if (get_pos().y > Sector::current()->get_height()) { kill(true); return; } - bool adjust = false; // can happen if back scrolling is disabled if(get_pos().x < camera->get_translation().x) { set_pos(Vector(camera->get_translation().x, get_pos().y)); - adjust = true; } if(get_pos().x >= camera->get_translation().x + SCREEN_WIDTH - bbox.get_width()) { set_pos(Vector( camera->get_translation().x + SCREEN_WIDTH - bbox.get_width(), get_pos().y)); - adjust = true; - } - - if(adjust) { - // FIXME -#if 0 - // squished now? - if(collision_object_map(bbox)) { - kill(KILL); - return; - } -#endif } } @@ -1126,10 +1072,14 @@ Player::add_velocity(const Vector& velocity) void Player::add_velocity(const Vector& velocity, const Vector& end_speed) { - if (end_speed.x > 0) physic.set_velocity_x(std::min(physic.get_velocity_x() + velocity.x, end_speed.x)); - if (end_speed.x < 0) physic.set_velocity_x(std::max(physic.get_velocity_x() + velocity.x, end_speed.x)); - if (end_speed.y > 0) physic.set_velocity_y(std::min(physic.get_velocity_y() + velocity.y, end_speed.y)); - if (end_speed.y < 0) physic.set_velocity_y(std::max(physic.get_velocity_y() + velocity.y, end_speed.y)); + if (end_speed.x > 0) + physic.set_velocity_x(std::min(physic.get_velocity_x() + velocity.x, end_speed.x)); + if (end_speed.x < 0) + physic.set_velocity_x(std::max(physic.get_velocity_x() + velocity.x, end_speed.x)); + if (end_speed.y > 0) + physic.set_velocity_y(std::min(physic.get_velocity_y() + velocity.y, end_speed.y)); + if (end_speed.y < 0) + physic.set_velocity_y(std::max(physic.get_velocity_y() + velocity.y, end_speed.y)); } void @@ -1146,7 +1096,8 @@ Player::bounce(BadGuy& ) void Player::deactivate() { - if (deactivated) return; + if (deactivated) + return; deactivated = true; physic.set_velocity_x(0); physic.set_velocity_y(0); @@ -1157,7 +1108,8 @@ Player::deactivate() void Player::activate() { - if (!deactivated) return; + if (!deactivated) + return; deactivated = false; } @@ -1169,7 +1121,9 @@ void Player::walk(float speed) void Player::set_ghost_mode(bool enable) { - if (ghost_mode == enable) return; + if (ghost_mode == enable) + return; + if (enable) { ghost_mode = true; set_group(COLGROUP_DISABLED); @@ -1182,4 +1136,3 @@ Player::set_ghost_mode(bool enable) log_debug << "You feel solid again." << std::endl; } } - diff --git a/src/object/player.hpp b/src/object/player.hpp index 885d41ed2..866a0bf74 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -97,7 +97,7 @@ private: int backflip_direction; Direction peeking; bool swimming; - + public: Direction dir; Direction old_dir; @@ -120,7 +120,7 @@ public: Timer idle_timer; Timer backflip_timer; Physic physic; - + public: Player(PlayerStatus* player_status); virtual ~Player(); @@ -153,25 +153,25 @@ public: { return peeking; } - + void kill(bool completely); void check_bounds(Camera* camera); void move(const Vector& vector); virtual bool add_bonus(const std::string& bonus); virtual void add_coins(int count); - + /** * picks up a bonus, taking care not to pick up lesser bonus items than we already have * * @returns true if the bonus has been set (or was already good enough) * false if the bonus could not be set (for example no space for big tux) */ - bool add_bonus(BonusType type, bool animate = false); + bool add_bonus(BonusType type, bool animate = false); /** * like add_bonus, but can also downgrade the bonus items carried - */ - bool set_bonus(BonusType type, bool animate = false); + */ + bool set_bonus(BonusType type, bool animate = false); PlayerStatus* get_status() { @@ -180,7 +180,7 @@ public: // set kick animation void kick(); - /** + /** * play cheer animation. * This might need some space and behave in an unpredictable way. Best to use this at level end. */ @@ -235,7 +235,7 @@ public: } /** - * Switches ghost mode on/off. + * Switches ghost mode on/off. * Lets Tux float around and through solid objects. */ void set_ghost_mode(bool enable); @@ -255,9 +255,9 @@ private: void handle_input(); void handle_input_ghost(); /**< input handling while in ghost mode */ bool deactivated; - + void init(); - + void handle_horizontal_input(); void handle_vertical_input(); diff --git a/src/object/portable.hpp b/src/object/portable.hpp index 6358b9d54..52802ba78 100644 --- a/src/object/portable.hpp +++ b/src/object/portable.hpp @@ -35,7 +35,7 @@ class Portable public: virtual ~Portable() { } - + /** * called each frame when the object has been grabbed. */ diff --git a/src/object/powerup.cpp b/src/object/powerup.cpp index b865ba81b..09a747063 100644 --- a/src/object/powerup.cpp +++ b/src/object/powerup.cpp @@ -93,4 +93,3 @@ PowerUp::update(float elapsed_time) } IMPLEMENT_FACTORY(PowerUp, "powerup"); - diff --git a/src/object/powerup.hpp b/src/object/powerup.hpp index 04ccb35c7..5ed2b4970 100644 --- a/src/object/powerup.hpp +++ b/src/object/powerup.hpp @@ -33,7 +33,7 @@ public: virtual void update(float elapsed_time); virtual void collision_solid(const CollisionHit& hit); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); - + private: Physic physic; std::string script; @@ -41,4 +41,3 @@ private: }; #endif - diff --git a/src/object/rainsplash.cpp b/src/object/rainsplash.cpp index b4241f6ae..913baea08 100644 --- a/src/object/rainsplash.cpp +++ b/src/object/rainsplash.cpp @@ -27,7 +27,7 @@ RainSplash::RainSplash(Vector pos, bool vertical) if (vertical) sprite = sprite_manager->create("images/objects/particles/rainsplash-vertical.sprite"); else sprite = sprite_manager->create("images/objects/particles/rainsplash.sprite"); } - + RainSplash::~RainSplash() { remove_me(); } @@ -38,7 +38,7 @@ RainSplash::hit(Player& ) } void -RainSplash::update(float time) +RainSplash::update(float time) { time = 0;//just so i don't get an "unused variable" error - don't know how to circumvent this frame++; @@ -46,7 +46,7 @@ RainSplash::update(float time) } void -RainSplash::draw(DrawingContext& context) +RainSplash::draw(DrawingContext& context) { sprite->draw(context, position, LAYER_OBJECTS); } diff --git a/src/object/rainsplash.hpp b/src/object/rainsplash.hpp index 180b292d3..61e438f21 100644 --- a/src/object/rainsplash.hpp +++ b/src/object/rainsplash.hpp @@ -33,7 +33,7 @@ class RainSplash : public GameObject public: RainSplash(Vector pos, bool vertical); ~RainSplash(); -protected: +protected: virtual void hit(Player& ); virtual void update(float time); virtual void draw(DrawingContext& context); @@ -44,4 +44,3 @@ private: }; #endif - diff --git a/src/object/rock.cpp b/src/object/rock.cpp index c05cea626..f0b6c2c43 100644 --- a/src/object/rock.cpp +++ b/src/object/rock.cpp @@ -53,7 +53,7 @@ Rock::update(float elapsed_time) { if( grabbed ) return; - + movement = physic.get_movement(elapsed_time); } @@ -66,7 +66,7 @@ Rock::collision_solid(const CollisionHit& hit) physic.set_velocity_x( 0 ); if( hit.crush ) physic.set_velocity(0, 0); - + if( hit.bottom && !on_ground ){ sound_manager->play( ROCK_SOUND, get_pos() ); on_ground = true; @@ -79,16 +79,16 @@ Rock::collision(GameObject& other, const CollisionHit& hit) if( !on_ground ){ return FORCE_MOVE; } - - //Fake being solid for moving_object. + + //Fake being solid for moving_object. MovingObject* moving_object = dynamic_cast (&other); if( moving_object ){ if( hit.top ){ float inside = moving_object->get_bbox().get_bottom() - get_bbox().get_top(); if( inside > 0 ){ Vector pos = moving_object->get_pos(); - pos.y -= inside; - moving_object->set_pos( pos ); + pos.y -= inside; + moving_object->set_pos( pos ); } } CollisionHit hit_other = hit; @@ -106,7 +106,7 @@ Rock::grab(MovingObject& , const Vector& pos, Direction) set_group( COLGROUP_DISABLED ); on_ground = true; grabbed = true; - + } void @@ -118,4 +118,3 @@ Rock::ungrab(MovingObject& , Direction ){ } IMPLEMENT_FACTORY(Rock, "rock"); - diff --git a/src/object/rock.hpp b/src/object/rock.hpp index 13c084029..8ce1cb40b 100644 --- a/src/object/rock.hpp +++ b/src/object/rock.hpp @@ -38,7 +38,7 @@ public: HitResponse collision(GameObject& other, const CollisionHit& hit); void update(float elapsed_time); void write(lisp::Writer& writer); - + void grab(MovingObject& object, const Vector& pos, Direction dir); void ungrab(MovingObject& object, Direction dir); diff --git a/src/object/scripted_object.cpp b/src/object/scripted_object.cpp index 90875f2c9..67963ec26 100644 --- a/src/object/scripted_object.cpp +++ b/src/object/scripted_object.cpp @@ -35,7 +35,7 @@ ScriptedObject::ScriptedObject(const lisp::Lisp& lisp) lisp.get("name", name); if(name == "") throw std::runtime_error("Scripted object must have a name specified"); - + // FIXME: do we need this? bbox is already set via .sprite file float width = sprite->get_width(); float height = sprite->get_height(); diff --git a/src/object/scripted_object.hpp b/src/object/scripted_object.hpp index 7231d3d24..1e432a729 100644 --- a/src/object/scripted_object.hpp +++ b/src/object/scripted_object.hpp @@ -39,7 +39,7 @@ public: void update(float elapsed_time); void draw(DrawingContext& context); - + void collision_solid(const CollisionHit& hit); HitResponse collision(GameObject& other, const CollisionHit& hit); @@ -73,4 +73,3 @@ private: }; #endif - diff --git a/src/object/skull_tile.cpp b/src/object/skull_tile.cpp index abbddd816..04f140c59 100644 --- a/src/object/skull_tile.cpp +++ b/src/object/skull_tile.cpp @@ -54,7 +54,7 @@ SkullTile::draw(DrawingContext& context) // shacking if(timer.get_timegone() > CRACKTIME) { pos.x += systemRandom.rand(-3, 3); - } + } sprite->draw(context, pos, layer); } @@ -71,7 +71,7 @@ SkullTile::update(float elapsed_time) } else if(hit) { if(timer.check()) { falling = true; - physic.enable_gravity(true); + physic.enable_gravity(true); flags &= ~FLAG_SOLID; timer.stop(); } else if(!timer.started()) { diff --git a/src/object/skull_tile.hpp b/src/object/skull_tile.hpp index 183ae34eb..f9a19fcba 100644 --- a/src/object/skull_tile.hpp +++ b/src/object/skull_tile.hpp @@ -46,4 +46,3 @@ private: }; #endif - diff --git a/src/object/specialriser.cpp b/src/object/specialriser.cpp index 9cb36903b..60c7861e0 100644 --- a/src/object/specialriser.cpp +++ b/src/object/specialriser.cpp @@ -56,4 +56,3 @@ SpecialRiser::draw(DrawingContext& context) child->draw(context); context.pop_transform(); } - diff --git a/src/object/specialriser.hpp b/src/object/specialriser.hpp index 922f3c08d..03f9347d8 100644 --- a/src/object/specialriser.hpp +++ b/src/object/specialriser.hpp @@ -41,4 +41,3 @@ private: }; #endif - diff --git a/src/object/spotlight.cpp b/src/object/spotlight.cpp index 6a29688d6..6903aa86e 100644 --- a/src/object/spotlight.cpp +++ b/src/object/spotlight.cpp @@ -40,7 +40,7 @@ Spotlight::Spotlight(const lisp::Lisp& lisp) lisp.get("green", color.green); lisp.get("blue", color.blue); lisp.get("alpha", color.alpha); - + center = sprite_manager->create("images/objects/spotlight/spotlight_center.sprite"); base = sprite_manager->create("images/objects/spotlight/spotlight_base.sprite"); lights = sprite_manager->create("images/objects/spotlight/spotlight_lights.sprite"); @@ -68,9 +68,9 @@ Spotlight::update(float delta) void Spotlight::draw(DrawingContext& context) { - context.push_target(); + context.push_target(); context.set_target(DrawingContext::LIGHTMAP); - + light->set_color(color); light->set_blend(Blend(GL_SRC_ALPHA, GL_ONE)); light->set_angle(angle); @@ -78,7 +78,7 @@ Spotlight::draw(DrawingContext& context) //lightcone->set_angle(angle); //lightcone->draw(context, position, 0); - + context.set_target(DrawingContext::NORMAL); lights->set_angle(angle); diff --git a/src/object/spotlight.hpp b/src/object/spotlight.hpp index 2cfabb42a..bb4e7ce7f 100644 --- a/src/object/spotlight.hpp +++ b/src/object/spotlight.hpp @@ -49,4 +49,3 @@ private: }; #endif - diff --git a/src/object/sprite_particle.cpp b/src/object/sprite_particle.cpp index 0babaf276..18d7b888e 100644 --- a/src/object/sprite_particle.cpp +++ b/src/object/sprite_particle.cpp @@ -25,7 +25,7 @@ #include "main.hpp" #include "log.hpp" -SpriteParticle::SpriteParticle(std::string sprite_name, std::string action, Vector position, AnchorPoint anchor, Vector velocity, Vector acceleration, int drawing_layer) +SpriteParticle::SpriteParticle(std::string sprite_name, std::string action, Vector position, AnchorPoint anchor, Vector velocity, Vector acceleration, int drawing_layer) : position(position), velocity(velocity), acceleration(acceleration), drawing_layer(drawing_layer) { sprite = sprite_manager->create(sprite_name); @@ -35,8 +35,8 @@ SpriteParticle::SpriteParticle(std::string sprite_name, std::string action, Vect this->position -= get_anchor_pos(sprite->get_current_hitbox(), anchor); } - -SpriteParticle::~SpriteParticle() + +SpriteParticle::~SpriteParticle() { remove_me(); } @@ -47,7 +47,7 @@ SpriteParticle::hit(Player& ) } void -SpriteParticle::update(float elapsed_time) +SpriteParticle::update(float elapsed_time) { // die when animation is complete if (sprite->animation_done()) { @@ -63,7 +63,7 @@ SpriteParticle::update(float elapsed_time) // die when too far offscreen Vector camera = Sector::current()->camera->get_translation(); - if ((position.x < camera.x - 128) || (position.x > SCREEN_WIDTH + camera.x + 128) || + if ((position.x < camera.x - 128) || (position.x > SCREEN_WIDTH + camera.x + 128) || (position.y < camera.y - 128) || (position.y > SCREEN_HEIGHT + camera.y + 128)) { remove_me(); return; @@ -71,7 +71,7 @@ SpriteParticle::update(float elapsed_time) } void -SpriteParticle::draw(DrawingContext& context) +SpriteParticle::draw(DrawingContext& context) { sprite->draw(context, position, drawing_layer); } diff --git a/src/object/sprite_particle.hpp b/src/object/sprite_particle.hpp index a09b04998..dba9caaff 100644 --- a/src/object/sprite_particle.hpp +++ b/src/object/sprite_particle.hpp @@ -35,7 +35,7 @@ class SpriteParticle : public GameObject public: SpriteParticle(std::string sprite_name, std::string action, Vector position, AnchorPoint anchor, Vector velocity, Vector acceleration, int drawing_layer = LAYER_OBJECTS-1); ~SpriteParticle(); -protected: +protected: virtual void hit(Player& player); virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); @@ -48,4 +48,3 @@ private: }; #endif - diff --git a/src/object/star.cpp b/src/object/star.cpp index 617704c54..316f572d3 100644 --- a/src/object/star.cpp +++ b/src/object/star.cpp @@ -66,4 +66,3 @@ Star::collision(GameObject& other, const CollisionHit& ) return FORCE_MOVE; } - diff --git a/src/object/text_object.cpp b/src/object/text_object.cpp index ef591eeb2..af3564368 100644 --- a/src/object/text_object.cpp +++ b/src/object/text_object.cpp @@ -145,4 +145,3 @@ TextObject::update(float elapsed_time) } } } - diff --git a/src/object/text_object.hpp b/src/object/text_object.hpp index c324e839c..e649ef10e 100644 --- a/src/object/text_object.hpp +++ b/src/object/text_object.hpp @@ -58,4 +58,3 @@ private: }; #endif - diff --git a/src/object/thunderstorm.cpp b/src/object/thunderstorm.cpp index 1aec3625f..f86279c73 100644 --- a/src/object/thunderstorm.cpp +++ b/src/object/thunderstorm.cpp @@ -74,8 +74,8 @@ Thunderstorm::update(float ) } } -void -Thunderstorm::draw(DrawingContext& context) +void +Thunderstorm::draw(DrawingContext& context) { if (!flash_display_timer.started()) return; @@ -149,4 +149,3 @@ Thunderstorm::electrify() } IMPLEMENT_FACTORY(Thunderstorm, "thunderstorm"); - diff --git a/src/object/thunderstorm.hpp b/src/object/thunderstorm.hpp index 77f8f6887..ee1430346 100644 --- a/src/object/thunderstorm.hpp +++ b/src/object/thunderstorm.hpp @@ -44,7 +44,7 @@ public: * Start playing thunder and lightning at configured interval */ void start(); - + /** * Stop playing thunder and lightning at configured interval */ @@ -74,11 +74,10 @@ private: std::string name; /**< user-defined name for use in scripts or empty string if not scriptable */ bool running; /**< whether we currently automatically trigger lightnings */ float interval; /**< time between two lightnings */ - + Timer time_to_thunder; /**< counts down until next thunder */ Timer time_to_lightning; /**< counts down until next lightning */ Timer flash_display_timer; /**< counts down while flash is displayed */ }; #endif - diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index d9712820e..96a51536d 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -66,7 +66,7 @@ TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager) } if(solid) flags |= FLAG_SOLID; - + reader.get("width", width); reader.get("height", height); if(width < 0 || height < 0) @@ -89,11 +89,11 @@ TileMap::TileMap(std::string name, int z_pos, bool solid, size_t width, size_t h x_offset(0), y_offset(0), drawing_effect(NO_EFFECT) { tilemanager = tile_manager; - + resize(width, height); if(solid) - flags |= FLAG_SOLID; + flags |= FLAG_SOLID; } TileMap::~TileMap() @@ -112,7 +112,7 @@ TileMap::write(lisp::Writer& writer) writer.write_int("width", width); writer.write_int("height", height); writer.write_int_vector("tiles", tiles); - + writer.end_list("tilemap"); } @@ -132,7 +132,7 @@ TileMap::draw(DrawingContext& context) { context.push_transform(); - if(drawing_effect != 0) context.set_drawing_effect(drawing_effect); + if(drawing_effect != 0) context.set_drawing_effect(drawing_effect); float trans_x = roundf(context.get_translation().x); float trans_y = roundf(context.get_translation().y); context.set_translation(Vector(trans_x * speed, trans_y * speed)); @@ -180,7 +180,7 @@ TileMap::set(int newwidth, int newheight, const std::vector&newt, // make sure all tiles are loaded for(Tiles::iterator i = tiles.begin(); i != tiles.end(); ++i) - tilemanager->get(*i); + tilemanager->get(*i); } void @@ -194,9 +194,9 @@ TileMap::resize(int new_width, int new_height) } } } - + tiles.resize(new_width * new_height); - + if(new_width > width) { // remap tiles for(int y = std::min(height, new_height)-1; y >= 0; --y) { @@ -205,7 +205,7 @@ TileMap::resize(int new_width, int new_height) tiles[y * new_width + x] = 0; continue; } - + tiles[y * new_width + x] = tiles[y * width + x]; } } diff --git a/src/object/tilemap.hpp b/src/object/tilemap.hpp index 981749309..cb87573b7 100644 --- a/src/object/tilemap.hpp +++ b/src/object/tilemap.hpp @@ -66,10 +66,10 @@ public: size_t get_height() const { return height; } - + float get_x_offset() const { return x_offset; } - + float get_y_offset() const { return y_offset; } @@ -81,7 +81,7 @@ public: int get_layer() const { return z_pos; } - + bool is_solid() const { return solid; } @@ -115,7 +115,7 @@ public: private: typedef std::vector Tiles; Tiles tiles; - + private: TileManager* tilemanager; std::string name; @@ -130,4 +130,3 @@ private: }; #endif /*SUPERTUX_TILEMAP_H*/ - diff --git a/src/object/trampoline.cpp b/src/object/trampoline.cpp index 0260e950e..ed83793ec 100644 --- a/src/object/trampoline.cpp +++ b/src/object/trampoline.cpp @@ -2,7 +2,7 @@ // // SuperTux - Trampoline // Copyright (C) 2006 Wolfgang Becker -// +// // 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 @@ -25,7 +25,7 @@ #include "audio/sound_manager.hpp" #include "sprite/sprite_manager.hpp" -/* Trampoline will accelerate player to to VY_INITIAL, if +/* Trampoline will accelerate player to to VY_INITIAL, if * he jumps on it to VY_MIN. */ namespace { const std::string TRAMPOLINE_SOUND = "sounds/trampoline.wav"; @@ -77,7 +77,7 @@ Trampoline::collision(GameObject& other, const CollisionHit& hit ) float vy = player->physic.get_velocity_y(); //player is falling down on trampoline if(hit.top && vy > 0) { - if(player->get_controller()->hold(Controller::JUMP)) { + if(player->get_controller()->hold(Controller::JUMP)) { vy = VY_MIN; } else { vy = VY_INITIAL; @@ -88,15 +88,15 @@ Trampoline::collision(GameObject& other, const CollisionHit& hit ) return FORCE_MOVE; } } - //Fake being solid for moving_object. + //Fake being solid for moving_object. MovingObject* moving_object = dynamic_cast (&other); if( moving_object ){ if( hit.top ){ float inside = moving_object->get_bbox().get_bottom() - get_bbox().get_top(); if( inside > 0 ){ Vector pos = moving_object->get_pos(); - pos.y -= inside; - moving_object->set_pos( pos ); + pos.y -= inside; + moving_object->set_pos( pos ); } } CollisionHit hit_other = hit; @@ -107,12 +107,12 @@ Trampoline::collision(GameObject& other, const CollisionHit& hit ) return FORCE_MOVE; } -void +void Trampoline::collision_solid( const CollisionHit& hit ){ if( hit.bottom ){ on_ground = true; } -} +} void Trampoline::grab( MovingObject&, const Vector& pos, Direction ){ diff --git a/src/object/trampoline.hpp b/src/object/trampoline.hpp index f856ca017..8f846c655 100644 --- a/src/object/trampoline.hpp +++ b/src/object/trampoline.hpp @@ -25,27 +25,26 @@ #include "object/portable.hpp" #include "physic.hpp" -/** +/** * Jumping on a trampolin makes tux jump higher. */ -class Trampoline : public MovingSprite, +class Trampoline : public MovingSprite, public Portable - + { public: Trampoline(const lisp::Lisp& reader); - + HitResponse collision(GameObject& other, const CollisionHit& hit); void collision_solid( const CollisionHit& hit ); void update( float elapsed_time ); void grab( MovingObject&, const Vector& pos, Direction ); void ungrab(MovingObject& , Direction ); - + private: Physic physic; bool on_ground; }; #endif - diff --git a/src/object/unstable_tile.hpp b/src/object/unstable_tile.hpp index cd19c4e0d..9c6e0bd76 100644 --- a/src/object/unstable_tile.hpp +++ b/src/object/unstable_tile.hpp @@ -26,7 +26,7 @@ #include "physic.hpp" #include "timer.hpp" -/** +/** * A block that disintegrates when stood on */ class UnstableTile : public MovingSprite @@ -50,4 +50,3 @@ private: }; #endif - diff --git a/src/object/weak_block.hpp b/src/object/weak_block.hpp index cc5baf85f..e36d1eb66 100644 --- a/src/object/weak_block.hpp +++ b/src/object/weak_block.hpp @@ -26,7 +26,7 @@ #include "physic.hpp" #include "timer.hpp" -/** +/** * A block that can be destroyed by Bullet hits */ class WeakBlock : public MovingSprite @@ -60,4 +60,3 @@ private: }; #endif - diff --git a/src/object/wind.hpp b/src/object/wind.hpp index 2da07d968..8411ca296 100644 --- a/src/object/wind.hpp +++ b/src/object/wind.hpp @@ -28,7 +28,7 @@ class Player; -/** +/** * Defines an area that will gently push Players in one direction */ class Wind : public MovingObject, public ScriptInterface @@ -39,12 +39,12 @@ public: void update(float elapsed_time); void draw(DrawingContext& context); HitResponse collision(GameObject& other, const CollisionHit& hit); - + /** * start blowing */ void start(); - + /** * stop blowing */ @@ -52,10 +52,10 @@ public: virtual void expose(HSQUIRRELVM vm, SQInteger table_idx); virtual void unexpose(HSQUIRRELVM vm, SQInteger table_idx); - + private: std::string name; /**< user-defined name for use in scripts or empty string if not scriptable */ - + bool blowing; /**< true if wind is currently switched on */ Vector speed; float acceleration; @@ -64,4 +64,3 @@ private: }; #endif - diff --git a/src/object_factory.cpp b/src/object_factory.cpp index afae27fee..0b6916961 100644 --- a/src/object_factory.cpp +++ b/src/object_factory.cpp @@ -46,7 +46,7 @@ GameObject* create_object(const std::string& name, const Vector& pos) lisptext << "(" << name << " (x " << pos.x << ")" << " (y " << pos.y << "))"; - + lisp::Parser parser; std::auto_ptr lisp (parser.parse(lisptext)); return create_object(name, *lisp); diff --git a/src/object_factory.hpp b/src/object_factory.hpp index 922eec44c..7e06739c6 100644 --- a/src/object_factory.hpp +++ b/src/object_factory.hpp @@ -32,7 +32,7 @@ class Factory public: virtual ~Factory() { } - + /** Creates a new gameobject from a lisp node. * Remember to delete the objects later */ diff --git a/src/object_remove_listener.hpp b/src/object_remove_listener.hpp index 4523707df..a405466d0 100644 --- a/src/object_remove_listener.hpp +++ b/src/object_remove_listener.hpp @@ -33,4 +33,3 @@ public: }; #endif - diff --git a/src/physfs/physfs_sdl.cpp b/src/physfs/physfs_sdl.cpp index 2a22af6bd..5ac130814 100644 --- a/src/physfs/physfs_sdl.cpp +++ b/src/physfs/physfs_sdl.cpp @@ -68,7 +68,7 @@ static int funcRead(struct SDL_RWops* context, void* ptr, int size, int maxnum) static int funcClose(struct SDL_RWops* context) { PHYSFS_file* file = (PHYSFS_file*) context->hidden.unknown.data1; - + PHYSFS_close(file); delete context; @@ -84,7 +84,7 @@ SDL_RWops* get_physfs_SDLRWops(const std::string& filename) << PHYSFS_getLastError(); throw std::runtime_error(msg.str()); } - + SDL_RWops* ops = new SDL_RWops(); ops->type = 0; ops->hidden.unknown.data1 = file; diff --git a/src/physfs/physfs_sdl.hpp b/src/physfs/physfs_sdl.hpp index 5707e7d01..214d0b127 100644 --- a/src/physfs/physfs_sdl.hpp +++ b/src/physfs/physfs_sdl.hpp @@ -26,4 +26,3 @@ SDL_RWops* get_physfs_SDLRWops(const std::string& filename); #endif - diff --git a/src/physfs/physfs_stream.cpp b/src/physfs/physfs_stream.cpp index acb267031..3a3c74b63 100644 --- a/src/physfs/physfs_stream.cpp +++ b/src/physfs/physfs_stream.cpp @@ -48,7 +48,7 @@ IFileStreambuf::underflow() if(PHYSFS_eof(file)) { return traits_type::eof(); } - + PHYSFS_sint64 bytesread = (size_t) PHYSFS_read(file, buf, 1, sizeof(buf)); if(bytesread <= 0) { return traits_type::eof(); @@ -76,7 +76,7 @@ IFileStreambuf::seekoff(off_type off, std::ios_base::seekdir dir, { off_type pos = off; PHYSFS_sint64 ptell = PHYSFS_tell(file); - + switch(dir) { case std::ios_base::beg: break; @@ -110,7 +110,7 @@ OFileStreambuf::OFileStreambuf(const std::string& filename) << PHYSFS_getLastError(); throw std::runtime_error(msg.str()); } - + setp(buf, buf+sizeof(buf)); } @@ -130,7 +130,7 @@ OFileStreambuf::overflow(int c) PHYSFS_sint64 res = PHYSFS_write(file, pbase(), 1, size); if(res <= 0) return traits_type::eof(); - + if(c != traits_type::eof()) { PHYSFS_sint64 res = PHYSFS_write(file, &c, 1, 1); if(res <= 0) @@ -170,4 +170,3 @@ OFileStream::~OFileStream() { delete rdbuf(); } - diff --git a/src/physfs/physfs_stream.hpp b/src/physfs/physfs_stream.hpp index 3f4bd1817..077a8760b 100644 --- a/src/physfs/physfs_stream.hpp +++ b/src/physfs/physfs_stream.hpp @@ -34,7 +34,7 @@ class IFileStreambuf : public std::streambuf public: IFileStreambuf(const std::string& filename); ~IFileStreambuf(); - + protected: virtual int underflow(); virtual pos_type seekoff(off_type pos, std::ios_base::seekdir, @@ -76,4 +76,3 @@ public: }; #endif - diff --git a/src/physic.cpp b/src/physic.cpp index 518ce8349..358b41c73 100644 --- a/src/physic.cpp +++ b/src/physic.cpp @@ -145,14 +145,13 @@ Vector Physic::get_movement(float elapsed_time) { float grav = gravity_enabled_flag ? 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; + vy += (ay + grav) * elapsed_time; return result; } - diff --git a/src/player_status.cpp b/src/player_status.cpp index f39ded0e8..ee8647701 100644 --- a/src/player_status.cpp +++ b/src/player_status.cpp @@ -45,7 +45,7 @@ PlayerStatus::PlayerStatus() max_score_multiplier(1) { reset(); - + tux_life.reset(sprite_manager->create("images/creatures/tux_small/tux-life.sprite")); Console::instance->registerCommand("coins", this); @@ -97,7 +97,7 @@ PlayerStatus::write(lisp::Writer& writer) } writer.write_int("fireflowers", max_fire_bullets); writer.write_int("iceflowers", max_ice_bullets); - + writer.write_int("coins", coins); writer.write_int("max-score-multiplier", max_score_multiplier); } @@ -106,7 +106,7 @@ void PlayerStatus::read(const lisp::Lisp& lisp) { reset(); - + std::string bonusname; if(lisp.get("bonus", bonusname)) { if(bonusname == "none") { @@ -136,7 +136,7 @@ PlayerStatus::draw(DrawingContext& context) context.set_translation(Vector(0, 0)); char str[60]; - + int displayCoins = std::max(player_status->coins, 0); snprintf(str, sizeof(str), "%d", displayCoins); const char* coinstext = _("COINS"); @@ -168,4 +168,3 @@ PlayerStatus::consoleCommand(std::string command, std::vector argum } return false; } - diff --git a/src/player_status.hpp b/src/player_status.hpp index 16cb9069b..155972524 100644 --- a/src/player_status.hpp +++ b/src/player_status.hpp @@ -36,7 +36,7 @@ enum BonusType { }; class DrawingContext; -/** +/** * This class memorizes player status between different game sessions (for * example when switching maps in the worldmap) */ @@ -45,7 +45,7 @@ class PlayerStatus : public Serializable, public ConsoleCommandReceiver public: PlayerStatus(); ~PlayerStatus(); - void reset(); + void reset(); void add_coins(int count, bool play_sound = true); void write(lisp::Writer& writer); @@ -54,7 +54,7 @@ public: void draw(DrawingContext& context); bool consoleCommand(std::string command, std::vector arguments); /**< callback from Console; return false if command was unknown, true otherwise */ - + int coins; BonusType bonus; int max_fire_bullets; /**< maximum number of fire bullets in play */ @@ -64,11 +64,11 @@ public: int max_score_multiplier; void operator= (const PlayerStatus& other); - + private: // don't use this PlayerStatus(const PlayerStatus& other); - + std::auto_ptr tux_life; }; diff --git a/src/random_generator.cpp b/src/random_generator.cpp index 69bd8406d..0fd8dc5ac 100644 --- a/src/random_generator.cpp +++ b/src/random_generator.cpp @@ -1,5 +1,5 @@ // $Id$ -// +// // A strong random number generator // // Copyright (C) 2006 Allen King @@ -9,16 +9,16 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. +// documentation and/or other materials provided with the distribution. // 3. Neither the name of the project nor the names of its contributors // may be used to endorse or promote products derived from this software -// without specific prior written permission. -// +// without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -28,7 +28,7 @@ // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // Transliterated into C++ Allen King 060417, from sources on @@ -58,7 +58,7 @@ int RandomGenerator::srand(int x) { x = time(0) % RandomGenerator::rand_max; // randomize with time if (debug > 0) - printf("==== srand(%10d) (%10d) rand_max=%x =====\n", + printf("==== srand(%10d) (%10d) rand_max=%x =====\n", x, x0, RandomGenerator::rand_max); RandomGenerator::srandom(x); @@ -86,7 +86,7 @@ int RandomGenerator::rand(int v) { } int RandomGenerator::rand(int u, int v) { - assert(v > u); + assert(v > u); return u + RandomGenerator::rand(v-u); } @@ -106,23 +106,23 @@ double RandomGenerator::randf(double u, double v) { } //----------------------------------------------------------------------- -// +// // Copyright (C) 2002 Michael Ringgaard. All rights reserved. // Copyright (C) 1983, 1993 The Regents of the University of California. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. +// documentation and/or other materials provided with the distribution. // 3. Neither the name of the project nor the names of its contributors // may be used to endorse or promote products derived from this software -// without specific prior written permission. -// +// without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -132,9 +132,9 @@ double RandomGenerator::randf(double u, double v) { // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. -// +// //**#include @@ -250,7 +250,7 @@ void RandomGenerator::initialize() { randtbl[30] = 0x535b6b41; randtbl[31] = 0xf3bec5da; -// static long randtbl[DEG_3 + 1] = +// static long randtbl[DEG_3 + 1] = // { // TYPE_3; // 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05, @@ -340,7 +340,7 @@ void RandomGenerator::srandom(unsigned long x) state[0] = x; if (rand_type == TYPE_0) lim = NSHUFF; - else + else { for (i = 1; i < rand_deg; i++) state[i] = good_rand(state[i - 1]); fptr = &state[rand_sep]; @@ -380,13 +380,13 @@ void RandomGenerator::srandomdev() done = 0; fd = open("/dev/urandom", O_RDONLY); - if (fd >= 0) + if (fd >= 0) { if (read(fd, state, len) == len) done = 1; close(fd); } - if (!done) + if (!done) { struct timeval tv; @@ -395,7 +395,7 @@ void RandomGenerator::srandomdev() return; } - if (rand_type != TYPE_0) + if (rand_type != TYPE_0) { fptr = &state[rand_sep]; rptr = &state[0]; @@ -435,37 +435,37 @@ char * RandomGenerator::initstate(unsigned long seed, char *arg_state, long n) if (n < BREAK_0) return NULL; - if (n < BREAK_1) + if (n < BREAK_1) { rand_type = TYPE_0; rand_deg = DEG_0; rand_sep = SEP_0; - } - else if (n < BREAK_2) + } + else if (n < BREAK_2) { rand_type = TYPE_1; rand_deg = DEG_1; rand_sep = SEP_1; - } - else if (n < BREAK_3) + } + else if (n < BREAK_3) { rand_type = TYPE_2; rand_deg = DEG_2; rand_sep = SEP_2; - } - else if (n < BREAK_4) + } + else if (n < BREAK_4) { rand_type = TYPE_3; rand_deg = DEG_3; rand_sep = SEP_3; - } - else + } + else { rand_type = TYPE_4; rand_deg = DEG_4; rand_sep = SEP_4; } - + state = (long *) (long_arg_state + 1); // First location end_ptr = &state[rand_deg]; // Must set end_ptr before srandom srandom(seed); @@ -507,7 +507,7 @@ char * RandomGenerator::setstate(char *arg_state) else state[-1] = MAX_TYPES * (rptr - state) + rand_type; - switch(type) + switch(type) { case TYPE_0: case TYPE_1: @@ -521,7 +521,7 @@ char * RandomGenerator::setstate(char *arg_state) } state = (long *) (new_state + 1); - if (rand_type != TYPE_0) + if (rand_type != TYPE_0) { rptr = &state[rear]; fptr = &state[(rear + rand_sep) % rand_deg]; @@ -558,22 +558,22 @@ long RandomGenerator::random() throw std::runtime_error("uninitialized RandomGenerator object"); } - if (rand_type == TYPE_0) + if (rand_type == TYPE_0) { i = state[0]; state[0] = i = (good_rand(i)) & 0x7fffffff; - } - else + } + else { f = fptr; r = rptr; *f += *r; i = (*f >> 1) & 0x7fffffff; // Chucking least random bit - if (++f >= end_ptr) + if (++f >= end_ptr) { f = state; ++r; } - else if (++r >= end_ptr) + else if (++r >= end_ptr) r = state; fptr = f; rptr = r; diff --git a/src/random_generator.hpp b/src/random_generator.hpp index 4bf605ea0..480a53ed0 100644 --- a/src/random_generator.hpp +++ b/src/random_generator.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // A strong random number generator // // Copyright (C) 2006 Allen King @@ -9,16 +9,16 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. +// documentation and/or other materials provided with the distribution. // 3. Neither the name of the project nor the names of its contributors // may be used to endorse or promote products derived from this software -// without specific prior written permission. -// +// without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -28,7 +28,7 @@ // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. #ifndef __RANDOM_GENERATOR__ diff --git a/src/ref.hpp b/src/ref.hpp index 76f5677a6..4e15c0f63 100644 --- a/src/ref.hpp +++ b/src/ref.hpp @@ -85,4 +85,3 @@ private: }; #endif - diff --git a/src/refcounter.hpp b/src/refcounter.hpp index c6d95984e..0a56b0680 100644 --- a/src/refcounter.hpp +++ b/src/refcounter.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // Windstille - A Jump'n Shoot Game // Copyright (C) 2005 Matthias Braun // @@ -12,7 +12,7 @@ // 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. diff --git a/src/resources.cpp b/src/resources.cpp index 94e85e1d2..5c49081e9 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -47,7 +47,7 @@ void load_shared() /* Load global images: */ gold_text = new Font("images/engine/fonts/gold.png", "images/engine/fonts/shadow.png", 16, 18); - blue_text = new Font("images/engine/fonts/blue.png", + blue_text = new Font("images/engine/fonts/blue.png", "images/engine/fonts/shadow.png", 16, 18, 3); white_text = new Font("images/engine/fonts/white.png", "images/engine/fonts/shadow.png", 16, 18); @@ -63,7 +63,7 @@ void load_shared() Menu::deactive_font = gray_text; Menu::label_font = white_big_text; Menu::field_font = gold_text; - + Button::info_font = white_small_text; sprite_manager = new SpriteManager(); @@ -136,4 +136,3 @@ void unload_shared() /* Free mouse-cursor */ delete mouse_cursor; } - diff --git a/src/screen.hpp b/src/screen.hpp index 8eebc1b75..a2b753c27 100644 --- a/src/screen.hpp +++ b/src/screen.hpp @@ -51,4 +51,3 @@ public: }; #endif - diff --git a/src/screen_fade.hpp b/src/screen_fade.hpp index 5a91489f6..952d0341c 100644 --- a/src/screen_fade.hpp +++ b/src/screen_fade.hpp @@ -30,10 +30,9 @@ class ScreenFade : public Screen public: virtual ~ScreenFade() {} - + /// returns true if the effect is completed virtual bool done() = 0; }; #endif - diff --git a/src/script_interface.hpp b/src/script_interface.hpp index 61226705b..3f47bcfb9 100644 --- a/src/script_interface.hpp +++ b/src/script_interface.hpp @@ -31,10 +31,9 @@ class ScriptInterface public: virtual ~ScriptInterface() {} - + virtual void expose(HSQUIRRELVM vm, SQInteger table_idx) = 0; virtual void unexpose(HSQUIRRELVM vm, SQInteger table_idx) = 0; }; #endif - diff --git a/src/scripting/ambient_sound.hpp b/src/scripting/ambient_sound.hpp index 2cff32c5d..b547b802b 100644 --- a/src/scripting/ambient_sound.hpp +++ b/src/scripting/ambient_sound.hpp @@ -20,4 +20,3 @@ public: } #endif - diff --git a/src/scripting/anchor_points.hpp b/src/scripting/anchor_points.hpp index 73ef04929..a0dff3874 100644 --- a/src/scripting/anchor_points.hpp +++ b/src/scripting/anchor_points.hpp @@ -36,4 +36,3 @@ static const int ANCHOR_BOTTOM_RIGHT = 0x0022; } #endif - diff --git a/src/scripting/camera.cpp b/src/scripting/camera.cpp index cb4a93b97..814284b8a 100644 --- a/src/scripting/camera.cpp +++ b/src/scripting/camera.cpp @@ -35,13 +35,13 @@ namespace Scripting Camera::~Camera() { } - + void Camera::shake(float , float , float ) { NOIMPL; } - + void Camera::set_pos(float , float ) { diff --git a/src/scripting/camera.hpp b/src/scripting/camera.hpp index cdd10e0e2..325ef6f63 100644 --- a/src/scripting/camera.hpp +++ b/src/scripting/camera.hpp @@ -53,4 +53,3 @@ public: } #endif - diff --git a/src/scripting/candle.cpp b/src/scripting/candle.cpp index cab136cd8..022352182 100644 --- a/src/scripting/candle.cpp +++ b/src/scripting/candle.cpp @@ -36,13 +36,13 @@ namespace Scripting Candle::~Candle() { } - - bool Candle::get_burning() + + bool Candle::get_burning() { return candle->get_burning(); } - void Candle::set_burning(bool burning) + void Candle::set_burning(bool burning) { candle->set_burning(burning); } diff --git a/src/scripting/candle.hpp b/src/scripting/candle.hpp index c7c022ee4..be64babfd 100644 --- a/src/scripting/candle.hpp +++ b/src/scripting/candle.hpp @@ -47,4 +47,3 @@ public: } #endif - diff --git a/src/scripting/display_effect.hpp b/src/scripting/display_effect.hpp index cbf9aa17a..3365b0911 100644 --- a/src/scripting/display_effect.hpp +++ b/src/scripting/display_effect.hpp @@ -52,4 +52,3 @@ public: } #endif - diff --git a/src/scripting/floating_image.cpp b/src/scripting/floating_image.cpp index 1647685cd..3b4034476 100644 --- a/src/scripting/floating_image.cpp +++ b/src/scripting/floating_image.cpp @@ -31,7 +31,7 @@ namespace Scripting FloatingImage::FloatingImage(const std::string& spritefile) { using namespace WorldMapNS; - + floating_image = new _FloatingImage(spritefile); if(Sector::current() != NULL) { Sector::current()->add_object(floating_image.get()); diff --git a/src/scripting/floating_image.hpp b/src/scripting/floating_image.hpp index 68d82f056..7434a842a 100644 --- a/src/scripting/floating_image.hpp +++ b/src/scripting/floating_image.hpp @@ -49,7 +49,7 @@ public: bool get_visible(); void set_action(const std::string& action); std::string get_action(); - + #ifndef SCRIPTING_API private: Ref<_FloatingImage> floating_image; @@ -59,4 +59,3 @@ private: } #endif - diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index 5dd10ed71..236a12ad2 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -131,11 +131,11 @@ static SQInteger squirrel_read_char(SQUserPointer file) void import(HSQUIRRELVM vm, const std::string& filename) { IFileStream in(filename); - + if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, filename.c_str(), SQTrue))) throw SquirrelError(vm, "Couldn't parse script"); - + sq_pushroottable(vm); if(SQ_FAILED(sq_call(vm, 1, SQFalse, SQTrue))) { sq_pop(vm, 1); @@ -162,7 +162,7 @@ void debug_draw_solids_only(bool enable) void save_state() { using namespace WorldMapNS; - + if(World::current() == NULL) throw std::runtime_error("Can't save state without active World"); @@ -272,4 +272,3 @@ int rand() } } - diff --git a/src/scripting/functions.hpp b/src/scripting/functions.hpp index 87066bfe2..94fa88c07 100644 --- a/src/scripting/functions.hpp +++ b/src/scripting/functions.hpp @@ -182,4 +182,3 @@ int rand(); } #endif - diff --git a/src/scripting/level.hpp b/src/scripting/level.hpp index 70c07d02f..2cdc258aa 100644 --- a/src/scripting/level.hpp +++ b/src/scripting/level.hpp @@ -44,4 +44,3 @@ public: } #endif - diff --git a/src/scripting/platform.cpp b/src/scripting/platform.cpp index cb20a73eb..fa44f2b3c 100644 --- a/src/scripting/platform.cpp +++ b/src/scripting/platform.cpp @@ -36,18 +36,18 @@ namespace Scripting Platform::~Platform() { } - - void Platform::goto_node(int node_no) + + void Platform::goto_node(int node_no) { platform->goto_node(node_no); } - void Platform::start_moving() + void Platform::start_moving() { platform->start_moving(); } - void Platform::stop_moving() + void Platform::stop_moving() { platform->stop_moving(); } diff --git a/src/scripting/platform.hpp b/src/scripting/platform.hpp index 1bff5ca2d..7d85f337d 100644 --- a/src/scripting/platform.hpp +++ b/src/scripting/platform.hpp @@ -53,4 +53,3 @@ public: } #endif - diff --git a/src/scripting/player.hpp b/src/scripting/player.hpp index d90784c16..8b36aa7f5 100644 --- a/src/scripting/player.hpp +++ b/src/scripting/player.hpp @@ -73,7 +73,7 @@ public: virtual void kill(bool completely) = 0; /** - * Switches ghost mode on/off. + * Switches ghost mode on/off. * Lets Tux float around and through solid objects. */ virtual void set_ghost_mode(bool enable) = 0; @@ -83,7 +83,7 @@ public: */ virtual bool get_ghost_mode() = 0; - /** + /** * play cheer animation. * This might need some space and behave in an unpredictable way. Best to use this at level end. */ @@ -117,4 +117,3 @@ public: } #endif - diff --git a/src/scripting/scripted_object.hpp b/src/scripting/scripted_object.hpp index 4fe3261fe..c39844366 100644 --- a/src/scripting/scripted_object.hpp +++ b/src/scripting/scripted_object.hpp @@ -38,11 +38,11 @@ public: virtual void set_pos(float x, float y) = 0; virtual float get_pos_x() = 0; virtual float get_pos_y() = 0; - + virtual void set_velocity(float x, float y) = 0; virtual float get_velocity_x() = 0; virtual float get_velocity_y() = 0; - + virtual void set_visible(bool visible) = 0; virtual bool is_visible() = 0; @@ -55,4 +55,3 @@ public: } #endif - diff --git a/src/scripting/serialize.cpp b/src/scripting/serialize.cpp index 79be04c4b..3455d2fc6 100644 --- a/src/scripting/serialize.cpp +++ b/src/scripting/serialize.cpp @@ -36,8 +36,8 @@ void load_squirrel_table(HSQUIRRELVM vm, SQInteger table_idx, const lisp::Lisp* using namespace lisp; if(table_idx < 0) - table_idx -= 2; - + table_idx -= 2; + lisp::ListIterator iter(lisp); while(iter.next() && iter.lisp() != NULL) { const std::string& token = iter.item(); @@ -80,7 +80,7 @@ void save_squirrel_table(HSQUIRRELVM vm, SQInteger table_idx, lisp::Writer& writ // offset because of sq_pushnull if(table_idx < 0) table_idx -= 1; - + //iterator table sq_pushnull(vm); while(SQ_SUCCEEDED(sq_next(vm, table_idx))) { @@ -136,4 +136,3 @@ void save_squirrel_table(HSQUIRRELVM vm, SQInteger table_idx, lisp::Writer& writ } } - diff --git a/src/scripting/serialize.hpp b/src/scripting/serialize.hpp index 3e9142a3c..d34b00fb8 100644 --- a/src/scripting/serialize.hpp +++ b/src/scripting/serialize.hpp @@ -34,5 +34,3 @@ namespace Scripting } #endif - - diff --git a/src/scripting/squirrel_error.hpp b/src/scripting/squirrel_error.hpp index 82905f65a..5e64b1dfa 100644 --- a/src/scripting/squirrel_error.hpp +++ b/src/scripting/squirrel_error.hpp @@ -44,4 +44,3 @@ private: } #endif - diff --git a/src/scripting/squirrel_util.cpp b/src/scripting/squirrel_util.cpp index b3cf9c17b..f16bb63bb 100644 --- a/src/scripting/squirrel_util.cpp +++ b/src/scripting/squirrel_util.cpp @@ -66,7 +66,7 @@ void init_squirrel(bool enable_debugger) debugger = sq_rdbg_init(global_vm, 1234, SQFalse); if(debugger == NULL) throw SquirrelError(global_vm, "Couldn't initialize squirrel debugger"); - + sq_enabledebuginfo(global_vm, SQTrue); log_info << "Waiting for debug client..." << std::endl; if(SQ_FAILED(sq_rdbg_waitforconnections(debugger))) @@ -88,13 +88,13 @@ void init_squirrel(bool enable_debugger) sq_deleteslot(global_vm, -2, SQFalse); sq_pushstring(global_vm, "rand", -1); sq_deleteslot(global_vm, -2, SQFalse); - + // register supertux API register_supertux_wrapper(global_vm); // TODO remove this at some point... it shoud just be functions not an object expose_object(global_vm, -1, new Scripting::Level(), "Level", true); - + sq_pop(global_vm, 1); // register print function @@ -141,12 +141,12 @@ std::string squirrel2string(HSQUIRRELVM v, SQInteger i) switch(sq_gettype(v, i)) { case OT_NULL: - os << ""; + os << ""; break; case OT_BOOL: { SQBool p; sq_getbool(v, i, &p); - if (p) + if (p) os << "true"; else os << "false"; @@ -168,7 +168,7 @@ std::string squirrel2string(HSQUIRRELVM v, SQInteger i) const SQChar* val; sq_getstring(v, i, &val); os << "\"" << val << "\""; - break; + break; } case OT_TABLE: { bool first = true; @@ -182,9 +182,9 @@ std::string squirrel2string(HSQUIRRELVM v, SQInteger i) first = false; //here -1 is the value and -2 is the key - os << squirrel2string(v, -2) << " => " + os << squirrel2string(v, -2) << " => " << squirrel2string(v, -1); - + sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 1); @@ -205,7 +205,7 @@ std::string squirrel2string(HSQUIRRELVM v, SQInteger i) //here -1 is the value and -2 is the key // we ignore the key, since that is just the index in an array os << squirrel2string(v, -1); - + sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 1); @@ -215,7 +215,7 @@ std::string squirrel2string(HSQUIRRELVM v, SQInteger i) case OT_USERDATA: os << ""; break; - case OT_CLOSURE: + case OT_CLOSURE: os << ""; break; case OT_NATIVECLOSURE: @@ -255,7 +255,7 @@ void print_squirrel_stack(HSQUIRRELVM v) switch(sq_gettype(v, i)) { case OT_NULL: - printf("null"); + printf("null"); break; case OT_INTEGER: { SQInteger val; @@ -273,7 +273,7 @@ void print_squirrel_stack(HSQUIRRELVM v) const SQChar* val; sq_getstring(v, i, &val); printf("string (%s)", val); - break; + break; } case OT_TABLE: printf("table"); @@ -284,8 +284,8 @@ void print_squirrel_stack(HSQUIRRELVM v) case OT_USERDATA: printf("userdata"); break; - case OT_CLOSURE: - printf("closure(function)"); + case OT_CLOSURE: + printf("closure(function)"); break; case OT_NATIVECLOSURE: printf("native closure(C function)"); @@ -329,14 +329,14 @@ static SQInteger squirrel_read_char(SQUserPointer file) void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) { if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true))) - throw SquirrelError(vm, "Couldn't parse script"); + throw SquirrelError(vm, "Couldn't parse script"); } void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) { compile_script(vm, in, sourcename); - + SQInteger oldtop = sq_gettop(vm); try { @@ -365,7 +365,7 @@ HSQOBJECT create_thread(HSQUIRRELVM vm) if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_object))) throw SquirrelError(vm, "Couldn't get squirrel thread from stack"); sq_addref(vm, &vm_object); - + sq_pop(vm, 1); return vm_object; diff --git a/src/scripting/squirrel_util.hpp b/src/scripting/squirrel_util.hpp index 874bb8eb0..5ebb44aad 100644 --- a/src/scripting/squirrel_util.hpp +++ b/src/scripting/squirrel_util.hpp @@ -39,7 +39,7 @@ namespace Scripting void print_squirrel_stack(HSQUIRRELVM vm); HSQOBJECT create_thread(HSQUIRRELVM vm); - SQObject vm_to_object(HSQUIRRELVM vm); + SQObject vm_to_object(HSQUIRRELVM vm); HSQUIRRELVM object_to_vm(HSQOBJECT object); void compile_script(HSQUIRRELVM vm, std::istream& in, @@ -69,10 +69,10 @@ namespace Scripting const std::string& name) { sq_pushstring(v, name.c_str(), name.length()); - + if(table_idx < 0) table_idx -= 1; - + if(SQ_FAILED(sq_deleteslot(v, table_idx, SQFalse))) { std::ostringstream msg; msg << "Couldn't unregister object '" << name << "' in squirrel root table"; diff --git a/src/scripting/text.hpp b/src/scripting/text.hpp index 5a7f1b714..d25febfa7 100644 --- a/src/scripting/text.hpp +++ b/src/scripting/text.hpp @@ -30,7 +30,7 @@ public: virtual ~Text() { } #endif - + virtual void set_text(const std::string& text) = 0; virtual void set_font(const std::string& fontname) = 0; virtual void fade_in(float fadetime) = 0; @@ -42,4 +42,3 @@ public: } #endif - diff --git a/src/scripting/thread_queue.cpp b/src/scripting/thread_queue.cpp index f14e9718d..6ecaef392 100644 --- a/src/scripting/thread_queue.cpp +++ b/src/scripting/thread_queue.cpp @@ -46,10 +46,10 @@ ThreadQueue::add(HSQUIRRELVM vm) sq_pop(global_vm, 2); throw SquirrelError(global_vm, "Couldn't get thread weakref from vm"); } - sq_addref(global_vm, &object); + sq_addref(global_vm, &object); threads.push_back(object); - sq_pop(global_vm, 2); + sq_pop(global_vm, 2); } void @@ -63,7 +63,7 @@ ThreadQueue::wakeup() size_t size_begin = threads.size(); while(i != end) { HSQOBJECT object = threads[i]; - + sq_pushobject(global_vm, object); sq_getweakrefval(global_vm, -1); @@ -74,7 +74,7 @@ ThreadQueue::wakeup() log_warning << "Couldn't wakeup scheduled squirrel VM" << std::endl; } } - + sq_release(global_vm, &object); sq_pop(global_vm, 1); i--; @@ -84,4 +84,3 @@ ThreadQueue::wakeup() } } - diff --git a/src/scripting/thread_queue.hpp b/src/scripting/thread_queue.hpp index 2614b65fd..ff0e651b3 100644 --- a/src/scripting/thread_queue.hpp +++ b/src/scripting/thread_queue.hpp @@ -47,4 +47,3 @@ private: } #endif - diff --git a/src/scripting/thunderstorm.hpp b/src/scripting/thunderstorm.hpp index 24a4d2eb8..50c32ea2d 100644 --- a/src/scripting/thunderstorm.hpp +++ b/src/scripting/thunderstorm.hpp @@ -40,7 +40,7 @@ public: * Start playing thunder and lightning at configured interval */ void start(); - + /** * Stop playing thunder and lightning at configured interval */ @@ -74,4 +74,3 @@ public: } #endif - diff --git a/src/scripting/time_scheduler.cpp b/src/scripting/time_scheduler.cpp index 8c3314b74..d28308b2f 100644 --- a/src/scripting/time_scheduler.cpp +++ b/src/scripting/time_scheduler.cpp @@ -98,4 +98,3 @@ TimeScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time) } } - diff --git a/src/scripting/time_scheduler.hpp b/src/scripting/time_scheduler.hpp index e3bf895f5..d26cb763b 100644 --- a/src/scripting/time_scheduler.hpp +++ b/src/scripting/time_scheduler.hpp @@ -54,7 +54,7 @@ private: return wakeup_time > other.wakeup_time; } }; - + typedef std::vector ScheduleHeap; ScheduleHeap schedule; }; @@ -62,4 +62,3 @@ private: } #endif - diff --git a/src/scripting/wind.cpp b/src/scripting/wind.cpp index 6140108d6..a0a33bf45 100644 --- a/src/scripting/wind.cpp +++ b/src/scripting/wind.cpp @@ -36,13 +36,13 @@ namespace Scripting Wind::~Wind() { } - - void Wind::start() + + void Wind::start() { wind->start(); } - void Wind::stop() + void Wind::stop() { wind->stop(); } diff --git a/src/scripting/wind.hpp b/src/scripting/wind.hpp index 0ad749401..e1b02d103 100644 --- a/src/scripting/wind.hpp +++ b/src/scripting/wind.hpp @@ -50,4 +50,3 @@ public: } #endif - diff --git a/src/scripting/wrapper.interface.hpp b/src/scripting/wrapper.interface.hpp index 9da2ff27d..88e966533 100644 --- a/src/scripting/wrapper.interface.hpp +++ b/src/scripting/wrapper.interface.hpp @@ -13,4 +13,3 @@ #include "wind.hpp" #include "ambient_sound.hpp" #include "thunderstorm.hpp" - diff --git a/src/sector.cpp b/src/sector.cpp index 5d98d0c56..f9aaf7cd1 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -96,7 +96,7 @@ Sector::Sector(Level* parent) Sector::~Sector() { using namespace Scripting; - + deactivate(); for(ScriptList::iterator i = scripts.begin(); @@ -106,7 +106,7 @@ Sector::~Sector() } sq_release(global_vm, §or_table); sq_collectgarbage(global_vm); - + update_game_objects(); assert(gameobjects_new.size() == 0); @@ -157,20 +157,20 @@ Sector::parse_object(const std::string& name, const lisp::Lisp& reader) return partsys; } else if(name == "money") { // for compatibility with old maps return new Jumpy(reader); - } + } try { return create_object(name, reader); } catch(std::exception& e) { log_warning << e.what() << "" << std::endl; } - + return 0; } void Sector::parse(const lisp::Lisp& sector) -{ +{ lisp::ListIterator iter(§or); while(iter.next()) { const std::string& token = iter.item(); @@ -227,14 +227,14 @@ Sector::parse_old_format(const lisp::Lisp& reader) bkgd_top.red = static_cast (r) / 255.0f; bkgd_top.green = static_cast (g) / 255.0f; bkgd_top.blue = static_cast (b) / 255.0f; - + reader.get("bkgd_red_bottom", r); reader.get("bkgd_green_bottom", g); reader.get("bkgd_blue_bottom", b); bkgd_bottom.red = static_cast (r) / 255.0f; bkgd_bottom.green = static_cast (g) / 255.0f; bkgd_bottom.blue = static_cast (b) / 255.0f; - + if(backgroundimage != "") { Background* background = new Background(); background->set_image( @@ -271,7 +271,7 @@ Sector::parse_old_format(const lisp::Lisp& reader) int width = 30, height = 15; reader.get("width", width); reader.get("height", height); - + std::vector tiles; if(reader.get_vector("interactive-tm", tiles) || reader.get_vector("tilemap", tiles)) { @@ -414,10 +414,10 @@ Sector::run_script(std::istream& in, const std::string& sourcename) i = scripts.erase(i); continue; } - + ++i; } - + HSQOBJECT object = create_thread(global_vm); scripts.push_back(object); @@ -465,7 +465,7 @@ Sector::activate(const std::string& spawnpoint) sp = *i; break; } - } + } if(!sp) { log_warning << "Spawnpoint '" << spawnpoint << "' not found." << std::endl; if(spawnpoint != "main") { @@ -527,11 +527,11 @@ Sector::deactivate() if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) throw Scripting::SquirrelError(vm, "Couldn't unset sector in roottable"); sq_pop(vm, 1); - + for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { GameObject* object = *i; - + try_unexpose(object); } @@ -557,10 +557,10 @@ Sector::update(float elapsed_time) GameObject* object = *i; if(!object->is_valid()) continue; - + object->update(elapsed_time); } - + /* Handle all possible collisions. */ handle_collisions(); update_game_objects(); @@ -593,14 +593,14 @@ Sector::update_game_objects() for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); /* nothing */) { GameObject* object = *i; - + if(object->is_valid()) { ++i; continue; } before_object_remove(object); - + object->unref(); i = gameobjects.erase(i); } @@ -612,7 +612,7 @@ Sector::update_game_objects() GameObject* object = *i; before_object_add(object); - + gameobjects.push_back(object); } gameobjects_new.clear(); @@ -629,7 +629,7 @@ Sector::before_object_add(GameObject* object) if(movingobject) { moving_objects.push_back(movingobject); } - + TileMap* tilemap = dynamic_cast (object); if(tilemap && tilemap->is_solid()) solid_tilemaps.push_back(tilemap); @@ -654,7 +654,7 @@ Sector::before_object_add(GameObject* object) if(_current == this) { try_expose(object); } - + return true; } @@ -692,7 +692,7 @@ Sector::try_unexpose(GameObject* object) } sq_settop(vm, oldtop); } -} +} void Sector::draw(DrawingContext& context) @@ -702,7 +702,7 @@ Sector::draw(DrawingContext& context) for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { - GameObject* object = *i; + GameObject* object = *i; if(!object->is_valid()) continue; @@ -731,7 +731,7 @@ Sector::draw(DrawingContext& context) } /*------------------------------------------------------------------------- - * Collision Detection + * Collision Detection *-------------------------------------------------------------------------*/ static const float SHIFT_DELTA = 7.0f; @@ -918,7 +918,7 @@ void Sector::collision_object(MovingObject* object1, MovingObject* object2) const { using namespace collision; - + const Rect& r1 = object1->dest; const Rect& r2 = object2->dest; @@ -961,13 +961,13 @@ Sector::collision_static(collision::Constraints* constraints, if(moving_object->get_group() != COLGROUP_STATIC || !moving_object->is_valid()) continue; - + check_collisions(constraints, movement, dest, moving_object->dest, &object, moving_object); } } -void +void Sector::collision_static_constrains(MovingObject& object) { using namespace collision; @@ -1037,11 +1037,11 @@ Sector::collision_static_constrains(MovingObject& object) } if(constraints.has_constraints()) { - if( constraints.hit.left || constraints.hit.right - || constraints.hit.top || constraints.hit.bottom + if( constraints.hit.left || constraints.hit.right + || constraints.hit.top || constraints.hit.bottom || constraints.hit.crush ) object.collision_solid(constraints.hit); - } + } // an extra pass to make sure we're not crushed horizontally constraints = Constraints(); @@ -1054,7 +1054,7 @@ Sector::collision_static_constrains(MovingObject& object) h.top = true; h.bottom = true; h.crush = true; - object.collision_solid(h); + object.collision_solid(h); } } } @@ -1063,7 +1063,7 @@ void Sector::handle_collisions() { using namespace collision; - + // calculate destination positions of the objects for(MovingObjects::iterator i = moving_objects.begin(); i != moving_objects.end(); ++i) { @@ -1124,7 +1124,7 @@ Sector::handle_collisions() moving_object->collision(*moving_object_2, hit); moving_object_2->collision(*moving_object, hit); } - } + } } // part3: COLGROUP_MOVING vs COLGROUP_MOVING @@ -1144,7 +1144,7 @@ Sector::handle_collisions() continue; collision_object(moving_object, moving_object_2); - } + } } // apply object movement @@ -1161,7 +1161,7 @@ bool Sector::is_free_space(const Rect& rect) const { using namespace collision; - + for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { TileMap* solids = *i; @@ -1299,7 +1299,7 @@ Sector::get_height() const return height; } -void +void Sector::change_solid_tiles(uint32_t old_tile_id, uint32_t new_tile_id) { for(std::list::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { diff --git a/src/sector.hpp b/src/sector.hpp index 00b4ff640..57a26659a 100644 --- a/src/sector.hpp +++ b/src/sector.hpp @@ -107,10 +107,10 @@ public: void play_music(MusicType musictype); MusicType get_music_type(); - + bool add_bullet(const Vector& pos, float xm, Direction dir); bool add_smoke_cloud(const Vector& pos); - + /** get currently activated sector. */ static Sector* current() { return _current; } @@ -150,7 +150,7 @@ public: * returns the width (in px) of a sector) */ float get_width() const; - + /** * returns the height (in px) of a sector) */ @@ -174,12 +174,12 @@ private: void try_expose(GameObject* object); void try_unexpose(GameObject* object); - + /** Checks for all possible collisions. And calls the collision_handlers, which the collision_objects provide for this case (or not). */ void handle_collisions(); - + /** * Does collision detection between 2 objects and does instant * collision response handling in case of a collision @@ -199,13 +199,13 @@ private: const Vector& movement, const Rect& dest, GameObject& object); void collision_static_constrains(MovingObject& object); - + GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp); void fix_old_tiles(); static Sector* _current; - + std::string name; std::vector bullets; @@ -214,7 +214,7 @@ private: /// container for newly created objects, they'll be added in Sector::update GameObjects gameobjects_new; - + MusicType currentmusic; HSQOBJECT sector_table; @@ -226,10 +226,10 @@ public: // TODO make this private again /// show collision rectangles of moving objects (for debugging) static bool show_collrects; static bool draw_solids_only; - + GameObjects gameobjects; MovingObjects moving_objects; - SpawnPoints spawnpoints; + SpawnPoints spawnpoints; std::string music; float gravity; @@ -242,4 +242,3 @@ public: // TODO make this private again }; #endif - diff --git a/src/serializable.hpp b/src/serializable.hpp index 612f4573b..ce4d3b73f 100644 --- a/src/serializable.hpp +++ b/src/serializable.hpp @@ -26,9 +26,8 @@ class Serializable public: virtual ~Serializable() { } - + virtual void write(lisp::Writer& writer) = 0; }; #endif /*SUPERTUX_SERIALIZABLE_H*/ - diff --git a/src/shrinkfade.cpp b/src/shrinkfade.cpp index 9486b1501..d921efbc9 100644 --- a/src/shrinkfade.cpp +++ b/src/shrinkfade.cpp @@ -51,7 +51,7 @@ ShrinkFade::draw(DrawingContext& context) float top = speedtop * accum_time; float right = SCREEN_WIDTH - speedright * accum_time; float bottom = SCREEN_HEIGHT - speedbottom * accum_time; - + context.draw_filled_rect(Vector(0, 0), Vector(left, SCREEN_HEIGHT), black, LAYER_GUI+1); diff --git a/src/shrinkfade.hpp b/src/shrinkfade.hpp index 8860f5bb3..7afe6426b 100644 --- a/src/shrinkfade.hpp +++ b/src/shrinkfade.hpp @@ -44,4 +44,3 @@ private: }; #endif - diff --git a/src/spawn_point.hpp b/src/spawn_point.hpp index b1708caac..17d4908fc 100644 --- a/src/spawn_point.hpp +++ b/src/spawn_point.hpp @@ -35,4 +35,3 @@ public: }; #endif - diff --git a/src/sprite/sprite.cpp b/src/sprite/sprite.cpp index 0c011ef14..7b818279a 100644 --- a/src/sprite/sprite.cpp +++ b/src/sprite/sprite.cpp @@ -33,9 +33,9 @@ Sprite::Sprite(SpriteData& newdata) : data(newdata), - frame(0), - animation_loops(-1), - angle(0.0f), + frame(0), + animation_loops(-1), + angle(0.0f), color(1.0f, 1.0f, 1.0f, 1.0f) { action = data.get_action("normal"); @@ -94,7 +94,7 @@ Sprite::update() if(frame >= get_frames()) { frame = fmodf(frame, get_frames()); - + animation_loops--; if(animation_done()) frame = get_frames()-1; @@ -126,7 +126,7 @@ Sprite::draw_part(DrawingContext& context, const Vector& source, update(); int frameidx = (int) frame; - + if(frameidx >= get_frames() || frameidx < 0) { #ifndef DEBUG // in optimized mode we get some small rounding errors in floating point @@ -135,7 +135,7 @@ Sprite::draw_part(DrawingContext& context, const Vector& source, #endif frameidx = get_frames() - 1; } - + context.draw_surface_part(action->surfaces[frameidx], source, size, pos - Vector(action->x_offset, action->y_offset), layer + action->z_order); diff --git a/src/sprite/sprite.hpp b/src/sprite/sprite.hpp index a43df0a16..f37c47364 100644 --- a/src/sprite/sprite.hpp +++ b/src/sprite/sprite.hpp @@ -109,14 +109,14 @@ public: { return (int)frame; } /** Set current frame */ void set_frame(int frame) - { - this->frame = (frame % get_frames()); + { + this->frame = (frame % get_frames()); } Surface* get_frame(unsigned int frame) { assert(frame < action->surfaces.size()); return action->surfaces[frame]; - } + } private: void update(); @@ -134,4 +134,3 @@ private: }; #endif - diff --git a/src/sprite/sprite_data.cpp b/src/sprite/sprite_data.cpp index 599e4e1d8..8d223af4c 100644 --- a/src/sprite/sprite_data.cpp +++ b/src/sprite/sprite_data.cpp @@ -36,7 +36,7 @@ SpriteData::Action::Action() y_offset = 0; hitbox_w = 0; hitbox_h = 0; - z_order = 0; + z_order = 0; fps = 10; } @@ -143,4 +143,3 @@ SpriteData::get_action(std::string act) } return i->second; } - diff --git a/src/sprite/sprite_data.hpp b/src/sprite/sprite_data.hpp index 3f73f4c1f..bc5ccb340 100644 --- a/src/sprite/sprite_data.hpp +++ b/src/sprite/sprite_data.hpp @@ -79,4 +79,3 @@ private: }; #endif - diff --git a/src/sprite/sprite_manager.cpp b/src/sprite/sprite_manager.cpp index 411255b54..5b3744174 100644 --- a/src/sprite/sprite_manager.cpp +++ b/src/sprite/sprite_manager.cpp @@ -61,7 +61,7 @@ SpriteManager::create(const std::string& name) } else { data = i->second; } - + return new Sprite(*data); } @@ -81,7 +81,6 @@ SpriteManager::load(const std::string& filename) std::auto_ptr data ( new SpriteData(sprite, FileSystem::dirname(filename)) ); sprites[filename] = data.release(); - + return sprites[filename]; } - diff --git a/src/sprite/sprite_manager.hpp b/src/sprite/sprite_manager.hpp index 4ebe6c0fd..7b5c1e476 100644 --- a/src/sprite/sprite_manager.hpp +++ b/src/sprite/sprite_manager.hpp @@ -30,7 +30,7 @@ class SpriteManager private: typedef std::map Sprites; Sprites sprites; - + public: SpriteManager(); ~SpriteManager(); diff --git a/src/squirrel/include/sqstdaux.h b/src/squirrel/include/sqstdaux.h index b90034823..c16b04373 100644 --- a/src/squirrel/include/sqstdaux.h +++ b/src/squirrel/include/sqstdaux.h @@ -1,16 +1,16 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_AUXLIB_H_ -#define _SQSTD_AUXLIB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v); -SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /* _SQSTD_AUXLIB_H_ */ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_AUXLIB_H_ +#define _SQSTD_AUXLIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v); +SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* _SQSTD_AUXLIB_H_ */ diff --git a/src/squirrel/include/sqstdblob.h b/src/squirrel/include/sqstdblob.h index eda4cc9c5..e54d7bec5 100644 --- a/src/squirrel/include/sqstdblob.h +++ b/src/squirrel/include/sqstdblob.h @@ -1,20 +1,19 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTDBLOB_H_ -#define _SQSTDBLOB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size); -SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr); -SQUIRREL_API SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx); - -SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*_SQSTDBLOB_H_*/ - +/* see copyright notice in squirrel.h */ +#ifndef _SQSTDBLOB_H_ +#define _SQSTDBLOB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size); +SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr); +SQUIRREL_API SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx); + +SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTDBLOB_H_*/ diff --git a/src/squirrel/include/sqstdio.h b/src/squirrel/include/sqstdio.h index 5f64612e1..c3137f19b 100644 --- a/src/squirrel/include/sqstdio.h +++ b/src/squirrel/include/sqstdio.h @@ -1,54 +1,53 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTDIO_H_ -#define _SQSTDIO_H_ - -#ifdef __cplusplus - -#define SQSTD_STREAM_TYPE_TAG 0x80000000 - -struct SQStream { - virtual ~SQStream() { }; - virtual SQInteger Read(void *buffer, SQInteger size) = 0; - virtual SQInteger Write(void *buffer, SQInteger size) = 0; - virtual SQInteger Flush() = 0; - virtual SQInteger Tell() = 0; - virtual SQInteger Len() = 0; - virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0; - virtual bool IsValid() = 0; - virtual bool EOS() = 0; -}; - -extern "C" { -#endif - -#define SQ_SEEK_CUR 0 -#define SQ_SEEK_END 1 -#define SQ_SEEK_SET 2 - -typedef void* SQFILE; - -SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *); -SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE); -SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE); -SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger); -SQUIRREL_API SQInteger sqstd_ftell(SQFILE); -SQUIRREL_API SQInteger sqstd_fflush(SQFILE); -SQUIRREL_API SQInteger sqstd_fclose(SQFILE); -SQUIRREL_API SQInteger sqstd_feof(SQFILE); - -SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own); -SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file); - -//compiler helpers -SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror); -SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror); -SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename); - -SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*_SQSTDIO_H_*/ - +/* see copyright notice in squirrel.h */ +#ifndef _SQSTDIO_H_ +#define _SQSTDIO_H_ + +#ifdef __cplusplus + +#define SQSTD_STREAM_TYPE_TAG 0x80000000 + +struct SQStream { + virtual ~SQStream() { }; + virtual SQInteger Read(void *buffer, SQInteger size) = 0; + virtual SQInteger Write(void *buffer, SQInteger size) = 0; + virtual SQInteger Flush() = 0; + virtual SQInteger Tell() = 0; + virtual SQInteger Len() = 0; + virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0; + virtual bool IsValid() = 0; + virtual bool EOS() = 0; +}; + +extern "C" { +#endif + +#define SQ_SEEK_CUR 0 +#define SQ_SEEK_END 1 +#define SQ_SEEK_SET 2 + +typedef void* SQFILE; + +SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *); +SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE); +SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE); +SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger); +SQUIRREL_API SQInteger sqstd_ftell(SQFILE); +SQUIRREL_API SQInteger sqstd_fflush(SQFILE); +SQUIRREL_API SQInteger sqstd_fclose(SQFILE); +SQUIRREL_API SQInteger sqstd_feof(SQFILE); + +SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own); +SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file); + +//compiler helpers +SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror); +SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror); +SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename); + +SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTDIO_H_*/ diff --git a/src/squirrel/include/sqstdmath.h b/src/squirrel/include/sqstdmath.h index 420f2ce67..65de6fd72 100644 --- a/src/squirrel/include/sqstdmath.h +++ b/src/squirrel/include/sqstdmath.h @@ -1,15 +1,15 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_MATH_H_ -#define _SQSTD_MATH_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*_SQSTD_MATH_H_*/ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_MATH_H_ +#define _SQSTD_MATH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTD_MATH_H_*/ diff --git a/src/squirrel/include/sqstdstring.h b/src/squirrel/include/sqstdstring.h index 9db0ffce9..ab68d1683 100644 --- a/src/squirrel/include/sqstdstring.h +++ b/src/squirrel/include/sqstdstring.h @@ -1,34 +1,34 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_STRING_H_ -#define _SQSTD_STRING_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//#define SQRex_True 1 -//#define SQRex_False 0 - -typedef unsigned int SQRexBool; -typedef struct SQRex SQRex; - -typedef struct { - const SQChar *begin; - SQInteger len; -} SQRexMatch; - -SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error); -SQUIRREL_API void sqstd_rex_free(SQRex *exp); -SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text); -SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end); -SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end); -SQUIRREL_API SQInteger sqstd_rex_getsubexpcount(SQRex* exp); -SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp); - -SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*_SQSTD_STRING_H_*/ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_STRING_H_ +#define _SQSTD_STRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//#define SQRex_True 1 +//#define SQRex_False 0 + +typedef unsigned int SQRexBool; +typedef struct SQRex SQRex; + +typedef struct { + const SQChar *begin; + SQInteger len; +} SQRexMatch; + +SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error); +SQUIRREL_API void sqstd_rex_free(SQRex *exp); +SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text); +SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end); +SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end); +SQUIRREL_API SQInteger sqstd_rex_getsubexpcount(SQRex* exp); +SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp); + +SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTD_STRING_H_*/ diff --git a/src/squirrel/include/sqstdsystem.h b/src/squirrel/include/sqstdsystem.h index daefa0fd5..b155a91f8 100644 --- a/src/squirrel/include/sqstdsystem.h +++ b/src/squirrel/include/sqstdsystem.h @@ -1,15 +1,15 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_SYSTEMLIB_H_ -#define _SQSTD_SYSTEMLIB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /* _SQSTD_SYSTEMLIB_H_ */ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_SYSTEMLIB_H_ +#define _SQSTD_SYSTEMLIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* _SQSTD_SYSTEMLIB_H_ */ diff --git a/src/squirrel/include/squirrel.h b/src/squirrel/include/squirrel.h index 12fb4d5d3..1a7efc566 100644 --- a/src/squirrel/include/squirrel.h +++ b/src/squirrel/include/squirrel.h @@ -1,414 +1,414 @@ -/* -Copyright (c) 2003-2006 Alberto Demichelis - -This software is provided 'as-is', without any -express or implied warranty. In no event will the -authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software -for any purpose, including commercial applications, -and to alter it and redistribute it freely, subject -to the following restrictions: - - 1. The origin of this software must not be - misrepresented; you must not claim that - you wrote the original software. If you - use this software in a product, an - acknowledgment in the product - documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly - marked as such, and must not be - misrepresented as being the original - software. - - 3. This notice may not be removed or - altered from any source distribution. - -*/ -#ifndef _SQUIRREL_H_ -#define _SQUIRREL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef SQUIRREL_API -#define SQUIRREL_API extern -#endif - -#ifdef _SQ64 -#ifdef _MSC_VER -typedef __int64 SQInteger; -typedef unsigned __int64 SQUnsignedInteger; -typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/ -#else -typedef long SQInteger; -typedef unsigned long SQUnsignedInteger; -typedef unsigned long SQHash; /*should be the same size of a pointer*/ -#endif -typedef int SQInt32; -#else -typedef int SQInteger; -typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/ -typedef unsigned int SQUnsignedInteger; -typedef unsigned int SQHash; /*should be the same size of a pointer*/ -#endif - -typedef float SQFloat; -typedef void* SQUserPointer; -typedef SQUnsignedInteger SQBool; -typedef SQInteger SQRESULT; - -#define SQTrue (1) -#define SQFalse (0) - - -struct SQVM; -struct SQTable; -struct SQArray; -struct SQString; -struct SQClosure; -struct SQGenerator; -struct SQNativeClosure; -struct SQUserData; -struct SQFunctionProto; -struct SQRefCounted; -struct SQClass; -struct SQInstance; -struct SQDelegable; - -#ifdef _UNICODE -#define SQUNICODE -#endif - -#ifdef SQUNICODE -#if defined(wchar_t) //this is if the compiler considers wchar_t as native type -#define wchar_t unsigned short -#endif -typedef wchar_t SQChar; -#define _SC(a) L##a -#define scstrcmp wcscmp -#define scsprintf swprintf -#define scstrlen wcslen -#define scstrtod wcstod -#define scstrtol wcstol -#define scatoi _wtoi -#define scstrtoul wcstoul -#define scvsprintf vswprintf -#define scstrstr wcsstr -#define scisspace iswspace -#define scisdigit iswdigit -#define scisxdigit iswxdigit -#define scisalpha iswalpha -#define sciscntrl iswcntrl -#define scisalnum iswalnum -#define scprintf wprintf -#define MAX_CHAR 0xFFFF -#else -typedef char SQChar; -#define _SC(a) a -#define scstrcmp strcmp -#define scsprintf sprintf -#define scstrlen strlen -#define scstrtod strtod -#define scstrtol strtol -#define scatoi atoi -#define scstrtoul strtoul -#define scvsprintf vsprintf -#define scstrstr strstr -#define scisspace isspace -#define scisdigit isdigit -#define scisxdigit isxdigit -#define sciscntrl iscntrl -#define scisalpha isalpha -#define scisalnum isalnum -#define scprintf printf -#define MAX_CHAR 0xFF -#endif - -#define SQUIRREL_VERSION _SC("Squirrel 2.1 stable") -#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2006 Alberto Demichelis") -#define SQUIRREL_AUTHOR _SC("Alberto Demichelis") - -#define SQ_VMSTATE_IDLE 0 -#define SQ_VMSTATE_RUNNING 1 -#define SQ_VMSTATE_SUSPENDED 2 - -#define SQUIRREL_EOB 0 -#define SQ_BYTECODE_STREAM_TAG 0xFAFA - -#define SQOBJECT_REF_COUNTED 0x08000000 -#define SQOBJECT_NUMERIC 0x04000000 -#define SQOBJECT_DELEGABLE 0x02000000 -#define SQOBJECT_CANBEFALSE 0x01000000 - -#define SQ_MATCHTYPEMASKSTRING (-99999) - -#define _RT_MASK 0x00FFFFFF -#define _RAW_TYPE(type) (type&_RT_MASK) - -#define _RT_NULL 0x00000001 -#define _RT_INTEGER 0x00000002 -#define _RT_FLOAT 0x00000004 -#define _RT_BOOL 0x00000008 -#define _RT_STRING 0x00000010 -#define _RT_TABLE 0x00000020 -#define _RT_ARRAY 0x00000040 -#define _RT_USERDATA 0x00000080 -#define _RT_CLOSURE 0x00000100 -#define _RT_NATIVECLOSURE 0x00000200 -#define _RT_GENERATOR 0x00000400 -#define _RT_USERPOINTER 0x00000800 -#define _RT_THREAD 0x00001000 -#define _RT_FUNCPROTO 0x00002000 -#define _RT_CLASS 0x00004000 -#define _RT_INSTANCE 0x00008000 -#define _RT_WEAKREF 0x00010000 - -typedef enum tagSQObjectType{ - OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), - OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), - OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), - OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE), - OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED), - OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED), - OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED), - OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED), - OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED), - OT_USERPOINTER = _RT_USERPOINTER, - OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) , - OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only - OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), - OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), - OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED) -}SQObjectType; - -#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) - - -typedef union tagSQObjectValue -{ - struct SQTable *pTable; - struct SQArray *pArray; - struct SQClosure *pClosure; - struct SQGenerator *pGenerator; - struct SQNativeClosure *pNativeClosure; - struct SQString *pString; - struct SQUserData *pUserData; - SQInteger nInteger; - SQFloat fFloat; - SQUserPointer pUserPointer; - struct SQFunctionProto *pFunctionProto; - struct SQRefCounted *pRefCounted; - struct SQDelegable *pDelegable; - struct SQVM *pThread; - struct SQClass *pClass; - struct SQInstance *pInstance; - struct SQWeakRef *pWeakRef; -}SQObjectValue; - - -typedef struct tagSQObject -{ - SQObjectValue _unVal; - SQObjectType _type; -}SQObject; - -typedef struct tagSQStackInfos{ - const SQChar* funcname; - const SQChar* source; - SQInteger line; -}SQStackInfos; - -typedef struct SQVM* HSQUIRRELVM; -typedef SQObject HSQOBJECT; -typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM); -typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); -typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/); -typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...); - -typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger); -typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); - -typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer); - -typedef struct tagSQRegFunction{ - const SQChar *name; - SQFUNCTION f; - SQInteger nparamscheck; - const SQChar *typemask; -}SQRegFunction; - -/*vm*/ -SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize); -SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize); -SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v); -SQUIRREL_API void sq_close(HSQUIRRELVM v); -SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p); -SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v); -SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc); -SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v); -SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v); -SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror); -SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v); - -/*compiler*/ -SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror); -SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror); -SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable); -SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable); -SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f); - -/*stack operations*/ -SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop); -SQUIRREL_API void sq_poptop(HSQUIRRELVM v); -SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); -SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); -SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize); -SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); -SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); - -/*object creation handling*/ -SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size); -SQUIRREL_API void sq_newtable(HSQUIRRELVM v); -SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size); -SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars); -SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask); -SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len); -SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f); -SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n); -SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b); -SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p); -SQUIRREL_API void sq_pushnull(HSQUIRRELVM v); -SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v); -SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b); -SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c); -SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i); -SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f); -SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b); -SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread); -SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p); -SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag); -SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag); -SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag); -SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook); -SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize); -SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars); -SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); -SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); -SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); -SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase); -SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t); - -/*object manipulation*/ -SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v); -SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v); -SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v); -/*SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,SQInteger idx);*/ -SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic); -SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); -SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); -SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); -SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); -SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); -SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx); -SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx); - -/*calls*/ -SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror); -SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror); -SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); -SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); -SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); -SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); -SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v); - -/*raw object handling*/ -SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po); -SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj); -SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po); -SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po); -SQUIRREL_API void sq_resetobject(HSQOBJECT *po); -SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o); -SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o); -SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o); -SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o); -SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag); - -/*GC*/ -SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v); - -/*serialization*/ -SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up); -SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up); - -/*mem allocation*/ -SQUIRREL_API void *sq_malloc(SQUnsignedInteger size); -SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize); -SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size); - -/*debug*/ -SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si); -SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v); - -/*UTILITY MACRO*/ -#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) -#define sq_istable(o) ((o)._type==OT_TABLE) -#define sq_isarray(o) ((o)._type==OT_ARRAY) -#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO) -#define sq_isclosure(o) ((o)._type==OT_CLOSURE) -#define sq_isgenerator(o) ((o)._type==OT_GENERATOR) -#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE) -#define sq_isstring(o) ((o)._type==OT_STRING) -#define sq_isinteger(o) ((o)._type==OT_INTEGER) -#define sq_isfloat(o) ((o)._type==OT_FLOAT) -#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER) -#define sq_isuserdata(o) ((o)._type==OT_USERDATA) -#define sq_isthread(o) ((o)._type==OT_THREAD) -#define sq_isnull(o) ((o)._type==OT_NULL) -#define sq_isclass(o) ((o)._type==OT_CLASS) -#define sq_isinstance(o) ((o)._type==OT_INSTANCE) -#define sq_isbool(o) ((o)._type==OT_BOOL) -#define sq_isweakref(o) ((o)._type==OT_WEAKREF) -#define sq_type(o) ((o)._type) - -/* deprecated */ -#define sq_createslot(v,n) sq_newslot(v,n,SQFalse) - -#define SQ_OK (0) -#define SQ_ERROR (-1) - -#define SQ_FAILED(res) (res<0) -#define SQ_SUCCEEDED(res) (res>=0) - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*_SQUIRREL_H_*/ +/* +Copyright (c) 2003-2006 Alberto Demichelis + +This software is provided 'as-is', without any +express or implied warranty. In no event will the +authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software +for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject +to the following restrictions: + + 1. The origin of this software must not be + misrepresented; you must not claim that + you wrote the original software. If you + use this software in a product, an + acknowledgment in the product + documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly + marked as such, and must not be + misrepresented as being the original + software. + + 3. This notice may not be removed or + altered from any source distribution. + +*/ +#ifndef _SQUIRREL_H_ +#define _SQUIRREL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SQUIRREL_API +#define SQUIRREL_API extern +#endif + +#ifdef _SQ64 +#ifdef _MSC_VER +typedef __int64 SQInteger; +typedef unsigned __int64 SQUnsignedInteger; +typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/ +#else +typedef long SQInteger; +typedef unsigned long SQUnsignedInteger; +typedef unsigned long SQHash; /*should be the same size of a pointer*/ +#endif +typedef int SQInt32; +#else +typedef int SQInteger; +typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/ +typedef unsigned int SQUnsignedInteger; +typedef unsigned int SQHash; /*should be the same size of a pointer*/ +#endif + +typedef float SQFloat; +typedef void* SQUserPointer; +typedef SQUnsignedInteger SQBool; +typedef SQInteger SQRESULT; + +#define SQTrue (1) +#define SQFalse (0) + + +struct SQVM; +struct SQTable; +struct SQArray; +struct SQString; +struct SQClosure; +struct SQGenerator; +struct SQNativeClosure; +struct SQUserData; +struct SQFunctionProto; +struct SQRefCounted; +struct SQClass; +struct SQInstance; +struct SQDelegable; + +#ifdef _UNICODE +#define SQUNICODE +#endif + +#ifdef SQUNICODE +#if defined(wchar_t) //this is if the compiler considers wchar_t as native type +#define wchar_t unsigned short +#endif +typedef wchar_t SQChar; +#define _SC(a) L##a +#define scstrcmp wcscmp +#define scsprintf swprintf +#define scstrlen wcslen +#define scstrtod wcstod +#define scstrtol wcstol +#define scatoi _wtoi +#define scstrtoul wcstoul +#define scvsprintf vswprintf +#define scstrstr wcsstr +#define scisspace iswspace +#define scisdigit iswdigit +#define scisxdigit iswxdigit +#define scisalpha iswalpha +#define sciscntrl iswcntrl +#define scisalnum iswalnum +#define scprintf wprintf +#define MAX_CHAR 0xFFFF +#else +typedef char SQChar; +#define _SC(a) a +#define scstrcmp strcmp +#define scsprintf sprintf +#define scstrlen strlen +#define scstrtod strtod +#define scstrtol strtol +#define scatoi atoi +#define scstrtoul strtoul +#define scvsprintf vsprintf +#define scstrstr strstr +#define scisspace isspace +#define scisdigit isdigit +#define scisxdigit isxdigit +#define sciscntrl iscntrl +#define scisalpha isalpha +#define scisalnum isalnum +#define scprintf printf +#define MAX_CHAR 0xFF +#endif + +#define SQUIRREL_VERSION _SC("Squirrel 2.1 stable") +#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2006 Alberto Demichelis") +#define SQUIRREL_AUTHOR _SC("Alberto Demichelis") + +#define SQ_VMSTATE_IDLE 0 +#define SQ_VMSTATE_RUNNING 1 +#define SQ_VMSTATE_SUSPENDED 2 + +#define SQUIRREL_EOB 0 +#define SQ_BYTECODE_STREAM_TAG 0xFAFA + +#define SQOBJECT_REF_COUNTED 0x08000000 +#define SQOBJECT_NUMERIC 0x04000000 +#define SQOBJECT_DELEGABLE 0x02000000 +#define SQOBJECT_CANBEFALSE 0x01000000 + +#define SQ_MATCHTYPEMASKSTRING (-99999) + +#define _RT_MASK 0x00FFFFFF +#define _RAW_TYPE(type) (type&_RT_MASK) + +#define _RT_NULL 0x00000001 +#define _RT_INTEGER 0x00000002 +#define _RT_FLOAT 0x00000004 +#define _RT_BOOL 0x00000008 +#define _RT_STRING 0x00000010 +#define _RT_TABLE 0x00000020 +#define _RT_ARRAY 0x00000040 +#define _RT_USERDATA 0x00000080 +#define _RT_CLOSURE 0x00000100 +#define _RT_NATIVECLOSURE 0x00000200 +#define _RT_GENERATOR 0x00000400 +#define _RT_USERPOINTER 0x00000800 +#define _RT_THREAD 0x00001000 +#define _RT_FUNCPROTO 0x00002000 +#define _RT_CLASS 0x00004000 +#define _RT_INSTANCE 0x00008000 +#define _RT_WEAKREF 0x00010000 + +typedef enum tagSQObjectType{ + OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), + OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE), + OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED), + OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED), + OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED), + OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED), + OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED), + OT_USERPOINTER = _RT_USERPOINTER, + OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) , + OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only + OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), + OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED) +}SQObjectType; + +#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) + + +typedef union tagSQObjectValue +{ + struct SQTable *pTable; + struct SQArray *pArray; + struct SQClosure *pClosure; + struct SQGenerator *pGenerator; + struct SQNativeClosure *pNativeClosure; + struct SQString *pString; + struct SQUserData *pUserData; + SQInteger nInteger; + SQFloat fFloat; + SQUserPointer pUserPointer; + struct SQFunctionProto *pFunctionProto; + struct SQRefCounted *pRefCounted; + struct SQDelegable *pDelegable; + struct SQVM *pThread; + struct SQClass *pClass; + struct SQInstance *pInstance; + struct SQWeakRef *pWeakRef; +}SQObjectValue; + + +typedef struct tagSQObject +{ + SQObjectValue _unVal; + SQObjectType _type; +}SQObject; + +typedef struct tagSQStackInfos{ + const SQChar* funcname; + const SQChar* source; + SQInteger line; +}SQStackInfos; + +typedef struct SQVM* HSQUIRRELVM; +typedef SQObject HSQOBJECT; +typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM); +typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); +typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/); +typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...); + +typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger); +typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); + +typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer); + +typedef struct tagSQRegFunction{ + const SQChar *name; + SQFUNCTION f; + SQInteger nparamscheck; + const SQChar *typemask; +}SQRegFunction; + +/*vm*/ +SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize); +SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize); +SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v); +SQUIRREL_API void sq_close(HSQUIRRELVM v); +SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p); +SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v); +SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc); +SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror); +SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v); + +/*compiler*/ +SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror); +SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror); +SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable); +SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable); +SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f); + +/*stack operations*/ +SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop); +SQUIRREL_API void sq_poptop(HSQUIRRELVM v); +SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); +SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); +SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize); +SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); +SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); + +/*object creation handling*/ +SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size); +SQUIRREL_API void sq_newtable(HSQUIRRELVM v); +SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size); +SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars); +SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask); +SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len); +SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f); +SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n); +SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b); +SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p); +SQUIRREL_API void sq_pushnull(HSQUIRRELVM v); +SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v); +SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b); +SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c); +SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i); +SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f); +SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b); +SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread); +SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p); +SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag); +SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag); +SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag); +SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook); +SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize); +SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars); +SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); +SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); +SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); +SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase); +SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t); + +/*object manipulation*/ +SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v); +SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v); +/*SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,SQInteger idx);*/ +SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic); +SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); +SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); +SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx); + +/*calls*/ +SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror); +SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror); +SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); +SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); +SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); +SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); +SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v); + +/*raw object handling*/ +SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po); +SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj); +SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API void sq_resetobject(HSQOBJECT *po); +SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o); +SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o); +SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o); +SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o); +SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag); + +/*GC*/ +SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v); + +/*serialization*/ +SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up); +SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up); + +/*mem allocation*/ +SQUIRREL_API void *sq_malloc(SQUnsignedInteger size); +SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize); +SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size); + +/*debug*/ +SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si); +SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v); + +/*UTILITY MACRO*/ +#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) +#define sq_istable(o) ((o)._type==OT_TABLE) +#define sq_isarray(o) ((o)._type==OT_ARRAY) +#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO) +#define sq_isclosure(o) ((o)._type==OT_CLOSURE) +#define sq_isgenerator(o) ((o)._type==OT_GENERATOR) +#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE) +#define sq_isstring(o) ((o)._type==OT_STRING) +#define sq_isinteger(o) ((o)._type==OT_INTEGER) +#define sq_isfloat(o) ((o)._type==OT_FLOAT) +#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER) +#define sq_isuserdata(o) ((o)._type==OT_USERDATA) +#define sq_isthread(o) ((o)._type==OT_THREAD) +#define sq_isnull(o) ((o)._type==OT_NULL) +#define sq_isclass(o) ((o)._type==OT_CLASS) +#define sq_isinstance(o) ((o)._type==OT_INSTANCE) +#define sq_isbool(o) ((o)._type==OT_BOOL) +#define sq_isweakref(o) ((o)._type==OT_WEAKREF) +#define sq_type(o) ((o)._type) + +/* deprecated */ +#define sq_createslot(v,n) sq_newslot(v,n,SQFalse) + +#define SQ_OK (0) +#define SQ_ERROR (-1) + +#define SQ_FAILED(res) (res<0) +#define SQ_SUCCEEDED(res) (res>=0) + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQUIRREL_H_*/ diff --git a/src/squirrel/sqdbg/sqdbgserver.cpp b/src/squirrel/sqdbg/sqdbgserver.cpp index c76ff0bff..d6d141cc8 100644 --- a/src/squirrel/sqdbg/sqdbgserver.cpp +++ b/src/squirrel/sqdbg/sqdbgserver.cpp @@ -1,634 +1,634 @@ -#include -#include -#include -#include "sqrdbg.h" -#include "sqdbgserver.h" - - -#ifndef _UNICODE -#define scstrcpy strcpy -#else -#define scstrcpy wcscpy -#endif -struct XMLEscape{ - const SQChar c; - const SQChar *esc; -}; - -#define SQDBG_DEBUG_HOOK _SC("_sqdbg_debug_hook_") -#define SQDBG_ERROR_HANDLER _SC("_sqdbg_error_handler_") - -XMLEscape g_escapes[]={ - {_SC('<'),_SC("<")},{'>',_SC(">")},{_SC('&'),_SC("&")},{_SC('\''),_SC("'")},{_SC('\"'),_SC(""")},{_SC('\n'),_SC(""n")},{_SC('\r'),_SC(""r")},{0, NULL} -}; - -const SQChar *IntToString(int n) -{ - static SQChar temp[256]; - scsprintf(temp,_SC("%d"),n); - return temp; -} - -int debug_hook(HSQUIRRELVM v); -int error_handler(HSQUIRRELVM v); - -int beginelement(HSQUIRRELVM v) -{ - SQUserPointer up; - const SQChar *name; - sq_getuserpointer(v,-1,&up); - SQDbgServer *self = (SQDbgServer*)up; - sq_getuserpointer(v,-1,&up); - sq_getstring(v,2,&name); - self->BeginElement(name); - return 0; -} - -int endelement(HSQUIRRELVM v) -{ - SQUserPointer up; - const SQChar *name; - sq_getuserpointer(v,-1,&up); - SQDbgServer *self = (SQDbgServer*)up; - sq_getuserpointer(v,-1,&up); - sq_getstring(v,2,&name); - self->EndElement(name); - return 0; -} - -int attribute(HSQUIRRELVM v) -{ - SQUserPointer up; - const SQChar *name,*value; - sq_getuserpointer(v,-1,&up); - SQDbgServer *self = (SQDbgServer*)up; - sq_getuserpointer(v,-1,&up); - sq_getstring(v,2,&name); - sq_getstring(v,3,&value); - self->Attribute(name,value); - return 0; -} - -const SQChar *EscapeXMLString(HSQUIRRELVM v,const SQChar *s) -{ - - SQChar *temp=sq_getscratchpad(v,((int)scstrlen(s)*6) + sizeof(SQChar)); - SQChar *dest=temp; - while(*s!=_SC('\0')){ - int i=0; - bool escaped=false; - while(g_escapes[i].esc!=NULL){ - if(*s==g_escapes[i].c){ - scstrcpy(dest,g_escapes[i].esc); - dest+=scstrlen(g_escapes[i].esc); - escaped=true; - break; - } - i++; - } - if(!escaped){*dest=*s;*dest++;} - *s++; - } - *dest=_SC('\0'); - return temp; -} - -SQDbgServer::SQDbgServer(HSQUIRRELVM v) -{ - _ready = false; - _nestedcalls = 0; - _autoupdate = false; - _v = v; - _state = eDBG_Running; - _accept = INVALID_SOCKET; - _endpoint = INVALID_SOCKET; - _maxrecursion = 10; - sq_resetobject(&_debugroot); -} - -SQDbgServer::~SQDbgServer() -{ - sq_release(_v,&_debugroot); - if(_accept != INVALID_SOCKET) - sqdbg_closesocket(_accept); - if(_endpoint != INVALID_SOCKET) - sqdbg_closesocket(_endpoint); -} - -bool SQDbgServer::Init() -{ - //creates an environment table for the debugger - - sq_newtable(_v); - sq_getstackobj(_v,-1,&_debugroot); - sq_addref(_v,&_debugroot); - - //creates a emptyslot to store the watches - sq_pushstring(_v,_SC("watches"),-1); - sq_pushnull(_v); - sq_createslot(_v,-3); - - sq_pushstring(_v,_SC("beginelement"),-1); - sq_pushuserpointer(_v,this); - sq_newclosure(_v,beginelement,1); - sq_setparamscheck(_v,2,_SC(".s")); - sq_createslot(_v,-3); - - sq_pushstring(_v,_SC("endelement"),-1); - sq_pushuserpointer(_v,this); - sq_newclosure(_v,endelement,1); - sq_setparamscheck(_v,2,_SC(".s")); - sq_createslot(_v,-3); - - sq_pushstring(_v,_SC("attribute"),-1); - sq_pushuserpointer(_v,this); - sq_newclosure(_v,attribute,1); - sq_setparamscheck(_v,3,_SC(".ss")); - sq_createslot(_v,-3); - - sq_pop(_v,1); - - //stores debug hook and error handler in the registry - sq_pushregistrytable(_v); - - sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); - sq_pushuserpointer(_v,this); - sq_newclosure(_v,debug_hook,1); - sq_createslot(_v,-3); - - sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); - sq_pushuserpointer(_v,this); - sq_newclosure(_v,error_handler,1); - sq_createslot(_v,-3); - - - sq_pop(_v,1); - - //sets the error handlers - SetErrorHandlers(); - return true; -} - -bool SQDbgServer::ReadMsg() -{ - return false; -} - -void SQDbgServer::BusyWait() -{ - while( !ReadMsg() ) - sleep(0); -} - -void SQDbgServer::SendChunk(const SQChar *chunk) -{ - char *buf=NULL; - int buf_len=0; -#ifdef _UNICODE - buf_len=(int)scstrlen(chunk)+1; - buf=(char *)sq_getscratchpad(_v,(buf_len)*3); - wcstombs((char *)buf,chunk,buf_len); -#else - buf_len=(int)scstrlen(chunk); - buf=(char *)chunk; -#endif - send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0); -} - - -void SQDbgServer::Terminated() -{ - BeginElement(_SC("terminated")); - EndElement(_SC("terminated")); - ::usleep(200); -} - -void SQDbgServer::Hook(int type,int line,const SQChar *src,const SQChar *func) -{ - switch(_state){ - case eDBG_Running: - if(type==_SC('l') && _breakpoints.size()) { - BreakPointSetItor itr = _breakpoints.find(BreakPoint(line,src)); - if(itr != _breakpoints.end()) { - Break(line,src,_SC("breakpoint")); - BreakExecution(); - } - } - break; - case eDBG_Suspended: - _nestedcalls=0; - case eDBG_StepOver: - switch(type){ - case _SC('l'): - if(_nestedcalls==0) { - Break(line,src,_SC("step")); - BreakExecution(); - } - break; - case _SC('c'): - _nestedcalls++; - break; - case _SC('r'): - if(_nestedcalls==0){ - _nestedcalls=0; - - }else{ - _nestedcalls--; - } - break; - } - break; - case eDBG_StepInto: - switch(type){ - case _SC('l'): - _nestedcalls=0; - Break(line,src,_SC("step")); - BreakExecution(); - break; - - } - break; - case eDBG_StepReturn: - switch(type){ - case _SC('l'): - break; - case _SC('c'): - _nestedcalls++; - break; - case _SC('r'): - if(_nestedcalls==0){ - _nestedcalls=0; - _state=eDBG_StepOver; - }else{ - _nestedcalls--; - } - - break; - } - break; - case eDBG_Disabled: - break; - } -} - - -#define MSG_ID(x,y) ((y<<8)|x) -//ab Add Breakpoint -//rb Remove Breakpoint -//sp Suspend -void SQDbgServer::ParseMsg(const char *msg) -{ - - switch(*((unsigned short *)msg)){ - case MSG_ID('a','b'): { - BreakPoint bp; - if(ParseBreakpoint(msg+3,bp)){ - AddBreakpoint(bp); - scprintf(_SC("added bp %d %s\n"),bp._line,bp._src.c_str()); - } - else - scprintf(_SC("error parsing add breakpoint")); - } - break; - case MSG_ID('r','b'): { - BreakPoint bp; - if(ParseBreakpoint(msg+3,bp)){ - RemoveBreakpoint(bp); - scprintf(_SC("removed bp %d %s\n"),bp._line,bp._src.c_str()); - }else - scprintf(_SC("error parsing remove breakpoint")); - } - break; - case MSG_ID('g','o'): - if(_state!=eDBG_Running){ - _state=eDBG_Running; - BeginDocument(); - BeginElement(_SC("resumed")); - EndElement(_SC("resumed")); - EndDocument(); -// Send(_SC("\r\n")); - scprintf(_SC("go (execution resumed)\n")); - } - break; - case MSG_ID('s','p'): - if(_state!=eDBG_Suspended){ - _state=eDBG_Suspended; - scprintf(_SC("suspend\n")); - } - break; - case MSG_ID('s','o'): - if(_state==eDBG_Suspended){ - _state=eDBG_StepOver; - } - break; - case MSG_ID('s','i'): - if(_state==eDBG_Suspended){ - _state=eDBG_StepInto; - scprintf(_SC("step into\n")); - } - break; - case MSG_ID('s','r'): - if(_state==eDBG_Suspended){ - _state=eDBG_StepReturn; - scprintf(_SC("step return\n")); - } - break; - case MSG_ID('d','i'): - if(_state!=eDBG_Disabled){ - _state=eDBG_Disabled; - scprintf(_SC("disabled\n")); - } - break; - case MSG_ID('a','w'): { - Watch w; - if(ParseWatch(msg+3,w)) - { - AddWatch(w); - scprintf(_SC("added watch %d %s\n"),w._id,w._exp.c_str()); - } - else - scprintf(_SC("error parsing add watch")); - } - break; - case MSG_ID('r','w'): { - int id; - if(ParseRemoveWatch(msg+3,id)) - { - RemoveWatch(id); - scprintf(_SC("added watch %d\n"),id); - } - else - scprintf(_SC("error parsing remove watch")); - } - break; - case MSG_ID('t','r'): - scprintf(_SC("terminate from user\n")); - break; - case MSG_ID('r','d'): - scprintf(_SC("ready\n")); - _ready=true; - break; - default: - scprintf(_SC("unknown packet")); - - } -} - -/* - see copyright notice in sqrdbg.h -*/ -bool SQDbgServer::ParseBreakpoint(const char *msg,BreakPoint &out) -{ - static char stemp[MAX_BP_PATH]; - char *ep=NULL; - out._line=strtoul(msg,&ep,16); - if(ep==msg || (*ep)!=':')return false; - - char *dest=stemp; - ep++; - while((*ep)!='\n' && (*ep)!='\0') - { - *dest=*ep; - *dest++;*ep++; - } - *dest='\0'; - *dest++; - *dest='\0'; -#ifdef _UNICODE - int len=(int)strlen(stemp); - SQChar *p=sq_getscratchpad(_v,(SQInteger)(mbstowcs(NULL,stemp,len)+2)*sizeof(SQChar)); - size_t destlen=mbstowcs(p,stemp,len); - p[destlen]=_SC('\0'); - out._src=p; -#else - out._src=stemp; -#endif - return true; -} - -bool SQDbgServer::ParseWatch(const char *msg,Watch &out) -{ - char *ep=NULL; - out._id=strtoul(msg,&ep,16); - if(ep==msg || (*ep)!=':')return false; - - //char *dest=out._src; - ep++; - while((*ep)!='\n' && (*ep)!='\0') - { - out._exp.append(1,*ep); - *ep++; - } - return true; -} - -bool SQDbgServer::ParseRemoveWatch(const char *msg,int &id) -{ - char *ep=NULL; - id=strtoul(msg,&ep,16); - if(ep==msg)return false; - return true; -} - - -void SQDbgServer::BreakExecution() -{ - _state=eDBG_Suspended; - while(_state==eDBG_Suspended){ - if(SQ_FAILED(sq_rdbg_update(this))) - exit(0); - usleep(10); - } -} - -//COMMANDS -void SQDbgServer::AddBreakpoint(BreakPoint &bp) -{ - _breakpoints.insert(bp); - BeginDocument(); - BeginElement(_SC("addbreakpoint")); - Attribute(_SC("line"),IntToString(bp._line)); - Attribute(_SC("src"),bp._src.c_str()); - EndElement(_SC("addbreakpoint")); - EndDocument(); -} - -void SQDbgServer::AddWatch(Watch &w) -{ - _watches.insert(w); -} - -void SQDbgServer::RemoveWatch(int id) -{ - WatchSetItor itor=_watches.find(Watch(id,_SC(""))); - if(itor==_watches.end()){ - BeginDocument(); - BeginElement(_SC("error")); - Attribute(_SC("desc"),_SC("the watch does not exists")); - EndElement(_SC("error")); - EndDocument(); - } - else{ - _watches.erase(itor); - scprintf(_SC("removed watch %d\n"),id); - } -} - -void SQDbgServer::RemoveBreakpoint(BreakPoint &bp) -{ - BreakPointSetItor itor=_breakpoints.find(bp); - if(itor==_breakpoints.end()){ - BeginDocument(); - BeginElement(_SC("break")); - Attribute(_SC("desc"),_SC("the breakpoint doesn't exists")); - EndElement(_SC("break")); - EndDocument(); - } - else{ - BeginDocument(); - BeginElement(_SC("removebreakpoint")); - Attribute(_SC("line"),IntToString(bp._line)); - Attribute(_SC("src"),bp._src.c_str()); - EndElement(_SC("removebreakpoint")); - EndDocument(); - _breakpoints.erase(itor); - } -} - -void SQDbgServer::Break(int line,const SQChar *src,const SQChar *type,const SQChar *error) -{ - if(!error){ - BeginDocument(); - BeginElement(_SC("break")); - Attribute(_SC("line"),IntToString(line)); - Attribute(_SC("src"),src); - Attribute(_SC("type"),type); - SerializeState(); - EndElement(_SC("break")); - EndDocument(); - }else{ - BeginDocument(); - BeginElement(_SC("break")); - Attribute(_SC("line"),IntToString(line)); - Attribute(_SC("src"),src); - Attribute(_SC("type"),type); - Attribute(_SC("error"),error); - SerializeState(); - EndElement(_SC("break")); - EndDocument(); - } -} - -void SQDbgServer::SerializeState() -{ - sq_pushnull(_v); - sq_setdebughook(_v); - sq_pushnull(_v); - sq_seterrorhandler(_v); - const SQChar *sz; - sq_pushobject(_v,_serializefunc); - sq_pushobject(_v,_debugroot); - sq_pushstring(_v,_SC("watches"),-1); - sq_newtable(_v); - for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i) - { - sq_pushinteger(_v,i->_id); - sq_pushstring(_v,i->_exp.c_str(),(int)i->_exp.length()); - sq_createslot(_v,-3); - } - sq_rawset(_v,-3); - if(SQ_SUCCEEDED(sq_call(_v,1,SQTrue,SQTrue))){ - if(SQ_SUCCEEDED(sqstd_getblob(_v,-1,(SQUserPointer*)&sz))) - SendChunk(sz); - } - sq_pop(_v,2); - - SetErrorHandlers(); -} - - -void SQDbgServer::SetErrorHandlers() -{ - sq_pushregistrytable(_v); - sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); - sq_rawget(_v,-2); - sq_setdebughook(_v); - sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); - sq_rawget(_v,-2); - sq_seterrorhandler(_v); - sq_pop(_v,1); -} - -void SQDbgServer::BeginElement(const SQChar *name) -{ - _xmlcurrentement++; - XMLElementState *self = &xmlstate[_xmlcurrentement]; - scstrcpy(self->name,name); - self->haschildren = false; - if(_xmlcurrentement > 0) { - XMLElementState *parent = &xmlstate[_xmlcurrentement-1]; - if(!parent->haschildren) { - SendChunk(_SC(">")); // closes the parent tag - parent->haschildren = true; - } - } - _scratchstring.resize(2+scstrlen(name)); - scsprintf(&_scratchstring[0],_SC("<%s"),name); - SendChunk(&_scratchstring[0]); -} - -void SQDbgServer::Attribute(const SQChar *name,const SQChar *value) -{ - XMLElementState *self = &xmlstate[_xmlcurrentement]; - assert(!self->haschildren); //cannot have attributes if already has children - const SQChar *escval = escape_xml(value); - _scratchstring.resize(5+scstrlen(name)+scstrlen(escval)); - scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval); - SendChunk(&_scratchstring[0]); -} - -void SQDbgServer::EndElement(const SQChar *name) -{ - XMLElementState *self = &xmlstate[_xmlcurrentement]; - assert(scstrcmp(self->name,name) == 0); - if(self->haschildren) { - _scratchstring.resize(4+scstrlen(name)); - scsprintf(&_scratchstring[0],_SC(""),name); - SendChunk(&_scratchstring[0]); - - } - else { - SendChunk(_SC("/>")); - } - _xmlcurrentement--; -} - -void SQDbgServer::EndDocument() -{ - SendChunk(_SC("\r\n")); -} - -//this can be done much better/faster(do we need that?) -const SQChar *SQDbgServer::escape_xml(const SQChar *s) -{ - SQChar *temp=sq_getscratchpad(_v,((int)scstrlen(s)*6) + sizeof(SQChar)); - SQChar *dest=temp; - while(*s!=_SC('\0')){ - int i=0; - bool escaped=false; - while(g_escapes[i].esc!=NULL){ - if(*s==g_escapes[i].c){ - scstrcpy(dest,g_escapes[i].esc); - dest+=scstrlen(g_escapes[i].esc); - escaped=true; - break; - } - i++; - } - if(!escaped){*dest=*s;*dest++;} - *s++; - } - *dest=_SC('\0'); - return temp; - -} +#include +#include +#include +#include "sqrdbg.h" +#include "sqdbgserver.h" + + +#ifndef _UNICODE +#define scstrcpy strcpy +#else +#define scstrcpy wcscpy +#endif +struct XMLEscape{ + const SQChar c; + const SQChar *esc; +}; + +#define SQDBG_DEBUG_HOOK _SC("_sqdbg_debug_hook_") +#define SQDBG_ERROR_HANDLER _SC("_sqdbg_error_handler_") + +XMLEscape g_escapes[]={ + {_SC('<'),_SC("<")},{'>',_SC(">")},{_SC('&'),_SC("&")},{_SC('\''),_SC("'")},{_SC('\"'),_SC(""")},{_SC('\n'),_SC(""n")},{_SC('\r'),_SC(""r")},{0, NULL} +}; + +const SQChar *IntToString(int n) +{ + static SQChar temp[256]; + scsprintf(temp,_SC("%d"),n); + return temp; +} + +int debug_hook(HSQUIRRELVM v); +int error_handler(HSQUIRRELVM v); + +int beginelement(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + self->BeginElement(name); + return 0; +} + +int endelement(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + self->EndElement(name); + return 0; +} + +int attribute(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *name,*value; + sq_getuserpointer(v,-1,&up); + SQDbgServer *self = (SQDbgServer*)up; + sq_getuserpointer(v,-1,&up); + sq_getstring(v,2,&name); + sq_getstring(v,3,&value); + self->Attribute(name,value); + return 0; +} + +const SQChar *EscapeXMLString(HSQUIRRELVM v,const SQChar *s) +{ + + SQChar *temp=sq_getscratchpad(v,((int)scstrlen(s)*6) + sizeof(SQChar)); + SQChar *dest=temp; + while(*s!=_SC('\0')){ + int i=0; + bool escaped=false; + while(g_escapes[i].esc!=NULL){ + if(*s==g_escapes[i].c){ + scstrcpy(dest,g_escapes[i].esc); + dest+=scstrlen(g_escapes[i].esc); + escaped=true; + break; + } + i++; + } + if(!escaped){*dest=*s;*dest++;} + *s++; + } + *dest=_SC('\0'); + return temp; +} + +SQDbgServer::SQDbgServer(HSQUIRRELVM v) +{ + _ready = false; + _nestedcalls = 0; + _autoupdate = false; + _v = v; + _state = eDBG_Running; + _accept = INVALID_SOCKET; + _endpoint = INVALID_SOCKET; + _maxrecursion = 10; + sq_resetobject(&_debugroot); +} + +SQDbgServer::~SQDbgServer() +{ + sq_release(_v,&_debugroot); + if(_accept != INVALID_SOCKET) + sqdbg_closesocket(_accept); + if(_endpoint != INVALID_SOCKET) + sqdbg_closesocket(_endpoint); +} + +bool SQDbgServer::Init() +{ + //creates an environment table for the debugger + + sq_newtable(_v); + sq_getstackobj(_v,-1,&_debugroot); + sq_addref(_v,&_debugroot); + + //creates a emptyslot to store the watches + sq_pushstring(_v,_SC("watches"),-1); + sq_pushnull(_v); + sq_createslot(_v,-3); + + sq_pushstring(_v,_SC("beginelement"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,beginelement,1); + sq_setparamscheck(_v,2,_SC(".s")); + sq_createslot(_v,-3); + + sq_pushstring(_v,_SC("endelement"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,endelement,1); + sq_setparamscheck(_v,2,_SC(".s")); + sq_createslot(_v,-3); + + sq_pushstring(_v,_SC("attribute"),-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,attribute,1); + sq_setparamscheck(_v,3,_SC(".ss")); + sq_createslot(_v,-3); + + sq_pop(_v,1); + + //stores debug hook and error handler in the registry + sq_pushregistrytable(_v); + + sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,debug_hook,1); + sq_createslot(_v,-3); + + sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); + sq_pushuserpointer(_v,this); + sq_newclosure(_v,error_handler,1); + sq_createslot(_v,-3); + + + sq_pop(_v,1); + + //sets the error handlers + SetErrorHandlers(); + return true; +} + +bool SQDbgServer::ReadMsg() +{ + return false; +} + +void SQDbgServer::BusyWait() +{ + while( !ReadMsg() ) + sleep(0); +} + +void SQDbgServer::SendChunk(const SQChar *chunk) +{ + char *buf=NULL; + int buf_len=0; +#ifdef _UNICODE + buf_len=(int)scstrlen(chunk)+1; + buf=(char *)sq_getscratchpad(_v,(buf_len)*3); + wcstombs((char *)buf,chunk,buf_len); +#else + buf_len=(int)scstrlen(chunk); + buf=(char *)chunk; +#endif + send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0); +} + + +void SQDbgServer::Terminated() +{ + BeginElement(_SC("terminated")); + EndElement(_SC("terminated")); + ::usleep(200); +} + +void SQDbgServer::Hook(int type,int line,const SQChar *src,const SQChar *func) +{ + switch(_state){ + case eDBG_Running: + if(type==_SC('l') && _breakpoints.size()) { + BreakPointSetItor itr = _breakpoints.find(BreakPoint(line,src)); + if(itr != _breakpoints.end()) { + Break(line,src,_SC("breakpoint")); + BreakExecution(); + } + } + break; + case eDBG_Suspended: + _nestedcalls=0; + case eDBG_StepOver: + switch(type){ + case _SC('l'): + if(_nestedcalls==0) { + Break(line,src,_SC("step")); + BreakExecution(); + } + break; + case _SC('c'): + _nestedcalls++; + break; + case _SC('r'): + if(_nestedcalls==0){ + _nestedcalls=0; + + }else{ + _nestedcalls--; + } + break; + } + break; + case eDBG_StepInto: + switch(type){ + case _SC('l'): + _nestedcalls=0; + Break(line,src,_SC("step")); + BreakExecution(); + break; + + } + break; + case eDBG_StepReturn: + switch(type){ + case _SC('l'): + break; + case _SC('c'): + _nestedcalls++; + break; + case _SC('r'): + if(_nestedcalls==0){ + _nestedcalls=0; + _state=eDBG_StepOver; + }else{ + _nestedcalls--; + } + + break; + } + break; + case eDBG_Disabled: + break; + } +} + + +#define MSG_ID(x,y) ((y<<8)|x) +//ab Add Breakpoint +//rb Remove Breakpoint +//sp Suspend +void SQDbgServer::ParseMsg(const char *msg) +{ + + switch(*((unsigned short *)msg)){ + case MSG_ID('a','b'): { + BreakPoint bp; + if(ParseBreakpoint(msg+3,bp)){ + AddBreakpoint(bp); + scprintf(_SC("added bp %d %s\n"),bp._line,bp._src.c_str()); + } + else + scprintf(_SC("error parsing add breakpoint")); + } + break; + case MSG_ID('r','b'): { + BreakPoint bp; + if(ParseBreakpoint(msg+3,bp)){ + RemoveBreakpoint(bp); + scprintf(_SC("removed bp %d %s\n"),bp._line,bp._src.c_str()); + }else + scprintf(_SC("error parsing remove breakpoint")); + } + break; + case MSG_ID('g','o'): + if(_state!=eDBG_Running){ + _state=eDBG_Running; + BeginDocument(); + BeginElement(_SC("resumed")); + EndElement(_SC("resumed")); + EndDocument(); +// Send(_SC("\r\n")); + scprintf(_SC("go (execution resumed)\n")); + } + break; + case MSG_ID('s','p'): + if(_state!=eDBG_Suspended){ + _state=eDBG_Suspended; + scprintf(_SC("suspend\n")); + } + break; + case MSG_ID('s','o'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepOver; + } + break; + case MSG_ID('s','i'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepInto; + scprintf(_SC("step into\n")); + } + break; + case MSG_ID('s','r'): + if(_state==eDBG_Suspended){ + _state=eDBG_StepReturn; + scprintf(_SC("step return\n")); + } + break; + case MSG_ID('d','i'): + if(_state!=eDBG_Disabled){ + _state=eDBG_Disabled; + scprintf(_SC("disabled\n")); + } + break; + case MSG_ID('a','w'): { + Watch w; + if(ParseWatch(msg+3,w)) + { + AddWatch(w); + scprintf(_SC("added watch %d %s\n"),w._id,w._exp.c_str()); + } + else + scprintf(_SC("error parsing add watch")); + } + break; + case MSG_ID('r','w'): { + int id; + if(ParseRemoveWatch(msg+3,id)) + { + RemoveWatch(id); + scprintf(_SC("added watch %d\n"),id); + } + else + scprintf(_SC("error parsing remove watch")); + } + break; + case MSG_ID('t','r'): + scprintf(_SC("terminate from user\n")); + break; + case MSG_ID('r','d'): + scprintf(_SC("ready\n")); + _ready=true; + break; + default: + scprintf(_SC("unknown packet")); + + } +} + +/* + see copyright notice in sqrdbg.h +*/ +bool SQDbgServer::ParseBreakpoint(const char *msg,BreakPoint &out) +{ + static char stemp[MAX_BP_PATH]; + char *ep=NULL; + out._line=strtoul(msg,&ep,16); + if(ep==msg || (*ep)!=':')return false; + + char *dest=stemp; + ep++; + while((*ep)!='\n' && (*ep)!='\0') + { + *dest=*ep; + *dest++;*ep++; + } + *dest='\0'; + *dest++; + *dest='\0'; +#ifdef _UNICODE + int len=(int)strlen(stemp); + SQChar *p=sq_getscratchpad(_v,(SQInteger)(mbstowcs(NULL,stemp,len)+2)*sizeof(SQChar)); + size_t destlen=mbstowcs(p,stemp,len); + p[destlen]=_SC('\0'); + out._src=p; +#else + out._src=stemp; +#endif + return true; +} + +bool SQDbgServer::ParseWatch(const char *msg,Watch &out) +{ + char *ep=NULL; + out._id=strtoul(msg,&ep,16); + if(ep==msg || (*ep)!=':')return false; + + //char *dest=out._src; + ep++; + while((*ep)!='\n' && (*ep)!='\0') + { + out._exp.append(1,*ep); + *ep++; + } + return true; +} + +bool SQDbgServer::ParseRemoveWatch(const char *msg,int &id) +{ + char *ep=NULL; + id=strtoul(msg,&ep,16); + if(ep==msg)return false; + return true; +} + + +void SQDbgServer::BreakExecution() +{ + _state=eDBG_Suspended; + while(_state==eDBG_Suspended){ + if(SQ_FAILED(sq_rdbg_update(this))) + exit(0); + usleep(10); + } +} + +//COMMANDS +void SQDbgServer::AddBreakpoint(BreakPoint &bp) +{ + _breakpoints.insert(bp); + BeginDocument(); + BeginElement(_SC("addbreakpoint")); + Attribute(_SC("line"),IntToString(bp._line)); + Attribute(_SC("src"),bp._src.c_str()); + EndElement(_SC("addbreakpoint")); + EndDocument(); +} + +void SQDbgServer::AddWatch(Watch &w) +{ + _watches.insert(w); +} + +void SQDbgServer::RemoveWatch(int id) +{ + WatchSetItor itor=_watches.find(Watch(id,_SC(""))); + if(itor==_watches.end()){ + BeginDocument(); + BeginElement(_SC("error")); + Attribute(_SC("desc"),_SC("the watch does not exists")); + EndElement(_SC("error")); + EndDocument(); + } + else{ + _watches.erase(itor); + scprintf(_SC("removed watch %d\n"),id); + } +} + +void SQDbgServer::RemoveBreakpoint(BreakPoint &bp) +{ + BreakPointSetItor itor=_breakpoints.find(bp); + if(itor==_breakpoints.end()){ + BeginDocument(); + BeginElement(_SC("break")); + Attribute(_SC("desc"),_SC("the breakpoint doesn't exists")); + EndElement(_SC("break")); + EndDocument(); + } + else{ + BeginDocument(); + BeginElement(_SC("removebreakpoint")); + Attribute(_SC("line"),IntToString(bp._line)); + Attribute(_SC("src"),bp._src.c_str()); + EndElement(_SC("removebreakpoint")); + EndDocument(); + _breakpoints.erase(itor); + } +} + +void SQDbgServer::Break(int line,const SQChar *src,const SQChar *type,const SQChar *error) +{ + if(!error){ + BeginDocument(); + BeginElement(_SC("break")); + Attribute(_SC("line"),IntToString(line)); + Attribute(_SC("src"),src); + Attribute(_SC("type"),type); + SerializeState(); + EndElement(_SC("break")); + EndDocument(); + }else{ + BeginDocument(); + BeginElement(_SC("break")); + Attribute(_SC("line"),IntToString(line)); + Attribute(_SC("src"),src); + Attribute(_SC("type"),type); + Attribute(_SC("error"),error); + SerializeState(); + EndElement(_SC("break")); + EndDocument(); + } +} + +void SQDbgServer::SerializeState() +{ + sq_pushnull(_v); + sq_setdebughook(_v); + sq_pushnull(_v); + sq_seterrorhandler(_v); + const SQChar *sz; + sq_pushobject(_v,_serializefunc); + sq_pushobject(_v,_debugroot); + sq_pushstring(_v,_SC("watches"),-1); + sq_newtable(_v); + for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i) + { + sq_pushinteger(_v,i->_id); + sq_pushstring(_v,i->_exp.c_str(),(int)i->_exp.length()); + sq_createslot(_v,-3); + } + sq_rawset(_v,-3); + if(SQ_SUCCEEDED(sq_call(_v,1,SQTrue,SQTrue))){ + if(SQ_SUCCEEDED(sqstd_getblob(_v,-1,(SQUserPointer*)&sz))) + SendChunk(sz); + } + sq_pop(_v,2); + + SetErrorHandlers(); +} + + +void SQDbgServer::SetErrorHandlers() +{ + sq_pushregistrytable(_v); + sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); + sq_rawget(_v,-2); + sq_setdebughook(_v); + sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); + sq_rawget(_v,-2); + sq_seterrorhandler(_v); + sq_pop(_v,1); +} + +void SQDbgServer::BeginElement(const SQChar *name) +{ + _xmlcurrentement++; + XMLElementState *self = &xmlstate[_xmlcurrentement]; + scstrcpy(self->name,name); + self->haschildren = false; + if(_xmlcurrentement > 0) { + XMLElementState *parent = &xmlstate[_xmlcurrentement-1]; + if(!parent->haschildren) { + SendChunk(_SC(">")); // closes the parent tag + parent->haschildren = true; + } + } + _scratchstring.resize(2+scstrlen(name)); + scsprintf(&_scratchstring[0],_SC("<%s"),name); + SendChunk(&_scratchstring[0]); +} + +void SQDbgServer::Attribute(const SQChar *name,const SQChar *value) +{ + XMLElementState *self = &xmlstate[_xmlcurrentement]; + assert(!self->haschildren); //cannot have attributes if already has children + const SQChar *escval = escape_xml(value); + _scratchstring.resize(5+scstrlen(name)+scstrlen(escval)); + scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval); + SendChunk(&_scratchstring[0]); +} + +void SQDbgServer::EndElement(const SQChar *name) +{ + XMLElementState *self = &xmlstate[_xmlcurrentement]; + assert(scstrcmp(self->name,name) == 0); + if(self->haschildren) { + _scratchstring.resize(4+scstrlen(name)); + scsprintf(&_scratchstring[0],_SC(""),name); + SendChunk(&_scratchstring[0]); + + } + else { + SendChunk(_SC("/>")); + } + _xmlcurrentement--; +} + +void SQDbgServer::EndDocument() +{ + SendChunk(_SC("\r\n")); +} + +//this can be done much better/faster(do we need that?) +const SQChar *SQDbgServer::escape_xml(const SQChar *s) +{ + SQChar *temp=sq_getscratchpad(_v,((int)scstrlen(s)*6) + sizeof(SQChar)); + SQChar *dest=temp; + while(*s!=_SC('\0')){ + int i=0; + bool escaped=false; + while(g_escapes[i].esc!=NULL){ + if(*s==g_escapes[i].c){ + scstrcpy(dest,g_escapes[i].esc); + dest+=scstrlen(g_escapes[i].esc); + escaped=true; + break; + } + i++; + } + if(!escaped){*dest=*s;*dest++;} + *s++; + } + *dest=_SC('\0'); + return temp; + +} diff --git a/src/squirrel/sqdbg/sqdbgserver.h b/src/squirrel/sqdbg/sqdbgserver.h index dcfa7cf6b..8c3fc2848 100644 --- a/src/squirrel/sqdbg/sqdbgserver.h +++ b/src/squirrel/sqdbg/sqdbgserver.h @@ -1,159 +1,159 @@ -#ifndef _SQ_DBGSERVER_H_ -#define _SQ_DBGSERVER_H_ - -#define MAX_BP_PATH 512 -#define MAX_MSG_LEN 2049 - -#include -#include -#include - -#ifdef _WIN32 -#include -#define sqdbg_closesocket(x) closesocket((x)) -typedef socklen_t int; -#else -#include -#include -#include -#include -#include -#include -#include -#include - -#define sqdbg_closesocket(x) close((x)) -typedef int SOCKET; -typedef struct timeval TIMEVAL; -#define SOCKET_ERROR -1 -#define INVALID_SOCKET -1 -#endif - -typedef std::basic_string SQDBGString; - -inline bool dbg_less(const SQChar *x,const SQChar *y) -{ - int n = 0; - do { - int xl = *x == '\\' ? '/' : tolower(*x); - int yl = *y == '\\' ? '/' : tolower(*y); - int diff = xl - yl; - if(diff != 0) - return diff > 0?true:false; - x++; y++; - }while(*x != 0 && *y != 0); - return false; -} - -struct BreakPoint{ - BreakPoint(){_line=0;} - BreakPoint(int line, const SQChar *src){ _line = line; _src = src; } - BreakPoint(const BreakPoint& bp){ _line = bp._line; _src=bp._src; } - inline bool operator<(const BreakPoint& bp) const - { - if(_line BreakPointSet; -typedef BreakPointSet::iterator BreakPointSetItor; - -typedef std::set WatchSet; -typedef WatchSet::iterator WatchSetItor; - -typedef std::vector SQCharVec; -struct SQDbgServer{ -public: - enum eDbgState{ - eDBG_Running, - eDBG_StepOver, - eDBG_StepInto, - eDBG_StepReturn, - eDBG_Suspended, - eDBG_Disabled, - }; - - SQDbgServer(HSQUIRRELVM v); - ~SQDbgServer(); - bool Init(); - //returns true if a message has been received - bool WaitForClient(); - bool ReadMsg(); - void BusyWait(); - void Hook(int type,int line,const SQChar *src,const SQChar *func); - void ParseMsg(const char *msg); - bool ParseBreakpoint(const char *msg,BreakPoint &out); - bool ParseWatch(const char *msg,Watch &out); - bool ParseRemoveWatch(const char *msg,int &id); - void Terminated(); - // - void BreakExecution(); - void Send(const SQChar *s,...); - void SendChunk(const SQChar *chunk); - void Break(int line,const SQChar *src,const SQChar *type,const SQChar *error=NULL); - - - void SerializeState(); - //COMMANDS - void AddBreakpoint(BreakPoint &bp); - void AddWatch(Watch &w); - void RemoveWatch(int id); - void RemoveBreakpoint(BreakPoint &bp); - - // - void SetErrorHandlers(); - - //XML RELATED STUFF/////////////////////// - #define MAX_NESTING 10 - struct XMLElementState { - SQChar name[256]; - bool haschildren; - }; - - XMLElementState xmlstate[MAX_NESTING]; - int _xmlcurrentement; - - void BeginDocument() { _xmlcurrentement = -1; } - void BeginElement(const SQChar *name); - void Attribute(const SQChar *name, const SQChar *value); - void EndElement(const SQChar *name); - void EndDocument(); - - const SQChar *escape_xml(const SQChar *x); - ////////////////////////////////////////////// - HSQUIRRELVM _v; - HSQOBJECT _debugroot; - eDbgState _state; - SOCKET _accept; - SOCKET _endpoint; - BreakPointSet _breakpoints; - WatchSet _watches; - int _recursionlevel; - int _maxrecursion; - int _nestedcalls; - bool _ready; - bool _autoupdate; - HSQOBJECT _serializefunc; - SQCharVec _scratchstring; - -}; - -#endif //_SQ_DBGSERVER_H_ +#ifndef _SQ_DBGSERVER_H_ +#define _SQ_DBGSERVER_H_ + +#define MAX_BP_PATH 512 +#define MAX_MSG_LEN 2049 + +#include +#include +#include + +#ifdef _WIN32 +#include +#define sqdbg_closesocket(x) closesocket((x)) +typedef socklen_t int; +#else +#include +#include +#include +#include +#include +#include +#include +#include + +#define sqdbg_closesocket(x) close((x)) +typedef int SOCKET; +typedef struct timeval TIMEVAL; +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 +#endif + +typedef std::basic_string SQDBGString; + +inline bool dbg_less(const SQChar *x,const SQChar *y) +{ + int n = 0; + do { + int xl = *x == '\\' ? '/' : tolower(*x); + int yl = *y == '\\' ? '/' : tolower(*y); + int diff = xl - yl; + if(diff != 0) + return diff > 0?true:false; + x++; y++; + }while(*x != 0 && *y != 0); + return false; +} + +struct BreakPoint{ + BreakPoint(){_line=0;} + BreakPoint(int line, const SQChar *src){ _line = line; _src = src; } + BreakPoint(const BreakPoint& bp){ _line = bp._line; _src=bp._src; } + inline bool operator<(const BreakPoint& bp) const + { + if(_line BreakPointSet; +typedef BreakPointSet::iterator BreakPointSetItor; + +typedef std::set WatchSet; +typedef WatchSet::iterator WatchSetItor; + +typedef std::vector SQCharVec; +struct SQDbgServer{ +public: + enum eDbgState{ + eDBG_Running, + eDBG_StepOver, + eDBG_StepInto, + eDBG_StepReturn, + eDBG_Suspended, + eDBG_Disabled, + }; + + SQDbgServer(HSQUIRRELVM v); + ~SQDbgServer(); + bool Init(); + //returns true if a message has been received + bool WaitForClient(); + bool ReadMsg(); + void BusyWait(); + void Hook(int type,int line,const SQChar *src,const SQChar *func); + void ParseMsg(const char *msg); + bool ParseBreakpoint(const char *msg,BreakPoint &out); + bool ParseWatch(const char *msg,Watch &out); + bool ParseRemoveWatch(const char *msg,int &id); + void Terminated(); + // + void BreakExecution(); + void Send(const SQChar *s,...); + void SendChunk(const SQChar *chunk); + void Break(int line,const SQChar *src,const SQChar *type,const SQChar *error=NULL); + + + void SerializeState(); + //COMMANDS + void AddBreakpoint(BreakPoint &bp); + void AddWatch(Watch &w); + void RemoveWatch(int id); + void RemoveBreakpoint(BreakPoint &bp); + + // + void SetErrorHandlers(); + + //XML RELATED STUFF/////////////////////// + #define MAX_NESTING 10 + struct XMLElementState { + SQChar name[256]; + bool haschildren; + }; + + XMLElementState xmlstate[MAX_NESTING]; + int _xmlcurrentement; + + void BeginDocument() { _xmlcurrentement = -1; } + void BeginElement(const SQChar *name); + void Attribute(const SQChar *name, const SQChar *value); + void EndElement(const SQChar *name); + void EndDocument(); + + const SQChar *escape_xml(const SQChar *x); + ////////////////////////////////////////////// + HSQUIRRELVM _v; + HSQOBJECT _debugroot; + eDbgState _state; + SOCKET _accept; + SOCKET _endpoint; + BreakPointSet _breakpoints; + WatchSet _watches; + int _recursionlevel; + int _maxrecursion; + int _nestedcalls; + bool _ready; + bool _autoupdate; + HSQOBJECT _serializefunc; + SQCharVec _scratchstring; + +}; + +#endif //_SQ_DBGSERVER_H_ diff --git a/src/squirrel/sqdbg/sqrdbg.cpp b/src/squirrel/sqdbg/sqrdbg.cpp index b58a41d01..c5243faab 100644 --- a/src/squirrel/sqdbg/sqrdbg.cpp +++ b/src/squirrel/sqdbg/sqrdbg.cpp @@ -1,166 +1,166 @@ -/* - see copyright notice in sqrdbg.h -*/ -#include -#include "sqrdbg.h" -#include "sqdbgserver.h" -int debug_hook(HSQUIRRELVM v); -int error_handler(HSQUIRRELVM v); - -#include "serialize_state.inl" - -HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate) -{ - sockaddr_in bindaddr; -#ifdef _WIN32 - WSADATA wsadata; - if (WSAStartup (MAKEWORD(1,1), &wsadata) != 0){ - return NULL; - } -#endif - - SQDbgServer *rdbg = new SQDbgServer(v); - rdbg->_autoupdate = autoupdate?true:false; - rdbg->_accept = socket(AF_INET,SOCK_STREAM,0); - bindaddr.sin_family = AF_INET; - bindaddr.sin_port = htons(port); - bindaddr.sin_addr.s_addr = htonl (INADDR_ANY); - if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){ - delete rdbg; - sq_throwerror(v,_SC("failed to bind the socket")); - return NULL; - } - if(!rdbg->Init()) { - delete rdbg; - sq_throwerror(v,_SC("failed to initialize the debugger")); - return NULL; - } - - return rdbg; -} - -SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg) -{ - if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) { - sq_throwerror(rdbg->_v,_SC("error compiling the serialization function")); - } - sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc); - sq_addref(rdbg->_v,&rdbg->_serializefunc); - sq_pop(rdbg->_v,1); - - sockaddr_in cliaddr; - socklen_t addrlen=sizeof(cliaddr); - if(listen(rdbg->_accept,0)==SOCKET_ERROR) - return sq_throwerror(rdbg->_v,_SC("error on listen(socket)")); - rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen); - //do not accept any other connection - sqdbg_closesocket(rdbg->_accept); - rdbg->_accept = INVALID_SOCKET; - if(rdbg->_endpoint==INVALID_SOCKET){ - return sq_throwerror(rdbg->_v,_SC("error accept(socket)")); - } - while(!rdbg->_ready){ - sq_rdbg_update(rdbg); - } - return SQ_OK; -} - -SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg) -{ - TIMEVAL time; - time.tv_sec=0; - time.tv_usec=0; - fd_set read_flags; - FD_ZERO(&read_flags); - FD_SET(rdbg->_endpoint, &read_flags); - select(FD_SETSIZE, &read_flags, NULL, NULL, &time); - - if(FD_ISSET(rdbg->_endpoint,&read_flags)){ - char temp[1024]; - int size=0; - char c,prev=0; - memset(&temp,0,sizeof(temp)); - int res; - FD_CLR(rdbg->_endpoint, &read_flags); - while((res = recv(rdbg->_endpoint,&c,1,0))>0){ - - if(c=='\n')break; - if(c!='\r'){ - temp[size]=c; - prev=c; - size++; - } - } - switch(res){ - case 0: - return sq_throwerror(rdbg->_v,_SC("disconnected")); - case SOCKET_ERROR: - return sq_throwerror(rdbg->_v,_SC("socket error")); - } - - temp[size]=0; - temp[size+1]=0; - rdbg->ParseMsg(temp); - } - return SQ_OK; -} - -int debug_hook(HSQUIRRELVM v) -{ - SQUserPointer up; - int event_type,line; - const SQChar *src,*func; - sq_getinteger(v,2,&event_type); - sq_getstring(v,3,&src); - sq_getinteger(v,4,&line); - sq_getstring(v,5,&func); - sq_getuserpointer(v,-1,&up); - HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up; - rdbg->Hook(event_type,line,src,func); - if(rdbg->_autoupdate) { - if(SQ_FAILED(sq_rdbg_update(rdbg))) - return sq_throwerror(v,_SC("socket failed")); - } - return 0; -} - -int error_handler(HSQUIRRELVM v) -{ - SQUserPointer up; - const SQChar *sErr=NULL; - const SQChar *fn=_SC("unknown"); - const SQChar *src=_SC("unknown"); - int line=-1; - SQStackInfos si; - sq_getuserpointer(v,-1,&up); - HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up; - if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si))) - { - if(si.funcname)fn=si.funcname; - if(si.source)src=si.source; - line=si.line; - scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line); - } - if(sq_gettop(v)>=1){ - if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { - scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); - rdbg->Break(si.line,src,_SC("error"),sErr); - } - else{ - scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n")); - rdbg->Break(si.line,src,_SC("error"),_SC("unknown")); - } - } - rdbg->BreakExecution(); - return 0; -} - - -SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg) -{ - delete rdbg; -#ifdef _WIN32 - WSACleanup(); -#endif - return SQ_OK; -} +/* + see copyright notice in sqrdbg.h +*/ +#include +#include "sqrdbg.h" +#include "sqdbgserver.h" +int debug_hook(HSQUIRRELVM v); +int error_handler(HSQUIRRELVM v); + +#include "serialize_state.inl" + +HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate) +{ + sockaddr_in bindaddr; +#ifdef _WIN32 + WSADATA wsadata; + if (WSAStartup (MAKEWORD(1,1), &wsadata) != 0){ + return NULL; + } +#endif + + SQDbgServer *rdbg = new SQDbgServer(v); + rdbg->_autoupdate = autoupdate?true:false; + rdbg->_accept = socket(AF_INET,SOCK_STREAM,0); + bindaddr.sin_family = AF_INET; + bindaddr.sin_port = htons(port); + bindaddr.sin_addr.s_addr = htonl (INADDR_ANY); + if(bind(rdbg->_accept,(sockaddr*)&bindaddr,sizeof(bindaddr))==SOCKET_ERROR){ + delete rdbg; + sq_throwerror(v,_SC("failed to bind the socket")); + return NULL; + } + if(!rdbg->Init()) { + delete rdbg; + sq_throwerror(v,_SC("failed to initialize the debugger")); + return NULL; + } + + return rdbg; +} + +SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg) +{ + if(SQ_FAILED(sq_compilebuffer(rdbg->_v,serialize_state_nut,(SQInteger)scstrlen(serialize_state_nut),_SC("SERIALIZE_STATE"),SQFalse))) { + sq_throwerror(rdbg->_v,_SC("error compiling the serialization function")); + } + sq_getstackobj(rdbg->_v,-1,&rdbg->_serializefunc); + sq_addref(rdbg->_v,&rdbg->_serializefunc); + sq_pop(rdbg->_v,1); + + sockaddr_in cliaddr; + socklen_t addrlen=sizeof(cliaddr); + if(listen(rdbg->_accept,0)==SOCKET_ERROR) + return sq_throwerror(rdbg->_v,_SC("error on listen(socket)")); + rdbg->_endpoint = accept(rdbg->_accept,(sockaddr*)&cliaddr,&addrlen); + //do not accept any other connection + sqdbg_closesocket(rdbg->_accept); + rdbg->_accept = INVALID_SOCKET; + if(rdbg->_endpoint==INVALID_SOCKET){ + return sq_throwerror(rdbg->_v,_SC("error accept(socket)")); + } + while(!rdbg->_ready){ + sq_rdbg_update(rdbg); + } + return SQ_OK; +} + +SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg) +{ + TIMEVAL time; + time.tv_sec=0; + time.tv_usec=0; + fd_set read_flags; + FD_ZERO(&read_flags); + FD_SET(rdbg->_endpoint, &read_flags); + select(FD_SETSIZE, &read_flags, NULL, NULL, &time); + + if(FD_ISSET(rdbg->_endpoint,&read_flags)){ + char temp[1024]; + int size=0; + char c,prev=0; + memset(&temp,0,sizeof(temp)); + int res; + FD_CLR(rdbg->_endpoint, &read_flags); + while((res = recv(rdbg->_endpoint,&c,1,0))>0){ + + if(c=='\n')break; + if(c!='\r'){ + temp[size]=c; + prev=c; + size++; + } + } + switch(res){ + case 0: + return sq_throwerror(rdbg->_v,_SC("disconnected")); + case SOCKET_ERROR: + return sq_throwerror(rdbg->_v,_SC("socket error")); + } + + temp[size]=0; + temp[size+1]=0; + rdbg->ParseMsg(temp); + } + return SQ_OK; +} + +int debug_hook(HSQUIRRELVM v) +{ + SQUserPointer up; + int event_type,line; + const SQChar *src,*func; + sq_getinteger(v,2,&event_type); + sq_getstring(v,3,&src); + sq_getinteger(v,4,&line); + sq_getstring(v,5,&func); + sq_getuserpointer(v,-1,&up); + HSQREMOTEDBG rdbg = (HSQREMOTEDBG)up; + rdbg->Hook(event_type,line,src,func); + if(rdbg->_autoupdate) { + if(SQ_FAILED(sq_rdbg_update(rdbg))) + return sq_throwerror(v,_SC("socket failed")); + } + return 0; +} + +int error_handler(HSQUIRRELVM v) +{ + SQUserPointer up; + const SQChar *sErr=NULL; + const SQChar *fn=_SC("unknown"); + const SQChar *src=_SC("unknown"); + int line=-1; + SQStackInfos si; + sq_getuserpointer(v,-1,&up); + HSQREMOTEDBG rdbg=(HSQREMOTEDBG)up; + if(SQ_SUCCEEDED(sq_stackinfos(v,1,&si))) + { + if(si.funcname)fn=si.funcname; + if(si.source)src=si.source; + line=si.line; + scprintf(_SC("*FUNCTION [%s] %s line [%d]\n"),fn,src,si.line); + } + if(sq_gettop(v)>=1){ + if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { + scprintf(_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); + rdbg->Break(si.line,src,_SC("error"),sErr); + } + else{ + scprintf(_SC("\nAN ERROR HAS OCCURED [unknown]\n")); + rdbg->Break(si.line,src,_SC("error"),_SC("unknown")); + } + } + rdbg->BreakExecution(); + return 0; +} + + +SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg) +{ + delete rdbg; +#ifdef _WIN32 + WSACleanup(); +#endif + return SQ_OK; +} diff --git a/src/squirrel/sqdbg/sqrdbg.h b/src/squirrel/sqdbg/sqrdbg.h index 3d15e7448..6302790cb 100644 --- a/src/squirrel/sqdbg/sqrdbg.h +++ b/src/squirrel/sqdbg/sqrdbg.h @@ -1,51 +1,50 @@ -/* -Copyright (c) 2003-2005 Alberto Demichelis - -This software is provided 'as-is', without any -express or implied warranty. In no event will the -authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software -for any purpose, including commercial applications, -and to alter it and redistribute it freely, subject -to the following restrictions: - - 1. The origin of this software must not be - misrepresented; you must not claim that - you wrote the original software. If you - use this software in a product, an - acknowledgment in the product - documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly - marked as such, and must not be - misrepresented as being the original - software. - - 3. This notice may not be removed or - altered from any source distribution. - -*/ -#ifndef _SQ_RDBG_H_ -#define _SQ_RDBG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -struct SQDbgServer; -typedef SQDbgServer* HSQREMOTEDBG; - -HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate); -SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg); -SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg); -SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif //_SQ_RDBG_H_ - +/* +Copyright (c) 2003-2005 Alberto Demichelis + +This software is provided 'as-is', without any +express or implied warranty. In no event will the +authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software +for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject +to the following restrictions: + + 1. The origin of this software must not be + misrepresented; you must not claim that + you wrote the original software. If you + use this software in a product, an + acknowledgment in the product + documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly + marked as such, and must not be + misrepresented as being the original + software. + + 3. This notice may not be removed or + altered from any source distribution. + +*/ +#ifndef _SQ_RDBG_H_ +#define _SQ_RDBG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct SQDbgServer; +typedef SQDbgServer* HSQREMOTEDBG; + +HSQREMOTEDBG sq_rdbg_init(HSQUIRRELVM v,unsigned short port,SQBool autoupdate); +SQRESULT sq_rdbg_waitforconnections(HSQREMOTEDBG rdbg); +SQRESULT sq_rdbg_shutdown(HSQREMOTEDBG rdbg); +SQRESULT sq_rdbg_update(HSQREMOTEDBG rdbg); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif //_SQ_RDBG_H_ diff --git a/src/squirrel/sqstdlib/sqstdaux.cpp b/src/squirrel/sqstdlib/sqstdaux.cpp index ddfac0812..da014f50d 100644 --- a/src/squirrel/sqstdlib/sqstdaux.cpp +++ b/src/squirrel/sqstdlib/sqstdaux.cpp @@ -1,129 +1,129 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include - -void sqstd_printcallstack(HSQUIRRELVM v) -{ - SQPRINTFUNCTION pf = sq_getprintfunc(v); - if(pf) { - SQStackInfos si; - SQInteger i; - SQFloat f; - const SQChar *s; - SQInteger level=1; //1 is to skip this function that is level 0 - const SQChar *name=0; - SQInteger seq=0; - pf(v,_SC("\nCALLSTACK\n")); - while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) - { - const SQChar *fn=_SC("unknown"); - const SQChar *src=_SC("unknown"); - if(si.funcname)fn=si.funcname; - if(si.source)src=si.source; - pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line); - level++; - } - level=0; - pf(v,_SC("\nLOCALS\n")); - - for(level=0;level<10;level++){ - seq=0; - while((name = sq_getlocal(v,level,seq))) - { - seq++; - switch(sq_gettype(v,-1)) - { - case OT_NULL: - pf(v,_SC("[%s] NULL\n"),name); - break; - case OT_INTEGER: - sq_getinteger(v,-1,&i); - pf(v,_SC("[%s] %d\n"),name,i); - break; - case OT_FLOAT: - sq_getfloat(v,-1,&f); - pf(v,_SC("[%s] %.14g\n"),name,f); - break; - case OT_USERPOINTER: - pf(v,_SC("[%s] USERPOINTER\n"),name); - break; - case OT_STRING: - sq_getstring(v,-1,&s); - pf(v,_SC("[%s] \"%s\"\n"),name,s); - break; - case OT_TABLE: - pf(v,_SC("[%s] TABLE\n"),name); - break; - case OT_ARRAY: - pf(v,_SC("[%s] ARRAY\n"),name); - break; - case OT_CLOSURE: - pf(v,_SC("[%s] CLOSURE\n"),name); - break; - case OT_NATIVECLOSURE: - pf(v,_SC("[%s] NATIVECLOSURE\n"),name); - break; - case OT_GENERATOR: - pf(v,_SC("[%s] NATIVECLOSURE\n"),name); - break; - case OT_USERDATA: - pf(v,_SC("[%s] USERDATA\n"),name); - break; - case OT_THREAD: - pf(v,_SC("[%s] THREAD\n"),name); - break; - case OT_CLASS: - pf(v,_SC("[%s] CLASS\n"),name); - break; - case OT_INSTANCE: - pf(v,_SC("[%s] INSTANCE\n"),name); - break; - case OT_WEAKREF: - pf(v,_SC("[%s] INSTANCE\n"),name); - break; - case OT_BOOL:{ - sq_getinteger(v,-1,&i); - pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false")); - } - break; - default: assert(0); break; - } - sq_pop(v,1); - } - } - } -} - -static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) -{ - SQPRINTFUNCTION pf = sq_getprintfunc(v); - if(pf) { - const SQChar *sErr = 0; - if(sq_gettop(v)>=1) { - if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { - pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); - } - else{ - pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n")); - } - sqstd_printcallstack(v); - } - } - return 0; -} - -void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column) -{ - SQPRINTFUNCTION pf = sq_getprintfunc(v); - if(pf) { - pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); - } -} - -void sqstd_seterrorhandlers(HSQUIRRELVM v) -{ - sq_setcompilererrorhandler(v,_sqstd_compiler_error); - sq_newclosure(v,_sqstd_aux_printerror,0); - sq_seterrorhandler(v); -} +/* see copyright notice in squirrel.h */ +#include +#include +#include + +void sqstd_printcallstack(HSQUIRRELVM v) +{ + SQPRINTFUNCTION pf = sq_getprintfunc(v); + if(pf) { + SQStackInfos si; + SQInteger i; + SQFloat f; + const SQChar *s; + SQInteger level=1; //1 is to skip this function that is level 0 + const SQChar *name=0; + SQInteger seq=0; + pf(v,_SC("\nCALLSTACK\n")); + while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) + { + const SQChar *fn=_SC("unknown"); + const SQChar *src=_SC("unknown"); + if(si.funcname)fn=si.funcname; + if(si.source)src=si.source; + pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line); + level++; + } + level=0; + pf(v,_SC("\nLOCALS\n")); + + for(level=0;level<10;level++){ + seq=0; + while((name = sq_getlocal(v,level,seq))) + { + seq++; + switch(sq_gettype(v,-1)) + { + case OT_NULL: + pf(v,_SC("[%s] NULL\n"),name); + break; + case OT_INTEGER: + sq_getinteger(v,-1,&i); + pf(v,_SC("[%s] %d\n"),name,i); + break; + case OT_FLOAT: + sq_getfloat(v,-1,&f); + pf(v,_SC("[%s] %.14g\n"),name,f); + break; + case OT_USERPOINTER: + pf(v,_SC("[%s] USERPOINTER\n"),name); + break; + case OT_STRING: + sq_getstring(v,-1,&s); + pf(v,_SC("[%s] \"%s\"\n"),name,s); + break; + case OT_TABLE: + pf(v,_SC("[%s] TABLE\n"),name); + break; + case OT_ARRAY: + pf(v,_SC("[%s] ARRAY\n"),name); + break; + case OT_CLOSURE: + pf(v,_SC("[%s] CLOSURE\n"),name); + break; + case OT_NATIVECLOSURE: + pf(v,_SC("[%s] NATIVECLOSURE\n"),name); + break; + case OT_GENERATOR: + pf(v,_SC("[%s] NATIVECLOSURE\n"),name); + break; + case OT_USERDATA: + pf(v,_SC("[%s] USERDATA\n"),name); + break; + case OT_THREAD: + pf(v,_SC("[%s] THREAD\n"),name); + break; + case OT_CLASS: + pf(v,_SC("[%s] CLASS\n"),name); + break; + case OT_INSTANCE: + pf(v,_SC("[%s] INSTANCE\n"),name); + break; + case OT_WEAKREF: + pf(v,_SC("[%s] INSTANCE\n"),name); + break; + case OT_BOOL:{ + sq_getinteger(v,-1,&i); + pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false")); + } + break; + default: assert(0); break; + } + sq_pop(v,1); + } + } + } +} + +static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) +{ + SQPRINTFUNCTION pf = sq_getprintfunc(v); + if(pf) { + const SQChar *sErr = 0; + if(sq_gettop(v)>=1) { + if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { + pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); + } + else{ + pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n")); + } + sqstd_printcallstack(v); + } + } + return 0; +} + +void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column) +{ + SQPRINTFUNCTION pf = sq_getprintfunc(v); + if(pf) { + pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); + } +} + +void sqstd_seterrorhandlers(HSQUIRRELVM v) +{ + sq_setcompilererrorhandler(v,_sqstd_compiler_error); + sq_newclosure(v,_sqstd_aux_printerror,0); + sq_seterrorhandler(v); +} diff --git a/src/squirrel/sqstdlib/sqstdblob.cpp b/src/squirrel/sqstdlib/sqstdblob.cpp index 5036db11a..ded369661 100644 --- a/src/squirrel/sqstdlib/sqstdblob.cpp +++ b/src/squirrel/sqstdlib/sqstdblob.cpp @@ -1,252 +1,251 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include -#include "sqstdstream.h" -#include "sqstdblobimpl.h" - -#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002) - -//Blob - - -#define SETUP_BLOB(v) \ - SQBlob *self = NULL; \ - { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ - return SQ_ERROR; } - - -static SQInteger _blob_resize(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - SQInteger size; - sq_getinteger(v,2,&size); - if(!self->Resize(size)) - return sq_throwerror(v,_SC("resize failed")); - return 0; -} - -static void __swap_dword(unsigned int *n) -{ - *n=(unsigned int)(((*n&0xFF000000)>>24) | - ((*n&0x00FF0000)>>8) | - ((*n&0x0000FF00)<<8) | - ((*n&0x000000FF)<<24)); -} - -static void __swap_word(unsigned short *n) -{ - *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00); -} - -static SQInteger _blob_swap4(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - SQInteger num=(self->Len()-(self->Len()%4))>>2; - unsigned int *t=(unsigned int *)self->GetBuf(); - for(SQInteger i = 0; i < num; i++) { - __swap_dword(&t[i]); - } - return 0; -} - -static SQInteger _blob_swap2(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - SQInteger num=(self->Len()-(self->Len()%2))>>1; - unsigned short *t = (unsigned short *)self->GetBuf(); - for(SQInteger i = 0; i < num; i++) { - __swap_word(&t[i]); - } - return 0; -} - -static SQInteger _blob__set(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - SQInteger idx,val; - sq_getinteger(v,2,&idx); - sq_getinteger(v,3,&val); - if(idx < 0 || idx >= self->Len()) - return sq_throwerror(v,_SC("index out of range")); - ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val; - sq_push(v,3); - return 1; -} - -static SQInteger _blob__get(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - SQInteger idx; - sq_getinteger(v,2,&idx); - if(idx < 0 || idx >= self->Len()) - return sq_throwerror(v,_SC("index out of range")); - sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]); - return 1; -} - -static SQInteger _blob__nexti(HSQUIRRELVM v) -{ - SETUP_BLOB(v); - if(sq_gettype(v,2) == OT_NULL) { - sq_pushinteger(v, 0); - return 1; - } - SQInteger idx; - if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) { - if(idx+1 < self->Len()) { - sq_pushinteger(v, idx+1); - return 1; - } - sq_pushnull(v); - return 1; - } - return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type")); -} - -static SQInteger _blob__typeof(HSQUIRRELVM v) -{ - sq_pushstring(v,_SC("blob"),-1); - return 1; -} - -static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size) -{ - SQBlob *self = (SQBlob*)p; - delete self; - return 1; -} - -static SQInteger _blob_constructor(HSQUIRRELVM v) -{ - SQInteger nparam = sq_gettop(v); - SQInteger size = 0; - if(nparam == 2) { - sq_getinteger(v, 2, &size); - } - if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); - SQBlob *b = new SQBlob(size); - if(SQ_FAILED(sq_setinstanceup(v,1,b))) { - delete b; - return sq_throwerror(v, _SC("cannot create blob with negative size")); - } - sq_setreleasehook(v,1,_blob_releasehook); - return 0; -} - -#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck} -static SQRegFunction _blob_methods[] = { - _DECL_BLOB_FUNC(constructor,-1,_SC("xn")), - _DECL_BLOB_FUNC(resize,2,_SC("xn")), - _DECL_BLOB_FUNC(swap2,1,_SC("x")), - _DECL_BLOB_FUNC(swap4,1,_SC("x")), - _DECL_BLOB_FUNC(_set,3,_SC("xnn")), - _DECL_BLOB_FUNC(_get,2,_SC("xn")), - _DECL_BLOB_FUNC(_typeof,1,_SC("x")), - _DECL_BLOB_FUNC(_nexti,2,_SC("x")), - {0,0,0,0} -}; - - - -//GLOBAL FUNCTIONS - -static SQInteger _g_blob_casti2f(HSQUIRRELVM v) -{ - SQInteger i; - sq_getinteger(v,2,&i); - sq_pushfloat(v,*((SQFloat *)&i)); - return 1; -} - -static SQInteger _g_blob_castf2i(HSQUIRRELVM v) -{ - SQFloat f; - sq_getfloat(v,2,&f); - sq_pushinteger(v,*((SQInteger *)&f)); - return 1; -} - -static SQInteger _g_blob_swap2(HSQUIRRELVM v) -{ - SQInteger i; - sq_getinteger(v,2,&i); - short s=(short)i; - sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF)); - return 1; -} - -static SQInteger _g_blob_swap4(HSQUIRRELVM v) -{ - SQInteger i; - sq_getinteger(v,2,&i); - unsigned int t4 = (unsigned int)i; - __swap_dword(&t4); - sq_pushinteger(v,(SQInteger)t4); - return 1; -} - -static SQInteger _g_blob_swapfloat(HSQUIRRELVM v) -{ - SQFloat f; - sq_getfloat(v,2,&f); - __swap_dword((unsigned int *)&f); - sq_pushfloat(v,f); - return 1; -} - -#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck} -static SQRegFunction bloblib_funcs[]={ - _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")), - _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")), - {0,0} -}; - -SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr) -{ - SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) - return -1; - *ptr = blob->GetBuf(); - return SQ_OK; -} - -SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx) -{ - SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) - return -1; - return blob->Len(); -} - -SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size) -{ - SQInteger top = sq_gettop(v); - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_blob"),-1); - if(SQ_SUCCEEDED(sq_get(v,-2))) { - sq_remove(v,-2); //removes the registry - sq_push(v,1); // push the this - sq_pushinteger(v,size); //size - SQBlob *blob = NULL; - if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse)) - && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) { - sq_remove(v,-2); - sq_remove(v,-2); - return blob->GetBuf(); - } - } - sq_settop(v,top); - return NULL; -} - -SQRESULT sqstd_register_bloblib(HSQUIRRELVM v) -{ - return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs); -} - +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include "sqstdstream.h" +#include "sqstdblobimpl.h" + +#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002) + +//Blob + + +#define SETUP_BLOB(v) \ + SQBlob *self = NULL; \ + { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ + return SQ_ERROR; } + + +static SQInteger _blob_resize(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger size; + sq_getinteger(v,2,&size); + if(!self->Resize(size)) + return sq_throwerror(v,_SC("resize failed")); + return 0; +} + +static void __swap_dword(unsigned int *n) +{ + *n=(unsigned int)(((*n&0xFF000000)>>24) | + ((*n&0x00FF0000)>>8) | + ((*n&0x0000FF00)<<8) | + ((*n&0x000000FF)<<24)); +} + +static void __swap_word(unsigned short *n) +{ + *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00); +} + +static SQInteger _blob_swap4(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%4))>>2; + unsigned int *t=(unsigned int *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_dword(&t[i]); + } + return 0; +} + +static SQInteger _blob_swap2(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%2))>>1; + unsigned short *t = (unsigned short *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_word(&t[i]); + } + return 0; +} + +static SQInteger _blob__set(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger idx,val; + sq_getinteger(v,2,&idx); + sq_getinteger(v,3,&val); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val; + sq_push(v,3); + return 1; +} + +static SQInteger _blob__get(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger idx; + sq_getinteger(v,2,&idx); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]); + return 1; +} + +static SQInteger _blob__nexti(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + if(sq_gettype(v,2) == OT_NULL) { + sq_pushinteger(v, 0); + return 1; + } + SQInteger idx; + if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) { + if(idx+1 < self->Len()) { + sq_pushinteger(v, idx+1); + return 1; + } + sq_pushnull(v); + return 1; + } + return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type")); +} + +static SQInteger _blob__typeof(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("blob"),-1); + return 1; +} + +static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size) +{ + SQBlob *self = (SQBlob*)p; + delete self; + return 1; +} + +static SQInteger _blob_constructor(HSQUIRRELVM v) +{ + SQInteger nparam = sq_gettop(v); + SQInteger size = 0; + if(nparam == 2) { + sq_getinteger(v, 2, &size); + } + if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); + SQBlob *b = new SQBlob(size); + if(SQ_FAILED(sq_setinstanceup(v,1,b))) { + delete b; + return sq_throwerror(v, _SC("cannot create blob with negative size")); + } + sq_setreleasehook(v,1,_blob_releasehook); + return 0; +} + +#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck} +static SQRegFunction _blob_methods[] = { + _DECL_BLOB_FUNC(constructor,-1,_SC("xn")), + _DECL_BLOB_FUNC(resize,2,_SC("xn")), + _DECL_BLOB_FUNC(swap2,1,_SC("x")), + _DECL_BLOB_FUNC(swap4,1,_SC("x")), + _DECL_BLOB_FUNC(_set,3,_SC("xnn")), + _DECL_BLOB_FUNC(_get,2,_SC("xn")), + _DECL_BLOB_FUNC(_typeof,1,_SC("x")), + _DECL_BLOB_FUNC(_nexti,2,_SC("x")), + {0,0,0,0} +}; + + + +//GLOBAL FUNCTIONS + +static SQInteger _g_blob_casti2f(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + sq_pushfloat(v,*((SQFloat *)&i)); + return 1; +} + +static SQInteger _g_blob_castf2i(HSQUIRRELVM v) +{ + SQFloat f; + sq_getfloat(v,2,&f); + sq_pushinteger(v,*((SQInteger *)&f)); + return 1; +} + +static SQInteger _g_blob_swap2(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + short s=(short)i; + sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF)); + return 1; +} + +static SQInteger _g_blob_swap4(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + unsigned int t4 = (unsigned int)i; + __swap_dword(&t4); + sq_pushinteger(v,(SQInteger)t4); + return 1; +} + +static SQInteger _g_blob_swapfloat(HSQUIRRELVM v) +{ + SQFloat f; + sq_getfloat(v,2,&f); + __swap_dword((unsigned int *)&f); + sq_pushfloat(v,f); + return 1; +} + +#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck} +static SQRegFunction bloblib_funcs[]={ + _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")), + {0,0} +}; + +SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr) +{ + SQBlob *blob; + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return -1; + *ptr = blob->GetBuf(); + return SQ_OK; +} + +SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx) +{ + SQBlob *blob; + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + return -1; + return blob->Len(); +} + +SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size) +{ + SQInteger top = sq_gettop(v); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_blob"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { + sq_remove(v,-2); //removes the registry + sq_push(v,1); // push the this + sq_pushinteger(v,size); //size + SQBlob *blob = NULL; + if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse)) + && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) { + sq_remove(v,-2); + sq_remove(v,-2); + return blob->GetBuf(); + } + } + sq_settop(v,top); + return NULL; +} + +SQRESULT sqstd_register_bloblib(HSQUIRRELVM v) +{ + return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs); +} diff --git a/src/squirrel/sqstdlib/sqstdblobimpl.h b/src/squirrel/sqstdlib/sqstdblobimpl.h index b2291b73c..9f22c0ae2 100644 --- a/src/squirrel/sqstdlib/sqstdblobimpl.h +++ b/src/squirrel/sqstdlib/sqstdblobimpl.h @@ -1,108 +1,108 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_BLOBIMPL_H_ -#define _SQSTD_BLOBIMPL_H_ - -struct SQBlob : public SQStream -{ - SQBlob(SQInteger size) { - _size = size; - _allocated = size; - _buf = (unsigned char *)sq_malloc(size); - memset(_buf, 0, _size); - _ptr = 0; - _owns = true; - } - virtual ~SQBlob() { - sq_free(_buf, _allocated); - } - SQInteger Write(void *buffer, SQInteger size) { - if(!CanAdvance(size)) { - GrowBufOf(_ptr + size - _size); - } - memcpy(&_buf[_ptr], buffer, size); - _ptr += size; - return size; - } - SQInteger Read(void *buffer,SQInteger size) { - SQInteger n = size; - if(!CanAdvance(size)) { - if((_size - _ptr) > 0) - n = _size - _ptr; - else return 0; - } - memcpy(buffer, &_buf[_ptr], n); - _ptr += n; - return n; - } - bool Resize(SQInteger n) { - if(!_owns) return false; - if(n != _allocated) { - unsigned char *newbuf = (unsigned char *)sq_malloc(n); - memset(newbuf,0,n); - if(_size > n) - memcpy(newbuf,_buf,n); - else - memcpy(newbuf,_buf,_size); - sq_free(_buf,_allocated); - _buf=newbuf; - _allocated = n; - if(_size > _allocated) - _size = _allocated; - if(_ptr > _allocated) - _ptr = _allocated; - } - return true; - } - bool GrowBufOf(SQInteger n) - { - bool ret = true; - if(_size + n > _allocated) { - if(_size + n > _size * 2) - ret = Resize(_size + n); - else - ret = Resize(_size * 2); - } - _size = _size + n; - return ret; - } - bool CanAdvance(SQInteger n) { - if(_ptr+n>_size)return false; - return true; - } - SQInteger Seek(SQInteger offset, SQInteger origin) { - switch(origin) { - case SQ_SEEK_SET: - if(offset > _size || offset < 0) return -1; - _ptr = offset; - break; - case SQ_SEEK_CUR: - if(_ptr + offset > _size || _ptr + offset < 0) return -1; - _ptr += offset; - break; - case SQ_SEEK_END: - if(_size + offset > _size || _size + offset < 0) return -1; - _ptr = _size + offset; - break; - default: return -1; - } - return 0; - } - bool IsValid() { - return _buf?true:false; - } - bool EOS() { - return _ptr == _size; - } - SQInteger Flush() { return 0; } - SQInteger Tell() { return _ptr; } - SQInteger Len() { return _size; } - SQUserPointer GetBuf(){ return _buf; } -private: - SQInteger _size; - SQInteger _allocated; - SQInteger _ptr; - unsigned char *_buf; - bool _owns; -}; - -#endif //_SQSTD_BLOBIMPL_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_BLOBIMPL_H_ +#define _SQSTD_BLOBIMPL_H_ + +struct SQBlob : public SQStream +{ + SQBlob(SQInteger size) { + _size = size; + _allocated = size; + _buf = (unsigned char *)sq_malloc(size); + memset(_buf, 0, _size); + _ptr = 0; + _owns = true; + } + virtual ~SQBlob() { + sq_free(_buf, _allocated); + } + SQInteger Write(void *buffer, SQInteger size) { + if(!CanAdvance(size)) { + GrowBufOf(_ptr + size - _size); + } + memcpy(&_buf[_ptr], buffer, size); + _ptr += size; + return size; + } + SQInteger Read(void *buffer,SQInteger size) { + SQInteger n = size; + if(!CanAdvance(size)) { + if((_size - _ptr) > 0) + n = _size - _ptr; + else return 0; + } + memcpy(buffer, &_buf[_ptr], n); + _ptr += n; + return n; + } + bool Resize(SQInteger n) { + if(!_owns) return false; + if(n != _allocated) { + unsigned char *newbuf = (unsigned char *)sq_malloc(n); + memset(newbuf,0,n); + if(_size > n) + memcpy(newbuf,_buf,n); + else + memcpy(newbuf,_buf,_size); + sq_free(_buf,_allocated); + _buf=newbuf; + _allocated = n; + if(_size > _allocated) + _size = _allocated; + if(_ptr > _allocated) + _ptr = _allocated; + } + return true; + } + bool GrowBufOf(SQInteger n) + { + bool ret = true; + if(_size + n > _allocated) { + if(_size + n > _size * 2) + ret = Resize(_size + n); + else + ret = Resize(_size * 2); + } + _size = _size + n; + return ret; + } + bool CanAdvance(SQInteger n) { + if(_ptr+n>_size)return false; + return true; + } + SQInteger Seek(SQInteger offset, SQInteger origin) { + switch(origin) { + case SQ_SEEK_SET: + if(offset > _size || offset < 0) return -1; + _ptr = offset; + break; + case SQ_SEEK_CUR: + if(_ptr + offset > _size || _ptr + offset < 0) return -1; + _ptr += offset; + break; + case SQ_SEEK_END: + if(_size + offset > _size || _size + offset < 0) return -1; + _ptr = _size + offset; + break; + default: return -1; + } + return 0; + } + bool IsValid() { + return _buf?true:false; + } + bool EOS() { + return _ptr == _size; + } + SQInteger Flush() { return 0; } + SQInteger Tell() { return _ptr; } + SQInteger Len() { return _size; } + SQUserPointer GetBuf(){ return _buf; } +private: + SQInteger _size; + SQInteger _allocated; + SQInteger _ptr; + unsigned char *_buf; + bool _owns; +}; + +#endif //_SQSTD_BLOBIMPL_H_ diff --git a/src/squirrel/sqstdlib/sqstdio.cpp b/src/squirrel/sqstdlib/sqstdio.cpp index 306cf12b7..ff995426e 100644 --- a/src/squirrel/sqstdlib/sqstdio.cpp +++ b/src/squirrel/sqstdlib/sqstdio.cpp @@ -1,410 +1,410 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include "sqstdstream.h" - -#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001) -//basic API -SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode) -{ -#ifndef _UNICODE - return (SQFILE)fopen(filename,mode); -#else - return (SQFILE)_wfopen(filename,mode); -#endif -} - -SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file) -{ - return (SQInteger)fread(buffer,size,count,(FILE *)file); -} - -SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file) -{ - return (SQInteger)fwrite(buffer,size,count,(FILE *)file); -} - -SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin) -{ - SQInteger realorigin; - switch(origin) { - case SQ_SEEK_CUR: realorigin = SEEK_CUR; break; - case SQ_SEEK_END: realorigin = SEEK_END; break; - case SQ_SEEK_SET: realorigin = SEEK_SET; break; - default: return -1; //failed - } - return fseek((FILE *)file,(long)offset,(int)realorigin); -} - -SQInteger sqstd_ftell(SQFILE file) -{ - return ftell((FILE *)file); -} - -SQInteger sqstd_fflush(SQFILE file) -{ - return fflush((FILE *)file); -} - -SQInteger sqstd_fclose(SQFILE file) -{ - return fclose((FILE *)file); -} - -SQInteger sqstd_feof(SQFILE file) -{ - return feof((FILE *)file); -} - -//File -struct SQFile : public SQStream { - SQFile() { _handle = NULL; _owns = false;} - SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;} - virtual ~SQFile() { Close(); } - bool Open(const SQChar *filename ,const SQChar *mode) { - Close(); - if( (_handle = sqstd_fopen(filename,mode)) ) { - _owns = true; - return true; - } - return false; - } - void Close() { - if(_handle && _owns) { - sqstd_fclose(_handle); - _handle = NULL; - _owns = false; - } - } - SQInteger Read(void *buffer,SQInteger size) { - return sqstd_fread(buffer,1,size,_handle); - } - SQInteger Write(void *buffer,SQInteger size) { - return sqstd_fwrite(buffer,1,size,_handle); - } - SQInteger Flush() { - return sqstd_fflush(_handle); - } - SQInteger Tell() { - return sqstd_ftell(_handle); - } - SQInteger Len() { - SQInteger prevpos=Tell(); - Seek(0,SQ_SEEK_END); - SQInteger size=Tell(); - Seek(prevpos,SQ_SEEK_SET); - return size; - } - SQInteger Seek(SQInteger offset, SQInteger origin) { - return sqstd_fseek(_handle,offset,origin); - } - bool IsValid() { return _handle?true:false; } - bool EOS() { return Tell()==Len()?true:false;} - SQFILE GetHandle() {return _handle;} -private: - SQFILE _handle; - bool _owns; -}; - -static SQInteger _file__typeof(HSQUIRRELVM v) -{ - sq_pushstring(v,_SC("file"),-1); - return 1; -} - -static SQInteger _file_releasehook(SQUserPointer p, SQInteger size) -{ - SQFile *self = (SQFile*)p; - delete self; - return 1; -} - -static SQInteger _file_constructor(HSQUIRRELVM v) -{ - const SQChar *filename,*mode; - bool owns = true; - SQFile *f; - SQFILE newf; - if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) { - sq_getstring(v, 2, &filename); - sq_getstring(v, 3, &mode); - newf = sqstd_fopen(filename, mode); - if(!newf) return sq_throwerror(v, _SC("cannot open file")); - } else if(sq_gettype(v,2) == OT_USERPOINTER) { - owns = !(sq_gettype(v,3) == OT_NULL); - sq_getuserpointer(v,2,&newf); - } else { - return sq_throwerror(v,_SC("wrong parameter")); - } - f = new SQFile(newf,owns); - if(SQ_FAILED(sq_setinstanceup(v,1,f))) { - delete f; - return sq_throwerror(v, _SC("cannot create blob with negative size")); - } - sq_setreleasehook(v,1,_file_releasehook); - return 0; -} - -//bindings -#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck} -static SQRegFunction _file_methods[] = { - _DECL_FILE_FUNC(constructor,3,_SC("x")), - _DECL_FILE_FUNC(_typeof,1,_SC("x")), - {0,0,0,0}, -}; - - - -SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own) -{ - SQInteger top = sq_gettop(v); - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_file"),-1); - if(SQ_SUCCEEDED(sq_get(v,-2))) { - sq_remove(v,-2); //removes the registry - sq_pushroottable(v); // push the this - sq_pushuserpointer(v,file); //file - if(own){ - sq_pushinteger(v,1); //true - } - else{ - sq_pushnull(v); //false - } - if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { - sq_remove(v,-2); - return SQ_OK; - } - } - sq_settop(v,top); - return SQ_OK; -} - -SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file) -{ - SQFile *fileobj = NULL; - if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { - *file = fileobj->GetHandle(); - return SQ_OK; - } - return sq_throwerror(v,_SC("not a file")); -} - - - -static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file) -{ - SQInteger ret; - char c; - if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) - return c; - return 0; -} - -static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file) -{ -#define READ() \ - if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \ - return 0; - - static const SQInteger utf8_lengths[16] = - { - 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */ - 0,0,0,0, /* 1000 to 1011 : not valid */ - 2,2, /* 1100, 1101 : 2 bytes */ - 3, /* 1110 : 3 bytes */ - 4 /* 1111 :4 bytes */ - }; - static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07}; - unsigned char inchar; - SQInteger c = 0; - READ(); - c = inchar; - // - if(c >= 0x80) { - SQInteger tmp; - SQInteger codelen = utf8_lengths[c>>4]; - if(codelen == 0) - return 0; - //"invalid UTF-8 stream"; - tmp = c&byte_masks[codelen]; - for(SQInteger n = 0; n < codelen-1; n++) { - tmp<<=6; - READ(); - tmp |= inchar & 0x3F; - } - c = tmp; - } - return c; -} - -static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file) -{ - SQInteger ret; - wchar_t c; - if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) - return (SQChar)c; - return 0; -} - -static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file) -{ - SQInteger ret; - unsigned short c; - if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) { - c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00); - return (SQChar)c; - } - return 0; -} - -SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size) -{ - SQInteger ret; - if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret; - return -1; -} - -SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size) -{ - return sqstd_fwrite(p,1,size,(SQFILE)file); -} - -SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror) -{ - SQFILE file = sqstd_fopen(filename,_SC("rb")); - SQInteger ret; - unsigned short us; - unsigned char uc; - SQLEXREADFUNC func = _io_file_lexfeed_ASCII; - if(file){ - ret = sqstd_fread(&us,1,2,file); - if(ret != 2) { - //probably an empty file - us = 0; - } - if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE - sqstd_fseek(file,0,SQ_SEEK_SET); - if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) { - sqstd_fclose(file); - return SQ_OK; - } - } - else { //SCRIPT - switch(us) - { - //gotta swap the next 2 lines on BIG endian machines - case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian; - case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian; - case 0xBBEF: - if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { - sqstd_fclose(file); - return sq_throwerror(v,_SC("io error")); - } - if(uc != 0xBF) { - sqstd_fclose(file); - return sq_throwerror(v,_SC("Unrecognozed ecoding")); - } - func = _io_file_lexfeed_UTF8; - break;//UTF-8 ; - default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii - } - - if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){ - sqstd_fclose(file); - return SQ_OK; - } - } - sqstd_fclose(file); - return SQ_ERROR; - } - return sq_throwerror(v,_SC("cannot open the file")); -} - -SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror) -{ - if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) { - sq_push(v,-2); - if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) { - sq_remove(v,retval?-2:-1); //removes the closure - return 1; - } - sq_pop(v,1); //removes the closure - } - return SQ_ERROR; -} - -SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename) -{ - SQFILE file = sqstd_fopen(filename,_SC("wb+")); - if(!file) return sq_throwerror(v,_SC("cannot open the file")); - if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) { - sqstd_fclose(file); - return SQ_OK; - } - sqstd_fclose(file); - return SQ_ERROR; //forward the error -} - -SQInteger _g_io_loadfile(HSQUIRRELVM v) -{ - const SQChar *filename; - SQBool printerror = SQFalse; - sq_getstring(v,2,&filename); - if(sq_gettop(v) >= 3) { - sq_getbool(v,3,&printerror); - } - if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) - return 1; - return SQ_ERROR; //propagates the error -} - -SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v) -{ - const SQChar *filename; - sq_getstring(v,2,&filename); - if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename))) - return 1; - return SQ_ERROR; //propagates the error -} - -SQInteger _g_io_dofile(HSQUIRRELVM v) -{ - const SQChar *filename; - SQBool printerror = SQFalse; - sq_getstring(v,2,&filename); - if(sq_gettop(v) >= 3) { - sq_getbool(v,3,&printerror); - } - sq_push(v,1); //repush the this - if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror))) - return 1; - return SQ_ERROR; //propagates the error -} - -#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck} -static SQRegFunction iolib_funcs[]={ - _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")), - _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")), - _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")), - {0,0} -}; - -SQRESULT sqstd_register_iolib(HSQUIRRELVM v) -{ - SQInteger top = sq_gettop(v); - //create delegate - declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs); - sq_pushstring(v,_SC("stdout"),-1); - sqstd_createfile(v,stdout,SQFalse); - sq_createslot(v,-3); - sq_pushstring(v,_SC("stdin"),-1); - sqstd_createfile(v,stdin,SQFalse); - sq_createslot(v,-3); - sq_pushstring(v,_SC("stderr"),-1); - sqstd_createfile(v,stderr,SQFalse); - sq_createslot(v,-3); - sq_settop(v,top); - return SQ_OK; -} +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include "sqstdstream.h" + +#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001) +//basic API +SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode) +{ +#ifndef _UNICODE + return (SQFILE)fopen(filename,mode); +#else + return (SQFILE)_wfopen(filename,mode); +#endif +} + +SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file) +{ + return (SQInteger)fread(buffer,size,count,(FILE *)file); +} + +SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file) +{ + return (SQInteger)fwrite(buffer,size,count,(FILE *)file); +} + +SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin) +{ + SQInteger realorigin; + switch(origin) { + case SQ_SEEK_CUR: realorigin = SEEK_CUR; break; + case SQ_SEEK_END: realorigin = SEEK_END; break; + case SQ_SEEK_SET: realorigin = SEEK_SET; break; + default: return -1; //failed + } + return fseek((FILE *)file,(long)offset,(int)realorigin); +} + +SQInteger sqstd_ftell(SQFILE file) +{ + return ftell((FILE *)file); +} + +SQInteger sqstd_fflush(SQFILE file) +{ + return fflush((FILE *)file); +} + +SQInteger sqstd_fclose(SQFILE file) +{ + return fclose((FILE *)file); +} + +SQInteger sqstd_feof(SQFILE file) +{ + return feof((FILE *)file); +} + +//File +struct SQFile : public SQStream { + SQFile() { _handle = NULL; _owns = false;} + SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;} + virtual ~SQFile() { Close(); } + bool Open(const SQChar *filename ,const SQChar *mode) { + Close(); + if( (_handle = sqstd_fopen(filename,mode)) ) { + _owns = true; + return true; + } + return false; + } + void Close() { + if(_handle && _owns) { + sqstd_fclose(_handle); + _handle = NULL; + _owns = false; + } + } + SQInteger Read(void *buffer,SQInteger size) { + return sqstd_fread(buffer,1,size,_handle); + } + SQInteger Write(void *buffer,SQInteger size) { + return sqstd_fwrite(buffer,1,size,_handle); + } + SQInteger Flush() { + return sqstd_fflush(_handle); + } + SQInteger Tell() { + return sqstd_ftell(_handle); + } + SQInteger Len() { + SQInteger prevpos=Tell(); + Seek(0,SQ_SEEK_END); + SQInteger size=Tell(); + Seek(prevpos,SQ_SEEK_SET); + return size; + } + SQInteger Seek(SQInteger offset, SQInteger origin) { + return sqstd_fseek(_handle,offset,origin); + } + bool IsValid() { return _handle?true:false; } + bool EOS() { return Tell()==Len()?true:false;} + SQFILE GetHandle() {return _handle;} +private: + SQFILE _handle; + bool _owns; +}; + +static SQInteger _file__typeof(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("file"),-1); + return 1; +} + +static SQInteger _file_releasehook(SQUserPointer p, SQInteger size) +{ + SQFile *self = (SQFile*)p; + delete self; + return 1; +} + +static SQInteger _file_constructor(HSQUIRRELVM v) +{ + const SQChar *filename,*mode; + bool owns = true; + SQFile *f; + SQFILE newf; + if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) { + sq_getstring(v, 2, &filename); + sq_getstring(v, 3, &mode); + newf = sqstd_fopen(filename, mode); + if(!newf) return sq_throwerror(v, _SC("cannot open file")); + } else if(sq_gettype(v,2) == OT_USERPOINTER) { + owns = !(sq_gettype(v,3) == OT_NULL); + sq_getuserpointer(v,2,&newf); + } else { + return sq_throwerror(v,_SC("wrong parameter")); + } + f = new SQFile(newf,owns); + if(SQ_FAILED(sq_setinstanceup(v,1,f))) { + delete f; + return sq_throwerror(v, _SC("cannot create blob with negative size")); + } + sq_setreleasehook(v,1,_file_releasehook); + return 0; +} + +//bindings +#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck} +static SQRegFunction _file_methods[] = { + _DECL_FILE_FUNC(constructor,3,_SC("x")), + _DECL_FILE_FUNC(_typeof,1,_SC("x")), + {0,0,0,0}, +}; + + + +SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own) +{ + SQInteger top = sq_gettop(v); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_file"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { + sq_remove(v,-2); //removes the registry + sq_pushroottable(v); // push the this + sq_pushuserpointer(v,file); //file + if(own){ + sq_pushinteger(v,1); //true + } + else{ + sq_pushnull(v); //false + } + if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { + sq_remove(v,-2); + return SQ_OK; + } + } + sq_settop(v,top); + return SQ_OK; +} + +SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file) +{ + SQFile *fileobj = NULL; + if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { + *file = fileobj->GetHandle(); + return SQ_OK; + } + return sq_throwerror(v,_SC("not a file")); +} + + + +static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file) +{ + SQInteger ret; + char c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) + return c; + return 0; +} + +static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file) +{ +#define READ() \ + if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \ + return 0; + + static const SQInteger utf8_lengths[16] = + { + 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */ + 0,0,0,0, /* 1000 to 1011 : not valid */ + 2,2, /* 1100, 1101 : 2 bytes */ + 3, /* 1110 : 3 bytes */ + 4 /* 1111 :4 bytes */ + }; + static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07}; + unsigned char inchar; + SQInteger c = 0; + READ(); + c = inchar; + // + if(c >= 0x80) { + SQInteger tmp; + SQInteger codelen = utf8_lengths[c>>4]; + if(codelen == 0) + return 0; + //"invalid UTF-8 stream"; + tmp = c&byte_masks[codelen]; + for(SQInteger n = 0; n < codelen-1; n++) { + tmp<<=6; + READ(); + tmp |= inchar & 0x3F; + } + c = tmp; + } + return c; +} + +static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file) +{ + SQInteger ret; + wchar_t c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) + return (SQChar)c; + return 0; +} + +static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file) +{ + SQInteger ret; + unsigned short c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) { + c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00); + return (SQChar)c; + } + return 0; +} + +SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size) +{ + SQInteger ret; + if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret; + return -1; +} + +SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size) +{ + return sqstd_fwrite(p,1,size,(SQFILE)file); +} + +SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror) +{ + SQFILE file = sqstd_fopen(filename,_SC("rb")); + SQInteger ret; + unsigned short us; + unsigned char uc; + SQLEXREADFUNC func = _io_file_lexfeed_ASCII; + if(file){ + ret = sqstd_fread(&us,1,2,file); + if(ret != 2) { + //probably an empty file + us = 0; + } + if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE + sqstd_fseek(file,0,SQ_SEEK_SET); + if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) { + sqstd_fclose(file); + return SQ_OK; + } + } + else { //SCRIPT + switch(us) + { + //gotta swap the next 2 lines on BIG endian machines + case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian; + case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian; + case 0xBBEF: + if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("io error")); + } + if(uc != 0xBF) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("Unrecognozed ecoding")); + } + func = _io_file_lexfeed_UTF8; + break;//UTF-8 ; + default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii + } + + if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){ + sqstd_fclose(file); + return SQ_OK; + } + } + sqstd_fclose(file); + return SQ_ERROR; + } + return sq_throwerror(v,_SC("cannot open the file")); +} + +SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror) +{ + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) { + sq_push(v,-2); + if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) { + sq_remove(v,retval?-2:-1); //removes the closure + return 1; + } + sq_pop(v,1); //removes the closure + } + return SQ_ERROR; +} + +SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename) +{ + SQFILE file = sqstd_fopen(filename,_SC("wb+")); + if(!file) return sq_throwerror(v,_SC("cannot open the file")); + if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) { + sqstd_fclose(file); + return SQ_OK; + } + sqstd_fclose(file); + return SQ_ERROR; //forward the error +} + +SQInteger _g_io_loadfile(HSQUIRRELVM v) +{ + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) + return 1; + return SQ_ERROR; //propagates the error +} + +SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v) +{ + const SQChar *filename; + sq_getstring(v,2,&filename); + if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename))) + return 1; + return SQ_ERROR; //propagates the error +} + +SQInteger _g_io_dofile(HSQUIRRELVM v) +{ + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + sq_push(v,1); //repush the this + if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror))) + return 1; + return SQ_ERROR; //propagates the error +} + +#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck} +static SQRegFunction iolib_funcs[]={ + _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")), + {0,0} +}; + +SQRESULT sqstd_register_iolib(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + //create delegate + declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs); + sq_pushstring(v,_SC("stdout"),-1); + sqstd_createfile(v,stdout,SQFalse); + sq_createslot(v,-3); + sq_pushstring(v,_SC("stdin"),-1); + sqstd_createfile(v,stdin,SQFalse); + sq_createslot(v,-3); + sq_pushstring(v,_SC("stderr"),-1); + sqstd_createfile(v,stderr,SQFalse); + sq_createslot(v,-3); + sq_settop(v,top); + return SQ_OK; +} diff --git a/src/squirrel/sqstdlib/sqstdmath.cpp b/src/squirrel/sqstdlib/sqstdmath.cpp index ae1a219be..01a808adf 100644 --- a/src/squirrel/sqstdlib/sqstdmath.cpp +++ b/src/squirrel/sqstdlib/sqstdmath.cpp @@ -1,105 +1,105 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include - -#define SINGLE_ARG_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \ - SQFloat f; \ - sq_getfloat(v,2,&f); \ - sq_pushfloat(v,(SQFloat)_funcname(f)); \ - return 1; \ -} - -#define TWO_ARGS_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \ - SQFloat p1,p2; \ - sq_getfloat(v,2,&p1); \ - sq_getfloat(v,3,&p2); \ - sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \ - return 1; \ -} - -static SQInteger math_srand(HSQUIRRELVM v) -{ - SQInteger i; - if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param")); - srand((unsigned int)i); - return 0; -} - -static SQInteger math_rand(HSQUIRRELVM v) -{ - sq_pushinteger(v,rand()); - return 1; -} - -static SQInteger math_abs(HSQUIRRELVM v) -{ - SQInteger n; - sq_getinteger(v,2,&n); - sq_pushinteger(v,(SQInteger)abs((int)n)); - return 1; -} - -SINGLE_ARG_FUNC(sqrt) -SINGLE_ARG_FUNC(fabs) -SINGLE_ARG_FUNC(sin) -SINGLE_ARG_FUNC(cos) -SINGLE_ARG_FUNC(asin) -SINGLE_ARG_FUNC(acos) -SINGLE_ARG_FUNC(log) -SINGLE_ARG_FUNC(log10) -SINGLE_ARG_FUNC(tan) -SINGLE_ARG_FUNC(atan) -TWO_ARGS_FUNC(atan2) -TWO_ARGS_FUNC(pow) -SINGLE_ARG_FUNC(floor) -SINGLE_ARG_FUNC(ceil) -SINGLE_ARG_FUNC(exp) - -#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck} -static SQRegFunction mathlib_funcs[] = { - _DECL_FUNC(sqrt,2,_SC(".n")), - _DECL_FUNC(sin,2,_SC(".n")), - _DECL_FUNC(cos,2,_SC(".n")), - _DECL_FUNC(asin,2,_SC(".n")), - _DECL_FUNC(acos,2,_SC(".n")), - _DECL_FUNC(log,2,_SC(".n")), - _DECL_FUNC(log10,2,_SC(".n")), - _DECL_FUNC(tan,2,_SC(".n")), - _DECL_FUNC(atan,2,_SC(".n")), - _DECL_FUNC(atan2,3,_SC(".nn")), - _DECL_FUNC(pow,3,_SC(".nn")), - _DECL_FUNC(floor,2,_SC(".n")), - _DECL_FUNC(ceil,2,_SC(".n")), - _DECL_FUNC(exp,2,_SC(".n")), - _DECL_FUNC(srand,2,_SC(".n")), - _DECL_FUNC(rand,1,NULL), - _DECL_FUNC(fabs,2,_SC(".n")), - _DECL_FUNC(abs,2,_SC(".n")), - {0,0}, -}; - -#ifndef M_PI -#define M_PI (3.14159265358979323846) -#endif - -SQRESULT sqstd_register_mathlib(HSQUIRRELVM v) -{ - SQInteger i=0; - while(mathlib_funcs[i].name!=0) { - sq_pushstring(v,mathlib_funcs[i].name,-1); - sq_newclosure(v,mathlib_funcs[i].f,0); - sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); - sq_createslot(v,-3); - i++; - } - sq_pushstring(v,_SC("RAND_MAX"),-1); - sq_pushinteger(v,RAND_MAX); - sq_createslot(v,-3); - sq_pushstring(v,_SC("PI"),-1); - sq_pushfloat(v,(SQFloat)M_PI); - sq_createslot(v,-3); - return SQ_OK; -} +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include + +#define SINGLE_ARG_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \ + SQFloat f; \ + sq_getfloat(v,2,&f); \ + sq_pushfloat(v,(SQFloat)_funcname(f)); \ + return 1; \ +} + +#define TWO_ARGS_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \ + SQFloat p1,p2; \ + sq_getfloat(v,2,&p1); \ + sq_getfloat(v,3,&p2); \ + sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \ + return 1; \ +} + +static SQInteger math_srand(HSQUIRRELVM v) +{ + SQInteger i; + if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param")); + srand((unsigned int)i); + return 0; +} + +static SQInteger math_rand(HSQUIRRELVM v) +{ + sq_pushinteger(v,rand()); + return 1; +} + +static SQInteger math_abs(HSQUIRRELVM v) +{ + SQInteger n; + sq_getinteger(v,2,&n); + sq_pushinteger(v,(SQInteger)abs((int)n)); + return 1; +} + +SINGLE_ARG_FUNC(sqrt) +SINGLE_ARG_FUNC(fabs) +SINGLE_ARG_FUNC(sin) +SINGLE_ARG_FUNC(cos) +SINGLE_ARG_FUNC(asin) +SINGLE_ARG_FUNC(acos) +SINGLE_ARG_FUNC(log) +SINGLE_ARG_FUNC(log10) +SINGLE_ARG_FUNC(tan) +SINGLE_ARG_FUNC(atan) +TWO_ARGS_FUNC(atan2) +TWO_ARGS_FUNC(pow) +SINGLE_ARG_FUNC(floor) +SINGLE_ARG_FUNC(ceil) +SINGLE_ARG_FUNC(exp) + +#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck} +static SQRegFunction mathlib_funcs[] = { + _DECL_FUNC(sqrt,2,_SC(".n")), + _DECL_FUNC(sin,2,_SC(".n")), + _DECL_FUNC(cos,2,_SC(".n")), + _DECL_FUNC(asin,2,_SC(".n")), + _DECL_FUNC(acos,2,_SC(".n")), + _DECL_FUNC(log,2,_SC(".n")), + _DECL_FUNC(log10,2,_SC(".n")), + _DECL_FUNC(tan,2,_SC(".n")), + _DECL_FUNC(atan,2,_SC(".n")), + _DECL_FUNC(atan2,3,_SC(".nn")), + _DECL_FUNC(pow,3,_SC(".nn")), + _DECL_FUNC(floor,2,_SC(".n")), + _DECL_FUNC(ceil,2,_SC(".n")), + _DECL_FUNC(exp,2,_SC(".n")), + _DECL_FUNC(srand,2,_SC(".n")), + _DECL_FUNC(rand,1,NULL), + _DECL_FUNC(fabs,2,_SC(".n")), + _DECL_FUNC(abs,2,_SC(".n")), + {0,0}, +}; + +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + +SQRESULT sqstd_register_mathlib(HSQUIRRELVM v) +{ + SQInteger i=0; + while(mathlib_funcs[i].name!=0) { + sq_pushstring(v,mathlib_funcs[i].name,-1); + sq_newclosure(v,mathlib_funcs[i].f,0); + sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + sq_pushstring(v,_SC("RAND_MAX"),-1); + sq_pushinteger(v,RAND_MAX); + sq_createslot(v,-3); + sq_pushstring(v,_SC("PI"),-1); + sq_pushfloat(v,(SQFloat)M_PI); + sq_createslot(v,-3); + return SQ_OK; +} diff --git a/src/squirrel/sqstdlib/sqstdrex.cpp b/src/squirrel/sqstdlib/sqstdrex.cpp index 9c3c2685d..59397a728 100644 --- a/src/squirrel/sqstdlib/sqstdrex.cpp +++ b/src/squirrel/sqstdlib/sqstdrex.cpp @@ -1,633 +1,632 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include "sqstdstring.h" - -#ifdef _UINCODE -#define scisprint iswprint -#else -#define scisprint isprint -#endif - -#ifdef _DEBUG -#include - -static const SQChar *g_nnames[] = -{ - _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), - _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), - _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), - _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") -}; - -#endif - -#define OP_GREEDY MAX_CHAR+1 // * + ? {n} -#define OP_OR MAX_CHAR+2 -#define OP_EXPR MAX_CHAR+3 //parentesis () -#define OP_NOCAPEXPR MAX_CHAR+4 //parentesis (?:) -#define OP_DOT MAX_CHAR+5 -#define OP_CLASS MAX_CHAR+6 -#define OP_CCLASS MAX_CHAR+7 -#define OP_NCLASS MAX_CHAR+8 //negates class the [^ -#define OP_RANGE MAX_CHAR+9 -#define OP_CHAR MAX_CHAR+10 -#define OP_EOL MAX_CHAR+11 -#define OP_BOL MAX_CHAR+12 -#define OP_WB MAX_CHAR+13 - -#define SQREX_SYMBOL_ANY_CHAR '.' -#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+' -#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*' -#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?' -#define SQREX_SYMBOL_BRANCH '|' -#define SQREX_SYMBOL_END_OF_STRING '$' -#define SQREX_SYMBOL_BEGINNING_OF_STRING '^' -#define SQREX_SYMBOL_ESCAPE_CHAR '\\' - - -typedef int SQRexNodeType; - -typedef struct tagSQRexNode{ - SQRexNodeType type; - SQInteger left; - SQInteger right; - SQInteger next; -}SQRexNode; - -struct SQRex{ - const SQChar *_eol; - const SQChar *_bol; - const SQChar *_p; - SQInteger _first; - SQInteger _op; - SQRexNode *_nodes; - SQInteger _nallocated; - SQInteger _nsize; - SQInteger _nsubexpr; - SQRexMatch *_matches; - SQInteger _currsubexp; - void *_jmpbuf; - const SQChar **_error; -}; - -static SQInteger sqstd_rex_list(SQRex *exp); - -static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type) -{ - SQRexNode n; - n.type = type; - n.next = n.right = n.left = -1; - if(type == OP_EXPR) - n.right = exp->_nsubexpr++; - if(exp->_nallocated < (exp->_nsize + 1)) { - SQInteger oldsize = exp->_nallocated; - exp->_nallocated *= 2; - exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode)); - } - exp->_nodes[exp->_nsize++] = n; - return (SQInteger)exp->_nsize - 1; -} - -static void sqstd_rex_error(SQRex *exp,const SQChar *error) -{ - if(exp->_error) *exp->_error = error; - longjmp(*((jmp_buf*)exp->_jmpbuf),-1); -} - -static void sqstd_rex_expect(SQRex *exp, SQInteger n){ - if((*exp->_p) != n) - sqstd_rex_error(exp, _SC("expected paren")); - exp->_p++; -} - -/*static SQBool sqstd_rex_ischar(SQChar c) -{ - switch(c) { - case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: - case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: - case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING: - case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}': - return SQFalse; - } - return SQTrue; -}*/ - -static SQChar sqstd_rex_escapechar(SQRex *exp) -{ - if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){ - exp->_p++; - switch(*exp->_p) { - case 'v': exp->_p++; return '\v'; - case 'n': exp->_p++; return '\n'; - case 't': exp->_p++; return '\t'; - case 'r': exp->_p++; return '\r'; - case 'f': exp->_p++; return '\f'; - default: return (*exp->_p++); - } - } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected")); - return (*exp->_p++); -} - -static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid) -{ - SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS); - exp->_nodes[n].left = classid; - return n; -} - -static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass) -{ - if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) { - exp->_p++; - switch(*exp->_p) { - case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n'); - case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t'); - case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r'); - case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f'); - case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v'); - case 'a': case 'A': case 'w': case 'W': case 's': case 'S': - case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': - case 'p': case 'P': case 'l': case 'u': - { - SQChar t = *exp->_p; - exp->_p++; - return sqstd_rex_charclass(exp,t); - } - case 'b': - case 'B': - if(!isclass) { - SQInteger node = sqstd_rex_newnode(exp,OP_WB); - exp->_nodes[node].left = *exp->_p; - exp->_p++; - return node; - } //else default - default: return sqstd_rex_newnode(exp,(*exp->_p++)); - } - } - else if(!scisprint(*exp->_p)) { - - sqstd_rex_error(exp,_SC("letter expected")); - } - return sqstd_rex_newnode(exp,*exp->_p++); -} -static SQInteger sqstd_rex_class(SQRex *exp) -{ - SQInteger ret = -1; - SQInteger first = -1,chain; - if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){ - ret = sqstd_rex_newnode(exp,OP_NCLASS); - exp->_p++; - }else ret = sqstd_rex_newnode(exp,OP_CLASS); - - if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class")); - chain = ret; - while(*exp->_p != ']' && exp->_p != exp->_eol) { - if(*exp->_p == '-' && first != -1){ - SQInteger r; - if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range")); - r = sqstd_rex_newnode(exp,OP_RANGE); - if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); - if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); - exp->_nodes[r].left = exp->_nodes[first].type; - exp->_nodes[r].right = sqstd_rex_escapechar(exp); - exp->_nodes[chain].next = r; - chain = r; - first = -1; - } - else{ - if(first!=-1){ - SQInteger c = first; - exp->_nodes[chain].next = c; - chain = c; - first = sqstd_rex_charnode(exp,SQTrue); - } - else{ - first = sqstd_rex_charnode(exp,SQTrue); - } - } - } - if(first!=-1){ - SQInteger c = first; - exp->_nodes[chain].next = c; - chain = c; - first = -1; - } - /* hack? */ - exp->_nodes[ret].left = exp->_nodes[ret].next; - exp->_nodes[ret].next = -1; - return ret; -} - -static SQInteger sqstd_rex_parsenumber(SQRex *exp) -{ - SQInteger ret = *exp->_p-'0'; - SQInteger positions = 10; - exp->_p++; - while(isdigit(*exp->_p)) { - ret = ret*10+(*exp->_p++-'0'); - if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); - positions *= 10; - }; - return ret; -} - -static SQInteger sqstd_rex_element(SQRex *exp) -{ - SQInteger ret; - switch(*exp->_p) - { - case '(': { - SQInteger expr; - exp->_p++; - - - if(*exp->_p =='?') { - exp->_p++; - sqstd_rex_expect(exp,':'); - expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR); - } - else - expr = sqstd_rex_newnode(exp,OP_EXPR); - exp->_nodes[expr].left = sqstd_rex_list(exp); - ret = expr; - sqstd_rex_expect(exp,')'); - } - break; - case '[': - exp->_p++; - ret = sqstd_rex_class(exp); - sqstd_rex_expect(exp,']'); - break; - case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break; - case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break; - default: - ret = sqstd_rex_charnode(exp,SQFalse); - break; - } - /* scope block */ - { - SQInteger op; - unsigned short p0 = 0, p1 = 0; - switch(*exp->_p){ - case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end; - case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end; - case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end; - case '{':{ - exp->_p++; - if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected")); - p0 = (unsigned short)sqstd_rex_parsenumber(exp); - switch(*exp->_p) { - case '}': - p1 = p0; exp->_p++; - goto __end; - case ',': - exp->_p++; - p1 = 0xFFFF; - if(isdigit(*exp->_p)){ - p1 = (unsigned short)sqstd_rex_parsenumber(exp); - } - sqstd_rex_expect(exp,'}'); - goto __end; - default: - sqstd_rex_error(exp,_SC(", or } expected")); - } - } - __end: { - SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); - op = OP_GREEDY; - exp->_nodes[nnode].left = ret; - exp->_nodes[nnode].right = ((p0)<<16)|p1; - ret = nnode; - } - } - } - 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') - exp->_nodes[ret].next = sqstd_rex_element(exp); - return ret; -} - -static SQInteger sqstd_rex_list(SQRex *exp) -{ - SQInteger ret=-1,e; - if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) { - exp->_p++; - ret = sqstd_rex_newnode(exp,OP_BOL); - } - e = sqstd_rex_element(exp); - if(ret != -1) { - exp->_nodes[ret].next = e; - } - else ret = e; - - if(*exp->_p == SQREX_SYMBOL_BRANCH) { - SQInteger temp; - exp->_p++; - temp = sqstd_rex_newnode(exp,OP_OR); - exp->_nodes[temp].left = ret; - exp->_nodes[temp].right = sqstd_rex_list(exp); - ret = temp; - } - return ret; -} - -static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c) -{ - switch(cclass) { - case 'a': return isalpha(c)?SQTrue:SQFalse; - case 'A': return !isalpha(c)?SQTrue:SQFalse; - case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse; - case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse; - case 's': return isspace(c)?SQTrue:SQFalse; - case 'S': return !isspace(c)?SQTrue:SQFalse; - case 'd': return isdigit(c)?SQTrue:SQFalse; - case 'D': return !isdigit(c)?SQTrue:SQFalse; - case 'x': return isxdigit(c)?SQTrue:SQFalse; - case 'X': return !isxdigit(c)?SQTrue:SQFalse; - case 'c': return iscntrl(c)?SQTrue:SQFalse; - case 'C': return !iscntrl(c)?SQTrue:SQFalse; - case 'p': return ispunct(c)?SQTrue:SQFalse; - case 'P': return !ispunct(c)?SQTrue:SQFalse; - case 'l': return islower(c)?SQTrue:SQFalse; - case 'u': return isupper(c)?SQTrue:SQFalse; - } - return SQFalse; /*cannot happen*/ -} - -static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c) -{ - do { - switch(node->type) { - case OP_RANGE: - if(c >= node->left && c <= node->right) return SQTrue; - break; - case OP_CCLASS: - if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; - break; - default: - if(c == node->type)return SQTrue; - } - } while((node->next != -1) && (node = &exp->_nodes[node->next])); - return SQFalse; -} - -static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next) -{ - - SQRexNodeType type = node->type; - switch(type) { - case OP_GREEDY: { - //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - SQRexNode *greedystop = NULL; - SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; - const SQChar *s=str, *good = str; - - if(node->next != -1) { - greedystop = &exp->_nodes[node->next]; - } - else { - greedystop = next; - } - - while((nmaches == 0xFFFF || nmaches < p1)) { - - const SQChar *stop; - if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) - break; - nmaches++; - good=s; - if(greedystop) { - //checks that 0 matches satisfy the expression(if so skips) - //if not would always stop(for instance if is a '?') - if(greedystop->type != OP_GREEDY || - (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) - { - SQRexNode *gnext = NULL; - if(greedystop->next != -1) { - gnext = &exp->_nodes[greedystop->next]; - }else if(next && next->next != -1){ - gnext = &exp->_nodes[next->next]; - } - stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); - if(stop) { - //if satisfied stop it - if(p0 == p1 && p0 == nmaches) break; - else if(nmaches >= p0 && p1 == 0xFFFF) break; - else if(nmaches >= p0 && nmaches <= p1) break; - } - } - } - - if(s >= exp->_eol) - break; - } - if(p0 == p1 && p0 == nmaches) return good; - else if(nmaches >= p0 && p1 == 0xFFFF) return good; - else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; - } - case OP_OR: { - const SQChar *asd = str; - SQRexNode *temp=&exp->_nodes[node->left]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - asd = str; - temp = &exp->_nodes[node->right]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - return NULL; - break; - } - case OP_EXPR: - case OP_NOCAPEXPR:{ - SQRexNode *n = &exp->_nodes[node->left]; - const SQChar *cur = str; - SQInteger capture = -1; - if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { - capture = exp->_currsubexp; - exp->_matches[capture].begin = cur; - exp->_currsubexp++; - } - - do { - SQRexNode *subnext = NULL; - if(n->next != -1) { - subnext = &exp->_nodes[n->next]; - }else { - subnext = next; - } - if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { - if(capture != -1){ - exp->_matches[capture].begin = 0; - exp->_matches[capture].len = 0; - } - return NULL; - } - } while((n->next != -1) && (n = &exp->_nodes[n->next])); - - if(capture != -1) - exp->_matches[capture].len = cur - exp->_matches[capture].begin; - return cur; - } - case OP_WB: - if(str == exp->_bol && !isspace(*str) - || (str == exp->_eol && !isspace(*(str-1))) - || (!isspace(*str) && isspace(*(str+1))) - || (isspace(*str) && !isspace(*(str+1))) ) { - return (node->left == 'b')?str:NULL; - } - return (node->left == 'b')?NULL:str; - case OP_BOL: - if(str == exp->_bol) return str; - return NULL; - case OP_EOL: - if(str == exp->_eol) return str; - return NULL; - case OP_DOT:{ - *str++; - } - return str; - case OP_NCLASS: - case OP_CLASS: - if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { - *str++; - return str; - } - return NULL; - case OP_CCLASS: - if(sqstd_rex_matchcclass(node->left,*str)) { - *str++; - return str; - } - return NULL; - default: /* char */ - if(*str != node->type) return NULL; - *str++; - return str; - } - return NULL; -} - -/* public api */ -SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) -{ - SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex)); - exp->_eol = exp->_bol = NULL; - exp->_p = pattern; - exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar); - exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); - exp->_nsize = 0; - exp->_matches = 0; - exp->_nsubexpr = 0; - exp->_first = sqstd_rex_newnode(exp,OP_EXPR); - exp->_error = error; - exp->_jmpbuf = sq_malloc(sizeof(jmp_buf)); - if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { - exp->_nodes[exp->_first].left=sqstd_rex_list(exp); - if(*exp->_p!='\0') - sqstd_rex_error(exp,_SC("unexpected character")); -#ifdef _DEBUG - { - SQInteger nsize,i; - SQRexNode *t; - nsize = exp->_nsize; - t = &exp->_nodes[0]; - scprintf(_SC("\n")); - for(i = 0;i < nsize; i++) { - if(exp->_nodes[i].type>MAX_CHAR) - scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); - else - scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); - scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); - } - scprintf(_SC("\n")); - } -#endif - exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch)); - memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch)); - } - else{ - sqstd_rex_free(exp); - return NULL; - } - return exp; -} - -void sqstd_rex_free(SQRex *exp) -{ - if(exp) { - if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); - if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf)); - if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch)); - sq_free(exp,sizeof(SQRex)); - } -} - -SQBool sqstd_rex_match(SQRex* exp,const SQChar* text) -{ - const SQChar* res = NULL; - exp->_bol = text; - exp->_eol = text + scstrlen(text); - exp->_currsubexp = 0; - res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) - return SQFalse; - return SQTrue; -} - -SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end) -{ - const SQChar *cur = NULL; - SQInteger node = exp->_first; - if(text_begin >= text_end) return SQFalse; - exp->_bol = text_begin; - exp->_eol = text_end; - do { - cur = text_begin; - while(node != -1) { - exp->_currsubexp = 0; - cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); - if(!cur) - break; - node = exp->_nodes[node].next; - } - *text_begin++; - } while(cur == NULL && text_begin != text_end); - - if(cur == NULL) - return SQFalse; - - --text_begin; - - if(out_begin) *out_begin = text_begin; - if(out_end) *out_end = cur; - return SQTrue; -} - -SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end) -{ - return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); -} - -SQInteger sqstd_rex_getsubexpcount(SQRex* exp) -{ - return exp->_nsubexpr; -} - -SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp) -{ - if( n<0 || n >= exp->_nsubexpr) return SQFalse; - *subexp = exp->_matches[n]; - return SQTrue; -} - +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include "sqstdstring.h" + +#ifdef _UINCODE +#define scisprint iswprint +#else +#define scisprint isprint +#endif + +#ifdef _DEBUG +#include + +static const SQChar *g_nnames[] = +{ + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") +}; + +#endif + +#define OP_GREEDY MAX_CHAR+1 // * + ? {n} +#define OP_OR MAX_CHAR+2 +#define OP_EXPR MAX_CHAR+3 //parentesis () +#define OP_NOCAPEXPR MAX_CHAR+4 //parentesis (?:) +#define OP_DOT MAX_CHAR+5 +#define OP_CLASS MAX_CHAR+6 +#define OP_CCLASS MAX_CHAR+7 +#define OP_NCLASS MAX_CHAR+8 //negates class the [^ +#define OP_RANGE MAX_CHAR+9 +#define OP_CHAR MAX_CHAR+10 +#define OP_EOL MAX_CHAR+11 +#define OP_BOL MAX_CHAR+12 +#define OP_WB MAX_CHAR+13 + +#define SQREX_SYMBOL_ANY_CHAR '.' +#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+' +#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*' +#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?' +#define SQREX_SYMBOL_BRANCH '|' +#define SQREX_SYMBOL_END_OF_STRING '$' +#define SQREX_SYMBOL_BEGINNING_OF_STRING '^' +#define SQREX_SYMBOL_ESCAPE_CHAR '\\' + + +typedef int SQRexNodeType; + +typedef struct tagSQRexNode{ + SQRexNodeType type; + SQInteger left; + SQInteger right; + SQInteger next; +}SQRexNode; + +struct SQRex{ + const SQChar *_eol; + const SQChar *_bol; + const SQChar *_p; + SQInteger _first; + SQInteger _op; + SQRexNode *_nodes; + SQInteger _nallocated; + SQInteger _nsize; + SQInteger _nsubexpr; + SQRexMatch *_matches; + SQInteger _currsubexp; + void *_jmpbuf; + const SQChar **_error; +}; + +static SQInteger sqstd_rex_list(SQRex *exp); + +static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type) +{ + SQRexNode n; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + SQInteger oldsize = exp->_nallocated; + exp->_nallocated *= 2; + exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + return (SQInteger)exp->_nsize - 1; +} + +static void sqstd_rex_error(SQRex *exp,const SQChar *error) +{ + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); +} + +static void sqstd_rex_expect(SQRex *exp, SQInteger n){ + if((*exp->_p) != n) + sqstd_rex_error(exp, _SC("expected paren")); + exp->_p++; +} + +/*static SQBool sqstd_rex_ischar(SQChar c) +{ + switch(c) { + case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: + case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: + case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING: + case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}': + return SQFalse; + } + return SQTrue; +}*/ + +static SQChar sqstd_rex_escapechar(SQRex *exp) +{ + if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected")); + return (*exp->_p++); +} + +static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid) +{ + SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; +} + +static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass) +{ + if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n'); + case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t'); + case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r'); + case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f'); + case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + SQChar t = *exp->_p; + exp->_p++; + return sqstd_rex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + SQInteger node = sqstd_rex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: return sqstd_rex_newnode(exp,(*exp->_p++)); + } + } + else if(!scisprint(*exp->_p)) { + + sqstd_rex_error(exp,_SC("letter expected")); + } + return sqstd_rex_newnode(exp,*exp->_p++); +} +static SQInteger sqstd_rex_class(SQRex *exp) +{ + SQInteger ret = -1; + SQInteger first = -1,chain; + if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){ + ret = sqstd_rex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = sqstd_rex_newnode(exp,OP_CLASS); + + if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + SQInteger r; + if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range")); + r = sqstd_rex_newnode(exp,OP_RANGE); + if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + exp->_nodes[r].right = sqstd_rex_escapechar(exp); + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + chain = c; + first = sqstd_rex_charnode(exp,SQTrue); + } + else{ + first = sqstd_rex_charnode(exp,SQTrue); + } + } + } + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; +} + +static SQInteger sqstd_rex_parsenumber(SQRex *exp) +{ + SQInteger ret = *exp->_p-'0'; + SQInteger positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; +} + +static SQInteger sqstd_rex_element(SQRex *exp) +{ + SQInteger ret; + switch(*exp->_p) + { + case '(': { + SQInteger expr; + exp->_p++; + + + if(*exp->_p =='?') { + exp->_p++; + sqstd_rex_expect(exp,':'); + expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = sqstd_rex_newnode(exp,OP_EXPR); + exp->_nodes[expr].left = sqstd_rex_list(exp); + ret = expr; + sqstd_rex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = sqstd_rex_class(exp); + sqstd_rex_expect(exp,']'); + break; + case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break; + case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break; + default: + ret = sqstd_rex_charnode(exp,SQFalse); + break; + } + /* scope block */ + { + SQInteger op; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end; + case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end; + case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end; + case '{':{ + exp->_p++; + if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected")); + p0 = (unsigned short)sqstd_rex_parsenumber(exp); + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + goto __end; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)sqstd_rex_parsenumber(exp); + } + sqstd_rex_expect(exp,'}'); + goto __end; + default: + sqstd_rex_error(exp,_SC(", or } expected")); + } + } + __end: { + SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY); + op = OP_GREEDY; + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + } + 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') + exp->_nodes[ret].next = sqstd_rex_element(exp); + return ret; +} + +static SQInteger sqstd_rex_list(SQRex *exp) +{ + SQInteger ret=-1,e; + if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = sqstd_rex_newnode(exp,OP_BOL); + } + e = sqstd_rex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; + + if(*exp->_p == SQREX_SYMBOL_BRANCH) { + SQInteger temp; + exp->_p++; + temp = sqstd_rex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + exp->_nodes[temp].right = sqstd_rex_list(exp); + ret = temp; + } + return ret; +} + +static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c) +{ + switch(cclass) { + case 'a': return isalpha(c)?SQTrue:SQFalse; + case 'A': return !isalpha(c)?SQTrue:SQFalse; + case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse; + case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse; + case 's': return isspace(c)?SQTrue:SQFalse; + case 'S': return !isspace(c)?SQTrue:SQFalse; + case 'd': return isdigit(c)?SQTrue:SQFalse; + case 'D': return !isdigit(c)?SQTrue:SQFalse; + case 'x': return isxdigit(c)?SQTrue:SQFalse; + case 'X': return !isxdigit(c)?SQTrue:SQFalse; + case 'c': return iscntrl(c)?SQTrue:SQFalse; + case 'C': return !iscntrl(c)?SQTrue:SQFalse; + case 'p': return ispunct(c)?SQTrue:SQFalse; + case 'P': return !ispunct(c)?SQTrue:SQFalse; + case 'l': return islower(c)?SQTrue:SQFalse; + case 'u': return isupper(c)?SQTrue:SQFalse; + } + return SQFalse; /*cannot happen*/ +} + +static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c) +{ + do { + switch(node->type) { + case OP_RANGE: + if(c >= node->left && c <= node->right) return SQTrue; + break; + case OP_CCLASS: + if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; + break; + default: + if(c == node->type)return SQTrue; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return SQFalse; +} + +static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next) +{ + + SQRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + SQRexNode *greedystop = NULL; + SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const SQChar *s=str, *good = str; + + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } + + while((nmaches == 0xFFFF || nmaches < p1)) { + + const SQChar *stop; + if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + SQRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } + + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const SQChar *asd = str; + SQRexNode *temp=&exp->_nodes[node->left]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + SQRexNode *n = &exp->_nodes[node->left]; + const SQChar *cur = str; + SQInteger capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + SQRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); + + if(capture != -1) + exp->_matches[capture].len = cur - exp->_matches[capture].begin; + return cur; + } + case OP_WB: + if(str == exp->_bol && !isspace(*str) + || (str == exp->_eol && !isspace(*(str-1))) + || (!isspace(*str) && isspace(*(str+1))) + || (isspace(*str) && !isspace(*(str+1))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT:{ + *str++; + } + return str; + case OP_NCLASS: + case OP_CLASS: + if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { + *str++; + return str; + } + return NULL; + case OP_CCLASS: + if(sqstd_rex_matchcclass(node->left,*str)) { + *str++; + return str; + } + return NULL; + default: /* char */ + if(*str != node->type) return NULL; + *str++; + return str; + } + return NULL; +} + +/* public api */ +SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) +{ + SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar); + exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = sqstd_rex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = sq_malloc(sizeof(jmp_buf)); + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + exp->_nodes[exp->_first].left=sqstd_rex_list(exp); + if(*exp->_p!='\0') + sqstd_rex_error(exp,_SC("unexpected character")); +#ifdef _DEBUG + { + SQInteger nsize,i; + SQRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } +#endif + exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch)); + } + else{ + sqstd_rex_free(exp); + return NULL; + } + return exp; +} + +void sqstd_rex_free(SQRex *exp) +{ + if(exp) { + if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); + if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf)); + if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch)); + sq_free(exp,sizeof(SQRex)); + } +} + +SQBool sqstd_rex_match(SQRex* exp,const SQChar* text) +{ + const SQChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return SQFalse; + return SQTrue; +} + +SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end) +{ + const SQChar *cur = NULL; + SQInteger node = exp->_first; + if(text_begin >= text_end) return SQFalse; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + *text_begin++; + } while(cur == NULL && text_begin != text_end); + + if(cur == NULL) + return SQFalse; + + --text_begin; + + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return SQTrue; +} + +SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end) +{ + return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); +} + +SQInteger sqstd_rex_getsubexpcount(SQRex* exp) +{ + return exp->_nsubexpr; +} + +SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp) +{ + if( n<0 || n >= exp->_nsubexpr) return SQFalse; + *subexp = exp->_matches[n]; + return SQTrue; +} diff --git a/src/squirrel/sqstdlib/sqstdstream.cpp b/src/squirrel/sqstdlib/sqstdstream.cpp index 669ca23f3..b94ab5e94 100644 --- a/src/squirrel/sqstdlib/sqstdstream.cpp +++ b/src/squirrel/sqstdlib/sqstdstream.cpp @@ -1,330 +1,330 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include -#include -#include -#include "sqstdstream.h" -#include "sqstdblobimpl.h" - -#define SETUP_STREAM(v) \ - SQStream *self = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \ - return sq_throwerror(v,_SC("invalid type tag")); \ - if(!self->IsValid()) \ - return sq_throwerror(v,_SC("the stream is invalid")); - -SQInteger _stream_readblob(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - SQUserPointer data,blobp; - SQInteger size,res; - sq_getinteger(v,2,&size); - if(size > self->Len()) { - size = self->Len(); - } - data = sq_getscratchpad(v,size); - res = self->Read(data,size); - if(res <= 0) - return sq_throwerror(v,_SC("no data left to read")); - blobp = sqstd_createblob(v,res); - memcpy(blobp,data,res); - return 1; -} - -#define SAFE_READN(ptr,len) { \ - if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \ - } -SQInteger _stream_readn(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - SQInteger format; - sq_getinteger(v, 2, &format); - switch(format) { - case 'l': { - SQInteger i; - SAFE_READN(&i, sizeof(i)); - sq_pushinteger(v, i); - } - break; - case 'i': { - SQInt32 i; - SAFE_READN(&i, sizeof(i)); - sq_pushinteger(v, i); - } - break; - case 's': { - short s; - SAFE_READN(&s, sizeof(short)); - sq_pushinteger(v, s); - } - break; - case 'w': { - unsigned short w; - SAFE_READN(&w, sizeof(unsigned short)); - sq_pushinteger(v, w); - } - break; - case 'c': { - char c; - SAFE_READN(&c, sizeof(char)); - sq_pushinteger(v, c); - } - break; - case 'b': { - unsigned char c; - SAFE_READN(&c, sizeof(unsigned char)); - sq_pushinteger(v, c); - } - break; - case 'f': { - float f; - SAFE_READN(&f, sizeof(float)); - sq_pushfloat(v, f); - } - break; - case 'd': { - double d; - SAFE_READN(&d, sizeof(double)); - sq_pushfloat(v, (SQFloat)d); - } - break; - default: - return sq_throwerror(v, _SC("invalid format")); - } - return 1; -} - -SQInteger _stream_writeblob(HSQUIRRELVM v) -{ - SQUserPointer data; - SQInteger size; - SETUP_STREAM(v); - if(SQ_FAILED(sqstd_getblob(v,2,&data))) - return sq_throwerror(v,_SC("invalid parameter")); - size = sqstd_getblobsize(v,2); - if(self->Write(data,size) != size) - return sq_throwerror(v,_SC("io error")); - sq_pushinteger(v,size); - return 1; -} - -SQInteger _stream_writen(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - SQInteger format, ti; - SQFloat tf; - sq_getinteger(v, 3, &format); - switch(format) { - case 'l': { - SQInteger i; - sq_getinteger(v, 2, &ti); - i = ti; - self->Write(&i, sizeof(SQInteger)); - } - break; - case 'i': { - SQInt32 i; - sq_getinteger(v, 2, &ti); - i = (SQInt32)ti; - self->Write(&i, sizeof(SQInt32)); - } - break; - case 's': { - short s; - sq_getinteger(v, 2, &ti); - s = (short)ti; - self->Write(&s, sizeof(short)); - } - break; - case 'w': { - unsigned short w; - sq_getinteger(v, 2, &ti); - w = (unsigned short)ti; - self->Write(&w, sizeof(unsigned short)); - } - break; - case 'c': { - char c; - sq_getinteger(v, 2, &ti); - c = (char)ti; - self->Write(&c, sizeof(char)); - } - break; - case 'b': { - unsigned char b; - sq_getinteger(v, 2, &ti); - b = (unsigned char)ti; - self->Write(&b, sizeof(unsigned char)); - } - break; - case 'f': { - float f; - sq_getfloat(v, 2, &tf); - f = tf; - self->Write(&f, sizeof(float)); - } - break; - case 'd': { - double d; - sq_getfloat(v, 2, &tf); - d = tf; - self->Write(&d, sizeof(double)); - } - break; - default: - return sq_throwerror(v, _SC("invalid format")); - } - return 0; -} - -SQInteger _stream_seek(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - SQInteger offset, origin = SQ_SEEK_SET; - sq_getinteger(v, 2, &offset); - if(sq_gettop(v) > 2) { - SQInteger t; - sq_getinteger(v, 3, &t); - switch(t) { - case 'b': origin = SQ_SEEK_SET; break; - case 'c': origin = SQ_SEEK_CUR; break; - case 'e': origin = SQ_SEEK_END; break; - default: return sq_throwerror(v,_SC("invalid origin")); - } - } - sq_pushinteger(v, self->Seek(offset, origin)); - return 1; -} - -SQInteger _stream_tell(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - sq_pushinteger(v, self->Tell()); - return 1; -} - -SQInteger _stream_len(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - sq_pushinteger(v, self->Len()); - return 1; -} - -SQInteger _stream_flush(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - if(!self->Flush()) - sq_pushinteger(v, 1); - else - sq_pushnull(v); - return 1; -} - -SQInteger _stream_eos(HSQUIRRELVM v) -{ - SETUP_STREAM(v); - if(self->EOS()) - sq_pushinteger(v, 1); - else - sq_pushnull(v); - return 1; -} - -static SQRegFunction _stream_methods[] = { - _DECL_STREAM_FUNC(readblob,2,_SC("xn")), - _DECL_STREAM_FUNC(readn,2,_SC("xn")), - _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), - _DECL_STREAM_FUNC(writen,3,_SC("xnn")), - _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), - _DECL_STREAM_FUNC(tell,1,_SC("x")), - _DECL_STREAM_FUNC(len,1,_SC("x")), - _DECL_STREAM_FUNC(eos,1,_SC("x")), - _DECL_STREAM_FUNC(flush,1,_SC("x")), - {0,0} -}; - -void init_streamclass(HSQUIRRELVM v) -{ - sq_pushregistrytable(v); - sq_pushstring(v,_SC("std_stream"),-1); - if(SQ_FAILED(sq_get(v,-2))) { - sq_pushstring(v,_SC("std_stream"),-1); - sq_newclass(v,SQFalse); - sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG); - SQInteger i = 0; - while(_stream_methods[i].name != 0) { - SQRegFunction &f = _stream_methods[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_createslot(v,-3); - i++; - } - sq_createslot(v,-3); - sq_pushroottable(v); - sq_pushstring(v,_SC("stream"),-1); - sq_pushstring(v,_SC("std_stream"),-1); - sq_get(v,-4); - sq_createslot(v,-3); - sq_pop(v,1); - } - else { - sq_pop(v,1); //result - } - sq_pop(v,1); -} - -SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,SQUserPointer typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals) -{ - if(sq_gettype(v,-1) != OT_TABLE) - return sq_throwerror(v,_SC("table expected")); - SQInteger top = sq_gettop(v); - //create delegate - init_streamclass(v); - sq_pushregistrytable(v); - sq_pushstring(v,reg_name,-1); - sq_pushstring(v,_SC("std_stream"),-1); - if(SQ_SUCCEEDED(sq_get(v,-3))) { - sq_newclass(v,SQTrue); - sq_settypetag(v,-1,typetag); - SQInteger i = 0; - while(methods[i].name != 0) { - SQRegFunction &f = methods[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); - i++; - } - sq_createslot(v,-3); - sq_pop(v,1); - - i = 0; - while(globals[i].name!=0) - { - SQRegFunction &f = globals[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); - i++; - } - //register the class in the target table - sq_pushstring(v,name,-1); - sq_pushregistrytable(v); - sq_pushstring(v,reg_name,-1); - sq_get(v,-2); - sq_remove(v,-2); - sq_createslot(v,-3); - - sq_settop(v,top); - return SQ_OK; - } - sq_settop(v,top); - return SQ_ERROR; -} +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include +#include +#include "sqstdstream.h" +#include "sqstdblobimpl.h" + +#define SETUP_STREAM(v) \ + SQStream *self = NULL; \ + if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \ + return sq_throwerror(v,_SC("invalid type tag")); \ + if(!self->IsValid()) \ + return sq_throwerror(v,_SC("the stream is invalid")); + +SQInteger _stream_readblob(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQUserPointer data,blobp; + SQInteger size,res; + sq_getinteger(v,2,&size); + if(size > self->Len()) { + size = self->Len(); + } + data = sq_getscratchpad(v,size); + res = self->Read(data,size); + if(res <= 0) + return sq_throwerror(v,_SC("no data left to read")); + blobp = sqstd_createblob(v,res); + memcpy(blobp,data,res); + return 1; +} + +#define SAFE_READN(ptr,len) { \ + if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \ + } +SQInteger _stream_readn(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger format; + sq_getinteger(v, 2, &format); + switch(format) { + case 'l': { + SQInteger i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 'i': { + SQInt32 i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 's': { + short s; + SAFE_READN(&s, sizeof(short)); + sq_pushinteger(v, s); + } + break; + case 'w': { + unsigned short w; + SAFE_READN(&w, sizeof(unsigned short)); + sq_pushinteger(v, w); + } + break; + case 'c': { + char c; + SAFE_READN(&c, sizeof(char)); + sq_pushinteger(v, c); + } + break; + case 'b': { + unsigned char c; + SAFE_READN(&c, sizeof(unsigned char)); + sq_pushinteger(v, c); + } + break; + case 'f': { + float f; + SAFE_READN(&f, sizeof(float)); + sq_pushfloat(v, f); + } + break; + case 'd': { + double d; + SAFE_READN(&d, sizeof(double)); + sq_pushfloat(v, (SQFloat)d); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 1; +} + +SQInteger _stream_writeblob(HSQUIRRELVM v) +{ + SQUserPointer data; + SQInteger size; + SETUP_STREAM(v); + if(SQ_FAILED(sqstd_getblob(v,2,&data))) + return sq_throwerror(v,_SC("invalid parameter")); + size = sqstd_getblobsize(v,2); + if(self->Write(data,size) != size) + return sq_throwerror(v,_SC("io error")); + sq_pushinteger(v,size); + return 1; +} + +SQInteger _stream_writen(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger format, ti; + SQFloat tf; + sq_getinteger(v, 3, &format); + switch(format) { + case 'l': { + SQInteger i; + sq_getinteger(v, 2, &ti); + i = ti; + self->Write(&i, sizeof(SQInteger)); + } + break; + case 'i': { + SQInt32 i; + sq_getinteger(v, 2, &ti); + i = (SQInt32)ti; + self->Write(&i, sizeof(SQInt32)); + } + break; + case 's': { + short s; + sq_getinteger(v, 2, &ti); + s = (short)ti; + self->Write(&s, sizeof(short)); + } + break; + case 'w': { + unsigned short w; + sq_getinteger(v, 2, &ti); + w = (unsigned short)ti; + self->Write(&w, sizeof(unsigned short)); + } + break; + case 'c': { + char c; + sq_getinteger(v, 2, &ti); + c = (char)ti; + self->Write(&c, sizeof(char)); + } + break; + case 'b': { + unsigned char b; + sq_getinteger(v, 2, &ti); + b = (unsigned char)ti; + self->Write(&b, sizeof(unsigned char)); + } + break; + case 'f': { + float f; + sq_getfloat(v, 2, &tf); + f = tf; + self->Write(&f, sizeof(float)); + } + break; + case 'd': { + double d; + sq_getfloat(v, 2, &tf); + d = tf; + self->Write(&d, sizeof(double)); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 0; +} + +SQInteger _stream_seek(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger offset, origin = SQ_SEEK_SET; + sq_getinteger(v, 2, &offset); + if(sq_gettop(v) > 2) { + SQInteger t; + sq_getinteger(v, 3, &t); + switch(t) { + case 'b': origin = SQ_SEEK_SET; break; + case 'c': origin = SQ_SEEK_CUR; break; + case 'e': origin = SQ_SEEK_END; break; + default: return sq_throwerror(v,_SC("invalid origin")); + } + } + sq_pushinteger(v, self->Seek(offset, origin)); + return 1; +} + +SQInteger _stream_tell(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + sq_pushinteger(v, self->Tell()); + return 1; +} + +SQInteger _stream_len(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + sq_pushinteger(v, self->Len()); + return 1; +} + +SQInteger _stream_flush(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + if(!self->Flush()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; +} + +SQInteger _stream_eos(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + if(self->EOS()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; +} + +static SQRegFunction _stream_methods[] = { + _DECL_STREAM_FUNC(readblob,2,_SC("xn")), + _DECL_STREAM_FUNC(readn,2,_SC("xn")), + _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), + _DECL_STREAM_FUNC(writen,3,_SC("xnn")), + _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), + _DECL_STREAM_FUNC(tell,1,_SC("x")), + _DECL_STREAM_FUNC(len,1,_SC("x")), + _DECL_STREAM_FUNC(eos,1,_SC("x")), + _DECL_STREAM_FUNC(flush,1,_SC("x")), + {0,0} +}; + +void init_streamclass(HSQUIRRELVM v) +{ + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_FAILED(sq_get(v,-2))) { + sq_pushstring(v,_SC("std_stream"),-1); + sq_newclass(v,SQFalse); + sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG); + SQInteger i = 0; + while(_stream_methods[i].name != 0) { + SQRegFunction &f = _stream_methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + sq_pushroottable(v); + sq_pushstring(v,_SC("stream"),-1); + sq_pushstring(v,_SC("std_stream"),-1); + sq_get(v,-4); + sq_createslot(v,-3); + sq_pop(v,1); + } + else { + sq_pop(v,1); //result + } + sq_pop(v,1); +} + +SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,SQUserPointer typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals) +{ + if(sq_gettype(v,-1) != OT_TABLE) + return sq_throwerror(v,_SC("table expected")); + SQInteger top = sq_gettop(v); + //create delegate + init_streamclass(v); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_SUCCEEDED(sq_get(v,-3))) { + sq_newclass(v,SQTrue); + sq_settypetag(v,-1,typetag); + SQInteger i = 0; + while(methods[i].name != 0) { + SQRegFunction &f = methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + sq_pop(v,1); + + i = 0; + while(globals[i].name!=0) + { + SQRegFunction &f = globals[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + //register the class in the target table + sq_pushstring(v,name,-1); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_get(v,-2); + sq_remove(v,-2); + sq_createslot(v,-3); + + sq_settop(v,top); + return SQ_OK; + } + sq_settop(v,top); + return SQ_ERROR; +} diff --git a/src/squirrel/sqstdlib/sqstdstream.h b/src/squirrel/sqstdlib/sqstdstream.h index 6f562da1e..6b5bb9d8a 100644 --- a/src/squirrel/sqstdlib/sqstdstream.h +++ b/src/squirrel/sqstdlib/sqstdstream.h @@ -1,18 +1,18 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTD_STREAM_H_ -#define _SQSTD_STREAM_H_ - -SQInteger _stream_readblob(HSQUIRRELVM v); -SQInteger _stream_readline(HSQUIRRELVM v); -SQInteger _stream_readn(HSQUIRRELVM v); -SQInteger _stream_writeblob(HSQUIRRELVM v); -SQInteger _stream_writen(HSQUIRRELVM v); -SQInteger _stream_seek(HSQUIRRELVM v); -SQInteger _stream_tell(HSQUIRRELVM v); -SQInteger _stream_len(HSQUIRRELVM v); -SQInteger _stream_eos(HSQUIRRELVM v); -SQInteger _stream_flush(HSQUIRRELVM v); - -#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck} -SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,SQUserPointer typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals); -#endif /*_SQSTD_STREAM_H_*/ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_STREAM_H_ +#define _SQSTD_STREAM_H_ + +SQInteger _stream_readblob(HSQUIRRELVM v); +SQInteger _stream_readline(HSQUIRRELVM v); +SQInteger _stream_readn(HSQUIRRELVM v); +SQInteger _stream_writeblob(HSQUIRRELVM v); +SQInteger _stream_writen(HSQUIRRELVM v); +SQInteger _stream_seek(HSQUIRRELVM v); +SQInteger _stream_tell(HSQUIRRELVM v); +SQInteger _stream_len(HSQUIRRELVM v); +SQInteger _stream_eos(HSQUIRRELVM v); +SQInteger _stream_flush(HSQUIRRELVM v); + +#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck} +SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,SQUserPointer typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals); +#endif /*_SQSTD_STREAM_H_*/ diff --git a/src/squirrel/sqstdlib/sqstdstring.cpp b/src/squirrel/sqstdlib/sqstdstring.cpp index 832f3aa07..d500012db 100644 --- a/src/squirrel/sqstdlib/sqstdstring.cpp +++ b/src/squirrel/sqstdlib/sqstdstring.cpp @@ -1,350 +1,350 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef _UNICODE -#define scstrchr wcschr -#define scsnprintf wsnprintf -#define scatoi _wtoi -#define scstrtok wcstok -#else -#define scstrchr strchr -#define scsnprintf snprintf -#define scatoi atoi -#define scstrtok strtok -#endif -#define MAX_FORMAT_LEN 20 -#define MAX_WFORMAT_LEN 3 -#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar)) - -static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width) -{ - SQChar swidth[MAX_WFORMAT_LEN]; - SQInteger wc = 0; - SQInteger start = n; - fmt[0] = '%'; - while (scstrchr(_SC("-+ #0"), src[n])) n++; - while (scisdigit(src[n])) { - swidth[wc] = src[n]; - n++; - wc++; - if(wc>=MAX_WFORMAT_LEN) - return sq_throwerror(v,_SC("width format too long")); - } - swidth[wc] = '\0'; - if(wc > 0) { - width = scatoi(swidth); - } - else - width = 0; - if (src[n] == '.') { - n++; - - wc = 0; - while (scisdigit(src[n])) { - swidth[wc] = src[n]; - n++; - wc++; - if(wc>=MAX_WFORMAT_LEN) - return sq_throwerror(v,_SC("precision format too long")); - } - swidth[wc] = '\0'; - if(wc > 0) { - width += scatoi(swidth); - } - } - if (n-start > MAX_FORMAT_LEN ) - return sq_throwerror(v,_SC("format too long")); - memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar)); - fmt[(n-start)+2] = '\0'; - return n; -} - -static SQInteger _string_format(HSQUIRRELVM v) -{ - const SQChar *format; - SQChar *dest; - SQChar fmt[MAX_FORMAT_LEN]; - sq_getstring(v,2,&format); - SQInteger allocated = (sq_getsize(v,2)+1)*sizeof(SQChar); - dest = sq_getscratchpad(v,allocated); - SQInteger n = 0,i = 0, nparam = 3, w = 0; - while(format[n] != '\0') { - if(format[n] != '%') { - assert(i < allocated); - dest[i++] = format[n]; - n++; - } - else if(format[n+1] == '%') { //handles %% - dest[i++] = '%'; - n += 2; - } - else { - n++; - if( nparam > sq_gettop(v) ) - return sq_throwerror(v,_SC("not enough paramters for the given format string")); - n = validate_format(v,fmt,format,n,w); - if(n < 0) return -1; - SQInteger addlen = 0; - SQInteger valtype = 0; - const SQChar *ts; - SQInteger ti; - SQFloat tf; - switch(format[n]) { - case 's': - if(SQ_FAILED(sq_getstring(v,nparam,&ts))) - return sq_throwerror(v,_SC("string expected for the specified format")); - addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); - valtype = 's'; - break; - case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X': - if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) - return sq_throwerror(v,_SC("integer expected for the specified format")); - addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); - valtype = 'i'; - break; - case 'f': case 'g': case 'G': case 'e': case 'E': - if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) - return sq_throwerror(v,_SC("float expected for the specified format")); - addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); - valtype = 'f'; - break; - default: - return sq_throwerror(v,_SC("invalid format")); - } - n++; - allocated += addlen; - dest = sq_getscratchpad(v,allocated); - switch(valtype) { - case 's': i += scsprintf(&dest[i],fmt,ts); break; - case 'i': i += scsprintf(&dest[i],fmt,ti); break; - case 'f': i += scsprintf(&dest[i],fmt,tf); break; - }; - nparam ++; - } - } - sq_pushstring(v,dest,i); - return 1; -} - -static void __strip_l(const SQChar *str,const SQChar **start) -{ - const SQChar *t = str; - while(((*t) != '\0') && scisspace(*t)){ t++; } - *start = t; -} - -static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end) -{ - if(len == 0) { - *end = str; - return; - } - const SQChar *t = &str[len-1]; - while(t != str && scisspace(*t)) { t--; } - *end = t+1; -} - -static SQInteger _string_strip(HSQUIRRELVM v) -{ - const SQChar *str,*start,*end; - sq_getstring(v,2,&str); - SQInteger len = sq_getsize(v,2); - __strip_l(str,&start); - __strip_r(str,len,&end); - sq_pushstring(v,start,end - start); - return 1; -} - -static SQInteger _string_lstrip(HSQUIRRELVM v) -{ - const SQChar *str,*start; - sq_getstring(v,2,&str); - __strip_l(str,&start); - sq_pushstring(v,start,-1); - return 1; -} - -static SQInteger _string_rstrip(HSQUIRRELVM v) -{ - const SQChar *str,*end; - sq_getstring(v,2,&str); - SQInteger len = sq_getsize(v,2); - __strip_r(str,len,&end); - sq_pushstring(v,str,end - str); - return 1; -} - -static SQInteger _string_split(HSQUIRRELVM v) -{ - const SQChar *str,*seps; - SQChar *stemp,*tok; - sq_getstring(v,2,&str); - sq_getstring(v,3,&seps); - if(sq_getsize(v,3) == 0) return sq_throwerror(v,_SC("empty separators string")); - SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar); - stemp = sq_getscratchpad(v,memsize); - memcpy(stemp,str,memsize); - tok = scstrtok(stemp,seps); - sq_newarray(v,0); - while( tok != NULL ) { - sq_pushstring(v,tok,-1); - sq_arrayappend(v,-2); - tok = scstrtok( NULL, seps ); - } - return 1; -} - -#define SETUP_REX(v) \ - SQRex *self = NULL; \ - sq_getinstanceup(v,1,(SQUserPointer *)&self,0); - -static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size) -{ - SQRex *self = ((SQRex *)p); - sqstd_rex_free(self); - return 1; -} - -static SQInteger _regexp_match(HSQUIRRELVM v) -{ - SETUP_REX(v); - const SQChar *str; - sq_getstring(v,2,&str); - if(sqstd_rex_match(self,str) == SQTrue) - { - sq_pushbool(v,SQTrue); - return 1; - } - sq_pushbool(v,SQFalse); - return 1; -} - -static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end) -{ - sq_newtable(v); - sq_pushstring(v,_SC("begin"),-1); - sq_pushinteger(v,begin - str); - sq_rawset(v,-3); - sq_pushstring(v,_SC("end"),-1); - sq_pushinteger(v,end - str); - sq_rawset(v,-3); -} - -static SQInteger _regexp_search(HSQUIRRELVM v) -{ - SETUP_REX(v); - const SQChar *str,*begin,*end; - SQInteger start = 0; - sq_getstring(v,2,&str); - if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); - if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { - _addrexmatch(v,str,begin,end); - return 1; - } - return 0; -} - -static SQInteger _regexp_capture(HSQUIRRELVM v) -{ - SETUP_REX(v); - const SQChar *str,*begin,*end; - SQInteger start = 0; - sq_getstring(v,2,&str); - if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); - if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { - SQInteger n = sqstd_rex_getsubexpcount(self); - SQRexMatch match; - sq_newarray(v,0); - for(SQInteger i = 0;i < n; i++) { - sqstd_rex_getsubexp(self,i,&match); - if(match.len > 0) - _addrexmatch(v,str,match.begin,match.begin+match.len); - else - _addrexmatch(v,str,str,str); //empty match - sq_arrayappend(v,-2); - } - return 1; - } - return 0; -} - -static SQInteger _regexp_subexpcount(HSQUIRRELVM v) -{ - SETUP_REX(v); - sq_pushinteger(v,sqstd_rex_getsubexpcount(self)); - return 1; -} - -static SQInteger _regexp_constructor(HSQUIRRELVM v) -{ - const SQChar *error,*pattern; - sq_getstring(v,2,&pattern); - SQRex *rex = sqstd_rex_compile(pattern,&error); - if(!rex) return sq_throwerror(v,error); - sq_setinstanceup(v,1,rex); - sq_setreleasehook(v,1,_rexobj_releasehook); - return 0; -} - -static SQInteger _regexp__typeof(HSQUIRRELVM v) -{ - sq_pushstring(v,_SC("regexp"),-1); - return 1; -} - -#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask} -static SQRegFunction rexobj_funcs[]={ - _DECL_REX_FUNC(constructor,2,_SC(".s")), - _DECL_REX_FUNC(search,-2,_SC("xsn")), - _DECL_REX_FUNC(match,2,_SC("xs")), - _DECL_REX_FUNC(capture,-2,_SC("xsn")), - _DECL_REX_FUNC(subexpcount,1,_SC("x")), - _DECL_REX_FUNC(_typeof,1,_SC("x")), - {0,0} -}; - -#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask} -static SQRegFunction stringlib_funcs[]={ - _DECL_FUNC(format,-2,_SC(".s")), - _DECL_FUNC(strip,2,_SC(".s")), - _DECL_FUNC(lstrip,2,_SC(".s")), - _DECL_FUNC(rstrip,2,_SC(".s")), - _DECL_FUNC(split,3,_SC(".ss")), - {0,0} -}; - - -SQInteger sqstd_register_stringlib(HSQUIRRELVM v) -{ - sq_pushstring(v,_SC("regexp"),-1); - sq_newclass(v,SQFalse); - SQInteger i = 0; - while(rexobj_funcs[i].name != 0) { - SQRegFunction &f = rexobj_funcs[i]; - sq_pushstring(v,f.name,-1); - sq_newclosure(v,f.f,0); - sq_setparamscheck(v,f.nparamscheck,f.typemask); - sq_setnativeclosurename(v,-1,f.name); - sq_createslot(v,-3); - i++; - } - sq_createslot(v,-3); - - i = 0; - while(stringlib_funcs[i].name!=0) - { - sq_pushstring(v,stringlib_funcs[i].name,-1); - sq_newclosure(v,stringlib_funcs[i].f,0); - sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); - sq_createslot(v,-3); - i++; - } - return 1; -} +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef _UNICODE +#define scstrchr wcschr +#define scsnprintf wsnprintf +#define scatoi _wtoi +#define scstrtok wcstok +#else +#define scstrchr strchr +#define scsnprintf snprintf +#define scatoi atoi +#define scstrtok strtok +#endif +#define MAX_FORMAT_LEN 20 +#define MAX_WFORMAT_LEN 3 +#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar)) + +static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width) +{ + SQChar swidth[MAX_WFORMAT_LEN]; + SQInteger wc = 0; + SQInteger start = n; + fmt[0] = '%'; + while (scstrchr(_SC("-+ #0"), src[n])) n++; + while (scisdigit(src[n])) { + swidth[wc] = src[n]; + n++; + wc++; + if(wc>=MAX_WFORMAT_LEN) + return sq_throwerror(v,_SC("width format too long")); + } + swidth[wc] = '\0'; + if(wc > 0) { + width = scatoi(swidth); + } + else + width = 0; + if (src[n] == '.') { + n++; + + wc = 0; + while (scisdigit(src[n])) { + swidth[wc] = src[n]; + n++; + wc++; + if(wc>=MAX_WFORMAT_LEN) + return sq_throwerror(v,_SC("precision format too long")); + } + swidth[wc] = '\0'; + if(wc > 0) { + width += scatoi(swidth); + } + } + if (n-start > MAX_FORMAT_LEN ) + return sq_throwerror(v,_SC("format too long")); + memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar)); + fmt[(n-start)+2] = '\0'; + return n; +} + +static SQInteger _string_format(HSQUIRRELVM v) +{ + const SQChar *format; + SQChar *dest; + SQChar fmt[MAX_FORMAT_LEN]; + sq_getstring(v,2,&format); + SQInteger allocated = (sq_getsize(v,2)+1)*sizeof(SQChar); + dest = sq_getscratchpad(v,allocated); + SQInteger n = 0,i = 0, nparam = 3, w = 0; + while(format[n] != '\0') { + if(format[n] != '%') { + assert(i < allocated); + dest[i++] = format[n]; + n++; + } + else if(format[n+1] == '%') { //handles %% + dest[i++] = '%'; + n += 2; + } + else { + n++; + if( nparam > sq_gettop(v) ) + return sq_throwerror(v,_SC("not enough paramters for the given format string")); + n = validate_format(v,fmt,format,n,w); + if(n < 0) return -1; + SQInteger addlen = 0; + SQInteger valtype = 0; + const SQChar *ts; + SQInteger ti; + SQFloat tf; + switch(format[n]) { + case 's': + if(SQ_FAILED(sq_getstring(v,nparam,&ts))) + return sq_throwerror(v,_SC("string expected for the specified format")); + addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); + valtype = 's'; + break; + case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X': + if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) + return sq_throwerror(v,_SC("integer expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'i'; + break; + case 'f': case 'g': case 'G': case 'e': case 'E': + if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) + return sq_throwerror(v,_SC("float expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'f'; + break; + default: + return sq_throwerror(v,_SC("invalid format")); + } + n++; + allocated += addlen; + dest = sq_getscratchpad(v,allocated); + switch(valtype) { + case 's': i += scsprintf(&dest[i],fmt,ts); break; + case 'i': i += scsprintf(&dest[i],fmt,ti); break; + case 'f': i += scsprintf(&dest[i],fmt,tf); break; + }; + nparam ++; + } + } + sq_pushstring(v,dest,i); + return 1; +} + +static void __strip_l(const SQChar *str,const SQChar **start) +{ + const SQChar *t = str; + while(((*t) != '\0') && scisspace(*t)){ t++; } + *start = t; +} + +static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end) +{ + if(len == 0) { + *end = str; + return; + } + const SQChar *t = &str[len-1]; + while(t != str && scisspace(*t)) { t--; } + *end = t+1; +} + +static SQInteger _string_strip(HSQUIRRELVM v) +{ + const SQChar *str,*start,*end; + sq_getstring(v,2,&str); + SQInteger len = sq_getsize(v,2); + __strip_l(str,&start); + __strip_r(str,len,&end); + sq_pushstring(v,start,end - start); + return 1; +} + +static SQInteger _string_lstrip(HSQUIRRELVM v) +{ + const SQChar *str,*start; + sq_getstring(v,2,&str); + __strip_l(str,&start); + sq_pushstring(v,start,-1); + return 1; +} + +static SQInteger _string_rstrip(HSQUIRRELVM v) +{ + const SQChar *str,*end; + sq_getstring(v,2,&str); + SQInteger len = sq_getsize(v,2); + __strip_r(str,len,&end); + sq_pushstring(v,str,end - str); + return 1; +} + +static SQInteger _string_split(HSQUIRRELVM v) +{ + const SQChar *str,*seps; + SQChar *stemp,*tok; + sq_getstring(v,2,&str); + sq_getstring(v,3,&seps); + if(sq_getsize(v,3) == 0) return sq_throwerror(v,_SC("empty separators string")); + SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar); + stemp = sq_getscratchpad(v,memsize); + memcpy(stemp,str,memsize); + tok = scstrtok(stemp,seps); + sq_newarray(v,0); + while( tok != NULL ) { + sq_pushstring(v,tok,-1); + sq_arrayappend(v,-2); + tok = scstrtok( NULL, seps ); + } + return 1; +} + +#define SETUP_REX(v) \ + SQRex *self = NULL; \ + sq_getinstanceup(v,1,(SQUserPointer *)&self,0); + +static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size) +{ + SQRex *self = ((SQRex *)p); + sqstd_rex_free(self); + return 1; +} + +static SQInteger _regexp_match(HSQUIRRELVM v) +{ + SETUP_REX(v); + const SQChar *str; + sq_getstring(v,2,&str); + if(sqstd_rex_match(self,str) == SQTrue) + { + sq_pushbool(v,SQTrue); + return 1; + } + sq_pushbool(v,SQFalse); + return 1; +} + +static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end) +{ + sq_newtable(v); + sq_pushstring(v,_SC("begin"),-1); + sq_pushinteger(v,begin - str); + sq_rawset(v,-3); + sq_pushstring(v,_SC("end"),-1); + sq_pushinteger(v,end - str); + sq_rawset(v,-3); +} + +static SQInteger _regexp_search(HSQUIRRELVM v) +{ + SETUP_REX(v); + const SQChar *str,*begin,*end; + SQInteger start = 0; + sq_getstring(v,2,&str); + if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); + if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { + _addrexmatch(v,str,begin,end); + return 1; + } + return 0; +} + +static SQInteger _regexp_capture(HSQUIRRELVM v) +{ + SETUP_REX(v); + const SQChar *str,*begin,*end; + SQInteger start = 0; + sq_getstring(v,2,&str); + if(sq_gettop(v) > 2) sq_getinteger(v,3,&start); + if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) { + SQInteger n = sqstd_rex_getsubexpcount(self); + SQRexMatch match; + sq_newarray(v,0); + for(SQInteger i = 0;i < n; i++) { + sqstd_rex_getsubexp(self,i,&match); + if(match.len > 0) + _addrexmatch(v,str,match.begin,match.begin+match.len); + else + _addrexmatch(v,str,str,str); //empty match + sq_arrayappend(v,-2); + } + return 1; + } + return 0; +} + +static SQInteger _regexp_subexpcount(HSQUIRRELVM v) +{ + SETUP_REX(v); + sq_pushinteger(v,sqstd_rex_getsubexpcount(self)); + return 1; +} + +static SQInteger _regexp_constructor(HSQUIRRELVM v) +{ + const SQChar *error,*pattern; + sq_getstring(v,2,&pattern); + SQRex *rex = sqstd_rex_compile(pattern,&error); + if(!rex) return sq_throwerror(v,error); + sq_setinstanceup(v,1,rex); + sq_setreleasehook(v,1,_rexobj_releasehook); + return 0; +} + +static SQInteger _regexp__typeof(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("regexp"),-1); + return 1; +} + +#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask} +static SQRegFunction rexobj_funcs[]={ + _DECL_REX_FUNC(constructor,2,_SC(".s")), + _DECL_REX_FUNC(search,-2,_SC("xsn")), + _DECL_REX_FUNC(match,2,_SC("xs")), + _DECL_REX_FUNC(capture,-2,_SC("xsn")), + _DECL_REX_FUNC(subexpcount,1,_SC("x")), + _DECL_REX_FUNC(_typeof,1,_SC("x")), + {0,0} +}; + +#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask} +static SQRegFunction stringlib_funcs[]={ + _DECL_FUNC(format,-2,_SC(".s")), + _DECL_FUNC(strip,2,_SC(".s")), + _DECL_FUNC(lstrip,2,_SC(".s")), + _DECL_FUNC(rstrip,2,_SC(".s")), + _DECL_FUNC(split,3,_SC(".ss")), + {0,0} +}; + + +SQInteger sqstd_register_stringlib(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("regexp"),-1); + sq_newclass(v,SQFalse); + SQInteger i = 0; + while(rexobj_funcs[i].name != 0) { + SQRegFunction &f = rexobj_funcs[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + + i = 0; + while(stringlib_funcs[i].name!=0) + { + sq_pushstring(v,stringlib_funcs[i].name,-1); + sq_newclosure(v,stringlib_funcs[i].f,0); + sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + return 1; +} diff --git a/src/squirrel/sqstdlib/sqstdsystem.cpp b/src/squirrel/sqstdlib/sqstdsystem.cpp index c7153a67c..7d4200c85 100644 --- a/src/squirrel/sqstdlib/sqstdsystem.cpp +++ b/src/squirrel/sqstdlib/sqstdsystem.cpp @@ -1,147 +1,147 @@ -/* see copyright notice in squirrel.h */ -#include -#include -#include -#include -#include - -#ifdef SQUNICODE -#include -#define scgetenv _wgetenv -#define scsystem _wsystem -#define scasctime _wasctime -#define scremove _wremove -#define screname _wrename -#else -#define scgetenv getenv -#define scsystem system -#define scasctime asctime -#define scremove remove -#define screname rename -#endif - -static SQInteger _system_getenv(HSQUIRRELVM v) -{ - const SQChar *s; - if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ - sq_pushstring(v,scgetenv(s),-1); - return 1; - } - return 0; -} - - -static SQInteger _system_system(HSQUIRRELVM v) -{ - const SQChar *s; - if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ - sq_pushinteger(v,scsystem(s)); - return 1; - } - return sq_throwerror(v,_SC("wrong param")); -} - - -static SQInteger _system_clock(HSQUIRRELVM v) -{ - sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); - return 1; -} - -static SQInteger _system_time(HSQUIRRELVM v) -{ - time_t t; - time(&t); - sq_pushinteger(v,*((SQInteger *)&t)); - return 1; -} - -static SQInteger _system_remove(HSQUIRRELVM v) -{ - const SQChar *s; - sq_getstring(v,2,&s); - if(scremove(s)==-1) - return sq_throwerror(v,_SC("remove() failed")); - return 0; -} - -static SQInteger _system_rename(HSQUIRRELVM v) -{ - const SQChar *oldn,*newn; - sq_getstring(v,2,&oldn); - sq_getstring(v,3,&newn); - if(screname(oldn,newn)==-1) - return sq_throwerror(v,_SC("rename() failed")); - return 0; -} - -static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val) -{ - sq_pushstring(v,name,-1); - sq_pushinteger(v,val); - sq_rawset(v,-3); -} - -static SQInteger _system_date(HSQUIRRELVM v) -{ - time_t t; - SQInteger it; - SQInteger format = 'l'; - if(sq_gettop(v) > 1) { - sq_getinteger(v,2,&it); - t = it; - if(sq_gettop(v) > 2) { - sq_getinteger(v,3,(SQInteger*)&format); - } - } - else { - time(&t); - } - tm *date; - if(format == 'u') - date = gmtime(&t); - else - date = localtime(&t); - if(!date) - return sq_throwerror(v,_SC("crt api failure")); - sq_newtable(v); - _set_integer_slot(v, _SC("sec"), date->tm_sec); - _set_integer_slot(v, _SC("min"), date->tm_min); - _set_integer_slot(v, _SC("hour"), date->tm_hour); - _set_integer_slot(v, _SC("day"), date->tm_mday); - _set_integer_slot(v, _SC("month"), date->tm_mon); - _set_integer_slot(v, _SC("year"), date->tm_year+1900); - _set_integer_slot(v, _SC("wday"), date->tm_wday); - _set_integer_slot(v, _SC("yday"), date->tm_yday); - return 1; -} - - - -#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} -static SQRegFunction systemlib_funcs[]={ - _DECL_FUNC(getenv,2,_SC(".s")), - _DECL_FUNC(system,2,_SC(".s")), - _DECL_FUNC(clock,1,NULL), - _DECL_FUNC(time,1,NULL), - _DECL_FUNC(date,-1,_SC(".nn")), - _DECL_FUNC(remove,2,_SC(".s")), - _DECL_FUNC(rename,3,_SC(".ss")), - {0,0} -}; - - -SQInteger sqstd_register_systemlib(HSQUIRRELVM v) -{ - SQInteger i=0; - while(systemlib_funcs[i].name!=0) - { - sq_pushstring(v,systemlib_funcs[i].name,-1); - sq_newclosure(v,systemlib_funcs[i].f,0); - sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); - sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); - sq_createslot(v,-3); - i++; - } - return 1; -} +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include + +#ifdef SQUNICODE +#include +#define scgetenv _wgetenv +#define scsystem _wsystem +#define scasctime _wasctime +#define scremove _wremove +#define screname _wrename +#else +#define scgetenv getenv +#define scsystem system +#define scasctime asctime +#define scremove remove +#define screname rename +#endif + +static SQInteger _system_getenv(HSQUIRRELVM v) +{ + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushstring(v,scgetenv(s),-1); + return 1; + } + return 0; +} + + +static SQInteger _system_system(HSQUIRRELVM v) +{ + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushinteger(v,scsystem(s)); + return 1; + } + return sq_throwerror(v,_SC("wrong param")); +} + + +static SQInteger _system_clock(HSQUIRRELVM v) +{ + sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); + return 1; +} + +static SQInteger _system_time(HSQUIRRELVM v) +{ + time_t t; + time(&t); + sq_pushinteger(v,*((SQInteger *)&t)); + return 1; +} + +static SQInteger _system_remove(HSQUIRRELVM v) +{ + const SQChar *s; + sq_getstring(v,2,&s); + if(scremove(s)==-1) + return sq_throwerror(v,_SC("remove() failed")); + return 0; +} + +static SQInteger _system_rename(HSQUIRRELVM v) +{ + const SQChar *oldn,*newn; + sq_getstring(v,2,&oldn); + sq_getstring(v,3,&newn); + if(screname(oldn,newn)==-1) + return sq_throwerror(v,_SC("rename() failed")); + return 0; +} + +static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val) +{ + sq_pushstring(v,name,-1); + sq_pushinteger(v,val); + sq_rawset(v,-3); +} + +static SQInteger _system_date(HSQUIRRELVM v) +{ + time_t t; + SQInteger it; + SQInteger format = 'l'; + if(sq_gettop(v) > 1) { + sq_getinteger(v,2,&it); + t = it; + if(sq_gettop(v) > 2) { + sq_getinteger(v,3,(SQInteger*)&format); + } + } + else { + time(&t); + } + tm *date; + if(format == 'u') + date = gmtime(&t); + else + date = localtime(&t); + if(!date) + return sq_throwerror(v,_SC("crt api failure")); + sq_newtable(v); + _set_integer_slot(v, _SC("sec"), date->tm_sec); + _set_integer_slot(v, _SC("min"), date->tm_min); + _set_integer_slot(v, _SC("hour"), date->tm_hour); + _set_integer_slot(v, _SC("day"), date->tm_mday); + _set_integer_slot(v, _SC("month"), date->tm_mon); + _set_integer_slot(v, _SC("year"), date->tm_year+1900); + _set_integer_slot(v, _SC("wday"), date->tm_wday); + _set_integer_slot(v, _SC("yday"), date->tm_yday); + return 1; +} + + + +#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} +static SQRegFunction systemlib_funcs[]={ + _DECL_FUNC(getenv,2,_SC(".s")), + _DECL_FUNC(system,2,_SC(".s")), + _DECL_FUNC(clock,1,NULL), + _DECL_FUNC(time,1,NULL), + _DECL_FUNC(date,-1,_SC(".nn")), + _DECL_FUNC(remove,2,_SC(".s")), + _DECL_FUNC(rename,3,_SC(".ss")), + {0,0} +}; + + +SQInteger sqstd_register_systemlib(HSQUIRRELVM v) +{ + SQInteger i=0; + while(systemlib_funcs[i].name!=0) + { + sq_pushstring(v,systemlib_funcs[i].name,-1); + sq_newclosure(v,systemlib_funcs[i].f,0); + sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + return 1; +} diff --git a/src/squirrel/squirrel/sqapi.cpp b/src/squirrel/squirrel/sqapi.cpp index b17bab90a..8857c9af0 100644 --- a/src/squirrel/squirrel/sqapi.cpp +++ b/src/squirrel/squirrel/sqapi.cpp @@ -1,1203 +1,1203 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqvm.h" -#include "sqstring.h" -#include "sqtable.h" -#include "sqarray.h" -#include "sqfuncproto.h" -#include "sqclosure.h" -#include "squserdata.h" -#include "sqcompiler.h" -#include "sqfuncstate.h" -#include "sqclass.h" - -bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o) -{ - *o = &stack_get(v,idx); - if(type(**o) != type){ - SQObjectPtr oval = v->PrintObjVal(**o); - v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval)); - return false; - } - return true; -} - -#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; } - -#define sq_aux_paramscheck(v,count) \ -{ \ - if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ -} - -SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e) -{ - v->_lasterror = e; - return SQ_ERROR; -} - -SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type) -{ - scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type)); - return sq_throwerror(v, _ss(v)->GetScratchPad(-1)); -} - -HSQUIRRELVM sq_open(SQInteger initialstacksize) -{ - SQSharedState *ss; - SQVM *v; - sq_new(ss, SQSharedState); - ss->Init(); - v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); - new (v) SQVM(ss); - ss->_root_vm = v; - if(v->Init(NULL, initialstacksize)) { - return v; - } else { - sq_delete(v, SQVM); - return NULL; - } - return v; -} - -HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize) -{ - SQSharedState *ss; - SQVM *v; - ss=_ss(friendvm); - - v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); - new (v) SQVM(ss); - - if(v->Init(friendvm, initialstacksize)) { - friendvm->Push(v); - return v; - } else { - sq_delete(v, SQVM); - return NULL; - } -} - -SQInteger sq_getvmstate(HSQUIRRELVM v) -{ - if(v->_suspended) - return SQ_VMSTATE_SUSPENDED; - else { - if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING; - else return SQ_VMSTATE_IDLE; - } -} - -void sq_seterrorhandler(HSQUIRRELVM v) -{ - SQObject o = stack_get(v, -1); - if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_errorhandler = o; - v->Pop(); - } -} - -void sq_setdebughook(HSQUIRRELVM v) -{ - SQObject o = stack_get(v,-1); - if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { - v->_debughook = o; - v->Pop(); - } -} - -void sq_close(HSQUIRRELVM v) -{ - SQSharedState *ss = _ss(v); - _thread(ss->_root_vm)->Finalize(); - sq_delete(ss, SQSharedState); -} - -SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) -{ - SQObjectPtr o; - if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { - v->Push(SQClosure::Create(_ss(v), _funcproto(o))); - return SQ_OK; - } - return SQ_ERROR; -} - -void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) -{ - _ss(v)->_debuginfo = enable?true:false; -} - -void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable) -{ - _ss(v)->_notifyallexceptions = enable?true:false; -} - -void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) -{ - if(!ISREFCOUNTED(type(*po))) return; - _ss(v)->_refs_table.AddRef(*po); -} - -SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po) -{ - if(!ISREFCOUNTED(type(*po))) return SQTrue; - return _ss(v)->_refs_table.Release(*po); -} - -const SQChar *sq_objtostring(HSQOBJECT *o) -{ - if(sq_type(*o) == OT_STRING) { - return _stringval(*o); - } - return NULL; -} - -SQInteger sq_objtointeger(HSQOBJECT *o) -{ - if(sq_isnumeric(*o)) { - return tointeger(*o); - } - return 0; -} - -SQFloat sq_objtofloat(HSQOBJECT *o) -{ - if(sq_isnumeric(*o)) { - return tofloat(*o); - } - return 0; -} - -SQBool sq_objtobool(HSQOBJECT *o) -{ - if(sq_isbool(*o)) { - return _integer(*o); - } - return SQFalse; -} - -void sq_pushnull(HSQUIRRELVM v) -{ - v->Push(_null_); -} - -void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len) -{ - if(s) - v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); - else v->Push(_null_); -} - -void sq_pushinteger(HSQUIRRELVM v,SQInteger n) -{ - v->Push(n); -} - -void sq_pushbool(HSQUIRRELVM v,SQBool b) -{ - v->Push(b?true:false); -} - -void sq_pushfloat(HSQUIRRELVM v,SQFloat n) -{ - v->Push(n); -} - -void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p) -{ - v->Push(p); -} - -SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size) -{ - SQUserData *ud = SQUserData::Create(_ss(v), size); - v->Push(ud); - return ud->_val; -} - -void sq_newtable(HSQUIRRELVM v) -{ - v->Push(SQTable::Create(_ss(v), 0)); -} - -void sq_newarray(HSQUIRRELVM v,SQInteger size) -{ - v->Push(SQArray::Create(_ss(v), size)); -} - -SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) -{ - SQClass *baseclass = NULL; - if(hasbase) { - SQObjectPtr &base = stack_get(v,-1); - if(type(base) != OT_CLASS) - return sq_throwerror(v,_SC("invalid base type")); - baseclass = _class(base); - } - SQClass *newclass = SQClass::Create(_ss(v), baseclass); - if(baseclass) v->Pop(); - v->Push(newclass); - return SQ_OK; -} - -SQBool sq_instanceof(HSQUIRRELVM v) -{ - SQObjectPtr &inst = stack_get(v,-1); - SQObjectPtr &cl = stack_get(v,-2); - if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS) - return sq_throwerror(v,_SC("invalid param type")); - return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse; -} - -SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx) -{ - sq_aux_paramscheck(v,2); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - _array(*arr)->Append(v->GetUp(-1)); - v->Pop(1); - return SQ_OK; -} - -SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval) -{ - sq_aux_paramscheck(v, 1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - if(_array(*arr)->Size() > 0) { - if(pushval != 0){ v->Push(_array(*arr)->Top()); } - _array(*arr)->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("empty array")); -} - -SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize) -{ - sq_aux_paramscheck(v,1); - SQObjectPtr *arr; - _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); - if(_array(*arr)->Size() > 0) { - _array(*arr)->Resize(newsize); - return SQ_OK; - } - return SQ_OK; -} - -SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx) -{ - sq_aux_paramscheck(v, 1); - SQObjectPtr *o; - _GETSAFE_OBJ(v, idx, OT_ARRAY,o); - SQArray *arr = _array(*o); - if(arr->Size() > 0) { - SQObjectPtr t; - SQInteger size = arr->Size(); - SQInteger n = size >> 1; size -= 1; - for(SQInteger i = 0; i < n; i++) { - t = arr->_values[i]; - arr->_values[i] = arr->_values[size-i]; - arr->_values[size-i] = t; - } - return SQ_OK; - } - return SQ_OK; -} - -void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) -{ - SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func); - nc->_nparamscheck = 0; - for(SQUnsignedInteger i = 0; i < nfreevars; i++) { - nc->_outervalues.push_back(v->Top()); - v->Pop(); - } - v->Push(SQObjectPtr(nc)); -} - -SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) -{ - SQObject o = stack_get(v, idx); - if(sq_isclosure(o)) { - SQClosure *c = _closure(o); - SQFunctionProto *proto = _funcproto(c->_function); - *nparams = (SQUnsignedInteger)proto->_parameters.size(); - *nfreevars = (SQUnsignedInteger)c->_outervalues.size(); - return SQ_OK; - } - return sq_throwerror(v,_SC("the object is not a closure")); -} - -SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name) -{ - SQObject o = stack_get(v, idx); - if(sq_isnativeclosure(o)) { - SQNativeClosure *nc = _nativeclosure(o); - nc->_name = SQString::Create(_ss(v),name); - return SQ_OK; - } - return sq_throwerror(v,_SC("the object is not a nativeclosure")); -} - -SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask) -{ - SQObject o = stack_get(v, -1); - if(!sq_isnativeclosure(o)) - return sq_throwerror(v, _SC("native closure expected")); - SQNativeClosure *nc = _nativeclosure(o); - nc->_nparamscheck = nparamscheck; - if(typemask) { - SQIntVec res; - if(!CompileTypemask(res, typemask)) - return sq_throwerror(v, _SC("invalid typemask")); - nc->_typecheck.copy(res); - } - else { - nc->_typecheck.resize(0); - } - if(nparamscheck == SQ_MATCHTYPEMASKSTRING) { - nc->_nparamscheck = nc->_typecheck.size(); - } - return SQ_OK; -} - -SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &o = stack_get(v,idx); - if(!sq_isnativeclosure(o) && - !sq_isclosure(o)) - return sq_throwerror(v,_SC("the target is not a closure")); - SQObjectPtr &env = stack_get(v,-1); - if(!sq_istable(env) && - !sq_isclass(env) && - !sq_isinstance(env)) - return sq_throwerror(v,_SC("invalid environment")); - SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env)); - SQObjectPtr ret; - if(sq_isclosure(o)) { - SQClosure *c = _closure(o)->Clone(); - c->_env = w; - ret = c; - } - else { //then must be a native closure - SQNativeClosure *c = _nativeclosure(o)->Clone(); - c->_env = w; - ret = c; - } - v->Pop(); - v->Push(ret); - return SQ_OK; -} - -void sq_pushroottable(HSQUIRRELVM v) -{ - v->Push(v->_roottable); -} - -void sq_pushregistrytable(HSQUIRRELVM v) -{ - v->Push(_ss(v)->_registry); -} - -SQRESULT sq_setroottable(HSQUIRRELVM v) -{ - SQObject o = stack_get(v, -1); - if(sq_istable(o) || sq_isnull(o)) { - v->_roottable = o; - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v, _SC("ivalid type")); -} - -void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p) -{ - v->_foreignptr = p; -} - -SQUserPointer sq_getforeignptr(HSQUIRRELVM v) -{ - return v->_foreignptr; -} - -void sq_push(HSQUIRRELVM v,SQInteger idx) -{ - v->Push(stack_get(v, idx)); -} - -SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx) -{ - return type(stack_get(v, idx)); -} - -void sq_tostring(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &o = stack_get(v, idx); - SQObjectPtr res; - v->ToString(o,res); - v->Push(res); -} - -void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b) -{ - SQObjectPtr &o = stack_get(v, idx); - *b = v->IsFalse(o)?SQFalse:SQTrue; -} - -SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i) -{ - SQObjectPtr &o = stack_get(v, idx); - if(sq_isnumeric(o)) { - *i = tointeger(o); - return SQ_OK; - } - return SQ_ERROR; -} - -SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f) -{ - SQObjectPtr &o = stack_get(v, idx); - if(sq_isnumeric(o)) { - *f = tofloat(o); - return SQ_OK; - } - return SQ_ERROR; -} - -SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b) -{ - SQObjectPtr &o = stack_get(v, idx); - if(sq_isbool(o)) { - *b = _integer(o); - return SQ_OK; - } - return SQ_ERROR; -} - -SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_STRING,o); - *c = _stringval(*o); - return SQ_OK; -} - -SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_THREAD,o); - *thread = _thread(*o); - return SQ_OK; -} - -SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &o = stack_get(v,idx); - v->Push(_null_); - if(!v->Clone(o, stack_get(v, -1))){ - v->Pop(); - return sq_aux_invalidtype(v, type(o)); - } - return SQ_OK; -} - -SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) -{ - SQObjectPtr &o = stack_get(v, idx); - SQObjectType type = type(o); - switch(type) { - case OT_STRING: return _string(o)->_len; - case OT_TABLE: return _table(o)->CountUsed(); - case OT_ARRAY: return _array(o)->Size(); - case OT_USERDATA: return _userdata(o)->_size; - default: - return sq_aux_invalidtype(v, type); - } -} - -SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_USERDATA,o); - (*p) = _userdataval(*o); - if(typetag) *typetag = _userdata(*o)->_typetag; - return SQ_OK; -} - -SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag) -{ - SQObjectPtr &o = stack_get(v,idx); - switch(type(o)) { - case OT_USERDATA: _userdata(o)->_typetag = typetag; break; - case OT_CLASS: _class(o)->_typetag = typetag; break; - default: return sq_throwerror(v,_SC("invalid object type")); - } - return SQ_OK; -} - -SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag) -{ - switch(type(*o)) { - case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; - case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break; - case OT_CLASS: *typetag = _class(*o)->_typetag; break; - default: return SQ_ERROR; - } - return SQ_OK; -} - -SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag) -{ - SQObjectPtr &o = stack_get(v,idx); - if(SQ_FAILED(sq_getobjtypetag(&o,typetag))) - return sq_throwerror(v,_SC("invalid object type")); - return SQ_OK; -} - -SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); - (*p) = _userpointer(*o); - return SQ_OK; -} - -SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p) -{ - SQObjectPtr &o = stack_get(v,idx); - if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); - _instance(o)->_userpointer = p; - return SQ_OK; -} - -SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag) -{ - SQObjectPtr &o = stack_get(v,idx); - if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); - (*p) = _instance(o)->_userpointer; - if(typetag != 0) { - SQClass *cl = _instance(o)->_class; - do{ - if(cl->_typetag == typetag) - return SQ_OK; - cl = cl->_base; - }while(cl != NULL); - return sq_throwerror(v,_SC("invalid type tag")); - } - return SQ_OK; -} - -SQInteger sq_gettop(HSQUIRRELVM v) -{ - return (v->_top) - v->_stackbase; -} - -void sq_settop(HSQUIRRELVM v, SQInteger newtop) -{ - SQInteger top = sq_gettop(v); - if(top > newtop) - sq_pop(v, top - newtop); - else - while(top < newtop) sq_pushnull(v); -} - -void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop) -{ - assert(v->_top >= nelemstopop); - v->Pop(nelemstopop); -} - -void sq_poptop(HSQUIRRELVM v) -{ - assert(v->_top >= 1); - v->Pop(); -} - - -void sq_remove(HSQUIRRELVM v, SQInteger idx) -{ - v->Remove(idx); -} - -SQInteger sq_cmp(HSQUIRRELVM v) -{ - SQInteger res; - v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res); - return res; -} - -SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic) -{ - sq_aux_paramscheck(v, 3); - SQObjectPtr &self = stack_get(v, idx); - if(type(self) == OT_TABLE || type(self) == OT_CLASS) { - SQObjectPtr &key = v->GetUp(-2); - if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); - v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); - v->Pop(2); - } - return SQ_OK; -} - -/*SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx) -{ - sq_aux_paramscheck(v, 3); - SQObjectPtr &self = stack_get(v, idx); - if(type(self) == OT_TABLE || type(self) == OT_CLASS) { - SQObjectPtr &key = v->GetUp(-2); - if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); - v->NewSlot(self, key, v->GetUp(-1)); - v->Pop(2); - } - return SQ_OK; -}*/ - -SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) -{ - sq_aux_paramscheck(v, 2); - SQObjectPtr *self; - _GETSAFE_OBJ(v, idx, OT_TABLE,self); - SQObjectPtr &key = v->GetUp(-1); - if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); - SQObjectPtr res; - if(!v->DeleteSlot(*self, key, res)){ - return SQ_ERROR; - } - if(pushval) v->GetUp(-1) = res; - else v->Pop(1); - return SQ_OK; -} - -SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self = stack_get(v, idx); - if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { - v->Pop(2); - return SQ_OK; - } - v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; -} - -SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self = stack_get(v, idx); - if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key")); - switch(type(self)) { - case OT_TABLE: - _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1)); - v->Pop(2); - return SQ_OK; - break; - case OT_CLASS: - _class(self)->NewSlot(_ss(v), v->GetUp(-2), v->GetUp(-1),false); - v->Pop(2); - return SQ_OK; - break; - case OT_INSTANCE: - if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) { - v->Pop(2); - return SQ_OK; - } - break; - case OT_ARRAY: - if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { - v->Pop(2); - return SQ_OK; - } - break; - default: - v->Pop(2); - return sq_throwerror(v, _SC("rawset works only on array/table/calsse and instance")); - } - v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; -} - -SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self = stack_get(v, idx); - SQObjectPtr &mt = v->GetUp(-1); - SQObjectType type = type(self); - switch(type) { - case OT_TABLE: - if(type(mt) == OT_TABLE) { - if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();} - else if(type(mt)==OT_NULL) { - _table(self)->SetDelegate(NULL); v->Pop(); } - else return sq_aux_invalidtype(v,type); - break; - case OT_USERDATA: - if(type(mt)==OT_TABLE) { - _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } - else if(type(mt)==OT_NULL) { - _userdata(self)->SetDelegate(NULL); v->Pop(); } - else return sq_aux_invalidtype(v, type); - break; - default: - return sq_aux_invalidtype(v, type); - break; - } - return SQ_OK; -} - -SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) -{ - sq_aux_paramscheck(v, 2); - SQObjectPtr *self; - _GETSAFE_OBJ(v, idx, OT_TABLE,self); - SQObjectPtr &key = v->GetUp(-1); - SQObjectPtr t; - if(_table(*self)->Get(key,t)) { - _table(*self)->Remove(key); - } - if(pushval != 0) - if(pushval) v->GetUp(-1) = t; - else - v->Pop(1); - return SQ_OK; -} - -SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self=stack_get(v,idx); - switch(type(self)){ - case OT_TABLE: - if(!_table(self)->_delegate)break; - v->Push(SQObjectPtr(_table(self)->_delegate)); - break; - case OT_USERDATA: - if(!_userdata(self)->_delegate)break; - v->Push(SQObjectPtr(_userdata(self)->_delegate)); - break; - default: return sq_throwerror(v,_SC("wrong type")); break; - } - return SQ_OK; - -} - -SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self=stack_get(v,idx); - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) - return SQ_OK; - v->Pop(1); - return sq_throwerror(v,_SC("the index doesn't exist")); -} - -SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &self=stack_get(v,idx); - switch(type(self)) { - case OT_TABLE: - if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1))) - return SQ_OK; - break; - case OT_CLASS: - if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1))) - return SQ_OK; - break; - case OT_INSTANCE: - if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1))) - return SQ_OK; - break; - case OT_ARRAY: - if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) - return SQ_OK; - break; - default: - v->Pop(1); - return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); - } - v->Pop(1); - return sq_throwerror(v,_SC("the index doesn't exist")); -} - -SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po) -{ - *po=stack_get(v,idx); - return SQ_OK; -} - -const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx) -{ - SQUnsignedInteger cstksize=v->_callsstack.size(); - SQUnsignedInteger lvl=(cstksize-level)-1; - SQInteger stackbase=v->_stackbase; - if(lvl_callsstack[(cstksize-i)-1]; - stackbase-=ci._prevstkbase; - } - SQVM::CallInfo &ci=v->_callsstack[lvl]; - if(type(ci._closure)!=OT_CLOSURE) - return NULL; - SQClosure *c=_closure(ci._closure); - SQFunctionProto *func=_funcproto(c->_function); - return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions._vals)-1); - } - return NULL; -} - -void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj) -{ - v->Push(SQObjectPtr(obj)); -} - -void sq_resetobject(HSQOBJECT *po) -{ - po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; -} - -SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) -{ - v->_lasterror=SQString::Create(_ss(v),err); - return -1; -} - -void sq_reseterror(HSQUIRRELVM v) -{ - v->_lasterror = _null_; -} - -void sq_getlasterror(HSQUIRRELVM v) -{ - v->Push(v->_lasterror); -} - -void sq_reservestack(HSQUIRRELVM v,SQInteger nsize) -{ - if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { - v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); - } -} - -SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror) -{ - if(type(v->GetUp(-1))==OT_GENERATOR){ - v->Push(_null_); //retval - if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) - {v->Raise_Error(v->_lasterror); return SQ_ERROR;} - if(!retval) - v->Pop(); - return SQ_OK; - } - return sq_throwerror(v,_SC("only generators can be resumed")); -} - -SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror) -{ - SQObjectPtr res; - if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ - v->Pop(params);//pop closure and args - if(retval){ - v->Push(res); return SQ_OK; - } - return SQ_OK; - } - else { - v->Pop(params); - return SQ_ERROR; - } - if(!v->_suspended) - v->Pop(params); - return sq_throwerror(v,_SC("call failed")); -} - -SQRESULT sq_suspendvm(HSQUIRRELVM v) -{ - return v->Suspend(); -} - -SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror) -{ - SQObjectPtr ret; - if(!v->_suspended) - return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); - if(wakeupret) { - v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval - v->Pop(); - } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_; - if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM)) - return SQ_ERROR; - if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) { - while (v->_top > 1) v->_stack[--v->_top] = _null_; - } - if(retval) - v->Push(ret); - return SQ_OK; -} - -void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook) -{ - if(sq_gettop(v) >= 1){ - SQObjectPtr &ud=stack_get(v,idx); - switch( type(ud) ) { - case OT_USERDATA: _userdata(ud)->_hook = hook; break; - case OT_INSTANCE: _instance(ud)->_hook = hook; break; - case OT_CLASS: _class(ud)->_hook = hook; break; - default: break; //shutup compiler - } - } -} - -void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f) -{ - _ss(v)->_compilererrorhandler = f; -} - -SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); - unsigned short tag = SQ_BYTECODE_STREAM_TAG; - if(w(up,&tag,2) != 2) - return sq_throwerror(v,_SC("io error")); - if(!_closure(*o)->Save(v,up,w)) - return SQ_ERROR; - return SQ_OK; -} - -SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up) -{ - SQObjectPtr func=SQFunctionProto::Create(); - SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func)); - unsigned short tag; - if(r(up,&tag,2) != 2) - return sq_throwerror(v,_SC("io error")); - if(tag != SQ_BYTECODE_STREAM_TAG) - return sq_throwerror(v,_SC("invalid stream")); - if(!_closure(closure)->Load(v,up,r)) - return SQ_ERROR; - v->Push(closure); - return SQ_OK; -} - -SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize) -{ - return _ss(v)->GetScratchPad(minsize); -} - -SQInteger sq_collectgarbage(HSQUIRRELVM v) -{ -#ifndef NO_GARBAGE_COLLECTOR - return _ss(v)->CollectGarbage(v); -#else - return -1; -#endif -} - -const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) -{ - SQObjectPtr &self = stack_get(v,idx); - const SQChar *name = NULL; - if(type(self) == OT_CLOSURE) { - if(_closure(self)->_outervalues.size()>nval) { - v->Push(_closure(self)->_outervalues[nval]); - SQFunctionProto *fp = _funcproto(_closure(self)->_function); - SQOuterVar &ov = fp->_outervalues[nval]; - name = _stringval(ov._name); - } - } - return name; -} - -SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) -{ - SQObjectPtr &self=stack_get(v,idx); - switch(type(self)) - { - case OT_CLOSURE: - if(_closure(self)->_outervalues.size()>nval){ - _closure(self)->_outervalues[nval]=stack_get(v,-1); - } - else return sq_throwerror(v,_SC("invalid free var index")); - break; - case OT_NATIVECLOSURE: - if(_nativeclosure(self)->_outervalues.size()>nval){ - _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1); - } - else return sq_throwerror(v,_SC("invalid free var index")); - break; - default: - return sq_aux_invalidtype(v,type(self)); - } - v->Pop(1); - return SQ_OK; -} - -SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - SQObjectPtr &key = stack_get(v,-2); - SQObjectPtr &val = stack_get(v,-1); - SQObjectPtr attrs; - if(type(key) == OT_NULL) { - attrs = _class(*o)->_attributes; - _class(*o)->_attributes = val; - v->Pop(2); - v->Push(attrs); - return SQ_OK; - }else if(_class(*o)->GetAttributes(key,attrs)) { - _class(*o)->SetAttributes(key,val); - v->Pop(2); - v->Push(attrs); - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong index")); -} - -SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - SQObjectPtr &key = stack_get(v,-1); - SQObjectPtr attrs; - if(type(key) == OT_NULL) { - attrs = _class(*o)->_attributes; - v->Pop(); - v->Push(attrs); - return SQ_OK; - } - else if(_class(*o)->GetAttributes(key,attrs)) { - v->Pop(); - v->Push(attrs); - return SQ_OK; - } - return sq_throwerror(v,_SC("wrong index")); -} - -SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - if(_class(*o)->_base) - v->Push(SQObjectPtr(_class(*o)->_base)); - else - v->Push(_null_); - return SQ_OK; -} - -SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); - v->Push(SQObjectPtr(_instance(*o)->_class)); - return SQ_OK; -} - -SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr *o = NULL; - _GETSAFE_OBJ(v, idx, OT_CLASS,o); - v->Push(_class(*o)->CreateInstance()); - return SQ_OK; -} - -void sq_weakref(HSQUIRRELVM v,SQInteger idx) -{ - SQObject &o=stack_get(v,idx); - if(ISREFCOUNTED(type(o))) { - v->Push(_refcounted(o)->GetWeakRef(type(o))); - return; - } - v->Push(o); -} - -SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr &o = stack_get(v,idx); - if(type(o) != OT_WEAKREF) { - return sq_throwerror(v,_SC("the object must be a weakref")); - } - v->Push(_weakref(o)->_obj); - return SQ_OK; -} - -SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t) -{ - SQSharedState *ss = _ss(v); - switch(t) { - case OT_TABLE: v->Push(ss->_table_default_delegate); break; - case OT_ARRAY: v->Push(ss->_array_default_delegate); break; - case OT_STRING: v->Push(ss->_string_default_delegate); break; - case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break; - case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break; - case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break; - case OT_THREAD: v->Push(ss->_thread_default_delegate); break; - case OT_CLASS: v->Push(ss->_class_default_delegate); break; - case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break; - case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break; - default: return sq_throwerror(v,_SC("the type doesn't have a default delegate")); - } - return SQ_OK; -} - -SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx) -{ - SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val; - if(type(o) == OT_GENERATOR) { - return sq_throwerror(v,_SC("cannot iterate a generator")); - } - bool finished; - if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished)) - return SQ_ERROR; - if(!finished) { - v->Push(realkey); - v->Push(val); - return SQ_OK; - } - return SQ_ERROR; -} - -struct BufState{ - const SQChar *buf; - SQInteger ptr; - SQInteger size; -}; - -SQInteger buf_lexfeed(SQUserPointer file) -{ - BufState *buf=(BufState*)file; - if(buf->size<(buf->ptr+1)) - return 0; - return buf->buf[buf->ptr++]; -} - -SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) { - BufState buf; - buf.buf = s; - buf.size = size; - buf.ptr = 0; - return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror); -} - -void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx) -{ - dest->Push(stack_get(src,idx)); -} - -void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc) -{ - _ss(v)->_printfunc = printfunc; -} - -SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) -{ - return _ss(v)->_printfunc; -} - -void *sq_malloc(SQUnsignedInteger size) -{ - return SQ_MALLOC(size); -} - -void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize) -{ - return SQ_REALLOC(p,oldsize,newsize); -} -void sq_free(void *p,SQUnsignedInteger size) -{ - SQ_FREE(p,size); -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "squserdata.h" +#include "sqcompiler.h" +#include "sqfuncstate.h" +#include "sqclass.h" + +bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o) +{ + *o = &stack_get(v,idx); + if(type(**o) != type){ + SQObjectPtr oval = v->PrintObjVal(**o); + v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval)); + return false; + } + return true; +} + +#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; } + +#define sq_aux_paramscheck(v,count) \ +{ \ + if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ +} + +SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e) +{ + v->_lasterror = e; + return SQ_ERROR; +} + +SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type) +{ + scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type)); + return sq_throwerror(v, _ss(v)->GetScratchPad(-1)); +} + +HSQUIRRELVM sq_open(SQInteger initialstacksize) +{ + SQSharedState *ss; + SQVM *v; + sq_new(ss, SQSharedState); + ss->Init(); + v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); + ss->_root_vm = v; + if(v->Init(NULL, initialstacksize)) { + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } + return v; +} + +HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize) +{ + SQSharedState *ss; + SQVM *v; + ss=_ss(friendvm); + + v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); + + if(v->Init(friendvm, initialstacksize)) { + friendvm->Push(v); + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } +} + +SQInteger sq_getvmstate(HSQUIRRELVM v) +{ + if(v->_suspended) + return SQ_VMSTATE_SUSPENDED; + else { + if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING; + else return SQ_VMSTATE_IDLE; + } +} + +void sq_seterrorhandler(HSQUIRRELVM v) +{ + SQObject o = stack_get(v, -1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_errorhandler = o; + v->Pop(); + } +} + +void sq_setdebughook(HSQUIRRELVM v) +{ + SQObject o = stack_get(v,-1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_debughook = o; + v->Pop(); + } +} + +void sq_close(HSQUIRRELVM v) +{ + SQSharedState *ss = _ss(v); + _thread(ss->_root_vm)->Finalize(); + sq_delete(ss, SQSharedState); +} + +SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) +{ + SQObjectPtr o; + if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { + v->Push(SQClosure::Create(_ss(v), _funcproto(o))); + return SQ_OK; + } + return SQ_ERROR; +} + +void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) +{ + _ss(v)->_debuginfo = enable?true:false; +} + +void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable) +{ + _ss(v)->_notifyallexceptions = enable?true:false; +} + +void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return; + _ss(v)->_refs_table.AddRef(*po); +} + +SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return SQTrue; + return _ss(v)->_refs_table.Release(*po); +} + +const SQChar *sq_objtostring(HSQOBJECT *o) +{ + if(sq_type(*o) == OT_STRING) { + return _stringval(*o); + } + return NULL; +} + +SQInteger sq_objtointeger(HSQOBJECT *o) +{ + if(sq_isnumeric(*o)) { + return tointeger(*o); + } + return 0; +} + +SQFloat sq_objtofloat(HSQOBJECT *o) +{ + if(sq_isnumeric(*o)) { + return tofloat(*o); + } + return 0; +} + +SQBool sq_objtobool(HSQOBJECT *o) +{ + if(sq_isbool(*o)) { + return _integer(*o); + } + return SQFalse; +} + +void sq_pushnull(HSQUIRRELVM v) +{ + v->Push(_null_); +} + +void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len) +{ + if(s) + v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); + else v->Push(_null_); +} + +void sq_pushinteger(HSQUIRRELVM v,SQInteger n) +{ + v->Push(n); +} + +void sq_pushbool(HSQUIRRELVM v,SQBool b) +{ + v->Push(b?true:false); +} + +void sq_pushfloat(HSQUIRRELVM v,SQFloat n) +{ + v->Push(n); +} + +void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p) +{ + v->Push(p); +} + +SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size) +{ + SQUserData *ud = SQUserData::Create(_ss(v), size); + v->Push(ud); + return ud->_val; +} + +void sq_newtable(HSQUIRRELVM v) +{ + v->Push(SQTable::Create(_ss(v), 0)); +} + +void sq_newarray(HSQUIRRELVM v,SQInteger size) +{ + v->Push(SQArray::Create(_ss(v), size)); +} + +SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) +{ + SQClass *baseclass = NULL; + if(hasbase) { + SQObjectPtr &base = stack_get(v,-1); + if(type(base) != OT_CLASS) + return sq_throwerror(v,_SC("invalid base type")); + baseclass = _class(base); + } + SQClass *newclass = SQClass::Create(_ss(v), baseclass); + if(baseclass) v->Pop(); + v->Push(newclass); + return SQ_OK; +} + +SQBool sq_instanceof(HSQUIRRELVM v) +{ + SQObjectPtr &inst = stack_get(v,-1); + SQObjectPtr &cl = stack_get(v,-2); + if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS) + return sq_throwerror(v,_SC("invalid param type")); + return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse; +} + +SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx) +{ + sq_aux_paramscheck(v,2); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + _array(*arr)->Append(v->GetUp(-1)); + v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(_array(*arr)->Size() > 0) { + if(pushval != 0){ v->Push(_array(*arr)->Top()); } + _array(*arr)->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("empty array")); +} + +SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize) +{ + sq_aux_paramscheck(v,1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(_array(*arr)->Size() > 0) { + _array(*arr)->Resize(newsize); + return SQ_OK; + } + return SQ_OK; +} + +SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *o; + _GETSAFE_OBJ(v, idx, OT_ARRAY,o); + SQArray *arr = _array(*o); + if(arr->Size() > 0) { + SQObjectPtr t; + SQInteger size = arr->Size(); + SQInteger n = size >> 1; size -= 1; + for(SQInteger i = 0; i < n; i++) { + t = arr->_values[i]; + arr->_values[i] = arr->_values[size-i]; + arr->_values[size-i] = t; + } + return SQ_OK; + } + return SQ_OK; +} + +void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) +{ + SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func); + nc->_nparamscheck = 0; + for(SQUnsignedInteger i = 0; i < nfreevars; i++) { + nc->_outervalues.push_back(v->Top()); + v->Pop(); + } + v->Push(SQObjectPtr(nc)); +} + +SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) +{ + SQObject o = stack_get(v, idx); + if(sq_isclosure(o)) { + SQClosure *c = _closure(o); + SQFunctionProto *proto = _funcproto(c->_function); + *nparams = (SQUnsignedInteger)proto->_parameters.size(); + *nfreevars = (SQUnsignedInteger)c->_outervalues.size(); + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a closure")); +} + +SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name) +{ + SQObject o = stack_get(v, idx); + if(sq_isnativeclosure(o)) { + SQNativeClosure *nc = _nativeclosure(o); + nc->_name = SQString::Create(_ss(v),name); + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a nativeclosure")); +} + +SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask) +{ + SQObject o = stack_get(v, -1); + if(!sq_isnativeclosure(o)) + return sq_throwerror(v, _SC("native closure expected")); + SQNativeClosure *nc = _nativeclosure(o); + nc->_nparamscheck = nparamscheck; + if(typemask) { + SQIntVec res; + if(!CompileTypemask(res, typemask)) + return sq_throwerror(v, _SC("invalid typemask")); + nc->_typecheck.copy(res); + } + else { + nc->_typecheck.resize(0); + } + if(nparamscheck == SQ_MATCHTYPEMASKSTRING) { + nc->_nparamscheck = nc->_typecheck.size(); + } + return SQ_OK; +} + +SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + SQObjectPtr &env = stack_get(v,-1); + if(!sq_istable(env) && + !sq_isclass(env) && + !sq_isinstance(env)) + return sq_throwerror(v,_SC("invalid environment")); + SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env)); + SQObjectPtr ret; + if(sq_isclosure(o)) { + SQClosure *c = _closure(o)->Clone(); + c->_env = w; + ret = c; + } + else { //then must be a native closure + SQNativeClosure *c = _nativeclosure(o)->Clone(); + c->_env = w; + ret = c; + } + v->Pop(); + v->Push(ret); + return SQ_OK; +} + +void sq_pushroottable(HSQUIRRELVM v) +{ + v->Push(v->_roottable); +} + +void sq_pushregistrytable(HSQUIRRELVM v) +{ + v->Push(_ss(v)->_registry); +} + +SQRESULT sq_setroottable(HSQUIRRELVM v) +{ + SQObject o = stack_get(v, -1); + if(sq_istable(o) || sq_isnull(o)) { + v->_roottable = o; + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("ivalid type")); +} + +void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p) +{ + v->_foreignptr = p; +} + +SQUserPointer sq_getforeignptr(HSQUIRRELVM v) +{ + return v->_foreignptr; +} + +void sq_push(HSQUIRRELVM v,SQInteger idx) +{ + v->Push(stack_get(v, idx)); +} + +SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx) +{ + return type(stack_get(v, idx)); +} + +void sq_tostring(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + v->ToString(o,res); + v->Push(res); +} + +void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b) +{ + SQObjectPtr &o = stack_get(v, idx); + *b = v->IsFalse(o)?SQFalse:SQTrue; +} + +SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *i = tointeger(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *f = tofloat(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isbool(o)) { + *b = _integer(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_STRING,o); + *c = _stringval(*o); + return SQ_OK; +} + +SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_THREAD,o); + *thread = _thread(*o); + return SQ_OK; +} + +SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + v->Push(_null_); + if(!v->Clone(o, stack_get(v, -1))){ + v->Pop(); + return sq_aux_invalidtype(v, type(o)); + } + return SQ_OK; +} + +SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectType type = type(o); + switch(type) { + case OT_STRING: return _string(o)->_len; + case OT_TABLE: return _table(o)->CountUsed(); + case OT_ARRAY: return _array(o)->Size(); + case OT_USERDATA: return _userdata(o)->_size; + default: + return sq_aux_invalidtype(v, type); + } +} + +SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERDATA,o); + (*p) = _userdataval(*o); + if(typetag) *typetag = _userdata(*o)->_typetag; + return SQ_OK; +} + +SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + switch(type(o)) { + case OT_USERDATA: _userdata(o)->_typetag = typetag; break; + case OT_CLASS: _class(o)->_typetag = typetag; break; + default: return sq_throwerror(v,_SC("invalid object type")); + } + return SQ_OK; +} + +SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag) +{ + switch(type(*o)) { + case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; + case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break; + case OT_CLASS: *typetag = _class(*o)->_typetag; break; + default: return SQ_ERROR; + } + return SQ_OK; +} + +SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + if(SQ_FAILED(sq_getobjtypetag(&o,typetag))) + return sq_throwerror(v,_SC("invalid object type")); + return SQ_OK; +} + +SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); + (*p) = _userpointer(*o); + return SQ_OK; +} + +SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + _instance(o)->_userpointer = p; + return SQ_OK; +} + +SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + (*p) = _instance(o)->_userpointer; + if(typetag != 0) { + SQClass *cl = _instance(o)->_class; + do{ + if(cl->_typetag == typetag) + return SQ_OK; + cl = cl->_base; + }while(cl != NULL); + return sq_throwerror(v,_SC("invalid type tag")); + } + return SQ_OK; +} + +SQInteger sq_gettop(HSQUIRRELVM v) +{ + return (v->_top) - v->_stackbase; +} + +void sq_settop(HSQUIRRELVM v, SQInteger newtop) +{ + SQInteger top = sq_gettop(v); + if(top > newtop) + sq_pop(v, top - newtop); + else + while(top < newtop) sq_pushnull(v); +} + +void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop) +{ + assert(v->_top >= nelemstopop); + v->Pop(nelemstopop); +} + +void sq_poptop(HSQUIRRELVM v) +{ + assert(v->_top >= 1); + v->Pop(); +} + + +void sq_remove(HSQUIRRELVM v, SQInteger idx) +{ + v->Remove(idx); +} + +SQInteger sq_cmp(HSQUIRRELVM v) +{ + SQInteger res; + v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res); + return res; +} + +SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic) +{ + sq_aux_paramscheck(v, 3); + SQObjectPtr &self = stack_get(v, idx); + if(type(self) == OT_TABLE || type(self) == OT_CLASS) { + SQObjectPtr &key = v->GetUp(-2); + if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); + v->Pop(2); + } + return SQ_OK; +} + +/*SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx) +{ + sq_aux_paramscheck(v, 3); + SQObjectPtr &self = stack_get(v, idx); + if(type(self) == OT_TABLE || type(self) == OT_CLASS) { + SQObjectPtr &key = v->GetUp(-2); + if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + v->NewSlot(self, key, v->GetUp(-1)); + v->Pop(2); + } + return SQ_OK; +}*/ + +SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + SQObjectPtr res; + if(!v->DeleteSlot(*self, key, res)){ + return SQ_ERROR; + } + if(pushval) v->GetUp(-1) = res; + else v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + v->Pop(2); + return SQ_OK; + } + v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; +} + +SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + switch(type(self)) { + case OT_TABLE: + _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1)); + v->Pop(2); + return SQ_OK; + break; + case OT_CLASS: + _class(self)->NewSlot(_ss(v), v->GetUp(-2), v->GetUp(-1),false); + v->Pop(2); + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) { + v->Pop(2); + return SQ_OK; + } + break; + case OT_ARRAY: + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + v->Pop(2); + return SQ_OK; + } + break; + default: + v->Pop(2); + return sq_throwerror(v, _SC("rawset works only on array/table/calsse and instance")); + } + v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; +} + +SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + SQObjectPtr &mt = v->GetUp(-1); + SQObjectType type = type(self); + switch(type) { + case OT_TABLE: + if(type(mt) == OT_TABLE) { + if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();} + else if(type(mt)==OT_NULL) { + _table(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v,type); + break; + case OT_USERDATA: + if(type(mt)==OT_TABLE) { + _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } + else if(type(mt)==OT_NULL) { + _userdata(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v, type); + break; + default: + return sq_aux_invalidtype(v, type); + break; + } + return SQ_OK; +} + +SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + SQObjectPtr t; + if(_table(*self)->Get(key,t)) { + _table(*self)->Remove(key); + } + if(pushval != 0) + if(pushval) v->GetUp(-1) = t; + else + v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)){ + case OT_TABLE: + if(!_table(self)->_delegate)break; + v->Push(SQObjectPtr(_table(self)->_delegate)); + break; + case OT_USERDATA: + if(!_userdata(self)->_delegate)break; + v->Push(SQObjectPtr(_userdata(self)->_delegate)); + break; + default: return sq_throwerror(v,_SC("wrong type")); break; + } + return SQ_OK; + +} + +SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + return SQ_OK; + v->Pop(1); + return sq_throwerror(v,_SC("the index doesn't exist")); +} + +SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)) { + case OT_TABLE: + if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_CLASS: + if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_ARRAY: + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + return SQ_OK; + break; + default: + v->Pop(1); + return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); + } + v->Pop(1); + return sq_throwerror(v,_SC("the index doesn't exist")); +} + +SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po) +{ + *po=stack_get(v,idx); + return SQ_OK; +} + +const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx) +{ + SQUnsignedInteger cstksize=v->_callsstack.size(); + SQUnsignedInteger lvl=(cstksize-level)-1; + SQInteger stackbase=v->_stackbase; + if(lvl_callsstack[(cstksize-i)-1]; + stackbase-=ci._prevstkbase; + } + SQVM::CallInfo &ci=v->_callsstack[lvl]; + if(type(ci._closure)!=OT_CLOSURE) + return NULL; + SQClosure *c=_closure(ci._closure); + SQFunctionProto *func=_funcproto(c->_function); + return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions._vals)-1); + } + return NULL; +} + +void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj) +{ + v->Push(SQObjectPtr(obj)); +} + +void sq_resetobject(HSQOBJECT *po) +{ + po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; +} + +SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) +{ + v->_lasterror=SQString::Create(_ss(v),err); + return -1; +} + +void sq_reseterror(HSQUIRRELVM v) +{ + v->_lasterror = _null_; +} + +void sq_getlasterror(HSQUIRRELVM v) +{ + v->Push(v->_lasterror); +} + +void sq_reservestack(HSQUIRRELVM v,SQInteger nsize) +{ + if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { + v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); + } +} + +SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror) +{ + if(type(v->GetUp(-1))==OT_GENERATOR){ + v->Push(_null_); //retval + if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) + {v->Raise_Error(v->_lasterror); return SQ_ERROR;} + if(!retval) + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("only generators can be resumed")); +} + +SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror) +{ + SQObjectPtr res; + if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){ + v->Pop(params);//pop closure and args + if(retval){ + v->Push(res); return SQ_OK; + } + return SQ_OK; + } + else { + v->Pop(params); + return SQ_ERROR; + } + if(!v->_suspended) + v->Pop(params); + return sq_throwerror(v,_SC("call failed")); +} + +SQRESULT sq_suspendvm(HSQUIRRELVM v) +{ + return v->Suspend(); +} + +SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror) +{ + SQObjectPtr ret; + if(!v->_suspended) + return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); + if(wakeupret) { + v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + v->Pop(); + } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_; + if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM)) + return SQ_ERROR; + if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) { + while (v->_top > 1) v->_stack[--v->_top] = _null_; + } + if(retval) + v->Push(ret); + return SQ_OK; +} + +void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook) +{ + if(sq_gettop(v) >= 1){ + SQObjectPtr &ud=stack_get(v,idx); + switch( type(ud) ) { + case OT_USERDATA: _userdata(ud)->_hook = hook; break; + case OT_INSTANCE: _instance(ud)->_hook = hook; break; + case OT_CLASS: _class(ud)->_hook = hook; break; + default: break; //shutup compiler + } + } +} + +void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f) +{ + _ss(v)->_compilererrorhandler = f; +} + +SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); + unsigned short tag = SQ_BYTECODE_STREAM_TAG; + if(w(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(!_closure(*o)->Save(v,up,w)) + return SQ_ERROR; + return SQ_OK; +} + +SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up) +{ + SQObjectPtr func=SQFunctionProto::Create(); + SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func)); + unsigned short tag; + if(r(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(tag != SQ_BYTECODE_STREAM_TAG) + return sq_throwerror(v,_SC("invalid stream")); + if(!_closure(closure)->Load(v,up,r)) + return SQ_ERROR; + v->Push(closure); + return SQ_OK; +} + +SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize) +{ + return _ss(v)->GetScratchPad(minsize); +} + +SQInteger sq_collectgarbage(HSQUIRRELVM v) +{ +#ifndef NO_GARBAGE_COLLECTOR + return _ss(v)->CollectGarbage(v); +#else + return -1; +#endif +} + +const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) +{ + SQObjectPtr &self = stack_get(v,idx); + const SQChar *name = NULL; + if(type(self) == OT_CLOSURE) { + if(_closure(self)->_outervalues.size()>nval) { + v->Push(_closure(self)->_outervalues[nval]); + SQFunctionProto *fp = _funcproto(_closure(self)->_function); + SQOuterVar &ov = fp->_outervalues[nval]; + name = _stringval(ov._name); + } + } + return name; +} + +SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)) + { + case OT_CLOSURE: + if(_closure(self)->_outervalues.size()>nval){ + _closure(self)->_outervalues[nval]=stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + break; + case OT_NATIVECLOSURE: + if(_nativeclosure(self)->_outervalues.size()>nval){ + _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + break; + default: + return sq_aux_invalidtype(v,type(self)); + } + v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-2); + SQObjectPtr &val = stack_get(v,-1); + SQObjectPtr attrs; + if(type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + _class(*o)->_attributes = val; + v->Pop(2); + v->Push(attrs); + return SQ_OK; + }else if(_class(*o)->GetAttributes(key,attrs)) { + _class(*o)->SetAttributes(key,val); + v->Pop(2); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQObjectPtr attrs; + if(type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + else if(_class(*o)->GetAttributes(key,attrs)) { + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + if(_class(*o)->_base) + v->Push(SQObjectPtr(_class(*o)->_base)); + else + v->Push(_null_); + return SQ_OK; +} + +SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); + v->Push(SQObjectPtr(_instance(*o)->_class)); + return SQ_OK; +} + +SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + v->Push(_class(*o)->CreateInstance()); + return SQ_OK; +} + +void sq_weakref(HSQUIRRELVM v,SQInteger idx) +{ + SQObject &o=stack_get(v,idx); + if(ISREFCOUNTED(type(o))) { + v->Push(_refcounted(o)->GetWeakRef(type(o))); + return; + } + v->Push(o); +} + +SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_WEAKREF) { + return sq_throwerror(v,_SC("the object must be a weakref")); + } + v->Push(_weakref(o)->_obj); + return SQ_OK; +} + +SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t) +{ + SQSharedState *ss = _ss(v); + switch(t) { + case OT_TABLE: v->Push(ss->_table_default_delegate); break; + case OT_ARRAY: v->Push(ss->_array_default_delegate); break; + case OT_STRING: v->Push(ss->_string_default_delegate); break; + case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break; + case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break; + case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break; + case OT_THREAD: v->Push(ss->_thread_default_delegate); break; + case OT_CLASS: v->Push(ss->_class_default_delegate); break; + case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break; + case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break; + default: return sq_throwerror(v,_SC("the type doesn't have a default delegate")); + } + return SQ_OK; +} + +SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val; + if(type(o) == OT_GENERATOR) { + return sq_throwerror(v,_SC("cannot iterate a generator")); + } + bool finished; + if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished)) + return SQ_ERROR; + if(!finished) { + v->Push(realkey); + v->Push(val); + return SQ_OK; + } + return SQ_ERROR; +} + +struct BufState{ + const SQChar *buf; + SQInteger ptr; + SQInteger size; +}; + +SQInteger buf_lexfeed(SQUserPointer file) +{ + BufState *buf=(BufState*)file; + if(buf->size<(buf->ptr+1)) + return 0; + return buf->buf[buf->ptr++]; +} + +SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) { + BufState buf; + buf.buf = s; + buf.size = size; + buf.ptr = 0; + return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror); +} + +void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx) +{ + dest->Push(stack_get(src,idx)); +} + +void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc) +{ + _ss(v)->_printfunc = printfunc; +} + +SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) +{ + return _ss(v)->_printfunc; +} + +void *sq_malloc(SQUnsignedInteger size) +{ + return SQ_MALLOC(size); +} + +void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize) +{ + return SQ_REALLOC(p,oldsize,newsize); +} +void sq_free(void *p,SQUnsignedInteger size) +{ + SQ_FREE(p,size); +} diff --git a/src/squirrel/squirrel/sqarray.h b/src/squirrel/squirrel/sqarray.h index b463e8162..451b07db8 100644 --- a/src/squirrel/squirrel/sqarray.h +++ b/src/squirrel/squirrel/sqarray.h @@ -1,79 +1,79 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQARRAY_H_ -#define _SQARRAY_H_ - -struct SQArray : public CHAINABLE_OBJ -{ -private: - SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} - ~SQArray() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } -public: - static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){ - SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray)); - new (newarray) SQArray(ss,nInitialSize); - return newarray; - } -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); -#endif - void Finalize(){ - _values.resize(0); - } - bool Get(const SQInteger nidx,SQObjectPtr &val) - { - if(nidx>=0 && nidx<(SQInteger)_values.size()){ - SQObjectPtr &o = _values[nidx]; - val = _realval(o); - return true; - } - else return false; - } - bool Set(const SQInteger nidx,const SQObjectPtr &val) - { - if(nidx>=0 && nidx<(SQInteger)_values.size()){ - _values[nidx]=val; - return true; - } - else return false; - } - SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval) - { - SQUnsignedInteger idx=TranslateIndex(refpos); - while(idx<_values.size()){ - //first found - outkey=(SQInteger)idx; - SQObjectPtr &o = _values[idx]; - outval = _realval(o); - //return idx for the next iteration - return ++idx; - } - //nothing to iterate anymore - return -1; - } - SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; } - SQInteger Size() const {return _values.size();} - void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); } - void Reserve(SQInteger size) { _values.reserve(size); } - void Append(const SQObject &o){_values.push_back(o);} - void Extend(const SQArray *a); - SQObjectPtr &Top(){return _values.top();} - void Pop(){_values.pop_back(); ShrinkIfNeeded(); } - void Insert(const SQObject& idx,const SQObject &val){_values.insert((SQUnsignedInteger)tointeger(idx),val);} - void ShrinkIfNeeded() { - if(_values.size() <= _values.capacity()>>2) //shrink the array - _values.shrinktofit(); - } - void Remove(SQUnsignedInteger idx){ - _values.remove(idx); - ShrinkIfNeeded(); - } - void Release() - { - sq_delete(this,SQArray); - } - SQObjectPtrVec _values; -}; -#endif //_SQARRAY_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQARRAY_H_ +#define _SQARRAY_H_ + +struct SQArray : public CHAINABLE_OBJ +{ +private: + SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + ~SQArray() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } +public: + static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){ + SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray)); + new (newarray) SQArray(ss,nInitialSize); + return newarray; + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(){ + _values.resize(0); + } + bool Get(const SQInteger nidx,SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + SQObjectPtr &o = _values[nidx]; + val = _realval(o); + return true; + } + else return false; + } + bool Set(const SQInteger nidx,const SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + _values[nidx]=val; + return true; + } + else return false; + } + SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval) + { + SQUnsignedInteger idx=TranslateIndex(refpos); + while(idx<_values.size()){ + //first found + outkey=(SQInteger)idx; + SQObjectPtr &o = _values[idx]; + outval = _realval(o); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; + } + SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; } + SQInteger Size() const {return _values.size();} + void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); } + void Reserve(SQInteger size) { _values.reserve(size); } + void Append(const SQObject &o){_values.push_back(o);} + void Extend(const SQArray *a); + SQObjectPtr &Top(){return _values.top();} + void Pop(){_values.pop_back(); ShrinkIfNeeded(); } + void Insert(const SQObject& idx,const SQObject &val){_values.insert((SQUnsignedInteger)tointeger(idx),val);} + void ShrinkIfNeeded() { + if(_values.size() <= _values.capacity()>>2) //shrink the array + _values.shrinktofit(); + } + void Remove(SQUnsignedInteger idx){ + _values.remove(idx); + ShrinkIfNeeded(); + } + void Release() + { + sq_delete(this,SQArray); + } + SQObjectPtrVec _values; +}; +#endif //_SQARRAY_H_ diff --git a/src/squirrel/squirrel/sqbaselib.cpp b/src/squirrel/squirrel/sqbaselib.cpp index b8d342143..cc8b3682e 100644 --- a/src/squirrel/squirrel/sqbaselib.cpp +++ b/src/squirrel/squirrel/sqbaselib.cpp @@ -1,862 +1,860 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqvm.h" -#include "sqstring.h" -#include "sqtable.h" -#include "sqarray.h" -#include "sqfuncproto.h" -#include "sqclosure.h" -#include "sqclass.h" -#include -#include -#include - -bool str2num(const SQChar *s,SQObjectPtr &res) -{ - SQChar *end; - if(scstrstr(s,_SC("."))){ - SQFloat r = SQFloat(scstrtod(s,&end)); - if(s == end) return false; - res = r; - return true; - } - else{ - SQInteger r = SQInteger(scstrtol(s,&end,10)); - if(s == end) return false; - res = r; - return true; - } -} - -#ifndef NO_GARBAGE_COLLECTOR -static SQInteger base_collectgarbage(HSQUIRRELVM v) -{ - sq_pushinteger(v, sq_collectgarbage(v)); - return 1; -} -#endif - -static SQInteger base_getroottable(HSQUIRRELVM v) -{ - v->Push(v->_roottable); - return 1; -} - -static SQInteger base_setroottable(HSQUIRRELVM v) -{ - SQObjectPtr &o=stack_get(v,2); - if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; - v->Push(o); - return 1; -} - -static SQInteger base_seterrorhandler(HSQUIRRELVM v) -{ - sq_seterrorhandler(v); - return 0; -} - -static SQInteger base_setdebughook(HSQUIRRELVM v) -{ - sq_setdebughook(v); - return 0; -} - -static SQInteger base_enabledebuginfo(HSQUIRRELVM v) -{ - SQObjectPtr &o=stack_get(v,2); - sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0); - return 0; -} - -static SQInteger base_getstackinfos(HSQUIRRELVM v) -{ - SQInteger level; - SQStackInfos si; - SQInteger seq = 0; - const SQChar *name = NULL; - sq_getinteger(v, -1, &level); - if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) - { - const SQChar *fn = _SC("unknown"); - const SQChar *src = _SC("unknown"); - if(si.funcname)fn = si.funcname; - if(si.source)src = si.source; - sq_newtable(v); - sq_pushstring(v, _SC("func"), -1); - sq_pushstring(v, fn, -1); - sq_createslot(v, -3); - sq_pushstring(v, _SC("src"), -1); - sq_pushstring(v, src, -1); - sq_createslot(v, -3); - sq_pushstring(v, _SC("line"), -1); - sq_pushinteger(v, si.line); - sq_createslot(v, -3); - sq_pushstring(v, _SC("locals"), -1); - sq_newtable(v); - seq=0; - while ((name = sq_getlocal(v, level, seq))) { - sq_pushstring(v, name, -1); - sq_push(v, -2); - sq_createslot(v, -4); - sq_pop(v, 1); - seq++; - } - sq_createslot(v, -3); - return 1; - } - - return 0; -} - -static SQInteger base_assert(HSQUIRRELVM v) -{ - if(v->IsFalse(stack_get(v,2))){ - return sq_throwerror(v,_SC("assertion failed")); - } - return 0; -} - -static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o) -{ - SQInteger top = sq_gettop(v); - sidx=0; - eidx=0; - o=stack_get(v,1); - SQObjectPtr &start=stack_get(v,2); - if(type(start)!=OT_NULL && sq_isnumeric(start)){ - sidx=tointeger(start); - } - if(top>2){ - SQObjectPtr &end=stack_get(v,3); - if(sq_isnumeric(end)){ - eidx=tointeger(end); - } - } - else { - eidx = sq_getsize(v,1); - } - return 1; -} - -static SQInteger base_print(HSQUIRRELVM v) -{ - const SQChar *str; - sq_tostring(v,2); - sq_getstring(v,-1,&str); - if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str); - return 0; -} - -static SQInteger base_compilestring(HSQUIRRELVM v) -{ - SQInteger nargs=sq_gettop(v); - const SQChar *src=NULL,*name=_SC("unnamedbuffer"); - SQInteger size; - sq_getstring(v,2,&src); - size=sq_getsize(v,2); - if(nargs>2){ - sq_getstring(v,3,&name); - } - if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse))) - return 1; - else - return SQ_ERROR; -} - -static SQInteger base_newthread(HSQUIRRELVM v) -{ - SQObjectPtr &func = stack_get(v,2); - SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2; - HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); - sq_move(newv,v,-2); - return 1; -} - -static SQInteger base_suspend(HSQUIRRELVM v) -{ - return sq_suspendvm(v); -} - -static SQInteger base_array(HSQUIRRELVM v) -{ - SQArray *a; - SQObject &size = stack_get(v,2); - if(sq_gettop(v) > 2) { - a = SQArray::Create(_ss(v),0); - a->Resize(tointeger(size),stack_get(v,3)); - } - else { - a = SQArray::Create(_ss(v),tointeger(size)); - } - v->Push(a); - return 1; -} - -static SQInteger base_type(HSQUIRRELVM v) -{ - SQObjectPtr &o = stack_get(v,2); - v->Push(SQString::Create(_ss(v),GetTypeName(o),-1)); - return 1; -} - -static SQRegFunction base_funcs[]={ - //generic - {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, - {_SC("setdebughook"),base_setdebughook,2, NULL}, - {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL}, - {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")}, - {_SC("getroottable"),base_getroottable,1, NULL}, - {_SC("setroottable"),base_setroottable,2, NULL}, - {_SC("assert"),base_assert,2, NULL}, - {_SC("print"),base_print,2, NULL}, - {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, - {_SC("newthread"),base_newthread,2, _SC(".c")}, - {_SC("suspend"),base_suspend,-1, NULL}, - {_SC("array"),base_array,-2, _SC(".n")}, - {_SC("type"),base_type,2, NULL}, -#ifndef NO_GARBAGE_COLLECTOR - {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")}, -#endif - {0,0} -}; - -void sq_base_register(HSQUIRRELVM v) -{ - SQInteger i=0; - sq_pushroottable(v); - while(base_funcs[i].name!=0) { - sq_pushstring(v,base_funcs[i].name,-1); - sq_newclosure(v,base_funcs[i].f,0); - sq_setnativeclosurename(v,-1,base_funcs[i].name); - sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); - sq_createslot(v,-3); - i++; - } - sq_pushstring(v,_SC("_charsize_"),-1); - sq_pushinteger(v,sizeof(SQChar)); - sq_createslot(v,-3); - sq_pushstring(v,_SC("_intsize_"),-1); - sq_pushinteger(v,sizeof(SQInteger)); - sq_createslot(v,-3); - sq_pop(v,1); -} - -static SQInteger default_delegate_len(HSQUIRRELVM v) -{ - v->Push(SQInteger(sq_getsize(v,1))); - return 1; -} - -static SQInteger default_delegate_tofloat(HSQUIRRELVM v) -{ - SQObjectPtr &o=stack_get(v,1); - switch(type(o)){ - case OT_STRING:{ - SQObjectPtr res; - if(str2num(_stringval(o),res)){ - v->Push(SQObjectPtr(tofloat(res))); - break; - }} - return sq_throwerror(v, _SC("cannot convert the string")); - break; - case OT_INTEGER:case OT_FLOAT: - v->Push(SQObjectPtr(tofloat(o))); - break; - case OT_BOOL: - v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); - break; - default: - v->Push(_null_); - break; - } - return 1; -} - -static SQInteger default_delegate_tointeger(HSQUIRRELVM v) -{ - SQObjectPtr &o=stack_get(v,1); - switch(type(o)){ - case OT_STRING:{ - SQObjectPtr res; - if(str2num(_stringval(o),res)){ - v->Push(SQObjectPtr(tointeger(res))); - break; - }} - return sq_throwerror(v, _SC("cannot convert the string")); - break; - case OT_INTEGER:case OT_FLOAT: - v->Push(SQObjectPtr(tointeger(o))); - break; - case OT_BOOL: - v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); - break; - default: - v->Push(_null_); - break; - } - return 1; -} - -static SQInteger default_delegate_tostring(HSQUIRRELVM v) -{ - sq_tostring(v,1); - return 1; -} - -static SQInteger obj_delegate_weakref(HSQUIRRELVM v) -{ - sq_weakref(v,1); - return 1; -} - -static SQInteger number_delegate_tochar(HSQUIRRELVM v) -{ - SQObject &o=stack_get(v,1); - SQChar c = (SQChar)tointeger(o); - v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1)); - return 1; -} - - -///////////////////////////////////////////////////////////////// -//TABLE DEFAULT DELEGATE - -static SQInteger table_rawdelete(HSQUIRRELVM v) -{ - if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue))) - return SQ_ERROR; - return 1; -} - - -static SQInteger container_rawexists(HSQUIRRELVM v) -{ - if(SQ_SUCCEEDED(sq_rawget(v,-2))) { - sq_pushbool(v,SQTrue); - return 1; - } - sq_pushbool(v,SQFalse); - return 1; -} - -static SQInteger table_rawset(HSQUIRRELVM v) -{ - return sq_rawset(v,-3); -} - - -static SQInteger table_rawget(HSQUIRRELVM v) -{ - return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; -} - -SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("t")}, - {_SC("rawget"),table_rawget,2, _SC("t")}, - {_SC("rawset"),table_rawset,3, _SC("t")}, - {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, - {_SC("rawin"),container_rawexists,2, _SC("t")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0} -}; - -//ARRAY DEFAULT DELEGATE/////////////////////////////////////// - -static SQInteger array_append(HSQUIRRELVM v) -{ - return sq_arrayappend(v,-2); -} - -static SQInteger array_extend(HSQUIRRELVM v) -{ - _array(stack_get(v,1))->Extend(_array(stack_get(v,2))); - return 0; -} - -static SQInteger array_reverse(HSQUIRRELVM v) -{ - return sq_arrayreverse(v,-1); -} - -static SQInteger array_pop(HSQUIRRELVM v) -{ - return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR; -} - -static SQInteger array_top(HSQUIRRELVM v) -{ - SQObject &o=stack_get(v,1); - if(_array(o)->Size()>0){ - v->Push(_array(o)->Top()); - return 1; - } - else return sq_throwerror(v,_SC("top() on a empty array")); -} - -static SQInteger array_insert(HSQUIRRELVM v) -{ - SQObject &o=stack_get(v,1); - SQObject &idx=stack_get(v,2); - SQObject &val=stack_get(v,3); - _array(o)->Insert(idx,val); - return 0; -} - -static SQInteger array_remove(HSQUIRRELVM v) -{ - SQObject &o = stack_get(v, 1); - SQObject &idx = stack_get(v, 2); - if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type")); - SQObjectPtr val; - if(_array(o)->Get(tointeger(idx), val)) { - _array(o)->Remove(tointeger(idx)); - v->Push(val); - return 1; - } - return sq_throwerror(v, _SC("idx out of range")); -} - -static SQInteger array_resize(HSQUIRRELVM v) -{ - SQObject &o = stack_get(v, 1); - SQObject &nsize = stack_get(v, 2); - SQObjectPtr fill; - if(sq_isnumeric(nsize)) { - if(sq_gettop(v) > 2) - fill = stack_get(v, 3); - _array(o)->Resize(tointeger(nsize),fill); - return 0; - } - return sq_throwerror(v, _SC("size must be a number")); -} - - -//QSORT ala Sedgewick -bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) -{ - if(func < 0) { - if(!v->ObjCmp(a,b,ret)) return false; - } - else { - SQInteger top = sq_gettop(v); - sq_push(v, func); - sq_pushroottable(v); - v->Push(a); - v->Push(b); - if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { - v->Raise_Error(_SC("compare func failed")); - return false; - } - sq_getinteger(v, -1, &ret); - sq_settop(v, top); - return true; - } - return true; -} -//QSORT ala Sedgewick -bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func) -{ - SQInteger i, j; - SQArray *a=_array(arr); - SQObjectPtr pivot,t; - if( l < r ){ - pivot = a->_values[l]; - i = l; j = r+1; - while(1){ - SQInteger ret; - do { - ++i; - if(i > r) break; - if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret)) - return false; - } while( ret <= 0); - do { - --j; - if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret)) - return false; - } - while( ret > 0 ); - if( i >= j ) break; - t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t; - } - t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t; - if(!_qsort( v, arr, l, j-1,func)) return false; - if(!_qsort( v, arr, j+1, r,func)) return false; - } - return true; -} - -static SQInteger array_sort(HSQUIRRELVM v) -{ - SQInteger func = -1; - SQObjectPtr &o = stack_get(v,1); - SQObject &funcobj = stack_get(v,2); - if(_array(o)->Size() > 1) { - if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2; - if(!_qsort(v, o, 0, _array(o)->Size()-1, func)) - return SQ_ERROR; - - } - return 0; -} -static SQInteger array_slice(HSQUIRRELVM v) -{ - SQInteger sidx,eidx; - SQObjectPtr o; - if(get_slice_params(v,sidx,eidx,o)==-1)return -1; - if(sidx<0)sidx=_array(o)->Size()+sidx; - if(eidx<0)eidx=_array(o)->Size()+eidx; - if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes")); - SQArray *arr=SQArray::Create(_ss(v),eidx-sidx); - SQObjectPtr t; - SQInteger count=0; - for(SQInteger i=sidx;iGet(i,t); - arr->Set(count++,t); - } - v->Push(arr); - return 1; - -} - -SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("a")}, - {_SC("append"),array_append,2, _SC("a")}, - {_SC("extend"),array_extend,2, _SC("aa")}, - {_SC("push"),array_append,2, _SC("a")}, - {_SC("pop"),array_pop,1, _SC("a")}, - {_SC("top"),array_top,1, _SC("a")}, - {_SC("insert"),array_insert,3, _SC("an")}, - {_SC("remove"),array_remove,2, _SC("an")}, - {_SC("resize"),array_resize,-2, _SC("an")}, - {_SC("reverse"),array_reverse,1, _SC("a")}, - {_SC("sort"),array_sort,-1, _SC("ac")}, - {_SC("slice"),array_slice,-1, _SC("ann")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0} -}; - -//STRING DEFAULT DELEGATE////////////////////////// -static SQInteger string_slice(HSQUIRRELVM v) -{ - SQInteger sidx,eidx; - SQObjectPtr o; - if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1; - if(sidx<0)sidx=_string(o)->_len+sidx; - if(eidx<0)eidx=_string(o)->_len+eidx; - if(eidxPush(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx)); - return 1; -} - -static SQInteger string_find(HSQUIRRELVM v) -{ - SQInteger top,start_idx=0; - const SQChar *str,*substr,*ret; - if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){ - if(top>2)sq_getinteger(v,3,&start_idx); - if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){ - ret=scstrstr(&str[start_idx],substr); - if(ret){ - sq_pushinteger(v,(SQInteger)(ret-str)); - return 1; - } - } - return 0; - } - return sq_throwerror(v,_SC("invalid param")); -} - -#define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \ -{ \ - SQObject str=stack_get(v,1); \ - SQInteger len=_string(str)->_len; \ - const SQChar *sThis=_stringval(str); \ - SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \ - for(SQInteger i=0;iPush(SQString::Create(_ss(v),sNew,len)); \ - return 1; \ -} - - -STRING_TOFUNCZ(tolower) -STRING_TOFUNCZ(toupper) - -SQRegFunction SQSharedState::_string_default_delegate_funcz[]={ - {_SC("len"),default_delegate_len,1, _SC("s")}, - {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")}, - {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")}, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("slice"),string_slice,-1, _SC(" s n n")}, - {_SC("find"),string_find,-2, _SC("s s n ")}, - {_SC("tolower"),string_tolower,1, _SC("s")}, - {_SC("toupper"),string_toupper,1, _SC("s")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {0,0} -}; - -//INTEGER DEFAULT DELEGATE////////////////////////// -SQRegFunction SQSharedState::_number_default_delegate_funcz[]={ - {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")}, - {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")}, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {0,0} -}; - -//CLOSURE DEFAULT DELEGATE////////////////////////// -static SQInteger closure_pcall(HSQUIRRELVM v) -{ - return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR; -} - -static SQInteger closure_call(HSQUIRRELVM v) -{ - return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR; -} - -static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror) -{ - SQArray *aparams=_array(stack_get(v,2)); - SQInteger nparams=aparams->Size(); - v->Push(stack_get(v,1)); - for(SQInteger i=0;iPush(aparams->_values[i]); - return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR; -} - -static SQInteger closure_acall(HSQUIRRELVM v) -{ - return _closure_acall(v,SQTrue); -} - -static SQInteger closure_pacall(HSQUIRRELVM v) -{ - return _closure_acall(v,SQFalse); -} - -static SQInteger closure_bindenv(HSQUIRRELVM v) -{ - if(SQ_FAILED(sq_bindenv(v,1))) - return SQ_ERROR; - return 1; -} - -static SQInteger closure_getinfos(HSQUIRRELVM v) { - SQObject o = stack_get(v,1); - SQTable *res = SQTable::Create(_ss(v),4); - if(type(o) == OT_CLOSURE) { - SQFunctionProto *f = _funcproto(_closure(o)->_function); - SQInteger nparams = f->_parameters.size() + (f->_varparams?1:0); - SQObjectPtr params = SQArray::Create(_ss(v),nparams); - for(SQUnsignedInteger n = 0; n_parameters.size(); n++) { - _array(params)->Set((SQInteger)n,f->_parameters[n]); - } - if(f->_varparams) { - _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); - } - res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false); - res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name); - res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); - res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); - res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); - } - else { //OT_NATIVECLOSURE - SQNativeClosure *nc = _nativeclosure(o); - res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true); - res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name); - res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck); - SQObjectPtr typecheck; - if(nc->_typecheck.size() > 0) { - typecheck = - SQArray::Create(_ss(v), nc->_typecheck.size()); - for(SQUnsignedInteger n = 0; n_typecheck.size(); n++) { - _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]); - } - } - res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck); - } - v->Push(res); - return 1; -} - - -SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ - {_SC("call"),closure_call,-1, _SC("c")}, - {_SC("pcall"),closure_pcall,-1, _SC("c")}, - {_SC("acall"),closure_acall,2, _SC("ca")}, - {_SC("pacall"),closure_pacall,2, _SC("ca")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")}, - {_SC("getinfos"),closure_getinfos,1, _SC("c")}, - {0,0} -}; - -//GENERATOR DEFAULT DELEGATE -static SQInteger generator_getstatus(HSQUIRRELVM v) -{ - SQObject &o=stack_get(v,1); - switch(_generator(o)->_state){ - case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break; - case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break; - case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break; - } - return 1; -} - -SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ - {_SC("getstatus"),generator_getstatus,1, _SC("g")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0} -}; - -//THREAD DEFAULT DELEGATE - -static SQInteger thread_call(HSQUIRRELVM v) -{ - SQObjectPtr o = stack_get(v,1); - if(type(o) == OT_THREAD) { - SQInteger nparams = sq_gettop(v); - _thread(o)->Push(_thread(o)->_roottable); - for(SQInteger i = 2; i<(nparams+1); i++) - sq_move(_thread(o),v,i); - if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) { - sq_move(v,_thread(o),-1); - return 1; - } - return SQ_ERROR; - } - return sq_throwerror(v,_SC("wrong parameter")); -} - -static SQInteger thread_wakeup(HSQUIRRELVM v) -{ - SQObjectPtr o = stack_get(v,1); - if(type(o) == OT_THREAD) { - SQVM *thread = _thread(o); - SQInteger state = sq_getvmstate(thread); - if(state != SQ_VMSTATE_SUSPENDED) { - switch(state) { - case SQ_VMSTATE_IDLE: - return sq_throwerror(v,_SC("cannot wakeup a idle thread")); - break; - case SQ_VMSTATE_RUNNING: - return sq_throwerror(v,_SC("cannot wakeup a running thread")); - break; - } - } - - SQInteger wakeupret = sq_gettop(v)>1?1:0; - if(wakeupret) { - sq_move(thread,v,2); - } - if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1,SQFalse))) { - sq_move(v,thread,-1); - sq_pop(thread,1); - if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { - sq_pop(thread,1); - } - return 1; - } - return SQ_ERROR; - } - return sq_throwerror(v,_SC("wrong parameter")); -} - -static SQInteger thread_getstatus(HSQUIRRELVM v) -{ - SQObjectPtr &o = stack_get(v,1); - switch(sq_getvmstate(_thread(o))) { - case SQ_VMSTATE_IDLE: - sq_pushstring(v,_SC("idle"),-1); - break; - case SQ_VMSTATE_RUNNING: - sq_pushstring(v,_SC("running"),-1); - break; - case SQ_VMSTATE_SUSPENDED: - sq_pushstring(v,_SC("suspended"),-1); - break; - default: - return sq_throwerror(v,_SC("internal VM error")); - } - return 1; -} - -SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { - {_SC("call"), thread_call, -1, _SC("v")}, - {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, - {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0}, -}; - -static SQInteger class_getattributes(HSQUIRRELVM v) -{ - if(SQ_SUCCEEDED(sq_getattributes(v,-2))) - return 1; - return SQ_ERROR; -} - -static SQInteger class_setattributes(HSQUIRRELVM v) -{ - if(SQ_SUCCEEDED(sq_setattributes(v,-3))) - return 1; - return SQ_ERROR; -} - -static SQInteger class_instance(HSQUIRRELVM v) -{ - if(SQ_SUCCEEDED(sq_createinstance(v,-1))) - return 1; - return SQ_ERROR; -} - -SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { - {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, - {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, - {_SC("rawin"),container_rawexists,2, _SC("y")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {_SC("instance"),class_instance,1, _SC("y")}, - {0,0} -}; - -static SQInteger instance_getclass(HSQUIRRELVM v) -{ - if(SQ_SUCCEEDED(sq_getclass(v,1))) - return 1; - return SQ_ERROR; -} - -SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { - {_SC("getclass"), instance_getclass, 1, _SC("x")}, - {_SC("rawin"),container_rawexists,2, _SC("x")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0} -}; - -static SQInteger weakref_ref(HSQUIRRELVM v) -{ - if(SQ_FAILED(sq_getweakrefval(v,1))) - return SQ_ERROR; - return 1; -} - -SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { - {_SC("ref"),weakref_ref,1, _SC("r")}, - {_SC("weakref"),obj_delegate_weakref,1, NULL }, - {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, - {0,0} -}; - - +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqclass.h" +#include +#include +#include + +bool str2num(const SQChar *s,SQObjectPtr &res) +{ + SQChar *end; + if(scstrstr(s,_SC("."))){ + SQFloat r = SQFloat(scstrtod(s,&end)); + if(s == end) return false; + res = r; + return true; + } + else{ + SQInteger r = SQInteger(scstrtol(s,&end,10)); + if(s == end) return false; + res = r; + return true; + } +} + +#ifndef NO_GARBAGE_COLLECTOR +static SQInteger base_collectgarbage(HSQUIRRELVM v) +{ + sq_pushinteger(v, sq_collectgarbage(v)); + return 1; +} +#endif + +static SQInteger base_getroottable(HSQUIRRELVM v) +{ + v->Push(v->_roottable); + return 1; +} + +static SQInteger base_setroottable(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,2); + if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; + v->Push(o); + return 1; +} + +static SQInteger base_seterrorhandler(HSQUIRRELVM v) +{ + sq_seterrorhandler(v); + return 0; +} + +static SQInteger base_setdebughook(HSQUIRRELVM v) +{ + sq_setdebughook(v); + return 0; +} + +static SQInteger base_enabledebuginfo(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,2); + sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0); + return 0; +} + +static SQInteger base_getstackinfos(HSQUIRRELVM v) +{ + SQInteger level; + SQStackInfos si; + SQInteger seq = 0; + const SQChar *name = NULL; + sq_getinteger(v, -1, &level); + if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) + { + const SQChar *fn = _SC("unknown"); + const SQChar *src = _SC("unknown"); + if(si.funcname)fn = si.funcname; + if(si.source)src = si.source; + sq_newtable(v); + sq_pushstring(v, _SC("func"), -1); + sq_pushstring(v, fn, -1); + sq_createslot(v, -3); + sq_pushstring(v, _SC("src"), -1); + sq_pushstring(v, src, -1); + sq_createslot(v, -3); + sq_pushstring(v, _SC("line"), -1); + sq_pushinteger(v, si.line); + sq_createslot(v, -3); + sq_pushstring(v, _SC("locals"), -1); + sq_newtable(v); + seq=0; + while ((name = sq_getlocal(v, level, seq))) { + sq_pushstring(v, name, -1); + sq_push(v, -2); + sq_createslot(v, -4); + sq_pop(v, 1); + seq++; + } + sq_createslot(v, -3); + return 1; + } + + return 0; +} + +static SQInteger base_assert(HSQUIRRELVM v) +{ + if(v->IsFalse(stack_get(v,2))){ + return sq_throwerror(v,_SC("assertion failed")); + } + return 0; +} + +static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o) +{ + SQInteger top = sq_gettop(v); + sidx=0; + eidx=0; + o=stack_get(v,1); + SQObjectPtr &start=stack_get(v,2); + if(type(start)!=OT_NULL && sq_isnumeric(start)){ + sidx=tointeger(start); + } + if(top>2){ + SQObjectPtr &end=stack_get(v,3); + if(sq_isnumeric(end)){ + eidx=tointeger(end); + } + } + else { + eidx = sq_getsize(v,1); + } + return 1; +} + +static SQInteger base_print(HSQUIRRELVM v) +{ + const SQChar *str; + sq_tostring(v,2); + sq_getstring(v,-1,&str); + if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str); + return 0; +} + +static SQInteger base_compilestring(HSQUIRRELVM v) +{ + SQInteger nargs=sq_gettop(v); + const SQChar *src=NULL,*name=_SC("unnamedbuffer"); + SQInteger size; + sq_getstring(v,2,&src); + size=sq_getsize(v,2); + if(nargs>2){ + sq_getstring(v,3,&name); + } + if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse))) + return 1; + else + return SQ_ERROR; +} + +static SQInteger base_newthread(HSQUIRRELVM v) +{ + SQObjectPtr &func = stack_get(v,2); + SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2; + HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); + sq_move(newv,v,-2); + return 1; +} + +static SQInteger base_suspend(HSQUIRRELVM v) +{ + return sq_suspendvm(v); +} + +static SQInteger base_array(HSQUIRRELVM v) +{ + SQArray *a; + SQObject &size = stack_get(v,2); + if(sq_gettop(v) > 2) { + a = SQArray::Create(_ss(v),0); + a->Resize(tointeger(size),stack_get(v,3)); + } + else { + a = SQArray::Create(_ss(v),tointeger(size)); + } + v->Push(a); + return 1; +} + +static SQInteger base_type(HSQUIRRELVM v) +{ + SQObjectPtr &o = stack_get(v,2); + v->Push(SQString::Create(_ss(v),GetTypeName(o),-1)); + return 1; +} + +static SQRegFunction base_funcs[]={ + //generic + {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, + {_SC("setdebughook"),base_setdebughook,2, NULL}, + {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL}, + {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")}, + {_SC("getroottable"),base_getroottable,1, NULL}, + {_SC("setroottable"),base_setroottable,2, NULL}, + {_SC("assert"),base_assert,2, NULL}, + {_SC("print"),base_print,2, NULL}, + {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, + {_SC("newthread"),base_newthread,2, _SC(".c")}, + {_SC("suspend"),base_suspend,-1, NULL}, + {_SC("array"),base_array,-2, _SC(".n")}, + {_SC("type"),base_type,2, NULL}, +#ifndef NO_GARBAGE_COLLECTOR + {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")}, +#endif + {0,0} +}; + +void sq_base_register(HSQUIRRELVM v) +{ + SQInteger i=0; + sq_pushroottable(v); + while(base_funcs[i].name!=0) { + sq_pushstring(v,base_funcs[i].name,-1); + sq_newclosure(v,base_funcs[i].f,0); + sq_setnativeclosurename(v,-1,base_funcs[i].name); + sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); + sq_createslot(v,-3); + i++; + } + sq_pushstring(v,_SC("_charsize_"),-1); + sq_pushinteger(v,sizeof(SQChar)); + sq_createslot(v,-3); + sq_pushstring(v,_SC("_intsize_"),-1); + sq_pushinteger(v,sizeof(SQInteger)); + sq_createslot(v,-3); + sq_pop(v,1); +} + +static SQInteger default_delegate_len(HSQUIRRELVM v) +{ + v->Push(SQInteger(sq_getsize(v,1))); + return 1; +} + +static SQInteger default_delegate_tofloat(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,1); + switch(type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res)){ + v->Push(SQObjectPtr(tofloat(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tofloat(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); + break; + default: + v->Push(_null_); + break; + } + return 1; +} + +static SQInteger default_delegate_tointeger(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,1); + switch(type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res)){ + v->Push(SQObjectPtr(tointeger(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tointeger(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); + break; + default: + v->Push(_null_); + break; + } + return 1; +} + +static SQInteger default_delegate_tostring(HSQUIRRELVM v) +{ + sq_tostring(v,1); + return 1; +} + +static SQInteger obj_delegate_weakref(HSQUIRRELVM v) +{ + sq_weakref(v,1); + return 1; +} + +static SQInteger number_delegate_tochar(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + SQChar c = (SQChar)tointeger(o); + v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1)); + return 1; +} + + +///////////////////////////////////////////////////////////////// +//TABLE DEFAULT DELEGATE + +static SQInteger table_rawdelete(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue))) + return SQ_ERROR; + return 1; +} + + +static SQInteger container_rawexists(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_rawget(v,-2))) { + sq_pushbool(v,SQTrue); + return 1; + } + sq_pushbool(v,SQFalse); + return 1; +} + +static SQInteger table_rawset(HSQUIRRELVM v) +{ + return sq_rawset(v,-3); +} + + +static SQInteger table_rawget(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; +} + +SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ + {_SC("len"),default_delegate_len,1, _SC("t")}, + {_SC("rawget"),table_rawget,2, _SC("t")}, + {_SC("rawset"),table_rawset,3, _SC("t")}, + {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, + {_SC("rawin"),container_rawexists,2, _SC("t")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0} +}; + +//ARRAY DEFAULT DELEGATE/////////////////////////////////////// + +static SQInteger array_append(HSQUIRRELVM v) +{ + return sq_arrayappend(v,-2); +} + +static SQInteger array_extend(HSQUIRRELVM v) +{ + _array(stack_get(v,1))->Extend(_array(stack_get(v,2))); + return 0; +} + +static SQInteger array_reverse(HSQUIRRELVM v) +{ + return sq_arrayreverse(v,-1); +} + +static SQInteger array_pop(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR; +} + +static SQInteger array_top(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + if(_array(o)->Size()>0){ + v->Push(_array(o)->Top()); + return 1; + } + else return sq_throwerror(v,_SC("top() on a empty array")); +} + +static SQInteger array_insert(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + SQObject &idx=stack_get(v,2); + SQObject &val=stack_get(v,3); + _array(o)->Insert(idx,val); + return 0; +} + +static SQInteger array_remove(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v, 1); + SQObject &idx = stack_get(v, 2); + if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type")); + SQObjectPtr val; + if(_array(o)->Get(tointeger(idx), val)) { + _array(o)->Remove(tointeger(idx)); + v->Push(val); + return 1; + } + return sq_throwerror(v, _SC("idx out of range")); +} + +static SQInteger array_resize(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v, 1); + SQObject &nsize = stack_get(v, 2); + SQObjectPtr fill; + if(sq_isnumeric(nsize)) { + if(sq_gettop(v) > 2) + fill = stack_get(v, 3); + _array(o)->Resize(tointeger(nsize),fill); + return 0; + } + return sq_throwerror(v, _SC("size must be a number")); +} + + +//QSORT ala Sedgewick +bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) +{ + if(func < 0) { + if(!v->ObjCmp(a,b,ret)) return false; + } + else { + SQInteger top = sq_gettop(v); + sq_push(v, func); + sq_pushroottable(v); + v->Push(a); + v->Push(b); + if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { + v->Raise_Error(_SC("compare func failed")); + return false; + } + sq_getinteger(v, -1, &ret); + sq_settop(v, top); + return true; + } + return true; +} +//QSORT ala Sedgewick +bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func) +{ + SQInteger i, j; + SQArray *a=_array(arr); + SQObjectPtr pivot,t; + if( l < r ){ + pivot = a->_values[l]; + i = l; j = r+1; + while(1){ + SQInteger ret; + do { + ++i; + if(i > r) break; + if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret)) + return false; + } while( ret <= 0); + do { + --j; + if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret)) + return false; + } + while( ret > 0 ); + if( i >= j ) break; + t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t; + } + t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t; + if(!_qsort( v, arr, l, j-1,func)) return false; + if(!_qsort( v, arr, j+1, r,func)) return false; + } + return true; +} + +static SQInteger array_sort(HSQUIRRELVM v) +{ + SQInteger func = -1; + SQObjectPtr &o = stack_get(v,1); + SQObject &funcobj = stack_get(v,2); + if(_array(o)->Size() > 1) { + if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2; + if(!_qsort(v, o, 0, _array(o)->Size()-1, func)) + return SQ_ERROR; + + } + return 0; +} +static SQInteger array_slice(HSQUIRRELVM v) +{ + SQInteger sidx,eidx; + SQObjectPtr o; + if(get_slice_params(v,sidx,eidx,o)==-1)return -1; + if(sidx<0)sidx=_array(o)->Size()+sidx; + if(eidx<0)eidx=_array(o)->Size()+eidx; + if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes")); + SQArray *arr=SQArray::Create(_ss(v),eidx-sidx); + SQObjectPtr t; + SQInteger count=0; + for(SQInteger i=sidx;iGet(i,t); + arr->Set(count++,t); + } + v->Push(arr); + return 1; + +} + +SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ + {_SC("len"),default_delegate_len,1, _SC("a")}, + {_SC("append"),array_append,2, _SC("a")}, + {_SC("extend"),array_extend,2, _SC("aa")}, + {_SC("push"),array_append,2, _SC("a")}, + {_SC("pop"),array_pop,1, _SC("a")}, + {_SC("top"),array_top,1, _SC("a")}, + {_SC("insert"),array_insert,3, _SC("an")}, + {_SC("remove"),array_remove,2, _SC("an")}, + {_SC("resize"),array_resize,-2, _SC("an")}, + {_SC("reverse"),array_reverse,1, _SC("a")}, + {_SC("sort"),array_sort,-1, _SC("ac")}, + {_SC("slice"),array_slice,-1, _SC("ann")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0} +}; + +//STRING DEFAULT DELEGATE////////////////////////// +static SQInteger string_slice(HSQUIRRELVM v) +{ + SQInteger sidx,eidx; + SQObjectPtr o; + if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1; + if(sidx<0)sidx=_string(o)->_len+sidx; + if(eidx<0)eidx=_string(o)->_len+eidx; + if(eidxPush(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx)); + return 1; +} + +static SQInteger string_find(HSQUIRRELVM v) +{ + SQInteger top,start_idx=0; + const SQChar *str,*substr,*ret; + if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){ + if(top>2)sq_getinteger(v,3,&start_idx); + if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){ + ret=scstrstr(&str[start_idx],substr); + if(ret){ + sq_pushinteger(v,(SQInteger)(ret-str)); + return 1; + } + } + return 0; + } + return sq_throwerror(v,_SC("invalid param")); +} + +#define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \ +{ \ + SQObject str=stack_get(v,1); \ + SQInteger len=_string(str)->_len; \ + const SQChar *sThis=_stringval(str); \ + SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \ + for(SQInteger i=0;iPush(SQString::Create(_ss(v),sNew,len)); \ + return 1; \ +} + + +STRING_TOFUNCZ(tolower) +STRING_TOFUNCZ(toupper) + +SQRegFunction SQSharedState::_string_default_delegate_funcz[]={ + {_SC("len"),default_delegate_len,1, _SC("s")}, + {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")}, + {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")}, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("slice"),string_slice,-1, _SC(" s n n")}, + {_SC("find"),string_find,-2, _SC("s s n ")}, + {_SC("tolower"),string_tolower,1, _SC("s")}, + {_SC("toupper"),string_toupper,1, _SC("s")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {0,0} +}; + +//INTEGER DEFAULT DELEGATE////////////////////////// +SQRegFunction SQSharedState::_number_default_delegate_funcz[]={ + {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")}, + {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")}, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {0,0} +}; + +//CLOSURE DEFAULT DELEGATE////////////////////////// +static SQInteger closure_pcall(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR; +} + +static SQInteger closure_call(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR; +} + +static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror) +{ + SQArray *aparams=_array(stack_get(v,2)); + SQInteger nparams=aparams->Size(); + v->Push(stack_get(v,1)); + for(SQInteger i=0;iPush(aparams->_values[i]); + return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR; +} + +static SQInteger closure_acall(HSQUIRRELVM v) +{ + return _closure_acall(v,SQTrue); +} + +static SQInteger closure_pacall(HSQUIRRELVM v) +{ + return _closure_acall(v,SQFalse); +} + +static SQInteger closure_bindenv(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_bindenv(v,1))) + return SQ_ERROR; + return 1; +} + +static SQInteger closure_getinfos(HSQUIRRELVM v) { + SQObject o = stack_get(v,1); + SQTable *res = SQTable::Create(_ss(v),4); + if(type(o) == OT_CLOSURE) { + SQFunctionProto *f = _funcproto(_closure(o)->_function); + SQInteger nparams = f->_parameters.size() + (f->_varparams?1:0); + SQObjectPtr params = SQArray::Create(_ss(v),nparams); + for(SQUnsignedInteger n = 0; n_parameters.size(); n++) { + _array(params)->Set((SQInteger)n,f->_parameters[n]); + } + if(f->_varparams) { + _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1)); + } + res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false); + res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name); + res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename); + res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params); + res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams); + } + else { //OT_NATIVECLOSURE + SQNativeClosure *nc = _nativeclosure(o); + res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true); + res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name); + res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck); + SQObjectPtr typecheck; + if(nc->_typecheck.size() > 0) { + typecheck = + SQArray::Create(_ss(v), nc->_typecheck.size()); + for(SQUnsignedInteger n = 0; n_typecheck.size(); n++) { + _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]); + } + } + res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck); + } + v->Push(res); + return 1; +} + + +SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ + {_SC("call"),closure_call,-1, _SC("c")}, + {_SC("pcall"),closure_pcall,-1, _SC("c")}, + {_SC("acall"),closure_acall,2, _SC("ca")}, + {_SC("pacall"),closure_pacall,2, _SC("ca")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")}, + {_SC("getinfos"),closure_getinfos,1, _SC("c")}, + {0,0} +}; + +//GENERATOR DEFAULT DELEGATE +static SQInteger generator_getstatus(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + switch(_generator(o)->_state){ + case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break; + case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break; + case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break; + } + return 1; +} + +SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ + {_SC("getstatus"),generator_getstatus,1, _SC("g")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0} +}; + +//THREAD DEFAULT DELEGATE + +static SQInteger thread_call(HSQUIRRELVM v) +{ + SQObjectPtr o = stack_get(v,1); + if(type(o) == OT_THREAD) { + SQInteger nparams = sq_gettop(v); + _thread(o)->Push(_thread(o)->_roottable); + for(SQInteger i = 2; i<(nparams+1); i++) + sq_move(_thread(o),v,i); + if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) { + sq_move(v,_thread(o),-1); + return 1; + } + return SQ_ERROR; + } + return sq_throwerror(v,_SC("wrong parameter")); +} + +static SQInteger thread_wakeup(HSQUIRRELVM v) +{ + SQObjectPtr o = stack_get(v,1); + if(type(o) == OT_THREAD) { + SQVM *thread = _thread(o); + SQInteger state = sq_getvmstate(thread); + if(state != SQ_VMSTATE_SUSPENDED) { + switch(state) { + case SQ_VMSTATE_IDLE: + return sq_throwerror(v,_SC("cannot wakeup a idle thread")); + break; + case SQ_VMSTATE_RUNNING: + return sq_throwerror(v,_SC("cannot wakeup a running thread")); + break; + } + } + + SQInteger wakeupret = sq_gettop(v)>1?1:0; + if(wakeupret) { + sq_move(thread,v,2); + } + if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1,SQFalse))) { + sq_move(v,thread,-1); + sq_pop(thread,1); + if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { + sq_pop(thread,1); + } + return 1; + } + return SQ_ERROR; + } + return sq_throwerror(v,_SC("wrong parameter")); +} + +static SQInteger thread_getstatus(HSQUIRRELVM v) +{ + SQObjectPtr &o = stack_get(v,1); + switch(sq_getvmstate(_thread(o))) { + case SQ_VMSTATE_IDLE: + sq_pushstring(v,_SC("idle"),-1); + break; + case SQ_VMSTATE_RUNNING: + sq_pushstring(v,_SC("running"),-1); + break; + case SQ_VMSTATE_SUSPENDED: + sq_pushstring(v,_SC("suspended"),-1); + break; + default: + return sq_throwerror(v,_SC("internal VM error")); + } + return 1; +} + +SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { + {_SC("call"), thread_call, -1, _SC("v")}, + {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, + {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0}, +}; + +static SQInteger class_getattributes(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_getattributes(v,-2))) + return 1; + return SQ_ERROR; +} + +static SQInteger class_setattributes(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_setattributes(v,-3))) + return 1; + return SQ_ERROR; +} + +static SQInteger class_instance(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_createinstance(v,-1))) + return 1; + return SQ_ERROR; +} + +SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { + {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, + {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, + {_SC("rawin"),container_rawexists,2, _SC("y")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("instance"),class_instance,1, _SC("y")}, + {0,0} +}; + +static SQInteger instance_getclass(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_getclass(v,1))) + return 1; + return SQ_ERROR; +} + +SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { + {_SC("getclass"), instance_getclass, 1, _SC("x")}, + {_SC("rawin"),container_rawexists,2, _SC("x")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0} +}; + +static SQInteger weakref_ref(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_getweakrefval(v,1))) + return SQ_ERROR; + return 1; +} + +SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { + {_SC("ref"),weakref_ref,1, _SC("r")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0} +}; diff --git a/src/squirrel/squirrel/sqclass.cpp b/src/squirrel/squirrel/sqclass.cpp index 1672f7cca..405c737a7 100644 --- a/src/squirrel/squirrel/sqclass.cpp +++ b/src/squirrel/squirrel/sqclass.cpp @@ -1,192 +1,192 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqvm.h" -#include "sqtable.h" -#include "sqclass.h" -#include "sqclosure.h" - -SQClass::SQClass(SQSharedState *ss,SQClass *base) -{ - _base = base; - _typetag = 0; - _hook = NULL; - _metamethods.resize(MT_LAST); //size it to max size - if(_base) { - _defaultvalues.copy(base->_defaultvalues); - _methods.copy(base->_methods); - _metamethods.copy(base->_metamethods); - __ObjAddRef(_base); - } - _members = base?base->_members->Clone() : SQTable::Create(ss,0); - __ObjAddRef(_members); - _locked = false; - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); -} - -void SQClass::Finalize() { - _attributes = _null_; - _defaultvalues.resize(0); - _methods.resize(0); - _metamethods.resize(0); - __ObjRelease(_members); - if(_base) { - __ObjRelease(_base); - } -} - -SQClass::~SQClass() -{ - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - Finalize(); -} - -bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) -{ - SQObjectPtr temp; - if(_locked) - return false; //the class already has an instance so cannot be modified - if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value - { - _defaultvalues[_member_idx(temp)].val = val; - return true; - } - if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) { - SQInteger mmidx; - if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && - (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { - _metamethods[mmidx] = val; - } - else { - if(type(temp) == OT_NULL) { - SQClassMemeber m; - m.val = val; - _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); - _methods.push_back(m); - } - else { - _methods[_member_idx(temp)].val = val; - } - } - return true; - } - SQClassMemeber m; - m.val = val; - _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size()))); - _defaultvalues.push_back(m); - return true; -} - -SQInstance *SQClass::CreateInstance() -{ - if(!_locked) Lock(); - return SQInstance::Create(_opt_ss(this),this); -} - -SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) -{ - SQObjectPtr oval; - SQInteger idx = _members->Next(false,refpos,outkey,oval); - if(idx != -1) { - if(_ismethod(oval)) { - outval = _methods[_member_idx(oval)].val; - } - else { - SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val; - outval = _realval(o); - } - } - return idx; -} - -bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val) -{ - SQObjectPtr idx; - if(_members->Get(key,idx)) { - if(_isfield(idx)) - _defaultvalues[_member_idx(idx)].attrs = val; - else - _methods[_member_idx(idx)].attrs = val; - return true; - } - return false; -} - -bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval) -{ - SQObjectPtr idx; - if(_members->Get(key,idx)) { - outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); - return true; - } - return false; -} - -/////////////////////////////////////////////////////////////////////// -void SQInstance::Init(SQSharedState *ss) -{ - _userpointer = NULL; - _hook = NULL; - __ObjAddRef(_class); - _delegate = _class->_members; - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); -} - -SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize) -{ - _memsize = memsize; - _class = c; - _nvalues = _class->_defaultvalues.size(); - for(SQUnsignedInteger n = 0; n < _nvalues; n++) { - new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val); - } - Init(ss); -} - -SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize) -{ - _memsize = memsize; - _class = i->_class; - _nvalues = _class->_defaultvalues.size(); - for(SQUnsignedInteger n = 0; n < _nvalues; n++) { - new (&_values[n]) SQObjectPtr(i->_values[n]); - } - Init(ss); -} - -void SQInstance::Finalize() -{ - __ObjRelease(_class); - for(SQUnsignedInteger i = 0; i < _nvalues; i++) { - _values[i] = _null_; - } -} - -SQInstance::~SQInstance() -{ - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - Finalize(); -} - -bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) -{ - if(type(_class->_metamethods[mm]) != OT_NULL) { - res = _class->_metamethods[mm]; - return true; - } - return false; -} - -bool SQInstance::InstanceOf(SQClass *trg) -{ - SQClass *parent = _class; - while(parent != NULL) { - if(parent == trg) - return true; - parent = parent->_base; - } - return false; -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqtable.h" +#include "sqclass.h" +#include "sqclosure.h" + +SQClass::SQClass(SQSharedState *ss,SQClass *base) +{ + _base = base; + _typetag = 0; + _hook = NULL; + _metamethods.resize(MT_LAST); //size it to max size + if(_base) { + _defaultvalues.copy(base->_defaultvalues); + _methods.copy(base->_methods); + _metamethods.copy(base->_metamethods); + __ObjAddRef(_base); + } + _members = base?base->_members->Clone() : SQTable::Create(ss,0); + __ObjAddRef(_members); + _locked = false; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); +} + +void SQClass::Finalize() { + _attributes = _null_; + _defaultvalues.resize(0); + _methods.resize(0); + _metamethods.resize(0); + __ObjRelease(_members); + if(_base) { + __ObjRelease(_base); + } +} + +SQClass::~SQClass() +{ + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + Finalize(); +} + +bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) +{ + SQObjectPtr temp; + if(_locked) + return false; //the class already has an instance so cannot be modified + if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value + { + _defaultvalues[_member_idx(temp)].val = val; + return true; + } + if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) { + SQInteger mmidx; + if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && + (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { + _metamethods[mmidx] = val; + } + else { + if(type(temp) == OT_NULL) { + SQClassMemeber m; + m.val = val; + _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); + _methods.push_back(m); + } + else { + _methods[_member_idx(temp)].val = val; + } + } + return true; + } + SQClassMemeber m; + m.val = val; + _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size()))); + _defaultvalues.push_back(m); + return true; +} + +SQInstance *SQClass::CreateInstance() +{ + if(!_locked) Lock(); + return SQInstance::Create(_opt_ss(this),this); +} + +SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQObjectPtr oval; + SQInteger idx = _members->Next(false,refpos,outkey,oval); + if(idx != -1) { + if(_ismethod(oval)) { + outval = _methods[_member_idx(oval)].val; + } + else { + SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val; + outval = _realval(o); + } + } + return idx; +} + +bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val) +{ + SQObjectPtr idx; + if(_members->Get(key,idx)) { + if(_isfield(idx)) + _defaultvalues[_member_idx(idx)].attrs = val; + else + _methods[_member_idx(idx)].attrs = val; + return true; + } + return false; +} + +bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval) +{ + SQObjectPtr idx; + if(_members->Get(key,idx)) { + outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////// +void SQInstance::Init(SQSharedState *ss) +{ + _userpointer = NULL; + _hook = NULL; + __ObjAddRef(_class); + _delegate = _class->_members; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); +} + +SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize) +{ + _memsize = memsize; + _class = c; + _nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < _nvalues; n++) { + new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val); + } + Init(ss); +} + +SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize) +{ + _memsize = memsize; + _class = i->_class; + _nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < _nvalues; n++) { + new (&_values[n]) SQObjectPtr(i->_values[n]); + } + Init(ss); +} + +void SQInstance::Finalize() +{ + __ObjRelease(_class); + for(SQUnsignedInteger i = 0; i < _nvalues; i++) { + _values[i] = _null_; + } +} + +SQInstance::~SQInstance() +{ + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + Finalize(); +} + +bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) +{ + if(type(_class->_metamethods[mm]) != OT_NULL) { + res = _class->_metamethods[mm]; + return true; + } + return false; +} + +bool SQInstance::InstanceOf(SQClass *trg) +{ + SQClass *parent = _class; + while(parent != NULL) { + if(parent == trg) + return true; + parent = parent->_base; + } + return false; +} diff --git a/src/squirrel/squirrel/sqclass.h b/src/squirrel/squirrel/sqclass.h index 460e591a0..a451eede5 100644 --- a/src/squirrel/squirrel/sqclass.h +++ b/src/squirrel/squirrel/sqclass.h @@ -1,142 +1,142 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQCLASS_H_ -#define _SQCLASS_H_ - -struct SQInstance; - -struct SQClassMemeber { - SQClassMemeber(){} - SQClassMemeber(const SQClassMemeber &o) { - val = o.val; - attrs = o.attrs; - } - SQObjectPtr val; - SQObjectPtr attrs; -}; - -typedef sqvector SQClassMemeberVec; - -#define MEMBER_TYPE_METHOD 0x01000000 -#define MEMBER_TYPE_FIELD 0x02000000 - -#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD) -#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD) -#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i)) -#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i)) -#define _member_type(o) (_integer(o)&0xFF000000) -#define _member_idx(o) (_integer(o)&0x00FFFFFF) - -struct SQClass : public CHAINABLE_OBJ -{ - SQClass(SQSharedState *ss,SQClass *base); -public: - static SQClass* Create(SQSharedState *ss,SQClass *base) { - SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass)); - new (newclass) SQClass(ss, base); - return newclass; - } - ~SQClass(); - bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic); - bool Get(const SQObjectPtr &key,SQObjectPtr &val) { - if(_members->Get(key,val)) { - if(_isfield(val)) { - SQObjectPtr &o = _defaultvalues[_member_idx(val)].val; - val = _realval(o); - } - else { - val = _methods[_member_idx(val)].val; - } - return true; - } - return false; - } - bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); - bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); - void Lock() { _locked = true; if(_base) _base->Lock(); } - void Release() { - if (_hook) { _hook(_typetag,0);} - sq_delete(this, SQClass); - } - void Finalize(); -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable ** ); -#endif - SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - SQInstance *CreateInstance(); - SQTable *_members; - SQClass *_base; - SQClassMemeberVec _defaultvalues; - SQClassMemeberVec _methods; - SQObjectPtrVec _metamethods; - SQObjectPtr _attributes; - SQUserPointer _typetag; - SQRELEASEHOOK _hook; - bool _locked; -}; - -#define calcinstancesize(_theclass_) \ - (sizeof(SQInstance)+(sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))) -struct SQInstance : public SQDelegable -{ - void Init(SQSharedState *ss); - SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize); - SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize); -public: - static SQInstance* Create(SQSharedState *ss,SQClass *theclass) { - - SQInteger size = calcinstancesize(theclass); - SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); - new (newinst) SQInstance(ss, theclass,size); - return newinst; - } - SQInstance *Clone(SQSharedState *ss) - { - SQInteger size = calcinstancesize(_class); - SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); - new (newinst) SQInstance(ss, this,size); - return newinst; - } - ~SQInstance(); - bool Get(const SQObjectPtr &key,SQObjectPtr &val) { - if(_class->_members->Get(key,val)) { - if(_isfield(val)) { - SQObjectPtr &o = _values[_member_idx(val)]; - val = _realval(o); - } - else { - val = _class->_methods[_member_idx(val)].val; - } - return true; - } - return false; - } - bool Set(const SQObjectPtr &key,const SQObjectPtr &val) { - SQObjectPtr idx; - if(_class->_members->Get(key,idx) && _isfield(idx)) { - _values[_member_idx(idx)] = val; - return true; - } - return false; - } - void Release() { - if (_hook) { _hook(_userpointer,0);} - SQInteger size = _memsize; - this->~SQInstance(); - SQ_FREE(this, size); - } - void Finalize(); -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable ** ); -#endif - bool InstanceOf(SQClass *trg); - bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); - - SQClass *_class; - SQUserPointer _userpointer; - SQRELEASEHOOK _hook; - SQUnsignedInteger _nvalues; - SQInteger _memsize; - SQObjectPtr _values[1]; -}; - -#endif //_SQCLASS_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQCLASS_H_ +#define _SQCLASS_H_ + +struct SQInstance; + +struct SQClassMemeber { + SQClassMemeber(){} + SQClassMemeber(const SQClassMemeber &o) { + val = o.val; + attrs = o.attrs; + } + SQObjectPtr val; + SQObjectPtr attrs; +}; + +typedef sqvector SQClassMemeberVec; + +#define MEMBER_TYPE_METHOD 0x01000000 +#define MEMBER_TYPE_FIELD 0x02000000 + +#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD) +#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD) +#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i)) +#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i)) +#define _member_type(o) (_integer(o)&0xFF000000) +#define _member_idx(o) (_integer(o)&0x00FFFFFF) + +struct SQClass : public CHAINABLE_OBJ +{ + SQClass(SQSharedState *ss,SQClass *base); +public: + static SQClass* Create(SQSharedState *ss,SQClass *base) { + SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass)); + new (newclass) SQClass(ss, base); + return newclass; + } + ~SQClass(); + bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _defaultvalues[_member_idx(val)].val; + val = _realval(o); + } + else { + val = _methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); + bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); + void Lock() { _locked = true; if(_base) _base->Lock(); } + void Release() { + if (_hook) { _hook(_typetag,0);} + sq_delete(this, SQClass); + } + void Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable ** ); +#endif + SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + SQInstance *CreateInstance(); + SQTable *_members; + SQClass *_base; + SQClassMemeberVec _defaultvalues; + SQClassMemeberVec _methods; + SQObjectPtrVec _metamethods; + SQObjectPtr _attributes; + SQUserPointer _typetag; + SQRELEASEHOOK _hook; + bool _locked; +}; + +#define calcinstancesize(_theclass_) \ + (sizeof(SQInstance)+(sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))) +struct SQInstance : public SQDelegable +{ + void Init(SQSharedState *ss); + SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize); + SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize); +public: + static SQInstance* Create(SQSharedState *ss,SQClass *theclass) { + + SQInteger size = calcinstancesize(theclass); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, theclass,size); + return newinst; + } + SQInstance *Clone(SQSharedState *ss) + { + SQInteger size = calcinstancesize(_class); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, this,size); + return newinst; + } + ~SQInstance(); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_class->_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _values[_member_idx(val)]; + val = _realval(o); + } + else { + val = _class->_methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool Set(const SQObjectPtr &key,const SQObjectPtr &val) { + SQObjectPtr idx; + if(_class->_members->Get(key,idx) && _isfield(idx)) { + _values[_member_idx(idx)] = val; + return true; + } + return false; + } + void Release() { + if (_hook) { _hook(_userpointer,0);} + SQInteger size = _memsize; + this->~SQInstance(); + SQ_FREE(this, size); + } + void Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable ** ); +#endif + bool InstanceOf(SQClass *trg); + bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + + SQClass *_class; + SQUserPointer _userpointer; + SQRELEASEHOOK _hook; + SQUnsignedInteger _nvalues; + SQInteger _memsize; + SQObjectPtr _values[1]; +}; + +#endif //_SQCLASS_H_ diff --git a/src/squirrel/squirrel/sqclosure.h b/src/squirrel/squirrel/sqclosure.h index 7a5df1b3e..d8dc90aef 100644 --- a/src/squirrel/squirrel/sqclosure.h +++ b/src/squirrel/squirrel/sqclosure.h @@ -1,120 +1,120 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQCLOSURE_H_ -#define _SQCLOSURE_H_ - -struct SQFunctionProto; - -struct SQClosure : public CHAINABLE_OBJ -{ -private: - SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} -public: - static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){ - SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure)); - new (nc) SQClosure(ss,func); - return nc; - } - void Release(){ - sq_delete(this,SQClosure); - } - SQClosure *Clone() - { - SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function)); - ret->_env = _env; - ret->_outervalues.copy(_outervalues); - return ret; - } - ~SQClosure() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } - bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); - bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read); -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0); } -#endif - SQObjectPtr _env; - SQObjectPtr _function; - SQObjectPtrVec _outervalues; -}; -////////////////////////////////////////////// -struct SQGenerator : public CHAINABLE_OBJ -{ - enum SQGeneratorState{eRunning,eSuspended,eDead}; -private: - SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=_null_;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} -public: - static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ - SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); - new (nc) SQGenerator(ss,closure); - return nc; - } - ~SQGenerator() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } - void Kill(){ - _state=eDead; - _stack.resize(0); - _closure=_null_;} - void Release(){ - sq_delete(this,SQGenerator); - } - bool Yield(SQVM *v); - bool Resume(SQVM *v,SQInteger target); -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); - void Finalize(){_stack.resize(0);_closure=_null_;} -#endif - SQObjectPtr _closure; - SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; - SQVM::CallInfo _ci; - ExceptionsTraps _etraps; - SQGeneratorState _state; -}; - -struct SQNativeClosure : public CHAINABLE_OBJ -{ -private: - SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } -public: - static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func) - { - SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure)); - new (nc) SQNativeClosure(ss,func); - return nc; - } - SQNativeClosure *Clone() - { - SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function); - ret->_env = _env; - ret->_name = _name; - ret->_outervalues.copy(_outervalues); - ret->_typecheck = _typecheck; - ret->_nparamscheck = _nparamscheck; - return ret; - } - ~SQNativeClosure() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); - } - void Release(){ - sq_delete(this,SQNativeClosure); - } -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); - void Finalize(){_outervalues.resize(0);} -#endif - SQObjectPtr _env; - SQFUNCTION _function; - SQObjectPtr _name; - SQObjectPtrVec _outervalues; - SQIntVec _typecheck; - SQInteger _nparamscheck; -}; - - - -#endif //_SQCLOSURE_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQCLOSURE_H_ +#define _SQCLOSURE_H_ + +struct SQFunctionProto; + +struct SQClosure : public CHAINABLE_OBJ +{ +private: + SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} +public: + static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){ + SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure)); + new (nc) SQClosure(ss,func); + return nc; + } + void Release(){ + sq_delete(this,SQClosure); + } + SQClosure *Clone() + { + SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function)); + ret->_env = _env; + ret->_outervalues.copy(_outervalues); + return ret; + } + ~SQClosure() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_outervalues.resize(0); } +#endif + SQObjectPtr _env; + SQObjectPtr _function; + SQObjectPtrVec _outervalues; +}; +////////////////////////////////////////////// +struct SQGenerator : public CHAINABLE_OBJ +{ + enum SQGeneratorState{eRunning,eSuspended,eDead}; +private: + SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=_null_;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} +public: + static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ + SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); + new (nc) SQGenerator(ss,closure); + return nc; + } + ~SQGenerator() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Kill(){ + _state=eDead; + _stack.resize(0); + _closure=_null_;} + void Release(){ + sq_delete(this,SQGenerator); + } + bool Yield(SQVM *v); + bool Resume(SQVM *v,SQInteger target); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_stack.resize(0);_closure=_null_;} +#endif + SQObjectPtr _closure; + SQObjectPtrVec _stack; + SQObjectPtrVec _vargsstack; + SQVM::CallInfo _ci; + ExceptionsTraps _etraps; + SQGeneratorState _state; +}; + +struct SQNativeClosure : public CHAINABLE_OBJ +{ +private: + SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } +public: + static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func) + { + SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure)); + new (nc) SQNativeClosure(ss,func); + return nc; + } + SQNativeClosure *Clone() + { + SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function); + ret->_env = _env; + ret->_name = _name; + ret->_outervalues.copy(_outervalues); + ret->_typecheck = _typecheck; + ret->_nparamscheck = _nparamscheck; + return ret; + } + ~SQNativeClosure() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Release(){ + sq_delete(this,SQNativeClosure); + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_outervalues.resize(0);} +#endif + SQObjectPtr _env; + SQFUNCTION _function; + SQObjectPtr _name; + SQObjectPtrVec _outervalues; + SQIntVec _typecheck; + SQInteger _nparamscheck; +}; + + + +#endif //_SQCLOSURE_H_ diff --git a/src/squirrel/squirrel/sqcompiler.cpp b/src/squirrel/squirrel/sqcompiler.cpp index 464a0c0d0..a6bab092c 100644 --- a/src/squirrel/squirrel/sqcompiler.cpp +++ b/src/squirrel/squirrel/sqcompiler.cpp @@ -1,1214 +1,1214 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include -#include -#include "sqopcodes.h" -#include "sqstring.h" -#include "sqfuncproto.h" -#include "sqcompiler.h" -#include "sqfuncstate.h" -#include "sqlexer.h" -#include "sqvm.h" - -#define DEREF_NO_DEREF -1 -#define DEREF_FIELD -2 - -struct ExpState -{ - ExpState() - { - _deref = DEREF_NO_DEREF; - _freevar = false; - _class_or_delete = false; - _funcarg = false; - } - bool _class_or_delete; - bool _funcarg; - bool _freevar; - SQInteger _deref; -}; - -typedef sqvector ExpStateVec; - -#define _exst (_expstates.top()) - -#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ - SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ - _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0); - -#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \ - __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \ - if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \ - if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \ - _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();} - -class SQCompiler -{ -public: - SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) - { - _vm=v; - _lex.Init(_ss(v), rg, up,ThrowError,this); - _sourcename = SQString::Create(_ss(v), sourcename); - _lineinfo = lineinfo;_raiseerror = raiseerror; - compilererror = NULL; - } - static void ThrowError(void *ud, const SQChar *s) { - SQCompiler *c = (SQCompiler *)ud; - c->Error(s); - } - void Error(const SQChar *s, ...) - { - static SQChar temp[256]; - va_list vl; - va_start(vl, s); - scvsprintf(temp, s, vl); - va_end(vl); - compilererror = temp; - longjmp(_errorjmp,1); - } - void Lex(){ _token = _lex.Lex();} - void PushExpState(){ _expstates.push_back(ExpState()); } - bool IsDerefToken(SQInteger tok) - { - switch(tok){ - case _SC('='): case _SC('('): case TK_NEWSLOT: - case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true; - } - return false; - } - ExpState PopExpState() - { - ExpState ret = _expstates.top(); - _expstates.pop_back(); - return ret; - } - SQObject Expect(SQInteger tok) - { - - if(_token != tok) { - if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { - //ret = SQString::Create(_ss(_vm),_SC("constructor")); - //do nothing - } - else { - const SQChar *etypename; - if(tok > 255) { - switch(tok) - { - case TK_IDENTIFIER: - etypename = _SC("IDENTIFIER"); - break; - case TK_STRING_LITERAL: - etypename = _SC("STRING_LITERAL"); - break; - case TK_INTEGER: - etypename = _SC("INTEGER"); - break; - case TK_FLOAT: - etypename = _SC("FLOAT"); - break; - default: - etypename = _lex.Tok2Str(tok); - } - Error(_SC("expected '%s'"), etypename); - } - Error(_SC("expected '%c'"), tok); - } - } - SQObjectPtr ret; - switch(tok) - { - case TK_IDENTIFIER: - ret = _fs->CreateString(_lex._svalue); - break; - case TK_STRING_LITERAL: - ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); - break; - case TK_INTEGER: - ret = SQObjectPtr(_lex._nvalue); - break; - case TK_FLOAT: - ret = SQObjectPtr(_lex._fvalue); - break; - } - Lex(); - return ret; - } - bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); } - void OptionalSemicolon() - { - if(_token == _SC(';')) { Lex(); return; } - if(!IsEndOfStatement()) { - Error(_SC("end of statement expected (; or lf)")); - } - } - void MoveIfCurrentTargetIsLocal() { - SQInteger trg = _fs->TopTarget(); - if(_fs->IsLocal(trg)) { - trg = _fs->PopTarget(); //no pops the target and move it - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg); - } - } - bool Compile(SQObjectPtr &o) - { - _debugline = 1; - _debugop = 0; - - SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); - funcstate._name = SQString::Create(_ss(_vm), _SC("main")); - _fs = &funcstate; - _fs->AddParameter(_fs->CreateString(_SC("this"))); - _fs->_sourcename = _sourcename; - SQInteger stacksize = _fs->GetStackSize(); - if(setjmp(_errorjmp) == 0) { - Lex(); - while(_token > 0){ - Statement(); - if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); - } - CleanStack(stacksize); - _fs->AddLineInfos(_lex._currentline, _lineinfo, true); - _fs->AddInstruction(_OP_RETURN, 0xFF); - _fs->SetStackSize(0); - o =_fs->BuildProto(); -#ifdef _DEBUG_DUMP - _fs->Dump(_funcproto(o)); -#endif - } - else { - if(_raiseerror && _ss(_vm)->_compilererrorhandler) { - _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"), - _lex._currentline, _lex._currentcolumn); - } - _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1); - return false; - } - return true; - } - void Statements() - { - while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) { - Statement(); - if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); - } - } - void Statement() - { - _fs->AddLineInfos(_lex._currentline, _lineinfo); - switch(_token){ - case _SC(';'): Lex(); break; - case TK_IF: IfStatement(); break; - case TK_WHILE: WhileStatement(); break; - case TK_DO: DoWhileStatement(); break; - case TK_FOR: ForStatement(); break; - case TK_FOREACH: ForEachStatement(); break; - case TK_SWITCH: SwitchStatement(); break; - case TK_LOCAL: LocalDeclStatement(); break; - case TK_RETURN: - case TK_YIELD: { - SQOpcode op; - if(_token == TK_RETURN) { - op = _OP_RETURN; - - } - else { - op = _OP_YIELD; - _fs->_bgenerator = true; - } - Lex(); - if(!IsEndOfStatement()) { - SQInteger retexp = _fs->GetCurrentPos()+1; - CommaExpr(); - if(op == _OP_RETURN && _fs->_traps > 0) - _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); - _fs->_returnexp = retexp; - _fs->AddInstruction(op, 1, _fs->PopTarget()); - } - else{ - if(op == _OP_RETURN && _fs->_traps > 0) - _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); - _fs->_returnexp = -1; - _fs->AddInstruction(op, 0xFF); - } - break;} - case TK_BREAK: - if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block")); - if(_fs->_breaktargets.top() > 0){ - _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); - } - _fs->AddInstruction(_OP_JMP, 0, -1234); - _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); - Lex(); - break; - case TK_CONTINUE: - if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block")); - if(_fs->_continuetargets.top() > 0) { - _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); - } - _fs->AddInstruction(_OP_JMP, 0, -1234); - _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); - Lex(); - break; - case TK_FUNCTION: - FunctionStatement(); - break; - case TK_CLASS: - ClassStatement(); - break; - case _SC('{'):{ - SQInteger stacksize = _fs->GetStackSize(); - Lex(); - Statements(); - Expect(_SC('}')); - _fs->SetStackSize(stacksize); - } - break; - case TK_TRY: - TryCatchStatement(); - break; - case TK_THROW: - Lex(); - CommaExpr(); - _fs->AddInstruction(_OP_THROW, _fs->PopTarget()); - break; - default: - CommaExpr(); - _fs->PopTarget(); - break; - } - _fs->SnoozeOpt(); - } - void EmitDerefOp(SQOpcode op) - { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(op,_fs->PushTarget(),src,key,val); - } - void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0) - { - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->PopTarget(); //key in OP_GET - _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); - } - void EmitCompoundArith(SQInteger tok,bool deref) - { - SQInteger oper; - switch(tok){ - case TK_MINUSEQ: oper = '-'; break; - case TK_PLUSEQ: oper = '+'; break; - case TK_MULEQ: oper = '*'; break; - case TK_DIVEQ: oper = '/'; break; - case TK_MODEQ: oper = '%'; break; - default: oper = 0; //shut up compiler - assert(0); break; - }; - if(deref) { - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger src = _fs->PopTarget(); - //mixes dest obj and source val in the arg1(hack?) - _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper); - } - else { - Emit2ArgsOP(_OP_COMPARITHL, oper); - } - } - void CommaExpr() - { - for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); - } - ExpState Expression(bool funcarg = false) - { - PushExpState(); - _exst._class_or_delete = false; - _exst._funcarg = funcarg; - LogicalOrExp(); - switch(_token) { - case _SC('='): - case TK_NEWSLOT: - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ: - { - SQInteger op = _token; - SQInteger ds = _exst._deref; - bool freevar = _exst._freevar; - if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression")); - Lex(); Expression(); - - switch(op){ - case TK_NEWSLOT: - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_NEWSLOT); - else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - Error(_SC("can't 'create' a local slot")); - break; - case _SC('='): //ASSIGN - if(freevar) Error(_SC("free variables cannot be modified")); - if(ds == DEREF_FIELD) - EmitDerefOp(_OP_SET); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger p2 = _fs->PopTarget(); //src in OP_GET - SQInteger p1 = _fs->TopTarget(); //key in OP_GET - _fs->AddInstruction(_OP_MOVE, p1, p2); - } - break; - case TK_MINUSEQ: - case TK_PLUSEQ: - case TK_MULEQ: - case TK_DIVEQ: - case TK_MODEQ: - EmitCompoundArith(op,ds == DEREF_FIELD); - break; - } - } - break; - case _SC('?'): { - Lex(); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - SQInteger jzpos = _fs->GetCurrentPos(); - SQInteger trg = _fs->PushTarget(); - Expression(); - SQInteger first_exp = _fs->PopTarget(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - SQInteger endfirstexp = _fs->GetCurrentPos(); - _fs->AddInstruction(_OP_JMP, 0, 0); - Expect(_SC(':')); - SQInteger jmppos = _fs->GetCurrentPos(); - Expression(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); - _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1); - _fs->SnoozeOpt(); - } - break; - } - return PopExpState(); - } - void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0) - { - Lex(); (this->*f)(); - SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); - _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3); - } - void LogicalOrExp() - { - LogicalAndExp(); - for(;;) if(_token == TK_OR) { - SQInteger first_exp = _fs->PopTarget(); - SQInteger trg = _fs->PushTarget(); - _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0); - SQInteger jpos = _fs->GetCurrentPos(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - Lex(); LogicalOrExp(); - _fs->SnoozeOpt(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SnoozeOpt(); - _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); - break; - }else return; - } - void LogicalAndExp() - { - BitwiseOrExp(); - for(;;) switch(_token) { - case TK_AND: { - SQInteger first_exp = _fs->PopTarget(); - SQInteger trg = _fs->PushTarget(); - _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0); - SQInteger jpos = _fs->GetCurrentPos(); - if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); - Lex(); LogicalAndExp(); - _fs->SnoozeOpt(); - SQInteger second_exp = _fs->PopTarget(); - if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); - _fs->SnoozeOpt(); - _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); - break; - } - case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break; - case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break; - default: - return; - } - } - void BitwiseOrExp() - { - BitwiseXorExp(); - for(;;) if(_token == _SC('|')) - {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); - }else return; - } - void BitwiseXorExp() - { - BitwiseAndExp(); - for(;;) if(_token == _SC('^')) - {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR); - }else return; - } - void BitwiseAndExp() - { - CompExp(); - for(;;) if(_token == _SC('&')) - {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND); - }else return; - } - void CompExp() - { - ShiftExp(); - for(;;) switch(_token) { - case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break; - case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; - case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; - case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; - case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; - case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break; - default: return; - } - } - void ShiftExp() - { - PlusExp(); - for(;;) switch(_token) { - case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; - case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; - case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; - default: return; - } - } - void PlusExp() - { - MultExp(); - for(;;) switch(_token) { - case _SC('+'): case _SC('-'): - BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break; - default: return; - } - } - - void MultExp() - { - PrefixedExpr(); - for(;;) switch(_token) { - case _SC('*'): case _SC('/'): case _SC('%'): - BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break; - default: return; - } - } - //if 'pos' != -1 the previous variable is a local variable - void PrefixedExpr() - { - SQInteger pos = Factor(); - for(;;) { - switch(_token) { - case _SC('.'): { - pos = -1; - Lex(); - if(_token == TK_PARENT) { - Lex(); - if(!NeedGet()) - Error(_SC("parent cannot be set")); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - } - _exst._deref = DEREF_FIELD; - _exst._freevar = false; - } - break; - case _SC('['): - if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); - Lex(); Expression(); Expect(_SC(']')); - pos = -1; - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; - _exst._freevar = false; - break; - case TK_MINUSMINUS: - case TK_PLUSPLUS: - if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { - SQInteger tok = _token; Lex(); - if(pos < 0) - Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1); - else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1); - } - - } - return; - break; - case _SC('('): - { - if(_exst._deref != DEREF_NO_DEREF) { - if(pos<0) { - SQInteger key = _fs->PopTarget(); //key - SQInteger table = _fs->PopTarget(); //table etc... - SQInteger closure = _fs->PushTarget(); - SQInteger ttarget = _fs->PushTarget(); - _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); - } - else{ - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - } - } - else - _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); - _exst._deref = DEREF_NO_DEREF; - Lex(); - FunctionCallArgs(); - } - break; - default: return; - } - } - } - SQInteger Factor() - { - switch(_token) - { - case TK_STRING_LITERAL: { - //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1)); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); - Lex(); - } - break; - case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break; - case TK_VARGV: { Lex(); - Expect(_SC('[')); - Expression(); - Expect(_SC(']')); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src); - } - break; - case TK_IDENTIFIER: - case TK_CONSTRUCTOR: - case TK_THIS:{ - _exst._freevar = false; - SQObject id; - switch(_token) { - case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; - case TK_THIS: id = _fs->CreateString(_SC("this")); break; - case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break; - } - SQInteger pos = -1; - Lex(); - if((pos = _fs->GetLocalVariable(id)) == -1) { - //checks if is a free variable - if((pos = _fs->GetOuterVariable(id)) != -1) { - _exst._deref = _fs->PushTarget(); - _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); - _exst._freevar = true; - } else { - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(NeedGet()) Emit2ArgsOP(_OP_GET); - _exst._deref = DEREF_FIELD; - } - } - else{ - _fs->PushTarget(pos); - _exst._deref = pos; - } - return _exst._deref; - } - break; - case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break; - case TK_DOUBLE_COLON: // "::" - _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget()); - _exst._deref = DEREF_FIELD; - _token = _SC('.'); //hack - return -1; - break; - case TK_NULL: - _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); - Lex(); - break; - case TK_INTEGER: { - if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits? - _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue); - } - else { - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue)); - } - Lex(); - } - break; - case TK_FLOAT: - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); - Lex(); - break; - case TK_TRUE: case TK_FALSE: - _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); - Lex(); - break; - case _SC('['): { - _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget()); - SQInteger apos = _fs->GetCurrentPos(),key = 0; - Lex(); - while(_token != _SC(']')) { - Expression(); - if(_token == _SC(',')) Lex(); - SQInteger val = _fs->PopTarget(); - SQInteger array = _fs->TopTarget(); - _fs->AddInstruction(_OP_APPENDARRAY, array, val); - key++; - } - _fs->SetIntructionParam(apos, 1, key); - Lex(); - } - break; - case _SC('{'):{ - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); - Lex();ParseTableOrClass(_SC(',')); - } - break; - case TK_FUNCTION: FunctionExp(_token);break; - case TK_CLASS: Lex(); ClassExp();break; - case _SC('-'): UnaryOP(_OP_NEG); break; - case _SC('!'): UnaryOP(_OP_NOT); break; - case _SC('~'): UnaryOP(_OP_BWNOT); break; - case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break; - case TK_RESUME : UnaryOP(_OP_RESUME); break; - case TK_CLONE : UnaryOP(_OP_CLONE); break; - case TK_MINUSMINUS : - case TK_PLUSPLUS :PrefixIncDec(_token); break; - case TK_DELETE : DeleteExpr(); break; - case TK_DELEGATE : DelegateExpr(); break; - case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); - break; - default: Error(_SC("expression expected")); - } - return -1; - } - void UnaryOP(SQOpcode op) - { - Lex(); PrefixedExpr(); - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(op, _fs->PushTarget(), src); - } - bool NeedGet() - { - switch(_token) { - case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS: - case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ: - return false; - } - return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('['))); - } - - void FunctionCallArgs() - { - SQInteger nargs = 1;//this - while(_token != _SC(')')) { - Expression(true); - MoveIfCurrentTargetIsLocal(); - nargs++; - if(_token == _SC(',')){ - Lex(); - if(_token == ')') Error(_SC("expression expected, found ')'")); - } - } - Lex(); - for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget(); - SQInteger stackbase = _fs->PopTarget(); - SQInteger closure = _fs->PopTarget(); - _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); - } - void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}') - { - SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; - - while(_token != terminator) { - bool hasattrs = false; - bool isstatic = false; - //check if is an attribute - if(separator == ';') { - if(_token == TK_ATTR_OPEN) { - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex(); - ParseTableOrClass(',',TK_ATTR_CLOSE); - hasattrs = true; - } - if(_token == TK_STATIC) { - isstatic = true; - Lex(); - } - } - switch(_token) { - case TK_FUNCTION: - case TK_CONSTRUCTOR:{ - SQInteger tk = _token; - Lex(); - SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); - Expect(_SC('(')); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - } - break; - case _SC('['): - Lex(); CommaExpr(); Expect(_SC(']')); - Expect(_SC('=')); Expression(); - break; - default : - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); - Expect(_SC('=')); Expression(); - } - - if(_token == separator) Lex();//optional comma/semicolon - nkeys++; - SQInteger val = _fs->PopTarget(); - SQInteger key = _fs->PopTarget(); - SQInteger attrs = hasattrs ? _fs->PopTarget():-1; - assert(hasattrs && attrs == key-1 || !hasattrs); - unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); - SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOTA, flags, table, key, val); - //_fs->PopTarget(); - } - if(separator == _SC(',')) //hack recognizes a table from the separator - _fs->SetIntructionParam(tpos, 1, nkeys); - Lex(); - } - void LocalDeclStatement() - { - SQObject varname; - do { - Lex(); varname = Expect(TK_IDENTIFIER); - if(_token == _SC('=')) { - Lex(); Expression(); - SQInteger src = _fs->PopTarget(); - SQInteger dest = _fs->PushTarget(); - if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src); - } - else{ - _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); - } - _fs->PopTarget(); - _fs->PushLocalVariable(varname); - - } while(_token == _SC(',')); - } - void IfStatement() - { - SQInteger jmppos; - bool haselse = false; - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - SQInteger jnepos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); - - Statement(); - // - if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon(); - - CleanStack(stacksize); - SQInteger endifblock = _fs->GetCurrentPos(); - if(_token == TK_ELSE){ - haselse = true; - stacksize = _fs->GetStackSize(); - _fs->AddInstruction(_OP_JMP); - jmppos = _fs->GetCurrentPos(); - Lex(); - Statement(); OptionalSemicolon(); - CleanStack(stacksize); - _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); - } - _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); - } - void WhileStatement() - { - SQInteger jzpos, jmppos; - SQInteger stacksize = _fs->GetStackSize(); - jmppos = _fs->GetCurrentPos(); - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - - BEGIN_BREAKBLE_BLOCK(); - _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); - jzpos = _fs->GetCurrentPos(); - stacksize = _fs->GetStackSize(); - - Statement(); - - CleanStack(stacksize); - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); - _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - - END_BREAKBLE_BLOCK(jmppos); - } - void DoWhileStatement() - { - Lex(); - SQInteger jzpos = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); - BEGIN_BREAKBLE_BLOCK() - Statement(); - CleanStack(stacksize); - Expect(TK_WHILE); - SQInteger continuetrg = _fs->GetCurrentPos(); - Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1); - END_BREAKBLE_BLOCK(continuetrg); - } - void ForStatement() - { - Lex(); - SQInteger stacksize = _fs->GetStackSize(); - Expect(_SC('(')); - if(_token == TK_LOCAL) LocalDeclStatement(); - else if(_token != _SC(';')){ - CommaExpr(); - _fs->PopTarget(); - } - Expect(_SC(';')); - _fs->SnoozeOpt(); - SQInteger jmppos = _fs->GetCurrentPos(); - SQInteger jzpos = -1; - if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); } - Expect(_SC(';')); - _fs->SnoozeOpt(); - SQInteger expstart = _fs->GetCurrentPos() + 1; - if(_token != _SC(')')) { - CommaExpr(); - _fs->PopTarget(); - } - Expect(_SC(')')); - _fs->SnoozeOpt(); - SQInteger expend = _fs->GetCurrentPos(); - SQInteger expsize = (expend - expstart) + 1; - SQInstructionVec exp; - if(expsize > 0) { - for(SQInteger i = 0; i < expsize; i++) - exp.push_back(_fs->GetInstruction(expstart + i)); - _fs->PopInstructions(expsize); - } - BEGIN_BREAKBLE_BLOCK() - Statement(); - SQInteger continuetrg = _fs->GetCurrentPos(); - if(expsize > 0) { - for(SQInteger i = 0; i < expsize; i++) - _fs->AddInstruction(exp[i]); - } - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); - if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); - CleanStack(stacksize); - - END_BREAKBLE_BLOCK(continuetrg); - } - void ForEachStatement() - { - SQObject idxname, valname; - Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER); - if(_token == _SC(',')) { - idxname = valname; - Lex(); valname = Expect(TK_IDENTIFIER); - } - else{ - idxname = _fs->CreateString(_SC("@INDEX@")); - } - Expect(TK_IN); - - //save the stack size - SQInteger stacksize = _fs->GetStackSize(); - //put the table in the stack(evaluate the table expression) - Expression(); Expect(_SC(')')); - SQInteger container = _fs->TopTarget(); - //push the index local var - SQInteger indexpos = _fs->PushLocalVariable(idxname); - _fs->AddInstruction(_OP_LOADNULLS, indexpos,1); - //push the value local var - SQInteger valuepos = _fs->PushLocalVariable(valname); - _fs->AddInstruction(_OP_LOADNULLS, valuepos,1); - //push reference index - SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible - _fs->AddInstruction(_OP_LOADNULLS, itrpos,1); - SQInteger jmppos = _fs->GetCurrentPos(); - _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos); - SQInteger foreachpos = _fs->GetCurrentPos(); - //generate the statement code - BEGIN_BREAKBLE_BLOCK() - Statement(); - _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); - _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); - //restore the local variable stack(remove index,val and ref idx) - CleanStack(stacksize); - END_BREAKBLE_BLOCK(foreachpos - 1); - } - void SwitchStatement() - { - Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); - Expect(_SC('{')); - SQInteger expr = _fs->TopTarget(); - bool bfirst = true; - SQInteger tonextcondjmp = -1; - SQInteger skipcondjmp = -1; - SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); - _fs->_breaktargets.push_back(0); - while(_token == TK_CASE) { - //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one - if(!bfirst) { - _fs->AddInstruction(_OP_JMP, 0, 0); - skipcondjmp = _fs->GetCurrentPos(); - _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); - } - //condition - Lex(); Expression(); Expect(_SC(':')); - SQInteger trg = _fs->PopTarget(); - _fs->AddInstruction(_OP_EQ, trg, trg, expr); - _fs->AddInstruction(_OP_JZ, trg, 0); - //end condition - if(skipcondjmp != -1) { - _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); - } - tonextcondjmp = _fs->GetCurrentPos(); - SQInteger stacksize = _fs->GetStackSize(); - Statements(); - _fs->SetStackSize(stacksize); - bfirst = false; - } - if(tonextcondjmp != -1) - _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); - if(_token == TK_DEFAULT) { - // _fs->AddLineInfos(_lex._currentline, _lineinfo); - Lex(); Expect(_SC(':')); - SQInteger stacksize = _fs->GetStackSize(); - Statements(); - _fs->SetStackSize(stacksize); - } - Expect(_SC('}')); - _fs->PopTarget(); - __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; - if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); - _fs->_breaktargets.pop_back(); - - } - void FunctionStatement() - { - SQObject id; - Lex(); id = Expect(TK_IDENTIFIER); - _fs->PushTarget(0); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); - - while(_token == TK_DOUBLE_COLON) { - Lex(); - id = Expect(TK_IDENTIFIER); - _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); - if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); - } - Expect(_SC('(')); - CreateFunction(id); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); - EmitDerefOp(_OP_NEWSLOT); - _fs->PopTarget(); - } - void ClassStatement() - { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; - PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name")); - if(es._deref == DEREF_FIELD) { - ClassExp(); - EmitDerefOp(_OP_NEWSLOT); - _fs->PopTarget(); - } - else Error(_SC("cannot create a class in a local with the syntax(class )")); - } - void TryCatchStatement() - { - SQObject exid; - Lex(); - _fs->AddInstruction(_OP_PUSHTRAP,0,0); - _fs->_traps++; - if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; - if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; - SQInteger trappos = _fs->GetCurrentPos(); - Statement(); - _fs->_traps--; - _fs->AddInstruction(_OP_POPTRAP, 1, 0); - if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; - if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--; - _fs->AddInstruction(_OP_JMP, 0, 0); - SQInteger jmppos = _fs->GetCurrentPos(); - _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); - Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); - SQInteger stacksize = _fs->GetStackSize(); - SQInteger ex_target = _fs->PushLocalVariable(exid); - _fs->SetIntructionParam(trappos, 0, ex_target); - Statement(); - _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); - CleanStack(stacksize); - } - void FunctionExp(SQInteger ftype) - { - Lex(); Expect(_SC('(')); - CreateFunction(_null_); - _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); - } - void ClassExp() - { - SQInteger base = -1; - SQInteger attrs = -1; - if(_token == TK_EXTENDS) { - Lex(); Expression(); - base = _fs->TopTarget(); - } - if(_token == TK_ATTR_OPEN) { - Lex(); - _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); - ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); - attrs = _fs->TopTarget(); - } - Expect(_SC('{')); - if(attrs != -1) _fs->PopTarget(); - if(base != -1) _fs->PopTarget(); - _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs); - ParseTableOrClass(_SC(';')); - } - void DelegateExpr() - { - Lex(); CommaExpr(); - Expect(_SC(':')); - CommaExpr(); - SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget(); - _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate); - } - void DeleteExpr() - { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; - PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression")); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE); - else Error(_SC("cannot delete a local")); - } - void PrefixIncDec(SQInteger token) - { - ExpState es; - Lex(); PushExpState(); - _exst._class_or_delete = true; - _exst._funcarg = false; - PrefixedExpr(); - es = PopExpState(); - if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1); - else { - SQInteger src = _fs->PopTarget(); - _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1); - } - } - void CreateFunction(SQObject &name) - { - - SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); - funcstate->_name = name; - SQObject paramname; - funcstate->AddParameter(_fs->CreateString(_SC("this"))); - funcstate->_sourcename = _sourcename; - while(_token!=_SC(')')) { - if(_token == TK_VARPARAMS) { - funcstate->_varparams = true; - Lex(); - if(_token != _SC(')')) Error(_SC("expected ')'")); - break; - } - else { - paramname = Expect(TK_IDENTIFIER); - funcstate->AddParameter(paramname); - if(_token == _SC(',')) Lex(); - else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); - } - } - Expect(_SC(')')); - //outer values - if(_token == _SC(':')) { - Lex(); Expect(_SC('(')); - while(_token != _SC(')')) { - paramname = Expect(TK_IDENTIFIER); - //outers are treated as implicit local variables - funcstate->AddOuterValue(paramname); - if(_token == _SC(',')) Lex(); - else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); - } - Lex(); - } - - SQFuncState *currchunk = _fs; - _fs = funcstate; - Statement(); - funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); - funcstate->AddInstruction(_OP_RETURN, -1); - funcstate->SetStackSize(0); - //_fs->->_stacksize = _fs->_stacksize; - SQFunctionProto *func = funcstate->BuildProto(); -#ifdef _DEBUG_DUMP - funcstate->Dump(func); -#endif - _fs = currchunk; - _fs->_functions.push_back(func); - _fs->PopChildState(); - } - void CleanStack(SQInteger stacksize) - { - if(_fs->GetStackSize() != stacksize) - _fs->SetStackSize(stacksize); - } - void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) - { - while(ntoresolve > 0) { - SQInteger pos = funcstate->_unresolvedbreaks.back(); - funcstate->_unresolvedbreaks.pop_back(); - //set the jmp instruction - funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0); - ntoresolve--; - } - } - void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos) - { - while(ntoresolve > 0) { - SQInteger pos = funcstate->_unresolvedcontinues.back(); - funcstate->_unresolvedcontinues.pop_back(); - //set the jmp instruction - funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0); - ntoresolve--; - } - } -private: - SQInteger _token; - SQFuncState *_fs; - SQObjectPtr _sourcename; - SQLexer _lex; - bool _lineinfo; - bool _raiseerror; - SQInteger _debugline; - SQInteger _debugop; - ExpStateVec _expstates; - SQChar *compilererror; - jmp_buf _errorjmp; - SQVM *_vm; -}; - -bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo) -{ - SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); - return p.Compile(out); -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include +#include +#include "sqopcodes.h" +#include "sqstring.h" +#include "sqfuncproto.h" +#include "sqcompiler.h" +#include "sqfuncstate.h" +#include "sqlexer.h" +#include "sqvm.h" + +#define DEREF_NO_DEREF -1 +#define DEREF_FIELD -2 + +struct ExpState +{ + ExpState() + { + _deref = DEREF_NO_DEREF; + _freevar = false; + _class_or_delete = false; + _funcarg = false; + } + bool _class_or_delete; + bool _funcarg; + bool _freevar; + SQInteger _deref; +}; + +typedef sqvector ExpStateVec; + +#define _exst (_expstates.top()) + +#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ + SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ + _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0); + +#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \ + __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \ + if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \ + if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \ + _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();} + +class SQCompiler +{ +public: + SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) + { + _vm=v; + _lex.Init(_ss(v), rg, up,ThrowError,this); + _sourcename = SQString::Create(_ss(v), sourcename); + _lineinfo = lineinfo;_raiseerror = raiseerror; + compilererror = NULL; + } + static void ThrowError(void *ud, const SQChar *s) { + SQCompiler *c = (SQCompiler *)ud; + c->Error(s); + } + void Error(const SQChar *s, ...) + { + static SQChar temp[256]; + va_list vl; + va_start(vl, s); + scvsprintf(temp, s, vl); + va_end(vl); + compilererror = temp; + longjmp(_errorjmp,1); + } + void Lex(){ _token = _lex.Lex();} + void PushExpState(){ _expstates.push_back(ExpState()); } + bool IsDerefToken(SQInteger tok) + { + switch(tok){ + case _SC('='): case _SC('('): case TK_NEWSLOT: + case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true; + } + return false; + } + ExpState PopExpState() + { + ExpState ret = _expstates.top(); + _expstates.pop_back(); + return ret; + } + SQObject Expect(SQInteger tok) + { + + if(_token != tok) { + if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { + //ret = SQString::Create(_ss(_vm),_SC("constructor")); + //do nothing + } + else { + const SQChar *etypename; + if(tok > 255) { + switch(tok) + { + case TK_IDENTIFIER: + etypename = _SC("IDENTIFIER"); + break; + case TK_STRING_LITERAL: + etypename = _SC("STRING_LITERAL"); + break; + case TK_INTEGER: + etypename = _SC("INTEGER"); + break; + case TK_FLOAT: + etypename = _SC("FLOAT"); + break; + default: + etypename = _lex.Tok2Str(tok); + } + Error(_SC("expected '%s'"), etypename); + } + Error(_SC("expected '%c'"), tok); + } + } + SQObjectPtr ret; + switch(tok) + { + case TK_IDENTIFIER: + ret = _fs->CreateString(_lex._svalue); + break; + case TK_STRING_LITERAL: + ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); + break; + case TK_INTEGER: + ret = SQObjectPtr(_lex._nvalue); + break; + case TK_FLOAT: + ret = SQObjectPtr(_lex._fvalue); + break; + } + Lex(); + return ret; + } + bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); } + void OptionalSemicolon() + { + if(_token == _SC(';')) { Lex(); return; } + if(!IsEndOfStatement()) { + Error(_SC("end of statement expected (; or lf)")); + } + } + void MoveIfCurrentTargetIsLocal() { + SQInteger trg = _fs->TopTarget(); + if(_fs->IsLocal(trg)) { + trg = _fs->PopTarget(); //no pops the target and move it + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg); + } + } + bool Compile(SQObjectPtr &o) + { + _debugline = 1; + _debugop = 0; + + SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); + funcstate._name = SQString::Create(_ss(_vm), _SC("main")); + _fs = &funcstate; + _fs->AddParameter(_fs->CreateString(_SC("this"))); + _fs->_sourcename = _sourcename; + SQInteger stacksize = _fs->GetStackSize(); + if(setjmp(_errorjmp) == 0) { + Lex(); + while(_token > 0){ + Statement(); + if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); + } + CleanStack(stacksize); + _fs->AddLineInfos(_lex._currentline, _lineinfo, true); + _fs->AddInstruction(_OP_RETURN, 0xFF); + _fs->SetStackSize(0); + o =_fs->BuildProto(); +#ifdef _DEBUG_DUMP + _fs->Dump(_funcproto(o)); +#endif + } + else { + if(_raiseerror && _ss(_vm)->_compilererrorhandler) { + _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"), + _lex._currentline, _lex._currentcolumn); + } + _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1); + return false; + } + return true; + } + void Statements() + { + while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) { + Statement(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); + } + } + void Statement() + { + _fs->AddLineInfos(_lex._currentline, _lineinfo); + switch(_token){ + case _SC(';'): Lex(); break; + case TK_IF: IfStatement(); break; + case TK_WHILE: WhileStatement(); break; + case TK_DO: DoWhileStatement(); break; + case TK_FOR: ForStatement(); break; + case TK_FOREACH: ForEachStatement(); break; + case TK_SWITCH: SwitchStatement(); break; + case TK_LOCAL: LocalDeclStatement(); break; + case TK_RETURN: + case TK_YIELD: { + SQOpcode op; + if(_token == TK_RETURN) { + op = _OP_RETURN; + + } + else { + op = _OP_YIELD; + _fs->_bgenerator = true; + } + Lex(); + if(!IsEndOfStatement()) { + SQInteger retexp = _fs->GetCurrentPos()+1; + CommaExpr(); + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); + _fs->_returnexp = retexp; + _fs->AddInstruction(op, 1, _fs->PopTarget()); + } + else{ + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); + _fs->_returnexp = -1; + _fs->AddInstruction(op, 0xFF); + } + break;} + case TK_BREAK: + if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block")); + if(_fs->_breaktargets.top() > 0){ + _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); + } + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_CONTINUE: + if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block")); + if(_fs->_continuetargets.top() > 0) { + _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); + } + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_FUNCTION: + FunctionStatement(); + break; + case TK_CLASS: + ClassStatement(); + break; + case _SC('{'):{ + SQInteger stacksize = _fs->GetStackSize(); + Lex(); + Statements(); + Expect(_SC('}')); + _fs->SetStackSize(stacksize); + } + break; + case TK_TRY: + TryCatchStatement(); + break; + case TK_THROW: + Lex(); + CommaExpr(); + _fs->AddInstruction(_OP_THROW, _fs->PopTarget()); + break; + default: + CommaExpr(); + _fs->PopTarget(); + break; + } + _fs->SnoozeOpt(); + } + void EmitDerefOp(SQOpcode op) + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op,_fs->PushTarget(),src,key,val); + } + void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0) + { + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); + } + void EmitCompoundArith(SQInteger tok,bool deref) + { + SQInteger oper; + switch(tok){ + case TK_MINUSEQ: oper = '-'; break; + case TK_PLUSEQ: oper = '+'; break; + case TK_MULEQ: oper = '*'; break; + case TK_DIVEQ: oper = '/'; break; + case TK_MODEQ: oper = '%'; break; + default: oper = 0; //shut up compiler + assert(0); break; + }; + if(deref) { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + //mixes dest obj and source val in the arg1(hack?) + _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper); + } + else { + Emit2ArgsOP(_OP_COMPARITHL, oper); + } + } + void CommaExpr() + { + for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()); + } + ExpState Expression(bool funcarg = false) + { + PushExpState(); + _exst._class_or_delete = false; + _exst._funcarg = funcarg; + LogicalOrExp(); + switch(_token) { + case _SC('='): + case TK_NEWSLOT: + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + { + SQInteger op = _token; + SQInteger ds = _exst._deref; + bool freevar = _exst._freevar; + if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression")); + Lex(); Expression(); + + switch(op){ + case TK_NEWSLOT: + if(freevar) Error(_SC("free variables cannot be modified")); + if(ds == DEREF_FIELD) + EmitDerefOp(_OP_NEWSLOT); + else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + Error(_SC("can't 'create' a local slot")); + break; + case _SC('='): //ASSIGN + if(freevar) Error(_SC("free variables cannot be modified")); + if(ds == DEREF_FIELD) + EmitDerefOp(_OP_SET); + else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->TopTarget(); //key in OP_GET + _fs->AddInstruction(_OP_MOVE, p1, p2); + } + break; + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + EmitCompoundArith(op,ds == DEREF_FIELD); + break; + } + } + break; + case _SC('?'): { + Lex(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jzpos = _fs->GetCurrentPos(); + SQInteger trg = _fs->PushTarget(); + Expression(); + SQInteger first_exp = _fs->PopTarget(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + SQInteger endfirstexp = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_JMP, 0, 0); + Expect(_SC(':')); + SQInteger jmppos = _fs->GetCurrentPos(); + Expression(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1); + _fs->SnoozeOpt(); + } + break; + } + return PopExpState(); + } + void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0) + { + Lex(); (this->*f)(); + SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3); + } + void LogicalOrExp() + { + LogicalAndExp(); + for(;;) if(_token == TK_OR) { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); LogicalOrExp(); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + break; + }else return; + } + void LogicalAndExp() + { + BitwiseOrExp(); + for(;;) switch(_token) { + case TK_AND: { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); LogicalAndExp(); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + break; + } + case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break; + case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break; + default: + return; + } + } + void BitwiseOrExp() + { + BitwiseXorExp(); + for(;;) if(_token == _SC('|')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); + }else return; + } + void BitwiseXorExp() + { + BitwiseAndExp(); + for(;;) if(_token == _SC('^')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR); + }else return; + } + void BitwiseAndExp() + { + CompExp(); + for(;;) if(_token == _SC('&')) + {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND); + }else return; + } + void CompExp() + { + ShiftExp(); + for(;;) switch(_token) { + case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break; + case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; + case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; + case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; + case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; + case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break; + default: return; + } + } + void ShiftExp() + { + PlusExp(); + for(;;) switch(_token) { + case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; + case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; + case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; + default: return; + } + } + void PlusExp() + { + MultExp(); + for(;;) switch(_token) { + case _SC('+'): case _SC('-'): + BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break; + default: return; + } + } + + void MultExp() + { + PrefixedExpr(); + for(;;) switch(_token) { + case _SC('*'): case _SC('/'): case _SC('%'): + BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break; + default: return; + } + } + //if 'pos' != -1 the previous variable is a local variable + void PrefixedExpr() + { + SQInteger pos = Factor(); + for(;;) { + switch(_token) { + case _SC('.'): { + pos = -1; + Lex(); + if(_token == TK_PARENT) { + Lex(); + if(!NeedGet()) + Error(_SC("parent cannot be set")); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src); + } + else { + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + if(NeedGet()) Emit2ArgsOP(_OP_GET); + } + _exst._deref = DEREF_FIELD; + _exst._freevar = false; + } + break; + case _SC('['): + if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); + Lex(); Expression(); Expect(_SC(']')); + pos = -1; + if(NeedGet()) Emit2ArgsOP(_OP_GET); + _exst._deref = DEREF_FIELD; + _exst._freevar = false; + break; + case TK_MINUSMINUS: + case TK_PLUSPLUS: + if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { + SQInteger tok = _token; Lex(); + if(pos < 0) + Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1); + else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1); + } + + } + return; + break; + case _SC('('): + { + if(_exst._deref != DEREF_NO_DEREF) { + if(pos<0) { + SQInteger key = _fs->PopTarget(); //key + SQInteger table = _fs->PopTarget(); //table etc... + SQInteger closure = _fs->PushTarget(); + SQInteger ttarget = _fs->PushTarget(); + _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); + } + else{ + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + } + } + else + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + _exst._deref = DEREF_NO_DEREF; + Lex(); + FunctionCallArgs(); + } + break; + default: return; + } + } + } + SQInteger Factor() + { + switch(_token) + { + case TK_STRING_LITERAL: { + //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1)); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); + Lex(); + } + break; + case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break; + case TK_VARGV: { Lex(); + Expect(_SC('[')); + Expression(); + Expect(_SC(']')); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src); + } + break; + case TK_IDENTIFIER: + case TK_CONSTRUCTOR: + case TK_THIS:{ + _exst._freevar = false; + SQObject id; + switch(_token) { + case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; + case TK_THIS: id = _fs->CreateString(_SC("this")); break; + case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break; + } + SQInteger pos = -1; + Lex(); + if((pos = _fs->GetLocalVariable(id)) == -1) { + //checks if is a free variable + if((pos = _fs->GetOuterVariable(id)) != -1) { + _exst._deref = _fs->PushTarget(); + _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); + _exst._freevar = true; + } else { + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(NeedGet()) Emit2ArgsOP(_OP_GET); + _exst._deref = DEREF_FIELD; + } + } + else{ + _fs->PushTarget(pos); + _exst._deref = pos; + } + return _exst._deref; + } + break; + case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break; + case TK_DOUBLE_COLON: // "::" + _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget()); + _exst._deref = DEREF_FIELD; + _token = _SC('.'); //hack + return -1; + break; + case TK_NULL: + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + Lex(); + break; + case TK_INTEGER: { + if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits? + _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue); + } + else { + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue)); + } + Lex(); + } + break; + case TK_FLOAT: + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); + Lex(); + break; + case TK_TRUE: case TK_FALSE: + _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); + Lex(); + break; + case _SC('['): { + _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget()); + SQInteger apos = _fs->GetCurrentPos(),key = 0; + Lex(); + while(_token != _SC(']')) { + Expression(); + if(_token == _SC(',')) Lex(); + SQInteger val = _fs->PopTarget(); + SQInteger array = _fs->TopTarget(); + _fs->AddInstruction(_OP_APPENDARRAY, array, val); + key++; + } + _fs->SetIntructionParam(apos, 1, key); + Lex(); + } + break; + case _SC('{'):{ + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + Lex();ParseTableOrClass(_SC(',')); + } + break; + case TK_FUNCTION: FunctionExp(_token);break; + case TK_CLASS: Lex(); ClassExp();break; + case _SC('-'): UnaryOP(_OP_NEG); break; + case _SC('!'): UnaryOP(_OP_NOT); break; + case _SC('~'): UnaryOP(_OP_BWNOT); break; + case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break; + case TK_RESUME : UnaryOP(_OP_RESUME); break; + case TK_CLONE : UnaryOP(_OP_CLONE); break; + case TK_MINUSMINUS : + case TK_PLUSPLUS :PrefixIncDec(_token); break; + case TK_DELETE : DeleteExpr(); break; + case TK_DELEGATE : DelegateExpr(); break; + case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); + break; + default: Error(_SC("expression expected")); + } + return -1; + } + void UnaryOP(SQOpcode op) + { + Lex(); PrefixedExpr(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), src); + } + bool NeedGet() + { + switch(_token) { + case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS: + case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ: + return false; + } + return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('['))); + } + + void FunctionCallArgs() + { + SQInteger nargs = 1;//this + while(_token != _SC(')')) { + Expression(true); + MoveIfCurrentTargetIsLocal(); + nargs++; + if(_token == _SC(',')){ + Lex(); + if(_token == ')') Error(_SC("expression expected, found ')'")); + } + } + Lex(); + for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget(); + SQInteger stackbase = _fs->PopTarget(); + SQInteger closure = _fs->PopTarget(); + _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); + } + void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}') + { + SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; + + while(_token != terminator) { + bool hasattrs = false; + bool isstatic = false; + //check if is an attribute + if(separator == ';') { + if(_token == TK_ATTR_OPEN) { + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex(); + ParseTableOrClass(',',TK_ATTR_CLOSE); + hasattrs = true; + } + if(_token == TK_STATIC) { + isstatic = true; + Lex(); + } + } + switch(_token) { + case TK_FUNCTION: + case TK_CONSTRUCTOR:{ + SQInteger tk = _token; + Lex(); + SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); + Expect(_SC('(')); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + } + break; + case _SC('['): + Lex(); CommaExpr(); Expect(_SC(']')); + Expect(_SC('=')); Expression(); + break; + default : + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + Expect(_SC('=')); Expression(); + } + + if(_token == separator) Lex();//optional comma/semicolon + nkeys++; + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger attrs = hasattrs ? _fs->PopTarget():-1; + assert(hasattrs && attrs == key-1 || !hasattrs); + unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); + SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOTA, flags, table, key, val); + //_fs->PopTarget(); + } + if(separator == _SC(',')) //hack recognizes a table from the separator + _fs->SetIntructionParam(tpos, 1, nkeys); + Lex(); + } + void LocalDeclStatement() + { + SQObject varname; + do { + Lex(); varname = Expect(TK_IDENTIFIER); + if(_token == _SC('=')) { + Lex(); Expression(); + SQInteger src = _fs->PopTarget(); + SQInteger dest = _fs->PushTarget(); + if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src); + } + else{ + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + } + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + + } while(_token == _SC(',')); + } + void IfStatement() + { + SQInteger jmppos; + bool haselse = false; + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jnepos = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + + Statement(); + // + if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon(); + + CleanStack(stacksize); + SQInteger endifblock = _fs->GetCurrentPos(); + if(_token == TK_ELSE){ + haselse = true; + stacksize = _fs->GetStackSize(); + _fs->AddInstruction(_OP_JMP); + jmppos = _fs->GetCurrentPos(); + Lex(); + Statement(); OptionalSemicolon(); + CleanStack(stacksize); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + } + _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); + } + void WhileStatement() + { + SQInteger jzpos, jmppos; + SQInteger stacksize = _fs->GetStackSize(); + jmppos = _fs->GetCurrentPos(); + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + + BEGIN_BREAKBLE_BLOCK(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + jzpos = _fs->GetCurrentPos(); + stacksize = _fs->GetStackSize(); + + Statement(); + + CleanStack(stacksize); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); + + END_BREAKBLE_BLOCK(jmppos); + } + void DoWhileStatement() + { + Lex(); + SQInteger jzpos = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + BEGIN_BREAKBLE_BLOCK() + Statement(); + CleanStack(stacksize); + Expect(TK_WHILE); + SQInteger continuetrg = _fs->GetCurrentPos(); + Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1); + END_BREAKBLE_BLOCK(continuetrg); + } + void ForStatement() + { + Lex(); + SQInteger stacksize = _fs->GetStackSize(); + Expect(_SC('(')); + if(_token == TK_LOCAL) LocalDeclStatement(); + else if(_token != _SC(';')){ + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger jmppos = _fs->GetCurrentPos(); + SQInteger jzpos = -1; + if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger expstart = _fs->GetCurrentPos() + 1; + if(_token != _SC(')')) { + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(')')); + _fs->SnoozeOpt(); + SQInteger expend = _fs->GetCurrentPos(); + SQInteger expsize = (expend - expstart) + 1; + SQInstructionVec exp; + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + exp.push_back(_fs->GetInstruction(expstart + i)); + _fs->PopInstructions(expsize); + } + BEGIN_BREAKBLE_BLOCK() + Statement(); + SQInteger continuetrg = _fs->GetCurrentPos(); + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + _fs->AddInstruction(exp[i]); + } + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); + if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); + CleanStack(stacksize); + + END_BREAKBLE_BLOCK(continuetrg); + } + void ForEachStatement() + { + SQObject idxname, valname; + Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER); + if(_token == _SC(',')) { + idxname = valname; + Lex(); valname = Expect(TK_IDENTIFIER); + } + else{ + idxname = _fs->CreateString(_SC("@INDEX@")); + } + Expect(TK_IN); + + //save the stack size + SQInteger stacksize = _fs->GetStackSize(); + //put the table in the stack(evaluate the table expression) + Expression(); Expect(_SC(')')); + SQInteger container = _fs->TopTarget(); + //push the index local var + SQInteger indexpos = _fs->PushLocalVariable(idxname); + _fs->AddInstruction(_OP_LOADNULLS, indexpos,1); + //push the value local var + SQInteger valuepos = _fs->PushLocalVariable(valname); + _fs->AddInstruction(_OP_LOADNULLS, valuepos,1); + //push reference index + SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible + _fs->AddInstruction(_OP_LOADNULLS, itrpos,1); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos); + SQInteger foreachpos = _fs->GetCurrentPos(); + //generate the statement code + BEGIN_BREAKBLE_BLOCK() + Statement(); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); + //restore the local variable stack(remove index,val and ref idx) + CleanStack(stacksize); + END_BREAKBLE_BLOCK(foreachpos - 1); + } + void SwitchStatement() + { + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + Expect(_SC('{')); + SQInteger expr = _fs->TopTarget(); + bool bfirst = true; + SQInteger tonextcondjmp = -1; + SQInteger skipcondjmp = -1; + SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); + _fs->_breaktargets.push_back(0); + while(_token == TK_CASE) { + //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one + if(!bfirst) { + _fs->AddInstruction(_OP_JMP, 0, 0); + skipcondjmp = _fs->GetCurrentPos(); + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + } + //condition + Lex(); Expression(); Expect(_SC(':')); + SQInteger trg = _fs->PopTarget(); + _fs->AddInstruction(_OP_EQ, trg, trg, expr); + _fs->AddInstruction(_OP_JZ, trg, 0); + //end condition + if(skipcondjmp != -1) { + _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); + } + tonextcondjmp = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + Statements(); + _fs->SetStackSize(stacksize); + bfirst = false; + } + if(tonextcondjmp != -1) + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + if(_token == TK_DEFAULT) { + // _fs->AddLineInfos(_lex._currentline, _lineinfo); + Lex(); Expect(_SC(':')); + SQInteger stacksize = _fs->GetStackSize(); + Statements(); + _fs->SetStackSize(stacksize); + } + Expect(_SC('}')); + _fs->PopTarget(); + __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; + if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); + _fs->_breaktargets.pop_back(); + + } + void FunctionStatement() + { + SQObject id; + Lex(); id = Expect(TK_IDENTIFIER); + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + + while(_token == TK_DOUBLE_COLON) { + Lex(); + id = Expect(TK_IDENTIFIER); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + } + Expect(_SC('(')); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + void ClassStatement() + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name")); + if(es._deref == DEREF_FIELD) { + ClassExp(); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + else Error(_SC("cannot create a class in a local with the syntax(class )")); + } + void TryCatchStatement() + { + SQObject exid; + Lex(); + _fs->AddInstruction(_OP_PUSHTRAP,0,0); + _fs->_traps++; + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; + SQInteger trappos = _fs->GetCurrentPos(); + Statement(); + _fs->_traps--; + _fs->AddInstruction(_OP_POPTRAP, 1, 0); + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--; + _fs->AddInstruction(_OP_JMP, 0, 0); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); + Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); + SQInteger stacksize = _fs->GetStackSize(); + SQInteger ex_target = _fs->PushLocalVariable(exid); + _fs->SetIntructionParam(trappos, 0, ex_target); + Statement(); + _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); + CleanStack(stacksize); + } + void FunctionExp(SQInteger ftype) + { + Lex(); Expect(_SC('(')); + CreateFunction(_null_); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); + } + void ClassExp() + { + SQInteger base = -1; + SQInteger attrs = -1; + if(_token == TK_EXTENDS) { + Lex(); Expression(); + base = _fs->TopTarget(); + } + if(_token == TK_ATTR_OPEN) { + Lex(); + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); + attrs = _fs->TopTarget(); + } + Expect(_SC('{')); + if(attrs != -1) _fs->PopTarget(); + if(base != -1) _fs->PopTarget(); + _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs); + ParseTableOrClass(_SC(';')); + } + void DelegateExpr() + { + Lex(); CommaExpr(); + Expect(_SC(':')); + CommaExpr(); + SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget(); + _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate); + } + void DeleteExpr() + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression")); + if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE); + else Error(_SC("cannot delete a local")); + } + void PrefixIncDec(SQInteger token) + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1); + else { + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1); + } + } + void CreateFunction(SQObject &name) + { + + SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); + funcstate->_name = name; + SQObject paramname; + funcstate->AddParameter(_fs->CreateString(_SC("this"))); + funcstate->_sourcename = _sourcename; + while(_token!=_SC(')')) { + if(_token == TK_VARPARAMS) { + funcstate->_varparams = true; + Lex(); + if(_token != _SC(')')) Error(_SC("expected ')'")); + break; + } + else { + paramname = Expect(TK_IDENTIFIER); + funcstate->AddParameter(paramname); + if(_token == _SC(',')) Lex(); + else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); + } + } + Expect(_SC(')')); + //outer values + if(_token == _SC(':')) { + Lex(); Expect(_SC('(')); + while(_token != _SC(')')) { + paramname = Expect(TK_IDENTIFIER); + //outers are treated as implicit local variables + funcstate->AddOuterValue(paramname); + if(_token == _SC(',')) Lex(); + else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); + } + Lex(); + } + + SQFuncState *currchunk = _fs; + _fs = funcstate; + Statement(); + funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); + funcstate->AddInstruction(_OP_RETURN, -1); + funcstate->SetStackSize(0); + //_fs->->_stacksize = _fs->_stacksize; + SQFunctionProto *func = funcstate->BuildProto(); +#ifdef _DEBUG_DUMP + funcstate->Dump(func); +#endif + _fs = currchunk; + _fs->_functions.push_back(func); + _fs->PopChildState(); + } + void CleanStack(SQInteger stacksize) + { + if(_fs->GetStackSize() != stacksize) + _fs->SetStackSize(stacksize); + } + void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedbreaks.back(); + funcstate->_unresolvedbreaks.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0); + ntoresolve--; + } + } + void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedcontinues.back(); + funcstate->_unresolvedcontinues.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0); + ntoresolve--; + } + } +private: + SQInteger _token; + SQFuncState *_fs; + SQObjectPtr _sourcename; + SQLexer _lex; + bool _lineinfo; + bool _raiseerror; + SQInteger _debugline; + SQInteger _debugop; + ExpStateVec _expstates; + SQChar *compilererror; + jmp_buf _errorjmp; + SQVM *_vm; +}; + +bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo) +{ + SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo); + return p.Compile(out); +} diff --git a/src/squirrel/squirrel/sqcompiler.h b/src/squirrel/squirrel/sqcompiler.h index ea0a831f7..ed2a89baa 100644 --- a/src/squirrel/squirrel/sqcompiler.h +++ b/src/squirrel/squirrel/sqcompiler.h @@ -1,75 +1,75 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQCOMPILER_H_ -#define _SQCOMPILER_H_ - -struct SQVM; - -#define TK_IDENTIFIER 258 -#define TK_STRING_LITERAL 259 -#define TK_INTEGER 260 -#define TK_FLOAT 261 -#define TK_DELEGATE 262 -#define TK_DELETE 263 -#define TK_EQ 264 -#define TK_NE 265 -#define TK_LE 266 -#define TK_GE 267 -#define TK_SWITCH 268 -#define TK_ARROW 269 -#define TK_AND 270 -#define TK_OR 271 -#define TK_IF 272 -#define TK_ELSE 273 -#define TK_WHILE 274 -#define TK_BREAK 275 -#define TK_FOR 276 -#define TK_DO 277 -#define TK_NULL 278 -#define TK_FOREACH 279 -#define TK_IN 280 -#define TK_NEWSLOT 281 -#define TK_MODULO 282 -#define TK_LOCAL 283 -#define TK_CLONE 284 -#define TK_FUNCTION 285 -#define TK_RETURN 286 -#define TK_TYPEOF 287 -#define TK_UMINUS 288 -#define TK_PLUSEQ 289 -#define TK_MINUSEQ 290 -#define TK_CONTINUE 291 -#define TK_YIELD 292 -#define TK_TRY 293 -#define TK_CATCH 294 -#define TK_THROW 295 -#define TK_SHIFTL 296 -#define TK_SHIFTR 297 -#define TK_RESUME 298 -#define TK_DOUBLE_COLON 299 -#define TK_CASE 300 -#define TK_DEFAULT 301 -#define TK_THIS 302 -#define TK_PLUSPLUS 303 -#define TK_MINUSMINUS 304 -#define TK_PARENT 305 -#define TK_USHIFTR 306 -#define TK_CLASS 307 -#define TK_EXTENDS 308 -#define TK_CONSTRUCTOR 310 -#define TK_INSTANCEOF 311 -#define TK_VARPARAMS 312 -#define TK_VARGC 313 -#define TK_VARGV 314 -#define TK_TRUE 315 -#define TK_FALSE 316 -#define TK_MULEQ 317 -#define TK_DIVEQ 318 -#define TK_MODEQ 319 -#define TK_ATTR_OPEN 320 -#define TK_ATTR_CLOSE 321 -#define TK_STATIC 322 - - -typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s); -bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo); -#endif //_SQCOMPILER_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQCOMPILER_H_ +#define _SQCOMPILER_H_ + +struct SQVM; + +#define TK_IDENTIFIER 258 +#define TK_STRING_LITERAL 259 +#define TK_INTEGER 260 +#define TK_FLOAT 261 +#define TK_DELEGATE 262 +#define TK_DELETE 263 +#define TK_EQ 264 +#define TK_NE 265 +#define TK_LE 266 +#define TK_GE 267 +#define TK_SWITCH 268 +#define TK_ARROW 269 +#define TK_AND 270 +#define TK_OR 271 +#define TK_IF 272 +#define TK_ELSE 273 +#define TK_WHILE 274 +#define TK_BREAK 275 +#define TK_FOR 276 +#define TK_DO 277 +#define TK_NULL 278 +#define TK_FOREACH 279 +#define TK_IN 280 +#define TK_NEWSLOT 281 +#define TK_MODULO 282 +#define TK_LOCAL 283 +#define TK_CLONE 284 +#define TK_FUNCTION 285 +#define TK_RETURN 286 +#define TK_TYPEOF 287 +#define TK_UMINUS 288 +#define TK_PLUSEQ 289 +#define TK_MINUSEQ 290 +#define TK_CONTINUE 291 +#define TK_YIELD 292 +#define TK_TRY 293 +#define TK_CATCH 294 +#define TK_THROW 295 +#define TK_SHIFTL 296 +#define TK_SHIFTR 297 +#define TK_RESUME 298 +#define TK_DOUBLE_COLON 299 +#define TK_CASE 300 +#define TK_DEFAULT 301 +#define TK_THIS 302 +#define TK_PLUSPLUS 303 +#define TK_MINUSMINUS 304 +#define TK_PARENT 305 +#define TK_USHIFTR 306 +#define TK_CLASS 307 +#define TK_EXTENDS 308 +#define TK_CONSTRUCTOR 310 +#define TK_INSTANCEOF 311 +#define TK_VARPARAMS 312 +#define TK_VARGC 313 +#define TK_VARGV 314 +#define TK_TRUE 315 +#define TK_FALSE 316 +#define TK_MULEQ 317 +#define TK_DIVEQ 318 +#define TK_MODEQ 319 +#define TK_ATTR_OPEN 320 +#define TK_ATTR_CLOSE 321 +#define TK_STATIC 322 + + +typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s); +bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo); +#endif //_SQCOMPILER_H_ diff --git a/src/squirrel/squirrel/sqdebug.cpp b/src/squirrel/squirrel/sqdebug.cpp index 732bd0173..96da72d2d 100644 --- a/src/squirrel/squirrel/sqdebug.cpp +++ b/src/squirrel/squirrel/sqdebug.cpp @@ -1,99 +1,99 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include -#include "sqvm.h" -#include "sqfuncproto.h" -#include "sqclosure.h" -#include "sqstring.h" - -SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si) -{ - SQInteger cssize = v->_callsstack.size(); - if (cssize > level) { - memset(si, 0, sizeof(SQStackInfos)); - SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; - switch (type(ci._closure)) { - case OT_CLOSURE:{ - SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function); - if (type(func->_name) == OT_STRING) - si->funcname = _stringval(func->_name); - if (type(func->_sourcename) == OT_STRING) - si->source = _stringval(func->_sourcename); - si->line = func->GetLine(ci._ip); - } - break; - case OT_NATIVECLOSURE: - si->source = _SC("NATIVE"); - si->funcname = _SC("unknown"); - if(type(_nativeclosure(ci._closure)->_name) == OT_STRING) - si->funcname = _stringval(_nativeclosure(ci._closure)->_name); - si->line = -1; - break; - default: break; //shutup compiler - } - return SQ_OK; - } - return SQ_ERROR; -} - -void SQVM::Raise_Error(const SQChar *s, ...) -{ - va_list vl; - va_start(vl, s); - scvsprintf(_sp(rsl((SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl); - va_end(vl); - _lasterror = SQString::Create(_ss(this),_spval,-1); -} - -void SQVM::Raise_Error(SQObjectPtr &desc) -{ - _lasterror = desc; -} - -SQString *SQVM::PrintObjVal(const SQObject &o) -{ - switch(type(o)) { - case OT_STRING: return _string(o); - case OT_INTEGER: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o)); - return SQString::Create(_ss(this), _spval); - break; - case OT_FLOAT: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o)); - return SQString::Create(_ss(this), _spval); - break; - default: - return SQString::Create(_ss(this), GetTypeName(o)); - } -} - -void SQVM::Raise_IdxError(SQObject &o) -{ - SQObjectPtr oval = PrintObjVal(o); - Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); -} - -void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) -{ - SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); - Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); -} - - -void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type) -{ - SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); - SQInteger found = 0; - for(SQInteger i=0; i<16; i++) - { - SQInteger mask = 0x00000001 << i; - if(typemask & (mask)) { - if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes); - found ++; - StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes); - } - } - Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)); -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include +#include "sqvm.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqstring.h" + +SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si) +{ + SQInteger cssize = v->_callsstack.size(); + if (cssize > level) { + memset(si, 0, sizeof(SQStackInfos)); + SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; + switch (type(ci._closure)) { + case OT_CLOSURE:{ + SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function); + if (type(func->_name) == OT_STRING) + si->funcname = _stringval(func->_name); + if (type(func->_sourcename) == OT_STRING) + si->source = _stringval(func->_sourcename); + si->line = func->GetLine(ci._ip); + } + break; + case OT_NATIVECLOSURE: + si->source = _SC("NATIVE"); + si->funcname = _SC("unknown"); + if(type(_nativeclosure(ci._closure)->_name) == OT_STRING) + si->funcname = _stringval(_nativeclosure(ci._closure)->_name); + si->line = -1; + break; + default: break; //shutup compiler + } + return SQ_OK; + } + return SQ_ERROR; +} + +void SQVM::Raise_Error(const SQChar *s, ...) +{ + va_list vl; + va_start(vl, s); + scvsprintf(_sp(rsl((SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl); + va_end(vl); + _lasterror = SQString::Create(_ss(this),_spval,-1); +} + +void SQVM::Raise_Error(SQObjectPtr &desc) +{ + _lasterror = desc; +} + +SQString *SQVM::PrintObjVal(const SQObject &o) +{ + switch(type(o)) { + case OT_STRING: return _string(o); + case OT_INTEGER: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o)); + return SQString::Create(_ss(this), _spval); + break; + case OT_FLOAT: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o)); + return SQString::Create(_ss(this), _spval); + break; + default: + return SQString::Create(_ss(this), GetTypeName(o)); + } +} + +void SQVM::Raise_IdxError(SQObject &o) +{ + SQObjectPtr oval = PrintObjVal(o); + Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); +} + +void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) +{ + SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); + Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); +} + + +void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type) +{ + SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); + SQInteger found = 0; + for(SQInteger i=0; i<16; i++) + { + SQInteger mask = 0x00000001 << i; + if(typemask & (mask)) { + if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes); + found ++; + StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes); + } + } + Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)); +} diff --git a/src/squirrel/squirrel/sqfuncproto.h b/src/squirrel/squirrel/sqfuncproto.h index b4079b0bf..6444fbfc3 100644 --- a/src/squirrel/squirrel/sqfuncproto.h +++ b/src/squirrel/squirrel/sqfuncproto.h @@ -1,88 +1,88 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQFUNCTION_H_ -#define _SQFUNCTION_H_ - -#include "sqopcodes.h" - -enum SQOuterType { - otLOCAL = 0, - otSYMBOL = 1, - otOUTER = 2 -}; - -struct SQOuterVar -{ - - SQOuterVar(){} - SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t) - { - _name = name; - _src=src; - _type=t; - } - SQOuterVar(const SQOuterVar &ov) - { - _type=ov._type; - _src=ov._src; - _name=ov._name; - } - SQOuterType _type; - SQObjectPtr _name; - SQObjectPtr _src; -}; - -struct SQLocalVarInfo -{ - SQLocalVarInfo():_start_op(0),_end_op(0){} - SQLocalVarInfo(const SQLocalVarInfo &lvi) - { - _name=lvi._name; - _start_op=lvi._start_op; - _end_op=lvi._end_op; - _pos=lvi._pos; - } - SQObjectPtr _name; - SQUnsignedInteger _start_op; - SQUnsignedInteger _end_op; - SQUnsignedInteger _pos; -}; - -struct SQLineInfo { SQInteger _line;SQInteger _op; }; - -typedef sqvector SQOuterVarVec; -typedef sqvector SQLocalVarInfoVec; -typedef sqvector SQLineInfoVec; - -struct SQFunctionProto : public SQRefCounted -{ -private: - SQFunctionProto(){ - _stacksize=0; - _bgenerator=false;} -public: - static SQFunctionProto *Create() - { - SQFunctionProto *f; - sq_new(f,SQFunctionProto); - return f; - } - void Release(){ sq_delete(this,SQFunctionProto);} - const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); - SQInteger GetLine(SQInstruction *curr); - bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); - bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read); - SQObjectPtrVec _literals; - SQObjectPtrVec _functions; - SQObjectPtrVec _parameters; - SQOuterVarVec _outervalues; - SQInstructionVec _instructions; - SQObjectPtr _sourcename; - SQObjectPtr _name; - SQLocalVarInfoVec _localvarinfos; - SQLineInfoVec _lineinfos; - SQInteger _stacksize; - bool _bgenerator; - bool _varparams; -}; - -#endif //_SQFUNCTION_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQFUNCTION_H_ +#define _SQFUNCTION_H_ + +#include "sqopcodes.h" + +enum SQOuterType { + otLOCAL = 0, + otSYMBOL = 1, + otOUTER = 2 +}; + +struct SQOuterVar +{ + + SQOuterVar(){} + SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t) + { + _name = name; + _src=src; + _type=t; + } + SQOuterVar(const SQOuterVar &ov) + { + _type=ov._type; + _src=ov._src; + _name=ov._name; + } + SQOuterType _type; + SQObjectPtr _name; + SQObjectPtr _src; +}; + +struct SQLocalVarInfo +{ + SQLocalVarInfo():_start_op(0),_end_op(0){} + SQLocalVarInfo(const SQLocalVarInfo &lvi) + { + _name=lvi._name; + _start_op=lvi._start_op; + _end_op=lvi._end_op; + _pos=lvi._pos; + } + SQObjectPtr _name; + SQUnsignedInteger _start_op; + SQUnsignedInteger _end_op; + SQUnsignedInteger _pos; +}; + +struct SQLineInfo { SQInteger _line;SQInteger _op; }; + +typedef sqvector SQOuterVarVec; +typedef sqvector SQLocalVarInfoVec; +typedef sqvector SQLineInfoVec; + +struct SQFunctionProto : public SQRefCounted +{ +private: + SQFunctionProto(){ + _stacksize=0; + _bgenerator=false;} +public: + static SQFunctionProto *Create() + { + SQFunctionProto *f; + sq_new(f,SQFunctionProto); + return f; + } + void Release(){ sq_delete(this,SQFunctionProto);} + const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); + SQInteger GetLine(SQInstruction *curr); + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read); + SQObjectPtrVec _literals; + SQObjectPtrVec _functions; + SQObjectPtrVec _parameters; + SQOuterVarVec _outervalues; + SQInstructionVec _instructions; + SQObjectPtr _sourcename; + SQObjectPtr _name; + SQLocalVarInfoVec _localvarinfos; + SQLineInfoVec _lineinfos; + SQInteger _stacksize; + bool _bgenerator; + bool _varparams; +}; + +#endif //_SQFUNCTION_H_ diff --git a/src/squirrel/squirrel/sqfuncstate.cpp b/src/squirrel/squirrel/sqfuncstate.cpp index b98670723..2ceb1b471 100644 --- a/src/squirrel/squirrel/sqfuncstate.cpp +++ b/src/squirrel/squirrel/sqfuncstate.cpp @@ -1,544 +1,544 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqcompiler.h" -#include "sqfuncproto.h" -#include "sqstring.h" -#include "sqtable.h" -#include "sqopcodes.h" -#include "sqfuncstate.h" - -#ifdef _DEBUG_DUMP -SQInstructionDesc g_InstrDesc[]={ - {_SC("_OP_LINE")}, - {_SC("_OP_LOAD")}, - {_SC("_OP_LOADINT")}, - {_SC("_OP_DLOAD")}, - {_SC("_OP_TAILCALL")}, - {_SC("_OP_CALL")}, - {_SC("_OP_PREPCALL")}, - {_SC("_OP_PREPCALLK")}, - {_SC("_OP_GETK")}, - {_SC("_OP_MOVE")}, - {_SC("_OP_NEWSLOT")}, - {_SC("_OP_DELETE")}, - {_SC("_OP_SET")}, - {_SC("_OP_GET")}, - {_SC("_OP_EQ")}, - {_SC("_OP_NE")}, - {_SC("_OP_ARITH")}, - {_SC("_OP_BITW")}, - {_SC("_OP_RETURN")}, - {_SC("_OP_LOADNULLS")}, - {_SC("_OP_LOADROOTTABLE")}, - {_SC("_OP_LOADBOOL")}, - {_SC("_OP_DMOVE")}, - {_SC("_OP_JMP")}, - {_SC("_OP_JNZ")}, - {_SC("_OP_JZ")}, - {_SC("_OP_LOADFREEVAR")}, - {_SC("_OP_VARGC")}, - {_SC("_OP_GETVARGV")}, - {_SC("_OP_NEWTABLE")}, - {_SC("_OP_NEWARRAY")}, - {_SC("_OP_APPENDARRAY")}, - {_SC("_OP_GETPARENT")}, - {_SC("_OP_COMPARITH")}, - {_SC("_OP_COMPARITHL")}, - {_SC("_OP_INC")}, - {_SC("_OP_INCL")}, - {_SC("_OP_PINC")}, - {_SC("_OP_PINCL")}, - {_SC("_OP_CMP")}, - {_SC("_OP_EXISTS")}, - {_SC("_OP_INSTANCEOF")}, - {_SC("_OP_AND")}, - {_SC("_OP_OR")}, - {_SC("_OP_NEG")}, - {_SC("_OP_NOT")}, - {_SC("_OP_BWNOT")}, - {_SC("_OP_CLOSURE")}, - {_SC("_OP_YIELD")}, - {_SC("_OP_RESUME")}, - {_SC("_OP_FOREACH")}, - {_SC("_OP_DELEGATE")}, - {_SC("_OP_CLONE")}, - {_SC("_OP_TYPEOF")}, - {_SC("_OP_PUSHTRAP")}, - {_SC("_OP_POPTRAP")}, - {_SC("_OP_THROW")}, - {_SC("_OP_CLASS")}, - {_SC("_OP_NEWSLOTA")} -}; -#endif -void DumpLiteral(SQObjectPtr &o) -{ - switch(type(o)){ - case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; - case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; - case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break; - default: assert(0); break; //shut up compiler - } -} - -SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed) -{ - _nliterals = 0; - _literals = SQTable::Create(ss,0); - _strings = SQTable::Create(ss,0); - _sharedstate = ss; - _lastline = 0; - _optimization = true; - _parent = parent; - _stacksize = 0; - _traps = 0; - _returnexp = 0; - _varparams = false; - _errfunc = efunc; - _errtarget = ed; - _bgenerator = false; - -} - -void SQFuncState::Error(const SQChar *err) -{ - _errfunc(_errtarget,err); -} - -#ifdef _DEBUG_DUMP -void SQFuncState::Dump(SQFunctionProto *func) -{ - SQUnsignedInteger n=0,i; - scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction)); - scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject)); - scprintf(_SC("--------------------------------------------------------------------\n")); - scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown")); - scprintf(_SC("-----LITERALS\n")); - SQObjectPtr refidx,key,val; - SQInteger idx; - SQObjectPtrVec templiterals; - templiterals.resize(_nliterals); - while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { - refidx=idx; - templiterals[_integer(val)]=key; - } - for(i=0;i>\n")); - n=0; - for(i=0;i<_parameters.size();i++){ - scprintf(_SC("[%d] "),n); - DumpLiteral(_parameters[i]); - scprintf(_SC("\n")); - n++; - } - scprintf(_SC("-----LOCALS\n")); - for(i=0;i_localvarinfos.size();i++){ - SQLocalVarInfo lvi=func->_localvarinfos[i]; - scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op); - n++; - } - scprintf(_SC("-----LINE INFO\n")); - for(i=0;i<_lineinfos.size();i++){ - SQLineInfo li=_lineinfos[i]; - scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line); - n++; - } - scprintf(_SC("-----dump\n")); - n=0; - for(i=0;i<_instructions.size();i++){ - SQInstruction &inst=_instructions[i]; - if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ - - SQInteger lidx = inst._arg1; - scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0); - if(lidx >= 0xFFFFFFFF) - scprintf(_SC("null")); - else { - SQInteger refidx; - SQObjectPtr val,key,refo; - while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; - } - DumpLiteral(key); - } - if(inst.op != _OP_DLOAD) { - scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3); - } - else { - scprintf(_SC(" %d "),inst._arg2); - lidx = inst._arg3; - if(lidx >= 0xFFFFFFFF) - scprintf(_SC("null")); - else { - SQInteger refidx; - SQObjectPtr val,key,refo; - while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { - refo = refidx; - } - DumpLiteral(key); - scprintf(_SC("\n")); - } - } - } - else if(inst.op==_OP_ARITH){ - scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - } - else - scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); - n++; - } - scprintf(_SC("-----\n")); - scprintf(_SC("stack size[%d]\n"),func->_stacksize); - scprintf(_SC("--------------------------------------------------------------------\n\n")); -} -#endif - -SQInteger SQFuncState::GetNumericConstant(const SQInteger cons) -{ - return GetConstant(SQObjectPtr(cons)); -} - -SQInteger SQFuncState::GetNumericConstant(const SQFloat cons) -{ - return GetConstant(SQObjectPtr(cons)); -} - -SQInteger SQFuncState::GetConstant(const SQObject &cons) -{ - SQObjectPtr val; - if(!_table(_literals)->Get(cons,val)) - { - val = _nliterals; - _table(_literals)->NewSlot(cons,val); - _nliterals++; - if(_nliterals > MAX_LITERALS) { - val.Null(); - Error(_SC("internal compiler error: too many literals")); - } - } - return _integer(val); -} - -void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3) -{ - _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); - _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); - _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); - _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); -} - -void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val) -{ - switch(arg){ - case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; - case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; - case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; - case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; - }; -} - -SQInteger SQFuncState::AllocStackPos() -{ - SQInteger npos=_vlocals.size(); - _vlocals.push_back(SQLocalVarInfo()); - if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) { - if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals")); - _stacksize=_vlocals.size(); - } - return npos; -} - -SQInteger SQFuncState::PushTarget(SQInteger n) -{ - if(n!=-1){ - _targetstack.push_back(n); - return n; - } - n=AllocStackPos(); - _targetstack.push_back(n); - return n; -} - -SQInteger SQFuncState::GetUpTarget(SQInteger n){ - return _targetstack[((_targetstack.size()-1)-n)]; -} - -SQInteger SQFuncState::TopTarget(){ - return _targetstack.back(); -} -SQInteger SQFuncState::PopTarget() -{ - SQInteger npos=_targetstack.back(); - SQLocalVarInfo t=_vlocals[_targetstack.back()]; - if(type(t._name)==OT_NULL){ - _vlocals.pop_back(); - } - _targetstack.pop_back(); - return npos; -} - -SQInteger SQFuncState::GetStackSize() -{ - return _vlocals.size(); -} - -void SQFuncState::SetStackSize(SQInteger n) -{ - SQInteger size=_vlocals.size(); - while(size>n){ - size--; - SQLocalVarInfo lvi=_vlocals.back(); - if(type(lvi._name)!=OT_NULL){ - lvi._end_op=GetCurrentPos(); - _localvarinfos.push_back(lvi); - } - _vlocals.pop_back(); - } -} - -bool SQFuncState::IsLocal(SQUnsignedInteger stkpos) -{ - if(stkpos>=_vlocals.size())return false; - else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true; - return false; -} - -SQInteger SQFuncState::PushLocalVariable(const SQObject &name) -{ - SQInteger pos=_vlocals.size(); - SQLocalVarInfo lvi; - lvi._name=name; - lvi._start_op=GetCurrentPos()+1; - lvi._pos=_vlocals.size(); - _vlocals.push_back(lvi); - if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); - - return pos; -} - -SQInteger SQFuncState::GetLocalVariable(const SQObject &name) -{ - SQInteger locals=_vlocals.size(); - while(locals>=1){ - if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){ - return locals-1; - } - locals--; - } - return -1; -} - -SQInteger SQFuncState::GetOuterVariable(const SQObject &name) -{ - SQInteger outers = _outervalues.size(); - for(SQInteger i = 0; iGetLocalVariable(name); - if(pos == -1) { - pos = _parent->GetOuterVariable(name); - if(pos != -1) { - _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local - return; - } - } - else { - _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local - return; - } - } - _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global -} - -void SQFuncState::AddParameter(const SQObject &name) -{ - PushLocalVariable(name); - _parameters.push_back(name); -} - -void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) -{ - if(_lastline!=line || force){ - SQLineInfo li; - li._line=line;li._op=(GetCurrentPos()+1); - if(lineop)AddInstruction(_OP_LINE,0,line); - _lineinfos.push_back(li); - _lastline=line; - } -} - -void SQFuncState::AddInstruction(SQInstruction &i) -{ - SQInteger size = _instructions.size(); - if(size > 0 && _optimization){ //simple optimizer - SQInstruction &pi = _instructions[size-1];//previous instruction - switch(i.op) { - case _OP_RETURN: - if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { - pi.op = _OP_TAILCALL; - } - break; - case _OP_GET: - if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){ - pi._arg1 = pi._arg1; - pi._arg2 = (unsigned char)i._arg1; - pi.op = _OP_GETK; - pi._arg0 = i._arg0; - - return; - } - break; - case _OP_PREPCALL: - if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ - pi.op = _OP_PREPCALLK; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = i._arg2; - pi._arg3 = i._arg3; - return; - } - break; - case _OP_APPENDARRAY: - if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ - pi.op = _OP_APPENDARRAY; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = MAX_FUNC_STACKSIZE; - pi._arg3 = MAX_FUNC_STACKSIZE; - return; - } - break; - case _OP_MOVE: - if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1)) - { - pi._arg0 = i._arg0; - _optimization = false; - return; - } - - if(pi.op == _OP_MOVE) - { - pi.op = _OP_DMOVE; - pi._arg2 = i._arg0; - pi._arg3 = (unsigned char)i._arg1; - return; - } - break; - case _OP_LOAD: - if(pi.op == _OP_LOAD && i._arg1 < 256) { - pi.op = _OP_DLOAD; - pi._arg2 = i._arg0; - pi._arg3 = (unsigned char)i._arg1; - return; - } - break; - case _OP_EQ:case _OP_NE: - if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) )) - { - pi.op = i.op; - pi._arg0 = i._arg0; - pi._arg1 = pi._arg1; - pi._arg2 = i._arg2; - pi._arg3 = MAX_FUNC_STACKSIZE; - return; - } - break; - case _OP_LOADNULLS: - if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { - - pi._arg1 = pi._arg1 + 1; - pi.op = _OP_LOADNULLS; - return; - } - break; - case _OP_LINE: - if(pi.op == _OP_LINE) { - _instructions.pop_back(); - _lineinfos.pop_back(); - } - break; - } - } - _optimization = true; - _instructions.push_back(i); -} - -SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len) -{ - SQObjectPtr ns(SQString::Create(_sharedstate,s,len)); - _table(_strings)->NewSlot(ns,(SQInteger)1); - return ns; -} - -SQFunctionProto *SQFuncState::BuildProto() -{ - SQFunctionProto *f=SQFunctionProto::Create(); - f->_literals.resize(_nliterals); - SQObjectPtr refidx,key,val; - SQInteger idx; - - f->_stacksize = _stacksize; - f->_sourcename = _sourcename; - f->_bgenerator = _bgenerator; - f->_name = _name; - - while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { - f->_literals[_integer(val)]=key; - refidx=idx; - } - - f->_functions.resize(_functions.size()); - f->_functions.copy(_functions); - f->_parameters.resize(_parameters.size()); - f->_parameters.copy(_parameters); - f->_outervalues.resize(_outervalues.size()); - f->_outervalues.copy(_outervalues); - f->_instructions.resize(_instructions.size()); - f->_instructions.copy(_instructions); - f->_localvarinfos.resize(_localvarinfos.size()); - f->_localvarinfos.copy(_localvarinfos); - f->_lineinfos.resize(_lineinfos.size()); - f->_lineinfos.copy(_lineinfos); - f->_varparams = _varparams; - - return f; -} - -SQFuncState *SQFuncState::PushChildState(SQSharedState *ss) -{ - SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState)); - new (child) SQFuncState(ss,this,_errfunc,_errtarget); - _childstates.push_back(child); - return child; -} - -void SQFuncState::PopChildState() -{ - SQFuncState *child = _childstates.back(); - sq_delete(child,SQFuncState); - _childstates.pop_back(); -} - -SQFuncState::~SQFuncState() -{ - while(_childstates.size() > 0) - { - PopChildState(); - } -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqcompiler.h" +#include "sqfuncproto.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqopcodes.h" +#include "sqfuncstate.h" + +#ifdef _DEBUG_DUMP +SQInstructionDesc g_InstrDesc[]={ + {_SC("_OP_LINE")}, + {_SC("_OP_LOAD")}, + {_SC("_OP_LOADINT")}, + {_SC("_OP_DLOAD")}, + {_SC("_OP_TAILCALL")}, + {_SC("_OP_CALL")}, + {_SC("_OP_PREPCALL")}, + {_SC("_OP_PREPCALLK")}, + {_SC("_OP_GETK")}, + {_SC("_OP_MOVE")}, + {_SC("_OP_NEWSLOT")}, + {_SC("_OP_DELETE")}, + {_SC("_OP_SET")}, + {_SC("_OP_GET")}, + {_SC("_OP_EQ")}, + {_SC("_OP_NE")}, + {_SC("_OP_ARITH")}, + {_SC("_OP_BITW")}, + {_SC("_OP_RETURN")}, + {_SC("_OP_LOADNULLS")}, + {_SC("_OP_LOADROOTTABLE")}, + {_SC("_OP_LOADBOOL")}, + {_SC("_OP_DMOVE")}, + {_SC("_OP_JMP")}, + {_SC("_OP_JNZ")}, + {_SC("_OP_JZ")}, + {_SC("_OP_LOADFREEVAR")}, + {_SC("_OP_VARGC")}, + {_SC("_OP_GETVARGV")}, + {_SC("_OP_NEWTABLE")}, + {_SC("_OP_NEWARRAY")}, + {_SC("_OP_APPENDARRAY")}, + {_SC("_OP_GETPARENT")}, + {_SC("_OP_COMPARITH")}, + {_SC("_OP_COMPARITHL")}, + {_SC("_OP_INC")}, + {_SC("_OP_INCL")}, + {_SC("_OP_PINC")}, + {_SC("_OP_PINCL")}, + {_SC("_OP_CMP")}, + {_SC("_OP_EXISTS")}, + {_SC("_OP_INSTANCEOF")}, + {_SC("_OP_AND")}, + {_SC("_OP_OR")}, + {_SC("_OP_NEG")}, + {_SC("_OP_NOT")}, + {_SC("_OP_BWNOT")}, + {_SC("_OP_CLOSURE")}, + {_SC("_OP_YIELD")}, + {_SC("_OP_RESUME")}, + {_SC("_OP_FOREACH")}, + {_SC("_OP_DELEGATE")}, + {_SC("_OP_CLONE")}, + {_SC("_OP_TYPEOF")}, + {_SC("_OP_PUSHTRAP")}, + {_SC("_OP_POPTRAP")}, + {_SC("_OP_THROW")}, + {_SC("_OP_CLASS")}, + {_SC("_OP_NEWSLOTA")} +}; +#endif +void DumpLiteral(SQObjectPtr &o) +{ + switch(type(o)){ + case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break; + case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break; + case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break; + default: assert(0); break; //shut up compiler + } +} + +SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed) +{ + _nliterals = 0; + _literals = SQTable::Create(ss,0); + _strings = SQTable::Create(ss,0); + _sharedstate = ss; + _lastline = 0; + _optimization = true; + _parent = parent; + _stacksize = 0; + _traps = 0; + _returnexp = 0; + _varparams = false; + _errfunc = efunc; + _errtarget = ed; + _bgenerator = false; + +} + +void SQFuncState::Error(const SQChar *err) +{ + _errfunc(_errtarget,err); +} + +#ifdef _DEBUG_DUMP +void SQFuncState::Dump(SQFunctionProto *func) +{ + SQUnsignedInteger n=0,i; + scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction)); + scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject)); + scprintf(_SC("--------------------------------------------------------------------\n")); + scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown")); + scprintf(_SC("-----LITERALS\n")); + SQObjectPtr refidx,key,val; + SQInteger idx; + SQObjectPtrVec templiterals; + templiterals.resize(_nliterals); + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + refidx=idx; + templiterals[_integer(val)]=key; + } + for(i=0;i>\n")); + n=0; + for(i=0;i<_parameters.size();i++){ + scprintf(_SC("[%d] "),n); + DumpLiteral(_parameters[i]); + scprintf(_SC("\n")); + n++; + } + scprintf(_SC("-----LOCALS\n")); + for(i=0;i_localvarinfos.size();i++){ + SQLocalVarInfo lvi=func->_localvarinfos[i]; + scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op); + n++; + } + scprintf(_SC("-----LINE INFO\n")); + for(i=0;i<_lineinfos.size();i++){ + SQLineInfo li=_lineinfos[i]; + scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line); + n++; + } + scprintf(_SC("-----dump\n")); + n=0; + for(i=0;i<_instructions.size();i++){ + SQInstruction &inst=_instructions[i]; + if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ + + SQInteger lidx = inst._arg1; + scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0); + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + } + if(inst.op != _OP_DLOAD) { + scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3); + } + else { + scprintf(_SC(" %d "),inst._arg2); + lidx = inst._arg3; + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + scprintf(_SC("\n")); + } + } + } + else if(inst.op==_OP_ARITH){ + scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + } + else + scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + n++; + } + scprintf(_SC("-----\n")); + scprintf(_SC("stack size[%d]\n"),func->_stacksize); + scprintf(_SC("--------------------------------------------------------------------\n\n")); +} +#endif + +SQInteger SQFuncState::GetNumericConstant(const SQInteger cons) +{ + return GetConstant(SQObjectPtr(cons)); +} + +SQInteger SQFuncState::GetNumericConstant(const SQFloat cons) +{ + return GetConstant(SQObjectPtr(cons)); +} + +SQInteger SQFuncState::GetConstant(const SQObject &cons) +{ + SQObjectPtr val; + if(!_table(_literals)->Get(cons,val)) + { + val = _nliterals; + _table(_literals)->NewSlot(cons,val); + _nliterals++; + if(_nliterals > MAX_LITERALS) { + val.Null(); + Error(_SC("internal compiler error: too many literals")); + } + } + return _integer(val); +} + +void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3) +{ + _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); + _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); + _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); + _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); +} + +void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val) +{ + switch(arg){ + case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; + case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; + }; +} + +SQInteger SQFuncState::AllocStackPos() +{ + SQInteger npos=_vlocals.size(); + _vlocals.push_back(SQLocalVarInfo()); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) { + if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals")); + _stacksize=_vlocals.size(); + } + return npos; +} + +SQInteger SQFuncState::PushTarget(SQInteger n) +{ + if(n!=-1){ + _targetstack.push_back(n); + return n; + } + n=AllocStackPos(); + _targetstack.push_back(n); + return n; +} + +SQInteger SQFuncState::GetUpTarget(SQInteger n){ + return _targetstack[((_targetstack.size()-1)-n)]; +} + +SQInteger SQFuncState::TopTarget(){ + return _targetstack.back(); +} +SQInteger SQFuncState::PopTarget() +{ + SQInteger npos=_targetstack.back(); + SQLocalVarInfo t=_vlocals[_targetstack.back()]; + if(type(t._name)==OT_NULL){ + _vlocals.pop_back(); + } + _targetstack.pop_back(); + return npos; +} + +SQInteger SQFuncState::GetStackSize() +{ + return _vlocals.size(); +} + +void SQFuncState::SetStackSize(SQInteger n) +{ + SQInteger size=_vlocals.size(); + while(size>n){ + size--; + SQLocalVarInfo lvi=_vlocals.back(); + if(type(lvi._name)!=OT_NULL){ + lvi._end_op=GetCurrentPos(); + _localvarinfos.push_back(lvi); + } + _vlocals.pop_back(); + } +} + +bool SQFuncState::IsLocal(SQUnsignedInteger stkpos) +{ + if(stkpos>=_vlocals.size())return false; + else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true; + return false; +} + +SQInteger SQFuncState::PushLocalVariable(const SQObject &name) +{ + SQInteger pos=_vlocals.size(); + SQLocalVarInfo lvi; + lvi._name=name; + lvi._start_op=GetCurrentPos()+1; + lvi._pos=_vlocals.size(); + _vlocals.push_back(lvi); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); + + return pos; +} + +SQInteger SQFuncState::GetLocalVariable(const SQObject &name) +{ + SQInteger locals=_vlocals.size(); + while(locals>=1){ + if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){ + return locals-1; + } + locals--; + } + return -1; +} + +SQInteger SQFuncState::GetOuterVariable(const SQObject &name) +{ + SQInteger outers = _outervalues.size(); + for(SQInteger i = 0; iGetLocalVariable(name); + if(pos == -1) { + pos = _parent->GetOuterVariable(name); + if(pos != -1) { + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local + return; + } + } + else { + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local + return; + } + } + _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global +} + +void SQFuncState::AddParameter(const SQObject &name) +{ + PushLocalVariable(name); + _parameters.push_back(name); +} + +void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) +{ + if(_lastline!=line || force){ + SQLineInfo li; + li._line=line;li._op=(GetCurrentPos()+1); + if(lineop)AddInstruction(_OP_LINE,0,line); + _lineinfos.push_back(li); + _lastline=line; + } +} + +void SQFuncState::AddInstruction(SQInstruction &i) +{ + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ //simple optimizer + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(i.op) { + case _OP_RETURN: + if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { + pi.op = _OP_TAILCALL; + } + break; + case _OP_GET: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){ + pi._arg1 = pi._arg1; + pi._arg2 = (unsigned char)i._arg1; + pi.op = _OP_GETK; + pi._arg0 = i._arg0; + + return; + } + break; + case _OP_PREPCALL: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_PREPCALLK; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = i._arg3; + return; + } + break; + case _OP_APPENDARRAY: + if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_APPENDARRAY; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = MAX_FUNC_STACKSIZE; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + break; + case _OP_MOVE: + if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1)) + { + pi._arg0 = i._arg0; + _optimization = false; + return; + } + + if(pi.op == _OP_MOVE) + { + pi.op = _OP_DMOVE; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_LOAD: + if(pi.op == _OP_LOAD && i._arg1 < 256) { + pi.op = _OP_DLOAD; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_EQ:case _OP_NE: + if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) )) + { + pi.op = i.op; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + break; + case _OP_LOADNULLS: + if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { + + pi._arg1 = pi._arg1 + 1; + pi.op = _OP_LOADNULLS; + return; + } + break; + case _OP_LINE: + if(pi.op == _OP_LINE) { + _instructions.pop_back(); + _lineinfos.pop_back(); + } + break; + } + } + _optimization = true; + _instructions.push_back(i); +} + +SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len) +{ + SQObjectPtr ns(SQString::Create(_sharedstate,s,len)); + _table(_strings)->NewSlot(ns,(SQInteger)1); + return ns; +} + +SQFunctionProto *SQFuncState::BuildProto() +{ + SQFunctionProto *f=SQFunctionProto::Create(); + f->_literals.resize(_nliterals); + SQObjectPtr refidx,key,val; + SQInteger idx; + + f->_stacksize = _stacksize; + f->_sourcename = _sourcename; + f->_bgenerator = _bgenerator; + f->_name = _name; + + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + f->_literals[_integer(val)]=key; + refidx=idx; + } + + f->_functions.resize(_functions.size()); + f->_functions.copy(_functions); + f->_parameters.resize(_parameters.size()); + f->_parameters.copy(_parameters); + f->_outervalues.resize(_outervalues.size()); + f->_outervalues.copy(_outervalues); + f->_instructions.resize(_instructions.size()); + f->_instructions.copy(_instructions); + f->_localvarinfos.resize(_localvarinfos.size()); + f->_localvarinfos.copy(_localvarinfos); + f->_lineinfos.resize(_lineinfos.size()); + f->_lineinfos.copy(_lineinfos); + f->_varparams = _varparams; + + return f; +} + +SQFuncState *SQFuncState::PushChildState(SQSharedState *ss) +{ + SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState)); + new (child) SQFuncState(ss,this,_errfunc,_errtarget); + _childstates.push_back(child); + return child; +} + +void SQFuncState::PopChildState() +{ + SQFuncState *child = _childstates.back(); + sq_delete(child,SQFuncState); + _childstates.pop_back(); +} + +SQFuncState::~SQFuncState() +{ + while(_childstates.size() > 0) + { + PopChildState(); + } +} diff --git a/src/squirrel/squirrel/sqfuncstate.h b/src/squirrel/squirrel/sqfuncstate.h index df6d2e9ea..fd191f2b3 100644 --- a/src/squirrel/squirrel/sqfuncstate.h +++ b/src/squirrel/squirrel/sqfuncstate.h @@ -1,80 +1,79 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQFUNCSTATE_H_ -#define _SQFUNCSTATE_H_ -/////////////////////////////////// -#include "squtils.h" - -struct SQFuncState -{ - SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed); - ~SQFuncState(); -#ifdef _DEBUG_DUMP - void Dump(SQFunctionProto *func); -#endif - void Error(const SQChar *err); - SQFuncState *PushChildState(SQSharedState *ss); - void PopChildState(); - void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);} - void AddInstruction(SQInstruction &i); - void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0); - void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val); - SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} - void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; - SQInteger GetConstant(const SQObject &cons); -private: - CompilerErrorFunc _errfunc; - void *_errtarget; -}; - - -#endif //_SQFUNCSTATE_H_ - +/* see copyright notice in squirrel.h */ +#ifndef _SQFUNCSTATE_H_ +#define _SQFUNCSTATE_H_ +/////////////////////////////////// +#include "squtils.h" + +struct SQFuncState +{ + SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed); + ~SQFuncState(); +#ifdef _DEBUG_DUMP + void Dump(SQFunctionProto *func); +#endif + void Error(const SQChar *err); + SQFuncState *PushChildState(SQSharedState *ss); + void PopChildState(); + void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);} + void AddInstruction(SQInstruction &i); + void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0); + void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val); + SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];} + void PopInstructions(SQInteger size){for(SQInteger i=0;i _childstates; + SQInteger GetConstant(const SQObject &cons); +private: + CompilerErrorFunc _errfunc; + void *_errtarget; +}; + + +#endif //_SQFUNCSTATE_H_ diff --git a/src/squirrel/squirrel/sqlexer.cpp b/src/squirrel/squirrel/sqlexer.cpp index 7244e73ac..2552f7d14 100644 --- a/src/squirrel/squirrel/sqlexer.cpp +++ b/src/squirrel/squirrel/sqlexer.cpp @@ -1,446 +1,446 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include -#include -#include "sqtable.h" -#include "sqstring.h" -#include "sqcompiler.h" -#include "sqlexer.h" - -#define CUR_CHAR (_currdata) -#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;} -#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB) -#define NEXT() {Next();_currentcolumn++;} -#define INIT_TEMP_STRING() { _longstr.resize(0);} -#define APPEND_CHAR(c) { _longstr.push_back(c);} -#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));} -#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id)) - -SQLexer::SQLexer(){} -SQLexer::~SQLexer() -{ - _keywords->Release(); -} - -void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed) -{ - _errfunc = efunc; - _errtarget = ed; - _sharedstate = ss; - _keywords = SQTable::Create(ss, 26); - ADD_KEYWORD(while, TK_WHILE); - ADD_KEYWORD(do, TK_DO); - ADD_KEYWORD(if, TK_IF); - ADD_KEYWORD(else, TK_ELSE); - ADD_KEYWORD(break, TK_BREAK); - ADD_KEYWORD(continue, TK_CONTINUE); - ADD_KEYWORD(return, TK_RETURN); - ADD_KEYWORD(null, TK_NULL); - ADD_KEYWORD(function, TK_FUNCTION); - ADD_KEYWORD(local, TK_LOCAL); - ADD_KEYWORD(for, TK_FOR); - ADD_KEYWORD(foreach, TK_FOREACH); - ADD_KEYWORD(in, TK_IN); - ADD_KEYWORD(typeof, TK_TYPEOF); - ADD_KEYWORD(delegate, TK_DELEGATE); - ADD_KEYWORD(delete, TK_DELETE); - ADD_KEYWORD(try, TK_TRY); - ADD_KEYWORD(catch, TK_CATCH); - ADD_KEYWORD(throw, TK_THROW); - ADD_KEYWORD(clone, TK_CLONE); - ADD_KEYWORD(yield, TK_YIELD); - ADD_KEYWORD(resume, TK_RESUME); - ADD_KEYWORD(switch, TK_SWITCH); - ADD_KEYWORD(case, TK_CASE); - ADD_KEYWORD(default, TK_DEFAULT); - ADD_KEYWORD(this, TK_THIS); - ADD_KEYWORD(parent,TK_PARENT); - ADD_KEYWORD(class,TK_CLASS); - ADD_KEYWORD(extends,TK_EXTENDS); - ADD_KEYWORD(constructor,TK_CONSTRUCTOR); - ADD_KEYWORD(instanceof,TK_INSTANCEOF); - ADD_KEYWORD(vargc,TK_VARGC); - ADD_KEYWORD(vargv,TK_VARGV); - ADD_KEYWORD(true,TK_TRUE); - ADD_KEYWORD(false,TK_FALSE); - ADD_KEYWORD(static,TK_STATIC); - - _readf = rg; - _up = up; - _lasttokenline = _currentline = 1; - _currentcolumn = 0; - _prevtoken = -1; - Next(); -} - -void SQLexer::Error(const SQChar *err) -{ - _errfunc(_errtarget,err); -} - -void SQLexer::Next() -{ - SQInteger t = _readf(_up); - if(t > MAX_CHAR) Error(_SC("Invalid character")); - if(t != 0) { - _currdata = (LexChar)t; - return; - } - _currdata = SQUIRREL_EOB; -} - -const SQChar *SQLexer::Tok2Str(SQInteger tok) -{ - SQObjectPtr itr, key, val; - SQInteger nitr; - while((nitr = _keywords->Next(false,itr, key, val)) != -1) { - itr = (SQInteger)nitr; - if(((SQInteger)_integer(val)) == tok) - return _stringval(key); - } - return NULL; -} - -void SQLexer::LexBlockComment() -{ - bool done = false; - while(!done) { - switch(CUR_CHAR) { - case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; - case _SC('\n'): _currentline++; NEXT(); continue; - case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment")); - default: NEXT(); - } - } -} - -SQInteger SQLexer::Lex() -{ - _lasttokenline = _currentline; - while(CUR_CHAR != SQUIRREL_EOB) { - switch(CUR_CHAR){ - case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; - case _SC('\n'): - _currentline++; - _prevtoken=_curtoken; - _curtoken=_SC('\n'); - NEXT(); - _currentcolumn=1; - continue; - case _SC('/'): - NEXT(); - switch(CUR_CHAR){ - case _SC('*'): - NEXT(); - LexBlockComment(); - continue; - case _SC('/'): - do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); - continue; - case _SC('='): - NEXT(); - RETURN_TOKEN(TK_DIVEQ); - continue; - case _SC('>'): - NEXT(); - RETURN_TOKEN(TK_ATTR_CLOSE); - continue; - default: - RETURN_TOKEN('/'); - } - case _SC('='): - NEXT(); - if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } - else { NEXT(); RETURN_TOKEN(TK_EQ); } - case _SC('<'): - NEXT(); - if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) } - else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); } - else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); } - else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); } - //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); } - else { RETURN_TOKEN('<') } - case _SC('>'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} - else if(CUR_CHAR == _SC('>')){ - NEXT(); - if(CUR_CHAR == _SC('>')){ - NEXT(); - RETURN_TOKEN(TK_USHIFTR); - } - RETURN_TOKEN(TK_SHIFTR); - } - else { RETURN_TOKEN('>') } - case _SC('!'): - NEXT(); - if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} - else { NEXT(); RETURN_TOKEN(TK_NE); } - case _SC('@'): { - SQInteger stype; - NEXT(); - if(CUR_CHAR != _SC('"')) - Error(_SC("string expected")); - if((stype=ReadString('"',true))!=-1) { - RETURN_TOKEN(stype); - } - Error(_SC("error parsing the string")); - } - case _SC('"'): - case _SC('\''): { - SQInteger stype; - if((stype=ReadString(CUR_CHAR,false))!=-1){ - RETURN_TOKEN(stype); - } - Error(_SC("error parsing the string")); - } - case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'): - case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'): - {SQInteger ret = CUR_CHAR; - NEXT(); RETURN_TOKEN(ret); } - case _SC('.'): - NEXT(); - if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } - NEXT(); - if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); } - NEXT(); - RETURN_TOKEN(TK_VARPARAMS); - case _SC('&'): - NEXT(); - if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') } - else { NEXT(); RETURN_TOKEN(TK_AND); } - case _SC('|'): - NEXT(); - if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') } - else { NEXT(); RETURN_TOKEN(TK_OR); } - case _SC(':'): - NEXT(); - if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') } - else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); } - case _SC('*'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);} - else RETURN_TOKEN('*'); - case _SC('%'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);} - else RETURN_TOKEN('%'); - case _SC('-'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);} - else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);} - else RETURN_TOKEN('-'); - case _SC('+'): - NEXT(); - if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);} - else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);} - else RETURN_TOKEN('+'); - case SQUIRREL_EOB: - return 0; - default:{ - if (scisdigit(CUR_CHAR)) { - SQInteger ret = ReadNumber(); - RETURN_TOKEN(ret); - } - else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) { - SQInteger t = ReadID(); - RETURN_TOKEN(t); - } - else { - SQInteger c = CUR_CHAR; - if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); - NEXT(); - RETURN_TOKEN(c); - } - RETURN_TOKEN(0); - } - } - } - return 0; -} - -SQInteger SQLexer::GetIDType(SQChar *s) -{ - SQObjectPtr t; - if(_keywords->Get(SQString::Create(_sharedstate, s), t)) { - return SQInteger(_integer(t)); - } - return TK_IDENTIFIER; -} - - -SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim) -{ - INIT_TEMP_STRING(); - NEXT(); - if(IS_EOB()) return -1; - for(;;) { - while(CUR_CHAR != ndelim) { - switch(CUR_CHAR) { - case SQUIRREL_EOB: - Error(_SC("unfinished string")); - return -1; - case _SC('\n'): - if(!verbatim) Error(_SC("newline in a constant")); - APPEND_CHAR(CUR_CHAR); NEXT(); - _currentline++; - break; - case _SC('\\'): - if(verbatim) { - APPEND_CHAR('\\'); NEXT(); - } - else { - NEXT(); - switch(CUR_CHAR) { - case _SC('x'): NEXT(); { - if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); - const SQInteger maxdigits = 4; - SQChar temp[maxdigits+1]; - SQInteger n = 0; - while(isxdigit(CUR_CHAR) && n < maxdigits) { - temp[n] = CUR_CHAR; - n++; - NEXT(); - } - temp[n] = 0; - SQChar *sTemp; - APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16)); - } - break; - case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break; - case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break; - case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break; - case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break; - case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break; - case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break; - case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break; - case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break; - case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break; - case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break; - case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break; - default: - Error(_SC("unrecognised escaper char")); - break; - } - } - break; - default: - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - } - NEXT(); - if(verbatim && CUR_CHAR == '"') { //double quotation - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - else { - break; - } - } - TERMINATE_BUFFER(); - SQInteger len = _longstr.size()-1; - if(ndelim == _SC('\'')) { - if(len == 0) Error(_SC("empty constant")); - if(len > 1) Error(_SC("constant too long")); - _nvalue = _longstr[0]; - return TK_INTEGER; - } - _svalue = &_longstr[0]; - return TK_STRING_LITERAL; -} - -void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res) -{ - *res = 0; - while(*s != 0) - { - if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0'); - else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10); - else { assert(0); } - } -} - -void LexInteger(const SQChar *s,SQUnsignedInteger *res) -{ - *res = 0; - while(*s != 0) - { - *res = (*res)*10+((*s++)-'0'); - } -} - -SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; } -#define MAX_HEX_DIGITS (sizeof(SQInteger)*2) -SQInteger SQLexer::ReadNumber() -{ -#define TINT 1 -#define TFLOAT 2 -#define THEX 3 -#define TSCIENTIFIC 4 - SQInteger type = TINT, firstchar = CUR_CHAR; - SQChar *sTemp; - INIT_TEMP_STRING(); - NEXT(); - if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) { - NEXT(); - type = THEX; - while(isxdigit(CUR_CHAR)) { - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number")); - } - else { - APPEND_CHAR((int)firstchar); - while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { - if(CUR_CHAR == _SC('.')) type = TFLOAT; - if(isexponent(CUR_CHAR)) { - if(type != TFLOAT) Error(_SC("invalid numeric format")); - type = TSCIENTIFIC; - APPEND_CHAR(CUR_CHAR); - NEXT(); - if(CUR_CHAR == '+' || CUR_CHAR == '-'){ - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); - } - - APPEND_CHAR(CUR_CHAR); - NEXT(); - } - } - TERMINATE_BUFFER(); - switch(type) { - case TSCIENTIFIC: - case TFLOAT: - _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp); - return TK_FLOAT; - case TINT: - LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue); - return TK_INTEGER; - case THEX: - LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); - return TK_INTEGER; - } - return 0; -} - -SQInteger SQLexer::ReadID() -{ - SQInteger res; - INIT_TEMP_STRING(); - do { - APPEND_CHAR(CUR_CHAR); - NEXT(); - } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_')); - TERMINATE_BUFFER(); - res = GetIDType(&_longstr[0]); - if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) { - _svalue = &_longstr[0]; - } - return res; -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include +#include +#include "sqtable.h" +#include "sqstring.h" +#include "sqcompiler.h" +#include "sqlexer.h" + +#define CUR_CHAR (_currdata) +#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;} +#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB) +#define NEXT() {Next();_currentcolumn++;} +#define INIT_TEMP_STRING() { _longstr.resize(0);} +#define APPEND_CHAR(c) { _longstr.push_back(c);} +#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));} +#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id)) + +SQLexer::SQLexer(){} +SQLexer::~SQLexer() +{ + _keywords->Release(); +} + +void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed) +{ + _errfunc = efunc; + _errtarget = ed; + _sharedstate = ss; + _keywords = SQTable::Create(ss, 26); + ADD_KEYWORD(while, TK_WHILE); + ADD_KEYWORD(do, TK_DO); + ADD_KEYWORD(if, TK_IF); + ADD_KEYWORD(else, TK_ELSE); + ADD_KEYWORD(break, TK_BREAK); + ADD_KEYWORD(continue, TK_CONTINUE); + ADD_KEYWORD(return, TK_RETURN); + ADD_KEYWORD(null, TK_NULL); + ADD_KEYWORD(function, TK_FUNCTION); + ADD_KEYWORD(local, TK_LOCAL); + ADD_KEYWORD(for, TK_FOR); + ADD_KEYWORD(foreach, TK_FOREACH); + ADD_KEYWORD(in, TK_IN); + ADD_KEYWORD(typeof, TK_TYPEOF); + ADD_KEYWORD(delegate, TK_DELEGATE); + ADD_KEYWORD(delete, TK_DELETE); + ADD_KEYWORD(try, TK_TRY); + ADD_KEYWORD(catch, TK_CATCH); + ADD_KEYWORD(throw, TK_THROW); + ADD_KEYWORD(clone, TK_CLONE); + ADD_KEYWORD(yield, TK_YIELD); + ADD_KEYWORD(resume, TK_RESUME); + ADD_KEYWORD(switch, TK_SWITCH); + ADD_KEYWORD(case, TK_CASE); + ADD_KEYWORD(default, TK_DEFAULT); + ADD_KEYWORD(this, TK_THIS); + ADD_KEYWORD(parent,TK_PARENT); + ADD_KEYWORD(class,TK_CLASS); + ADD_KEYWORD(extends,TK_EXTENDS); + ADD_KEYWORD(constructor,TK_CONSTRUCTOR); + ADD_KEYWORD(instanceof,TK_INSTANCEOF); + ADD_KEYWORD(vargc,TK_VARGC); + ADD_KEYWORD(vargv,TK_VARGV); + ADD_KEYWORD(true,TK_TRUE); + ADD_KEYWORD(false,TK_FALSE); + ADD_KEYWORD(static,TK_STATIC); + + _readf = rg; + _up = up; + _lasttokenline = _currentline = 1; + _currentcolumn = 0; + _prevtoken = -1; + Next(); +} + +void SQLexer::Error(const SQChar *err) +{ + _errfunc(_errtarget,err); +} + +void SQLexer::Next() +{ + SQInteger t = _readf(_up); + if(t > MAX_CHAR) Error(_SC("Invalid character")); + if(t != 0) { + _currdata = (LexChar)t; + return; + } + _currdata = SQUIRREL_EOB; +} + +const SQChar *SQLexer::Tok2Str(SQInteger tok) +{ + SQObjectPtr itr, key, val; + SQInteger nitr; + while((nitr = _keywords->Next(false,itr, key, val)) != -1) { + itr = (SQInteger)nitr; + if(((SQInteger)_integer(val)) == tok) + return _stringval(key); + } + return NULL; +} + +void SQLexer::LexBlockComment() +{ + bool done = false; + while(!done) { + switch(CUR_CHAR) { + case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; + case _SC('\n'): _currentline++; NEXT(); continue; + case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment")); + default: NEXT(); + } + } +} + +SQInteger SQLexer::Lex() +{ + _lasttokenline = _currentline; + while(CUR_CHAR != SQUIRREL_EOB) { + switch(CUR_CHAR){ + case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; + case _SC('\n'): + _currentline++; + _prevtoken=_curtoken; + _curtoken=_SC('\n'); + NEXT(); + _currentcolumn=1; + continue; + case _SC('/'): + NEXT(); + switch(CUR_CHAR){ + case _SC('*'): + NEXT(); + LexBlockComment(); + continue; + case _SC('/'): + do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); + continue; + case _SC('='): + NEXT(); + RETURN_TOKEN(TK_DIVEQ); + continue; + case _SC('>'): + NEXT(); + RETURN_TOKEN(TK_ATTR_CLOSE); + continue; + default: + RETURN_TOKEN('/'); + } + case _SC('='): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } + else { NEXT(); RETURN_TOKEN(TK_EQ); } + case _SC('<'): + NEXT(); + if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) } + else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); } + else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); } + else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); } + //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); } + else { RETURN_TOKEN('<') } + case _SC('>'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} + else if(CUR_CHAR == _SC('>')){ + NEXT(); + if(CUR_CHAR == _SC('>')){ + NEXT(); + RETURN_TOKEN(TK_USHIFTR); + } + RETURN_TOKEN(TK_SHIFTR); + } + else { RETURN_TOKEN('>') } + case _SC('!'): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} + else { NEXT(); RETURN_TOKEN(TK_NE); } + case _SC('@'): { + SQInteger stype; + NEXT(); + if(CUR_CHAR != _SC('"')) + Error(_SC("string expected")); + if((stype=ReadString('"',true))!=-1) { + RETURN_TOKEN(stype); + } + Error(_SC("error parsing the string")); + } + case _SC('"'): + case _SC('\''): { + SQInteger stype; + if((stype=ReadString(CUR_CHAR,false))!=-1){ + RETURN_TOKEN(stype); + } + Error(_SC("error parsing the string")); + } + case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'): + case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'): + {SQInteger ret = CUR_CHAR; + NEXT(); RETURN_TOKEN(ret); } + case _SC('.'): + NEXT(); + if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } + NEXT(); + if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); } + NEXT(); + RETURN_TOKEN(TK_VARPARAMS); + case _SC('&'): + NEXT(); + if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') } + else { NEXT(); RETURN_TOKEN(TK_AND); } + case _SC('|'): + NEXT(); + if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') } + else { NEXT(); RETURN_TOKEN(TK_OR); } + case _SC(':'): + NEXT(); + if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') } + else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); } + case _SC('*'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);} + else RETURN_TOKEN('*'); + case _SC('%'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);} + else RETURN_TOKEN('%'); + case _SC('-'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);} + else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);} + else RETURN_TOKEN('-'); + case _SC('+'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);} + else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);} + else RETURN_TOKEN('+'); + case SQUIRREL_EOB: + return 0; + default:{ + if (scisdigit(CUR_CHAR)) { + SQInteger ret = ReadNumber(); + RETURN_TOKEN(ret); + } + else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) { + SQInteger t = ReadID(); + RETURN_TOKEN(t); + } + else { + SQInteger c = CUR_CHAR; + if (sciscntrl((int)c)) Error(_SC("unexpected character(control)")); + NEXT(); + RETURN_TOKEN(c); + } + RETURN_TOKEN(0); + } + } + } + return 0; +} + +SQInteger SQLexer::GetIDType(SQChar *s) +{ + SQObjectPtr t; + if(_keywords->Get(SQString::Create(_sharedstate, s), t)) { + return SQInteger(_integer(t)); + } + return TK_IDENTIFIER; +} + + +SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim) +{ + INIT_TEMP_STRING(); + NEXT(); + if(IS_EOB()) return -1; + for(;;) { + while(CUR_CHAR != ndelim) { + switch(CUR_CHAR) { + case SQUIRREL_EOB: + Error(_SC("unfinished string")); + return -1; + case _SC('\n'): + if(!verbatim) Error(_SC("newline in a constant")); + APPEND_CHAR(CUR_CHAR); NEXT(); + _currentline++; + break; + case _SC('\\'): + if(verbatim) { + APPEND_CHAR('\\'); NEXT(); + } + else { + NEXT(); + switch(CUR_CHAR) { + case _SC('x'): NEXT(); { + if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); + const SQInteger maxdigits = 4; + SQChar temp[maxdigits+1]; + SQInteger n = 0; + while(isxdigit(CUR_CHAR) && n < maxdigits) { + temp[n] = CUR_CHAR; + n++; + NEXT(); + } + temp[n] = 0; + SQChar *sTemp; + APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16)); + } + break; + case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break; + case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break; + case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break; + case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break; + case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break; + case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break; + case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break; + case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break; + case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break; + case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break; + case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break; + default: + Error(_SC("unrecognised escaper char")); + break; + } + } + break; + default: + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + } + NEXT(); + if(verbatim && CUR_CHAR == '"') { //double quotation + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + else { + break; + } + } + TERMINATE_BUFFER(); + SQInteger len = _longstr.size()-1; + if(ndelim == _SC('\'')) { + if(len == 0) Error(_SC("empty constant")); + if(len > 1) Error(_SC("constant too long")); + _nvalue = _longstr[0]; + return TK_INTEGER; + } + _svalue = &_longstr[0]; + return TK_STRING_LITERAL; +} + +void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res) +{ + *res = 0; + while(*s != 0) + { + if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0'); + else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10); + else { assert(0); } + } +} + +void LexInteger(const SQChar *s,SQUnsignedInteger *res) +{ + *res = 0; + while(*s != 0) + { + *res = (*res)*10+((*s++)-'0'); + } +} + +SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; } +#define MAX_HEX_DIGITS (sizeof(SQInteger)*2) +SQInteger SQLexer::ReadNumber() +{ +#define TINT 1 +#define TFLOAT 2 +#define THEX 3 +#define TSCIENTIFIC 4 + SQInteger type = TINT, firstchar = CUR_CHAR; + SQChar *sTemp; + INIT_TEMP_STRING(); + NEXT(); + if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) { + NEXT(); + type = THEX; + while(isxdigit(CUR_CHAR)) { + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number")); + } + else { + APPEND_CHAR((int)firstchar); + while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) { + if(CUR_CHAR == _SC('.')) type = TFLOAT; + if(isexponent(CUR_CHAR)) { + if(type != TFLOAT) Error(_SC("invalid numeric format")); + type = TSCIENTIFIC; + APPEND_CHAR(CUR_CHAR); + NEXT(); + if(CUR_CHAR == '+' || CUR_CHAR == '-'){ + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected")); + } + + APPEND_CHAR(CUR_CHAR); + NEXT(); + } + } + TERMINATE_BUFFER(); + switch(type) { + case TSCIENTIFIC: + case TFLOAT: + _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp); + return TK_FLOAT; + case TINT: + LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue); + return TK_INTEGER; + case THEX: + LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue); + return TK_INTEGER; + } + return 0; +} + +SQInteger SQLexer::ReadID() +{ + SQInteger res; + INIT_TEMP_STRING(); + do { + APPEND_CHAR(CUR_CHAR); + NEXT(); + } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_')); + TERMINATE_BUFFER(); + res = GetIDType(&_longstr[0]); + if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) { + _svalue = &_longstr[0]; + } + return res; +} diff --git a/src/squirrel/squirrel/sqlexer.h b/src/squirrel/squirrel/sqlexer.h index be3b188b3..52993e59a 100644 --- a/src/squirrel/squirrel/sqlexer.h +++ b/src/squirrel/squirrel/sqlexer.h @@ -1,45 +1,45 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQLEXER_H_ -#define _SQLEXER_H_ - -#ifdef _UNICODE -typedef SQChar LexChar; -#else -typedef unsigned char LexChar; -#endif - -struct SQLexer -{ - SQLexer(); - ~SQLexer(); - void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed); - void Error(const SQChar *err); - SQInteger Lex(); - const SQChar *Tok2Str(SQInteger tok); -private: - SQInteger GetIDType(SQChar *s); - SQInteger ReadString(SQInteger ndelim,bool verbatim); - SQInteger ReadNumber(); - void LexBlockComment(); - SQInteger ReadID(); - void Next(); - SQInteger _curtoken; - SQTable *_keywords; -public: - SQInteger _prevtoken; - SQInteger _currentline; - SQInteger _lasttokenline; - SQInteger _currentcolumn; - const SQChar *_svalue; - SQInteger _nvalue; - SQFloat _fvalue; - SQLEXREADFUNC _readf; - SQUserPointer _up; - LexChar _currdata; - SQSharedState *_sharedstate; - sqvector _longstr; - CompilerErrorFunc _errfunc; - void *_errtarget; -}; - -#endif +/* see copyright notice in squirrel.h */ +#ifndef _SQLEXER_H_ +#define _SQLEXER_H_ + +#ifdef _UNICODE +typedef SQChar LexChar; +#else +typedef unsigned char LexChar; +#endif + +struct SQLexer +{ + SQLexer(); + ~SQLexer(); + void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed); + void Error(const SQChar *err); + SQInteger Lex(); + const SQChar *Tok2Str(SQInteger tok); +private: + SQInteger GetIDType(SQChar *s); + SQInteger ReadString(SQInteger ndelim,bool verbatim); + SQInteger ReadNumber(); + void LexBlockComment(); + SQInteger ReadID(); + void Next(); + SQInteger _curtoken; + SQTable *_keywords; +public: + SQInteger _prevtoken; + SQInteger _currentline; + SQInteger _lasttokenline; + SQInteger _currentcolumn; + const SQChar *_svalue; + SQInteger _nvalue; + SQFloat _fvalue; + SQLEXREADFUNC _readf; + SQUserPointer _up; + LexChar _currdata; + SQSharedState *_sharedstate; + sqvector _longstr; + CompilerErrorFunc _errfunc; + void *_errtarget; +}; + +#endif diff --git a/src/squirrel/squirrel/sqmem.cpp b/src/squirrel/squirrel/sqmem.cpp index 520f7eb76..6faf8165a 100644 --- a/src/squirrel/squirrel/sqmem.cpp +++ b/src/squirrel/squirrel/sqmem.cpp @@ -1,9 +1,9 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); } - -void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); } - -void sq_vm_free(void *p, SQUnsignedInteger size){ free(p); } +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); } + +void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); } + +void sq_vm_free(void *p, SQUnsignedInteger size){ free(p); } diff --git a/src/squirrel/squirrel/sqobject.cpp b/src/squirrel/squirrel/sqobject.cpp index f01ce9302..e699e35e2 100644 --- a/src/squirrel/squirrel/sqobject.cpp +++ b/src/squirrel/squirrel/sqobject.cpp @@ -1,515 +1,514 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqvm.h" -#include "sqstring.h" -#include "sqarray.h" -#include "sqtable.h" -#include "squserdata.h" -#include "sqfuncproto.h" -#include "sqclass.h" -#include "sqclosure.h" - -SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) -{ - SQString *str=ADD_STRING(ss,s,len); - str->_sharedstate=ss; - return str; -} - -void SQString::Release() -{ - REMOVE_STRING(_sharedstate,this); -} - -SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) -{ - SQInteger idx = (SQInteger)TranslateIndex(refpos); - while(idx < _len){ - outkey = (SQInteger)idx; - outval = SQInteger(_val[idx]); - //return idx for the next iteration - return ++idx; - } - //nothing to iterate anymore - return -1; -} - -SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx) -{ - switch(type(idx)){ - case OT_NULL: - return 0; - case OT_INTEGER: - return (SQUnsignedInteger)_integer(idx); - default: assert(0); break; - } - return 0; -} - -SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type) -{ - if(!_weakref) { - sq_new(_weakref,SQWeakRef); - _weakref->_obj._type = type; - _weakref->_obj._unVal.pRefCounted = this; - } - return _weakref; -} - -SQRefCounted::~SQRefCounted() -{ - if(_weakref) { - _weakref->_obj._type = OT_NULL; - _weakref->_obj._unVal.pRefCounted = NULL; - } -} - -void SQWeakRef::Release() { - if(ISREFCOUNTED(_obj._type)) { - _obj._unVal.pRefCounted->_weakref = NULL; - } - sq_delete(this,SQWeakRef); -} - -bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) { - if(_delegate) { - return _delegate->Get((*_ss(v)->_metamethods)[mm],res); - } - return false; -} - -bool SQDelegable::SetDelegate(SQTable *mt) -{ - SQTable *temp = mt; - while (temp) { - if (temp->_delegate == this) return false; //cycle detected - temp = temp->_delegate; - } - if (mt) __ObjAddRef(mt); - __ObjRelease(_delegate); - _delegate = mt; - return true; -} - -bool SQGenerator::Yield(SQVM *v) -{ - if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} - if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } - SQInteger size = v->_top-v->_stackbase; - _ci=*v->ci; - _stack.resize(size); - for(SQInteger n =0; n_stack[v->_stackbase+n]; - v->_stack[v->_stackbase+n] = _null_; - } - SQInteger nvargs = v->ci->_vargs.size; - SQInteger vargsbase = v->ci->_vargs.base; - for(SQInteger j = nvargs - 1; j >= 0; j--) { - _vargsstack.push_back(v->_vargsstack[vargsbase+j]); - } - _ci._generator=_null_; - for(SQInteger i=0;i<_ci._etraps;i++) { - _etraps.push_back(v->_etraps.top()); - v->_etraps.pop_back(); - } - _state=eSuspended; - return true; -} - -bool SQGenerator::Resume(SQVM *v,SQInteger target) -{ - SQInteger size=_stack.size(); - if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } - if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } - SQInteger prevtop=v->_top-v->_stackbase; - PUSH_CALLINFO(v,_ci); - SQInteger oldstackbase=v->_stackbase; - v->_stackbase=v->_top; - v->ci->_target=target; - v->ci->_generator=SQObjectPtr(this); - v->ci->_vargs.size = _vargsstack.size(); - - for(SQInteger i=0;i<_ci._etraps;i++) { - v->_etraps.push_back(_etraps.top()); - _etraps.pop_back(); - } - for(SQInteger n =0; n_stack[v->_stackbase+n] = _stack._vals[n]; - _stack._vals[0] = _null_; - } - while(_vargsstack.size()) { - v->_vargsstack.push_back(_vargsstack.back()); - _vargsstack.pop_back(); - } - v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size; - v->_top=v->_stackbase+size; - v->ci->_prevtop=prevtop; - v->ci->_prevstkbase=v->_stackbase-oldstackbase; - _state=eRunning; - return true; -} - -void SQArray::Extend(const SQArray *a){ - SQInteger xlen; - if((xlen=a->Size())) - for(SQInteger i=0;i_values[i]); -} - -const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop) -{ - SQUnsignedInteger nvars=_localvarinfos.size(); - const SQChar *res=NULL; - if(nvars>=nseq){ - for(SQUnsignedInteger i=0;i=nop) - { - if(nseq==0){ - vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]); - res=_stringval(_localvarinfos[i]._name); - break; - } - nseq--; - } - } - } - return res; -} - -SQInteger SQFunctionProto::GetLine(SQInstruction *curr) -{ - SQInteger op = (SQInteger)(curr-_instructions._vals); - SQInteger line=_lineinfos[0]._line; - for(SQUnsignedInteger i=1;i<_lineinfos.size();i++){ - if(_lineinfos[i]._op>=op) - return line; - line=_lineinfos[i]._line; - } - return line; -} - -//#define _ERROR_TRAP() error_trap: -#define _CHECK_IO(exp) { if(!exp)return false; } -bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) -{ - if(write(up,dest,size) != size) { - v->Raise_Error(_SC("io error (write function failure)")); - return false; - } - return true; -} - -bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size) -{ - if(size && read(up,dest,size) != size) { - v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated")); - return false; - } - return true; -} - -bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag) -{ - return SafeWrite(v,write,up,&tag,sizeof(tag)); -} - -bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) -{ - SQInteger t; - _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); - if(t != tag){ - v->Raise_Error(_SC("invalid or corrupted closure stream")); - return false; - } - return true; -} - -bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) -{ - _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType))); - switch(type(o)){ - case OT_STRING: - _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); - _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len))); - break; - case OT_INTEGER: - _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break; - case OT_FLOAT: - _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break; - case OT_NULL: - break; - default: - v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o)); - return false; - } - return true; -} - -bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) -{ - SQObjectType t; - _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType))); - switch(t){ - case OT_STRING:{ - SQInteger len; - _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger))); - _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len))); - o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len); - } - break; - case OT_INTEGER:{ - SQInteger i; - _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break; - } - case OT_FLOAT:{ - SQFloat f; - _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; - } - case OT_NULL: - o=_null_; - break; - default: - v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); - return false; - } - return true; -} - -bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) -{ - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); - _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); - _CHECK_IO(_funcproto(_function)->Save(v,up,write)); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); - return true; -} - -bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read) -{ - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); - _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); - _CHECK_IO(_funcproto(_function)->Load(v,up,read)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); - return true; -} - -bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) -{ - SQInteger i,nsize=_literals.size(); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(WriteObject(v,up,write,_sourcename)); - _CHECK_IO(WriteObject(v,up,write,_name)); - _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize))); - for(i=0;iSave(v,up,write)); - } - _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize))); - _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator))); - _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams))); - return true; -} - -bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read) -{ - SQInteger i, nsize = _literals.size(); - SQObjectPtr o; - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(ReadObject(v, up, read, _sourcename)); - _CHECK_IO(ReadObject(v, up, read, _name)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); - for(i = 0;i < nsize; i++){ - _CHECK_IO(ReadObject(v, up, read, o)); - _literals.push_back(o); - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); - for(i = 0; i < nsize; i++){ - _CHECK_IO(ReadObject(v, up, read, o)); - _parameters.push_back(o); - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize))); - for(i = 0; i < nsize; i++){ - SQUnsignedInteger type; - SQObjectPtr name; - _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); - _CHECK_IO(ReadObject(v, up, read, o)); - _CHECK_IO(ReadObject(v, up, read, name)); - _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type)); - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize))); - for(i = 0; i < nsize; i++){ - SQLocalVarInfo lvi; - _CHECK_IO(ReadObject(v, up, read, lvi._name)); - _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger))); - _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger))); - _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger))); - _localvarinfos.push_back(lvi); - } - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize))); - _lineinfos.resize(nsize); - _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); - _instructions.resize(nsize); - _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize)); - _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); - _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); - for(i = 0; i < nsize; i++){ - o = SQFunctionProto::Create(); - _CHECK_IO(_funcproto(o)->Load(v, up, read)); - _functions.push_back(o); - } - _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize))); - _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator))); - _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams))); - return true; -} - -#ifndef NO_GARBAGE_COLLECTOR - -#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \ - _uiRef|=MARK_FLAG; - -#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \ - AddToChain(chain, this); } - -void SQVM::Mark(SQCollectable **chain) -{ - START_MARK() - SQSharedState::MarkObject(_lasterror,chain); - SQSharedState::MarkObject(_errorhandler,chain); - SQSharedState::MarkObject(_debughook,chain); - SQSharedState::MarkObject(_roottable, chain); - SQSharedState::MarkObject(temp_reg, chain); - for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); - END_MARK() -} - -void SQArray::Mark(SQCollectable **chain) -{ - START_MARK() - SQInteger len = _values.size(); - for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain); - END_MARK() -} -void SQTable::Mark(SQCollectable **chain) -{ - START_MARK() - if(_delegate) _delegate->Mark(chain); - SQInteger len = _numofnodes; - for(SQInteger i = 0; i < len; i++){ - SQSharedState::MarkObject(_nodes[i].key, chain); - SQSharedState::MarkObject(_nodes[i].val, chain); - } - END_MARK() -} - -void SQClass::Mark(SQCollectable **chain) -{ - START_MARK() - _members->Mark(chain); - if(_base) _base->Mark(chain); - SQSharedState::MarkObject(_attributes, chain); - for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) { - SQSharedState::MarkObject(_defaultvalues[i].val, chain); - SQSharedState::MarkObject(_defaultvalues[i].attrs, chain); - } - for(SQUnsignedInteger j =0; j< _methods.size(); j++) { - SQSharedState::MarkObject(_methods[j].val, chain); - SQSharedState::MarkObject(_methods[j].attrs, chain); - } - for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) { - SQSharedState::MarkObject(_metamethods[k], chain); - } - END_MARK() -} - -void SQInstance::Mark(SQCollectable **chain) -{ - START_MARK() - _class->Mark(chain); - for(SQUnsignedInteger i =0; i< _nvalues; i++) { - SQSharedState::MarkObject(_values[i], chain); - } - END_MARK() -} - -void SQGenerator::Mark(SQCollectable **chain) -{ - START_MARK() - for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); - for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); - SQSharedState::MarkObject(_closure, chain); - END_MARK() -} - -void SQClosure::Mark(SQCollectable **chain) -{ - START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); - END_MARK() -} - -void SQNativeClosure::Mark(SQCollectable **chain) -{ - START_MARK() - for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); - END_MARK() -} - -void SQUserData::Mark(SQCollectable **chain){ - START_MARK() - if(_delegate) _delegate->Mark(chain); - END_MARK() -} - -void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; } - -#endif - +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqstring.h" +#include "sqarray.h" +#include "sqtable.h" +#include "squserdata.h" +#include "sqfuncproto.h" +#include "sqclass.h" +#include "sqclosure.h" + +SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) +{ + SQString *str=ADD_STRING(ss,s,len); + str->_sharedstate=ss; + return str; +} + +void SQString::Release() +{ + REMOVE_STRING(_sharedstate,this); +} + +SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while(idx < _len){ + outkey = (SQInteger)idx; + outval = SQInteger(_val[idx]); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; +} + +SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx) +{ + switch(type(idx)){ + case OT_NULL: + return 0; + case OT_INTEGER: + return (SQUnsignedInteger)_integer(idx); + default: assert(0); break; + } + return 0; +} + +SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type) +{ + if(!_weakref) { + sq_new(_weakref,SQWeakRef); + _weakref->_obj._type = type; + _weakref->_obj._unVal.pRefCounted = this; + } + return _weakref; +} + +SQRefCounted::~SQRefCounted() +{ + if(_weakref) { + _weakref->_obj._type = OT_NULL; + _weakref->_obj._unVal.pRefCounted = NULL; + } +} + +void SQWeakRef::Release() { + if(ISREFCOUNTED(_obj._type)) { + _obj._unVal.pRefCounted->_weakref = NULL; + } + sq_delete(this,SQWeakRef); +} + +bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) { + if(_delegate) { + return _delegate->Get((*_ss(v)->_metamethods)[mm],res); + } + return false; +} + +bool SQDelegable::SetDelegate(SQTable *mt) +{ + SQTable *temp = mt; + while (temp) { + if (temp->_delegate == this) return false; //cycle detected + temp = temp->_delegate; + } + if (mt) __ObjAddRef(mt); + __ObjRelease(_delegate); + _delegate = mt; + return true; +} + +bool SQGenerator::Yield(SQVM *v) +{ + if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} + if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } + SQInteger size = v->_top-v->_stackbase; + _ci=*v->ci; + _stack.resize(size); + for(SQInteger n =0; n_stack[v->_stackbase+n]; + v->_stack[v->_stackbase+n] = _null_; + } + SQInteger nvargs = v->ci->_vargs.size; + SQInteger vargsbase = v->ci->_vargs.base; + for(SQInteger j = nvargs - 1; j >= 0; j--) { + _vargsstack.push_back(v->_vargsstack[vargsbase+j]); + } + _ci._generator=_null_; + for(SQInteger i=0;i<_ci._etraps;i++) { + _etraps.push_back(v->_etraps.top()); + v->_etraps.pop_back(); + } + _state=eSuspended; + return true; +} + +bool SQGenerator::Resume(SQVM *v,SQInteger target) +{ + SQInteger size=_stack.size(); + if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } + if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } + SQInteger prevtop=v->_top-v->_stackbase; + PUSH_CALLINFO(v,_ci); + SQInteger oldstackbase=v->_stackbase; + v->_stackbase=v->_top; + v->ci->_target=target; + v->ci->_generator=SQObjectPtr(this); + v->ci->_vargs.size = _vargsstack.size(); + + for(SQInteger i=0;i<_ci._etraps;i++) { + v->_etraps.push_back(_etraps.top()); + _etraps.pop_back(); + } + for(SQInteger n =0; n_stack[v->_stackbase+n] = _stack._vals[n]; + _stack._vals[0] = _null_; + } + while(_vargsstack.size()) { + v->_vargsstack.push_back(_vargsstack.back()); + _vargsstack.pop_back(); + } + v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size; + v->_top=v->_stackbase+size; + v->ci->_prevtop=prevtop; + v->ci->_prevstkbase=v->_stackbase-oldstackbase; + _state=eRunning; + return true; +} + +void SQArray::Extend(const SQArray *a){ + SQInteger xlen; + if((xlen=a->Size())) + for(SQInteger i=0;i_values[i]); +} + +const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop) +{ + SQUnsignedInteger nvars=_localvarinfos.size(); + const SQChar *res=NULL; + if(nvars>=nseq){ + for(SQUnsignedInteger i=0;i=nop) + { + if(nseq==0){ + vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]); + res=_stringval(_localvarinfos[i]._name); + break; + } + nseq--; + } + } + } + return res; +} + +SQInteger SQFunctionProto::GetLine(SQInstruction *curr) +{ + SQInteger op = (SQInteger)(curr-_instructions._vals); + SQInteger line=_lineinfos[0]._line; + for(SQUnsignedInteger i=1;i<_lineinfos.size();i++){ + if(_lineinfos[i]._op>=op) + return line; + line=_lineinfos[i]._line; + } + return line; +} + +//#define _ERROR_TRAP() error_trap: +#define _CHECK_IO(exp) { if(!exp)return false; } +bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) +{ + if(write(up,dest,size) != size) { + v->Raise_Error(_SC("io error (write function failure)")); + return false; + } + return true; +} + +bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size) +{ + if(size && read(up,dest,size) != size) { + v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated")); + return false; + } + return true; +} + +bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag) +{ + return SafeWrite(v,write,up,&tag,sizeof(tag)); +} + +bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) +{ + SQInteger t; + _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); + if(t != tag){ + v->Raise_Error(_SC("invalid or corrupted closure stream")); + return false; + } + return true; +} + +bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) +{ + _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType))); + switch(type(o)){ + case OT_STRING: + _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); + _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len))); + break; + case OT_INTEGER: + _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break; + case OT_FLOAT: + _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break; + case OT_NULL: + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o)); + return false; + } + return true; +} + +bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) +{ + SQObjectType t; + _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType))); + switch(t){ + case OT_STRING:{ + SQInteger len; + _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger))); + _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len))); + o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len); + } + break; + case OT_INTEGER:{ + SQInteger i; + _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break; + } + case OT_FLOAT:{ + SQFloat f; + _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; + } + case OT_NULL: + o=_null_; + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); + return false; + } + return true; +} + +bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) +{ + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); + _CHECK_IO(_funcproto(_function)->Save(v,up,write)); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); + return true; +} + +bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read) +{ + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); + _CHECK_IO(_funcproto(_function)->Load(v,up,read)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); + return true; +} + +bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) +{ + SQInteger i,nsize=_literals.size(); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(WriteObject(v,up,write,_sourcename)); + _CHECK_IO(WriteObject(v,up,write,_name)); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize))); + for(i=0;iSave(v,up,write)); + } + _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize))); + _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator))); + _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams))); + return true; +} + +bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read) +{ + SQInteger i, nsize = _literals.size(); + SQObjectPtr o; + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(ReadObject(v, up, read, _sourcename)); + _CHECK_IO(ReadObject(v, up, read, _name)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); + for(i = 0;i < nsize; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + _literals.push_back(o); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); + for(i = 0; i < nsize; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + _parameters.push_back(o); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize))); + for(i = 0; i < nsize; i++){ + SQUnsignedInteger type; + SQObjectPtr name; + _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); + _CHECK_IO(ReadObject(v, up, read, o)); + _CHECK_IO(ReadObject(v, up, read, name)); + _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type)); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize))); + for(i = 0; i < nsize; i++){ + SQLocalVarInfo lvi; + _CHECK_IO(ReadObject(v, up, read, lvi._name)); + _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger))); + _localvarinfos.push_back(lvi); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize))); + _lineinfos.resize(nsize); + _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); + _instructions.resize(nsize); + _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize))); + for(i = 0; i < nsize; i++){ + o = SQFunctionProto::Create(); + _CHECK_IO(_funcproto(o)->Load(v, up, read)); + _functions.push_back(o); + } + _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize))); + _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator))); + _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams))); + return true; +} + +#ifndef NO_GARBAGE_COLLECTOR + +#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \ + _uiRef|=MARK_FLAG; + +#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \ + AddToChain(chain, this); } + +void SQVM::Mark(SQCollectable **chain) +{ + START_MARK() + SQSharedState::MarkObject(_lasterror,chain); + SQSharedState::MarkObject(_errorhandler,chain); + SQSharedState::MarkObject(_debughook,chain); + SQSharedState::MarkObject(_roottable, chain); + SQSharedState::MarkObject(temp_reg, chain); + for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); + for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); + END_MARK() +} + +void SQArray::Mark(SQCollectable **chain) +{ + START_MARK() + SQInteger len = _values.size(); + for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain); + END_MARK() +} +void SQTable::Mark(SQCollectable **chain) +{ + START_MARK() + if(_delegate) _delegate->Mark(chain); + SQInteger len = _numofnodes; + for(SQInteger i = 0; i < len; i++){ + SQSharedState::MarkObject(_nodes[i].key, chain); + SQSharedState::MarkObject(_nodes[i].val, chain); + } + END_MARK() +} + +void SQClass::Mark(SQCollectable **chain) +{ + START_MARK() + _members->Mark(chain); + if(_base) _base->Mark(chain); + SQSharedState::MarkObject(_attributes, chain); + for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) { + SQSharedState::MarkObject(_defaultvalues[i].val, chain); + SQSharedState::MarkObject(_defaultvalues[i].attrs, chain); + } + for(SQUnsignedInteger j =0; j< _methods.size(); j++) { + SQSharedState::MarkObject(_methods[j].val, chain); + SQSharedState::MarkObject(_methods[j].attrs, chain); + } + for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) { + SQSharedState::MarkObject(_metamethods[k], chain); + } + END_MARK() +} + +void SQInstance::Mark(SQCollectable **chain) +{ + START_MARK() + _class->Mark(chain); + for(SQUnsignedInteger i =0; i< _nvalues; i++) { + SQSharedState::MarkObject(_values[i], chain); + } + END_MARK() +} + +void SQGenerator::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); + for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); + SQSharedState::MarkObject(_closure, chain); + END_MARK() +} + +void SQClosure::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + END_MARK() +} + +void SQNativeClosure::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + END_MARK() +} + +void SQUserData::Mark(SQCollectable **chain){ + START_MARK() + if(_delegate) _delegate->Mark(chain); + END_MARK() +} + +void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; } + +#endif diff --git a/src/squirrel/squirrel/sqobject.h b/src/squirrel/squirrel/sqobject.h index c4489131b..ee655b08e 100644 --- a/src/squirrel/squirrel/sqobject.h +++ b/src/squirrel/squirrel/sqobject.h @@ -1,331 +1,331 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQOBJECT_H_ -#define _SQOBJECT_H_ - -#include "squtils.h" - -#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) -#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T')) -#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L')) - -struct SQSharedState; - -enum SQMetaMethod{ - MT_ADD=0, - MT_SUB=1, - MT_MUL=2, - MT_DIV=3, - MT_UNM=4, - MT_MODULO=5, - MT_SET=6, - MT_GET=7, - MT_TYPEOF=8, - MT_NEXTI=9, - MT_CMP=10, - MT_CALL=11, - MT_CLONED=12, - MT_NEWSLOT=13, - MT_DELSLOT=14, - MT_TOSTRING=15, - MT_NEWMEMBER=16, - MT_INHERITED=17, - MT_LAST = 18 -}; - -#define MM_ADD _SC("_add") -#define MM_SUB _SC("_sub") -#define MM_MUL _SC("_mul") -#define MM_DIV _SC("_div") -#define MM_UNM _SC("_unm") -#define MM_MODULO _SC("_modulo") -#define MM_SET _SC("_set") -#define MM_GET _SC("_get") -#define MM_TYPEOF _SC("_typeof") -#define MM_NEXTI _SC("_nexti") -#define MM_CMP _SC("_cmp") -#define MM_CALL _SC("_call") -#define MM_CLONED _SC("_cloned") -#define MM_NEWSLOT _SC("_newslot") -#define MM_DELSLOT _SC("_delslot") -#define MM_TOSTRING _SC("_tostring") -#define MM_NEWMEMBER _SC("_newmember") -#define MM_INHERITED _SC("_inherited") - -#define MINPOWER2 4 - -struct SQRefCounted -{ - SQRefCounted() { _uiRef = 0; _weakref = NULL; } - virtual ~SQRefCounted(); - SQWeakRef *GetWeakRef(SQObjectType type); - SQUnsignedInteger _uiRef; - struct SQWeakRef *_weakref; - virtual void Release()=0; -}; - -struct SQWeakRef : SQRefCounted -{ - void Release(); - SQObject _obj; -}; - -#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj) - -struct SQObjectPtr; - -#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \ - { \ - unval.pRefCounted->_uiRef++; \ - } - -#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \ - { \ - unval.pRefCounted->Release(); \ - } - -#define __ObjRelease(obj) { \ - if((obj)) { \ - (obj)->_uiRef--; \ - if((obj)->_uiRef == 0) \ - (obj)->Release(); \ - (obj) = NULL; \ - } \ -} - -#define __ObjAddRef(obj) { \ - (obj)->_uiRef++; \ -} - -#define type(obj) ((obj)._type) -#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE) -#define raw_type(obj) _RAW_TYPE((obj)._type) - -#define _integer(obj) ((obj)._unVal.nInteger) -#define _float(obj) ((obj)._unVal.fFloat) -#define _string(obj) ((obj)._unVal.pString) -#define _table(obj) ((obj)._unVal.pTable) -#define _array(obj) ((obj)._unVal.pArray) -#define _closure(obj) ((obj)._unVal.pClosure) -#define _generator(obj) ((obj)._unVal.pGenerator) -#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure) -#define _userdata(obj) ((obj)._unVal.pUserData) -#define _userpointer(obj) ((obj)._unVal.pUserPointer) -#define _thread(obj) ((obj)._unVal.pThread) -#define _funcproto(obj) ((obj)._unVal.pFunctionProto) -#define _class(obj) ((obj)._unVal.pClass) -#define _instance(obj) ((obj)._unVal.pInstance) -#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable) -#define _weakref(obj) ((obj)._unVal.pWeakRef) -#define _refcounted(obj) ((obj)._unVal.pRefCounted) -#define _rawval(obj) ((obj)._unVal.pRefCounted) - -#define _stringval(obj) (obj)._unVal.pString->_val -#define _userdataval(obj) (obj)._unVal.pUserData->_val - -#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) -#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) -///////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////// -struct SQObjectPtr : public SQObject -{ - SQObjectPtr() - { - _type=OT_NULL; - _unVal.pUserPointer=NULL; - } - SQObjectPtr(const SQObjectPtr &o) - { - _type=o._type; - _unVal=o._unVal; - __AddRef(_type,_unVal); - } - SQObjectPtr(const SQObject &o) - { - _type=o._type; - _unVal=o._unVal; - __AddRef(_type,_unVal); - } - SQObjectPtr(SQTable *pTable) - { - _type=OT_TABLE; - _unVal.pTable=pTable; - assert(_unVal.pTable); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClass *pClass) - { - _type=OT_CLASS; - _unVal.pClass=pClass; - assert(_unVal.pClass); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQInstance *pInstance) - { - _type=OT_INSTANCE; - _unVal.pInstance=pInstance; - assert(_unVal.pInstance); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQArray *pArray) - { - _type=OT_ARRAY; - _unVal.pArray=pArray; - assert(_unVal.pArray); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQClosure *pClosure) - { - _type=OT_CLOSURE; - _unVal.pClosure=pClosure; - assert(_unVal.pClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQGenerator *pGenerator) - { - _type=OT_GENERATOR; - _unVal.pGenerator=pGenerator; - assert(_unVal.pGenerator); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQNativeClosure *pNativeClosure) - { - _type=OT_NATIVECLOSURE; - _unVal.pNativeClosure=pNativeClosure; - assert(_unVal.pNativeClosure); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQString *pString) - { - _type=OT_STRING; - _unVal.pString=pString; - assert(_unVal.pString); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQUserData *pUserData) - { - _type=OT_USERDATA; - _unVal.pUserData=pUserData; - assert(_unVal.pUserData); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQVM *pThread) - { - _type=OT_THREAD; - _unVal.pThread=pThread; - assert(_unVal.pThread); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQWeakRef *pWeakRef) - { - _type=OT_WEAKREF; - _unVal.pWeakRef=pWeakRef; - assert(_unVal.pWeakRef); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQFunctionProto *pFunctionProto) - { - _type=OT_FUNCPROTO; - _unVal.pFunctionProto=pFunctionProto; - assert(_unVal.pFunctionProto); - __AddRef(_type,_unVal); - } - SQObjectPtr(SQInteger nInteger) - { - _unVal.pUserPointer=NULL; - _type=OT_INTEGER; - _unVal.nInteger=nInteger; - } - SQObjectPtr(SQFloat fFloat) - { - _unVal.pUserPointer=NULL; - _type=OT_FLOAT; - _unVal.fFloat=fFloat; - } - SQObjectPtr(bool bBool) - { - _unVal.pUserPointer=NULL; - _type = OT_BOOL; - _unVal.nInteger = bBool?1:0; - } - SQObjectPtr(SQUserPointer pUserPointer) - { - _type=OT_USERPOINTER; - _unVal.pUserPointer=pUserPointer; - } - ~SQObjectPtr() - { - __Release(_type,_unVal); - } - inline void Null() - { - __Release(_type,_unVal); - _type=OT_NULL; - _unVal.pUserPointer=NULL; - } - inline SQObjectPtr& operator=(const SQObjectPtr& obj) - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType=_type; - unOldVal=_unVal; - _unVal = obj._unVal; - _type = obj._type; - __AddRef(_type,_unVal); - __Release(tOldType,unOldVal); - return *this; - } - inline SQObjectPtr& operator=(const SQObject& obj) - { - SQObjectType tOldType; - SQObjectValue unOldVal; - tOldType=_type; - unOldVal=_unVal; - _unVal = obj._unVal; - _type = obj._type; - __AddRef(_type,_unVal); - __Release(tOldType,unOldVal); - return *this; - } - private: - SQObjectPtr(const SQChar *){} //safety -}; -///////////////////////////////////////////////////////////////////////////////////// -#ifndef NO_GARBAGE_COLLECTOR -#define MARK_FLAG 0x80000000 -struct SQCollectable : public SQRefCounted { - SQCollectable *_next; - SQCollectable *_prev; - SQSharedState *_sharedstate; - virtual void Release()=0; - virtual void Mark(SQCollectable **chain)=0; - void UnMark(); - virtual void Finalize()=0; - static void AddToChain(SQCollectable **chain,SQCollectable *c); - static void RemoveFromChain(SQCollectable **chain,SQCollectable *c); -}; - - -#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj) -#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);} -#define CHAINABLE_OBJ SQCollectable -#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;} -#else - -#define ADD_TO_CHAIN(chain,obj) ((void)0) -#define REMOVE_FROM_CHAIN(chain,obj) ((void)0) -#define CHAINABLE_OBJ SQRefCounted -#define INIT_CHAIN() ((void)0) -#endif - -struct SQDelegable : public CHAINABLE_OBJ { - bool SetDelegate(SQTable *m); - virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); - SQTable *_delegate; -}; - -SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx); -typedef sqvector SQObjectPtrVec; -typedef sqvector SQIntVec; - - -#endif //_SQOBJECT_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQOBJECT_H_ +#define _SQOBJECT_H_ + +#include "squtils.h" + +#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) +#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T')) +#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L')) + +struct SQSharedState; + +enum SQMetaMethod{ + MT_ADD=0, + MT_SUB=1, + MT_MUL=2, + MT_DIV=3, + MT_UNM=4, + MT_MODULO=5, + MT_SET=6, + MT_GET=7, + MT_TYPEOF=8, + MT_NEXTI=9, + MT_CMP=10, + MT_CALL=11, + MT_CLONED=12, + MT_NEWSLOT=13, + MT_DELSLOT=14, + MT_TOSTRING=15, + MT_NEWMEMBER=16, + MT_INHERITED=17, + MT_LAST = 18 +}; + +#define MM_ADD _SC("_add") +#define MM_SUB _SC("_sub") +#define MM_MUL _SC("_mul") +#define MM_DIV _SC("_div") +#define MM_UNM _SC("_unm") +#define MM_MODULO _SC("_modulo") +#define MM_SET _SC("_set") +#define MM_GET _SC("_get") +#define MM_TYPEOF _SC("_typeof") +#define MM_NEXTI _SC("_nexti") +#define MM_CMP _SC("_cmp") +#define MM_CALL _SC("_call") +#define MM_CLONED _SC("_cloned") +#define MM_NEWSLOT _SC("_newslot") +#define MM_DELSLOT _SC("_delslot") +#define MM_TOSTRING _SC("_tostring") +#define MM_NEWMEMBER _SC("_newmember") +#define MM_INHERITED _SC("_inherited") + +#define MINPOWER2 4 + +struct SQRefCounted +{ + SQRefCounted() { _uiRef = 0; _weakref = NULL; } + virtual ~SQRefCounted(); + SQWeakRef *GetWeakRef(SQObjectType type); + SQUnsignedInteger _uiRef; + struct SQWeakRef *_weakref; + virtual void Release()=0; +}; + +struct SQWeakRef : SQRefCounted +{ + void Release(); + SQObject _obj; +}; + +#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj) + +struct SQObjectPtr; + +#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \ + { \ + unval.pRefCounted->_uiRef++; \ + } + +#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \ + { \ + unval.pRefCounted->Release(); \ + } + +#define __ObjRelease(obj) { \ + if((obj)) { \ + (obj)->_uiRef--; \ + if((obj)->_uiRef == 0) \ + (obj)->Release(); \ + (obj) = NULL; \ + } \ +} + +#define __ObjAddRef(obj) { \ + (obj)->_uiRef++; \ +} + +#define type(obj) ((obj)._type) +#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE) +#define raw_type(obj) _RAW_TYPE((obj)._type) + +#define _integer(obj) ((obj)._unVal.nInteger) +#define _float(obj) ((obj)._unVal.fFloat) +#define _string(obj) ((obj)._unVal.pString) +#define _table(obj) ((obj)._unVal.pTable) +#define _array(obj) ((obj)._unVal.pArray) +#define _closure(obj) ((obj)._unVal.pClosure) +#define _generator(obj) ((obj)._unVal.pGenerator) +#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure) +#define _userdata(obj) ((obj)._unVal.pUserData) +#define _userpointer(obj) ((obj)._unVal.pUserPointer) +#define _thread(obj) ((obj)._unVal.pThread) +#define _funcproto(obj) ((obj)._unVal.pFunctionProto) +#define _class(obj) ((obj)._unVal.pClass) +#define _instance(obj) ((obj)._unVal.pInstance) +#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable) +#define _weakref(obj) ((obj)._unVal.pWeakRef) +#define _refcounted(obj) ((obj)._unVal.pRefCounted) +#define _rawval(obj) ((obj)._unVal.pRefCounted) + +#define _stringval(obj) (obj)._unVal.pString->_val +#define _userdataval(obj) (obj)._unVal.pUserData->_val + +#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) +#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +struct SQObjectPtr : public SQObject +{ + SQObjectPtr() + { + _type=OT_NULL; + _unVal.pUserPointer=NULL; + } + SQObjectPtr(const SQObjectPtr &o) + { + _type=o._type; + _unVal=o._unVal; + __AddRef(_type,_unVal); + } + SQObjectPtr(const SQObject &o) + { + _type=o._type; + _unVal=o._unVal; + __AddRef(_type,_unVal); + } + SQObjectPtr(SQTable *pTable) + { + _type=OT_TABLE; + _unVal.pTable=pTable; + assert(_unVal.pTable); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQClass *pClass) + { + _type=OT_CLASS; + _unVal.pClass=pClass; + assert(_unVal.pClass); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQInstance *pInstance) + { + _type=OT_INSTANCE; + _unVal.pInstance=pInstance; + assert(_unVal.pInstance); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQArray *pArray) + { + _type=OT_ARRAY; + _unVal.pArray=pArray; + assert(_unVal.pArray); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQClosure *pClosure) + { + _type=OT_CLOSURE; + _unVal.pClosure=pClosure; + assert(_unVal.pClosure); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQGenerator *pGenerator) + { + _type=OT_GENERATOR; + _unVal.pGenerator=pGenerator; + assert(_unVal.pGenerator); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQNativeClosure *pNativeClosure) + { + _type=OT_NATIVECLOSURE; + _unVal.pNativeClosure=pNativeClosure; + assert(_unVal.pNativeClosure); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQString *pString) + { + _type=OT_STRING; + _unVal.pString=pString; + assert(_unVal.pString); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQUserData *pUserData) + { + _type=OT_USERDATA; + _unVal.pUserData=pUserData; + assert(_unVal.pUserData); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQVM *pThread) + { + _type=OT_THREAD; + _unVal.pThread=pThread; + assert(_unVal.pThread); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQWeakRef *pWeakRef) + { + _type=OT_WEAKREF; + _unVal.pWeakRef=pWeakRef; + assert(_unVal.pWeakRef); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQFunctionProto *pFunctionProto) + { + _type=OT_FUNCPROTO; + _unVal.pFunctionProto=pFunctionProto; + assert(_unVal.pFunctionProto); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQInteger nInteger) + { + _unVal.pUserPointer=NULL; + _type=OT_INTEGER; + _unVal.nInteger=nInteger; + } + SQObjectPtr(SQFloat fFloat) + { + _unVal.pUserPointer=NULL; + _type=OT_FLOAT; + _unVal.fFloat=fFloat; + } + SQObjectPtr(bool bBool) + { + _unVal.pUserPointer=NULL; + _type = OT_BOOL; + _unVal.nInteger = bBool?1:0; + } + SQObjectPtr(SQUserPointer pUserPointer) + { + _type=OT_USERPOINTER; + _unVal.pUserPointer=pUserPointer; + } + ~SQObjectPtr() + { + __Release(_type,_unVal); + } + inline void Null() + { + __Release(_type,_unVal); + _type=OT_NULL; + _unVal.pUserPointer=NULL; + } + inline SQObjectPtr& operator=(const SQObjectPtr& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + inline SQObjectPtr& operator=(const SQObject& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + private: + SQObjectPtr(const SQChar *){} //safety +}; +///////////////////////////////////////////////////////////////////////////////////// +#ifndef NO_GARBAGE_COLLECTOR +#define MARK_FLAG 0x80000000 +struct SQCollectable : public SQRefCounted { + SQCollectable *_next; + SQCollectable *_prev; + SQSharedState *_sharedstate; + virtual void Release()=0; + virtual void Mark(SQCollectable **chain)=0; + void UnMark(); + virtual void Finalize()=0; + static void AddToChain(SQCollectable **chain,SQCollectable *c); + static void RemoveFromChain(SQCollectable **chain,SQCollectable *c); +}; + + +#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj) +#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);} +#define CHAINABLE_OBJ SQCollectable +#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;} +#else + +#define ADD_TO_CHAIN(chain,obj) ((void)0) +#define REMOVE_FROM_CHAIN(chain,obj) ((void)0) +#define CHAINABLE_OBJ SQRefCounted +#define INIT_CHAIN() ((void)0) +#endif + +struct SQDelegable : public CHAINABLE_OBJ { + bool SetDelegate(SQTable *m); + virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + SQTable *_delegate; +}; + +SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx); +typedef sqvector SQObjectPtrVec; +typedef sqvector SQIntVec; + + +#endif //_SQOBJECT_H_ diff --git a/src/squirrel/squirrel/sqopcodes.h b/src/squirrel/squirrel/sqopcodes.h index 2d0ffa6fa..be7fe29a2 100644 --- a/src/squirrel/squirrel/sqopcodes.h +++ b/src/squirrel/squirrel/sqopcodes.h @@ -1,113 +1,113 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQOPCODES_H_ -#define _SQOPCODES_H_ - -#define MAX_FUNC_STACKSIZE 0xFF -#define MAX_LITERALS ((SQInteger)0x7FFFFFFF) - -enum BitWiseOP { - BW_AND = 0, - BW_OR = 2, //like ADD - BW_XOR = 3, - BW_SHIFTL = 4, - BW_SHIFTR = 5, - BW_USHIFTR = 6 -}; - -enum CmpOP { - CMP_G = 0, - CMP_GE = 2, //like ADD - CMP_L = 3, - CMP_LE = 4 -}; -enum SQOpcode -{ - _OP_LINE= 0x00, - _OP_LOAD= 0x01, - _OP_LOADINT= 0x02, - _OP_DLOAD= 0x03, - _OP_TAILCALL= 0x04, - _OP_CALL= 0x05, - _OP_PREPCALL= 0x06, - _OP_PREPCALLK= 0x07, - _OP_GETK= 0x08, - _OP_MOVE= 0x09, - _OP_NEWSLOT= 0x0A, - _OP_DELETE= 0x0B, - _OP_SET= 0x0C, - _OP_GET= 0x0D, - _OP_EQ= 0x0E, - _OP_NE= 0x0F, - _OP_ARITH= 0x10, - _OP_BITW= 0x11, - _OP_RETURN= 0x12, - _OP_LOADNULLS= 0x13, - _OP_LOADROOTTABLE= 0x14, - _OP_LOADBOOL= 0x15, - _OP_DMOVE= 0x16, - _OP_JMP= 0x17, - _OP_JNZ= 0x18, - _OP_JZ= 0x19, - _OP_LOADFREEVAR= 0x1A, - _OP_VARGC= 0x1B, - _OP_GETVARGV= 0x1C, - _OP_NEWTABLE= 0x1D, - _OP_NEWARRAY= 0x1E, - _OP_APPENDARRAY= 0x1F, - _OP_GETPARENT= 0x20, - _OP_COMPARITH= 0x21, - _OP_COMPARITHL= 0x22, - _OP_INC= 0x23, - _OP_INCL= 0x24, - _OP_PINC= 0x25, - _OP_PINCL= 0x26, - _OP_CMP= 0x27, - _OP_EXISTS= 0x28, - _OP_INSTANCEOF= 0x29, - _OP_AND= 0x2A, - _OP_OR= 0x2B, - _OP_NEG= 0x2C, - _OP_NOT= 0x2D, - _OP_BWNOT= 0x2E, - _OP_CLOSURE= 0x2F, - _OP_YIELD= 0x30, - _OP_RESUME= 0x31, - _OP_FOREACH= 0x32, - _OP_DELEGATE= 0x33, - _OP_CLONE= 0x34, - _OP_TYPEOF= 0x35, - _OP_PUSHTRAP= 0x36, - _OP_POPTRAP= 0x37, - _OP_THROW= 0x38, - _OP_CLASS= 0x39, - _OP_NEWSLOTA= 0x3A -}; - -struct SQInstructionDesc { - const SQChar *name; -}; - -struct SQInstruction -{ - SQInstruction(){}; - SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0) - { op = _op; - _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1; - _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3; - } - - - SQInt32 _arg1; - unsigned char op; - unsigned char _arg0; - unsigned char _arg2; - unsigned char _arg3; -}; - -#include "squtils.h" -typedef sqvector SQInstructionVec; - -#define NEW_SLOT_ATTRIBUTES_FLAG 0x01 -#define NEW_SLOT_STATIC_FLAG 0x02 - -#endif // _SQOPCODES_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQOPCODES_H_ +#define _SQOPCODES_H_ + +#define MAX_FUNC_STACKSIZE 0xFF +#define MAX_LITERALS ((SQInteger)0x7FFFFFFF) + +enum BitWiseOP { + BW_AND = 0, + BW_OR = 2, //like ADD + BW_XOR = 3, + BW_SHIFTL = 4, + BW_SHIFTR = 5, + BW_USHIFTR = 6 +}; + +enum CmpOP { + CMP_G = 0, + CMP_GE = 2, //like ADD + CMP_L = 3, + CMP_LE = 4 +}; +enum SQOpcode +{ + _OP_LINE= 0x00, + _OP_LOAD= 0x01, + _OP_LOADINT= 0x02, + _OP_DLOAD= 0x03, + _OP_TAILCALL= 0x04, + _OP_CALL= 0x05, + _OP_PREPCALL= 0x06, + _OP_PREPCALLK= 0x07, + _OP_GETK= 0x08, + _OP_MOVE= 0x09, + _OP_NEWSLOT= 0x0A, + _OP_DELETE= 0x0B, + _OP_SET= 0x0C, + _OP_GET= 0x0D, + _OP_EQ= 0x0E, + _OP_NE= 0x0F, + _OP_ARITH= 0x10, + _OP_BITW= 0x11, + _OP_RETURN= 0x12, + _OP_LOADNULLS= 0x13, + _OP_LOADROOTTABLE= 0x14, + _OP_LOADBOOL= 0x15, + _OP_DMOVE= 0x16, + _OP_JMP= 0x17, + _OP_JNZ= 0x18, + _OP_JZ= 0x19, + _OP_LOADFREEVAR= 0x1A, + _OP_VARGC= 0x1B, + _OP_GETVARGV= 0x1C, + _OP_NEWTABLE= 0x1D, + _OP_NEWARRAY= 0x1E, + _OP_APPENDARRAY= 0x1F, + _OP_GETPARENT= 0x20, + _OP_COMPARITH= 0x21, + _OP_COMPARITHL= 0x22, + _OP_INC= 0x23, + _OP_INCL= 0x24, + _OP_PINC= 0x25, + _OP_PINCL= 0x26, + _OP_CMP= 0x27, + _OP_EXISTS= 0x28, + _OP_INSTANCEOF= 0x29, + _OP_AND= 0x2A, + _OP_OR= 0x2B, + _OP_NEG= 0x2C, + _OP_NOT= 0x2D, + _OP_BWNOT= 0x2E, + _OP_CLOSURE= 0x2F, + _OP_YIELD= 0x30, + _OP_RESUME= 0x31, + _OP_FOREACH= 0x32, + _OP_DELEGATE= 0x33, + _OP_CLONE= 0x34, + _OP_TYPEOF= 0x35, + _OP_PUSHTRAP= 0x36, + _OP_POPTRAP= 0x37, + _OP_THROW= 0x38, + _OP_CLASS= 0x39, + _OP_NEWSLOTA= 0x3A +}; + +struct SQInstructionDesc { + const SQChar *name; +}; + +struct SQInstruction +{ + SQInstruction(){}; + SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0) + { op = _op; + _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1; + _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3; + } + + + SQInt32 _arg1; + unsigned char op; + unsigned char _arg0; + unsigned char _arg2; + unsigned char _arg3; +}; + +#include "squtils.h" +typedef sqvector SQInstructionVec; + +#define NEW_SLOT_ATTRIBUTES_FLAG 0x01 +#define NEW_SLOT_STATIC_FLAG 0x02 + +#endif // _SQOPCODES_H_ diff --git a/src/squirrel/squirrel/sqpcheader.h b/src/squirrel/squirrel/sqpcheader.h index f0e5cf2df..db49f5e0d 100644 --- a/src/squirrel/squirrel/sqpcheader.h +++ b/src/squirrel/squirrel/sqpcheader.h @@ -1,19 +1,19 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQPCHEADER_H_ -#define _SQPCHEADER_H_ - -#if defined(_MSC_VER) && defined(_DEBUG) -#include -#endif - -#include -#include -#include -#include -#include -//squirrel stuff -#include -#include "sqobject.h" -#include "sqstate.h" - -#endif //_SQPCHEADER_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQPCHEADER_H_ +#define _SQPCHEADER_H_ + +#if defined(_MSC_VER) && defined(_DEBUG) +#include +#endif + +#include +#include +#include +#include +#include +//squirrel stuff +#include +#include "sqobject.h" +#include "sqstate.h" + +#endif //_SQPCHEADER_H_ diff --git a/src/squirrel/squirrel/sqstate.cpp b/src/squirrel/squirrel/sqstate.cpp index 475afe96c..85da8c8c3 100644 --- a/src/squirrel/squirrel/sqstate.cpp +++ b/src/squirrel/squirrel/sqstate.cpp @@ -1,562 +1,562 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqopcodes.h" -#include "sqvm.h" -#include "sqfuncproto.h" -#include "sqclosure.h" -#include "sqstring.h" -#include "sqtable.h" -#include "sqarray.h" -#include "squserdata.h" -#include "sqclass.h" - -SQObjectPtr _null_; -SQObjectPtr _true_(true); -SQObjectPtr _false_(false); -SQObjectPtr _one_((SQInteger)1); -SQObjectPtr _minusone_((SQInteger)-1); - -SQSharedState::SQSharedState() -{ - _compilererrorhandler = NULL; - _printfunc = NULL; - _debuginfo = false; - _notifyallexceptions = false; -} - -#define newsysstring(s) { \ - _systemstrings->push_back(SQString::Create(this,s)); \ - } - -#define newmetamethod(s) { \ - _metamethods->push_back(SQString::Create(this,s)); \ - _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ - } - -bool CompileTypemask(SQIntVec &res,const SQChar *typemask) -{ - SQInteger i = 0; - - SQInteger mask = 0; - while(typemask[i] != 0) { - - switch(typemask[i]){ - case 'o': mask |= _RT_NULL; break; - case 'i': mask |= _RT_INTEGER; break; - case 'f': mask |= _RT_FLOAT; break; - case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; - case 's': mask |= _RT_STRING; break; - case 't': mask |= _RT_TABLE; break; - case 'a': mask |= _RT_ARRAY; break; - case 'u': mask |= _RT_USERDATA; break; - case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; - case 'b': mask |= _RT_BOOL; break; - case 'g': mask |= _RT_GENERATOR; break; - case 'p': mask |= _RT_USERPOINTER; break; - case 'v': mask |= _RT_THREAD; break; - case 'x': mask |= _RT_INSTANCE; break; - case 'y': mask |= _RT_CLASS; break; - case 'r': mask |= _RT_WEAKREF; break; - case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue; - case ' ': i++; continue; //ignores spaces - default: - return false; - } - i++; - if(typemask[i] == '|') { - i++; - if(typemask[i] == 0) - return false; - continue; - } - res.push_back(mask); - mask = 0; - - } - return true; -} - -SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) -{ - SQInteger i=0; - SQTable *t=SQTable::Create(ss,0); - while(funcz[i].name!=0){ - SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); - nc->_nparamscheck = funcz[i].nparamscheck; - nc->_name = SQString::Create(ss,funcz[i].name); - if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) - return NULL; - t->NewSlot(SQString::Create(ss,funcz[i].name),nc); - i++; - } - return t; -} - -void SQSharedState::Init() -{ - _scratchpad=NULL; - _scratchpadsize=0; -#ifndef NO_GARBAGE_COLLECTOR - _gc_chain=NULL; -#endif - sq_new(_stringtable,StringTable); - sq_new(_metamethods,SQObjectPtrVec); - sq_new(_systemstrings,SQObjectPtrVec); - sq_new(_types,SQObjectPtrVec); - _metamethodsmap = SQTable::Create(this,MT_LAST-1); - //adding type strings to avoid memory trashing - //types names - newsysstring(_SC("null")); - newsysstring(_SC("table")); - newsysstring(_SC("array")); - newsysstring(_SC("closure")); - newsysstring(_SC("string")); - newsysstring(_SC("userdata")); - newsysstring(_SC("integer")); - newsysstring(_SC("float")); - newsysstring(_SC("userpointer")); - newsysstring(_SC("function")); - newsysstring(_SC("generator")); - newsysstring(_SC("thread")); - newsysstring(_SC("class")); - newsysstring(_SC("instance")); - newsysstring(_SC("bool")); - //meta methods - newmetamethod(MM_ADD); - newmetamethod(MM_SUB); - newmetamethod(MM_MUL); - newmetamethod(MM_DIV); - newmetamethod(MM_UNM); - newmetamethod(MM_MODULO); - newmetamethod(MM_SET); - newmetamethod(MM_GET); - newmetamethod(MM_TYPEOF); - newmetamethod(MM_NEXTI); - newmetamethod(MM_CMP); - newmetamethod(MM_CALL); - newmetamethod(MM_CLONED); - newmetamethod(MM_NEWSLOT); - newmetamethod(MM_DELSLOT); - newmetamethod(MM_TOSTRING); - newmetamethod(MM_NEWMEMBER); - newmetamethod(MM_INHERITED); - - _constructoridx = SQString::Create(this,_SC("constructor")); - _registry = SQTable::Create(this,0); - _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz); - _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz); - _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz); - _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz); - _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz); - _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz); - _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz); - _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz); - _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz); - _weakref_default_delegate=CreateDefaultDelegate(this,_weakref_default_delegate_funcz); - -} - -SQSharedState::~SQSharedState() -{ - _constructoridx = _null_; - _refs_table.Finalize(); - _table(_registry)->Finalize(); - _table(_metamethodsmap)->Finalize(); -// _refs_table = _null_; - _registry = _null_; - _metamethodsmap = _null_; - while(!_systemstrings->empty()){ - _systemstrings->back()=_null_; - _systemstrings->pop_back(); - } - _thread(_root_vm)->Finalize(); - _root_vm = _null_; - _table_default_delegate=_null_; - _array_default_delegate=_null_; - _string_default_delegate=_null_; - _number_default_delegate=_null_; - _closure_default_delegate=_null_; - _generator_default_delegate=_null_; - _thread_default_delegate=_null_; - _class_default_delegate=_null_; - _instance_default_delegate=_null_; - _weakref_default_delegate=_null_; - -#ifndef NO_GARBAGE_COLLECTOR - - - SQCollectable *t=_gc_chain; - SQCollectable *nx=NULL; - while(t){ - t->_uiRef++; - t->Finalize(); - nx=t->_next; - if(--t->_uiRef==0) - t->Release(); - t=nx; - } - assert(_gc_chain==NULL); //just to proove a theory - while(_gc_chain){ - _gc_chain->_uiRef++; - _gc_chain->Release(); - } -#endif - sq_delete(_types,SQObjectPtrVec); - sq_delete(_systemstrings,SQObjectPtrVec); - sq_delete(_metamethods,SQObjectPtrVec); - sq_delete(_stringtable,StringTable); - if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); -} - - -SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name) -{ - if(type(name) != OT_STRING) - return -1; - SQObjectPtr ret; - if(_table(_metamethodsmap)->Get(name,ret)) { - return _integer(ret); - } - return -1; -} - -#ifndef NO_GARBAGE_COLLECTOR - -void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) -{ - switch(type(o)){ - case OT_TABLE:_table(o)->Mark(chain);break; - case OT_ARRAY:_array(o)->Mark(chain);break; - case OT_USERDATA:_userdata(o)->Mark(chain);break; - case OT_CLOSURE:_closure(o)->Mark(chain);break; - case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break; - case OT_GENERATOR:_generator(o)->Mark(chain);break; - case OT_THREAD:_thread(o)->Mark(chain);break; - case OT_CLASS:_class(o)->Mark(chain);break; - case OT_INSTANCE:_instance(o)->Mark(chain);break; - default: break; //shutup compiler - } -} - - -SQInteger SQSharedState::CollectGarbage(SQVM *vm) -{ - SQInteger n=0; - SQCollectable *tchain=NULL; - SQVM *vms=_thread(_root_vm); - - vms->Mark(&tchain); - SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); - _refs_table.Mark(&tchain); - MarkObject(_registry,&tchain); - MarkObject(_metamethodsmap,&tchain); - MarkObject(_table_default_delegate,&tchain); - MarkObject(_array_default_delegate,&tchain); - MarkObject(_string_default_delegate,&tchain); - MarkObject(_number_default_delegate,&tchain); - MarkObject(_generator_default_delegate,&tchain); - MarkObject(_thread_default_delegate,&tchain); - MarkObject(_closure_default_delegate,&tchain); - MarkObject(_class_default_delegate,&tchain); - MarkObject(_instance_default_delegate,&tchain); - MarkObject(_weakref_default_delegate,&tchain); - - SQCollectable *t=_gc_chain; - SQCollectable *nx=NULL; - while(t){ - t->_uiRef++; - t->Finalize(); - nx=t->_next; - if(--t->_uiRef==0) - t->Release(); - t=nx; - n++; - } - - t=tchain; - while(t){ - t->UnMark(); - t=t->_next; - } - _gc_chain=tchain; - SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); - assert(z == x); - return n; -} -#endif - -#ifndef NO_GARBAGE_COLLECTOR -void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c) -{ - c->_prev=NULL; - c->_next=*chain; - if(*chain) (*chain)->_prev=c; - *chain=c; -} - -void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c) -{ - if(c->_prev) c->_prev->_next=c->_next; - else *chain=c->_next; - if(c->_next) - c->_next->_prev=c->_prev; - c->_next=NULL; - c->_prev=NULL; -} -#endif - -SQChar* SQSharedState::GetScratchPad(SQInteger size) -{ - SQInteger newsize; - if(size>0){ - if(_scratchpadsize>1); - _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); - _scratchpadsize=newsize; - - }else if(_scratchpadsize>=(size<<5)){ - newsize=_scratchpadsize>>1; - _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); - _scratchpadsize=newsize; - } - } - return _scratchpad; -} - -RefTable::RefTable() -{ - AllocNodes(4); -} - -void RefTable::Finalize() -{ - RefNode *nodes = (RefNode *)&_buckets[_numofslots]; - for(SQUnsignedInteger n = 0; n < _numofslots; n++) { - nodes->obj = _null_; - nodes++; - } -} - -RefTable::~RefTable() -{ - SQ_FREE(_buckets,_buffersize); -} -#ifndef NO_GARBAGE_COLLECTOR -void RefTable::Mark(SQCollectable **chain) -{ - RefNode *nodes = (RefNode *)&_buckets[_numofslots]; - for(SQUnsignedInteger n = 0; n < _numofslots; n++) { - if(type(nodes->obj) != OT_NULL) { - SQSharedState::MarkObject(nodes->obj,chain); - } - nodes++; - } -} -#endif -void RefTable::AddRef(SQObject &obj) -{ - SQHash mainpos; - RefNode *prev; - RefNode *ref = Get(obj,mainpos,&prev,true); - ref->refs++; -} - -SQBool RefTable::Release(SQObject &obj) -{ - SQHash mainpos; - RefNode *prev; - RefNode *ref = Get(obj,mainpos,&prev,false); - if(ref) { - if(--ref->refs == 0) { - ref->obj = _null_; - if(prev) { - prev->next = ref->next; - } - else { - _buckets[mainpos] = ref->next; - } - ref->next = _freelist; - _freelist = ref; - _slotused--; - //<>test for shrink? - return SQTrue; - } - } - return SQFalse; -} - -void RefTable::Resize(SQUnsignedInteger size) -{ - RefNode **oldbuffer = _buckets; - RefNode *oldnodes = (RefNode *)&_buckets[_numofslots]; - SQUnsignedInteger oldnumofslots = _numofslots; - SQUnsignedInteger oldbuffersize = _buffersize; - AllocNodes(size); - //rehash - for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { - if(type(oldnodes->obj) != OT_NULL) { - //add back; - assert(oldnodes->refs != 0); - RefNode *nn = Add(::HashObj(oldnodes->obj)&(_numofslots-1),oldnodes->obj); - nn->refs = oldnodes->refs; - oldnodes->obj = _null_; - } - oldnodes++; - } - SQ_FREE(oldbuffer,oldbuffersize); -} - -RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj) -{ - RefNode *t = _buckets[mainpos]; - RefNode *newnode = _freelist; - newnode->obj = obj; - _buckets[mainpos] = newnode; - _freelist = _freelist->next; - newnode->next = t; - assert(newnode->refs == 0); - _slotused++; - return newnode; -} - -RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add) -{ - RefNode *ref; - mainpos = ::HashObj(obj)&(_numofslots-1); - *prev = NULL; - for (ref = _buckets[mainpos]; ref; ) { - if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj)) - break; - *prev = ref; - ref = ref->next; - } - if(ref == NULL && add) { - if(_numofslots == _slotused) { - Resize(_numofslots*2); - } - ref = Add(mainpos,obj); - } - return ref; -} - -void RefTable::AllocNodes(SQUnsignedInteger size) -{ - RefNode **bucks; - RefNode *firstnode; - _buffersize = size * sizeof(RefNode *) + size * sizeof(RefNode); - bucks = (RefNode **)SQ_MALLOC(_buffersize); - firstnode = (RefNode *)&bucks[size]; - RefNode *temp = firstnode; - SQUnsignedInteger n; - for(n = 0; n < size - 1; n++) { - bucks[n] = NULL; - temp->refs = 0; - new (&temp->obj) SQObjectPtr; - temp->next = temp+1; - temp++; - } - bucks[n] = NULL; - temp->refs = 0; - new (&temp->obj) SQObjectPtr; - temp->next = NULL; - _freelist = firstnode; - _buckets = bucks; - _slotused = 0; - _numofslots = size; -} -////////////////////////////////////////////////////////////////////////// -//StringTable -/* -* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) -* http://www.lua.org/copyright.html#4 -* http://www.lua.org/source/4.0.1/src_lstring.c.html -*/ - -StringTable::StringTable() -{ - AllocNodes(4); - _slotused = 0; -} - -StringTable::~StringTable() -{ - SQ_FREE(_strings,sizeof(SQString*)*_numofslots); - _strings=NULL; -} - -void StringTable::AllocNodes(SQInteger size) -{ - _numofslots=size; - //_slotused=0; - _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); - memset(_strings,0,sizeof(SQString*)*_numofslots); -} - -SQString *StringTable::Add(const SQChar *news,SQInteger len) -{ - if(len<0) - len = (SQInteger)scstrlen(news); - SQHash h = ::_hashstr(news,len)&(_numofslots-1); - SQString *s; - for (s = _strings[h]; s; s = s->_next){ - if(s->_len == len && (!memcmp(news,s->_val,rsl(len)))) - return s; //found - } - - SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); - new (t) SQString; - memcpy(t->_val,news,rsl(len)); - t->_val[len] = _SC('\0'); - t->_len = len; - t->_hash = ::_hashstr(news,len); - t->_next = _strings[h]; - _strings[h] = t; - _slotused++; - if (_slotused > _numofslots) /* too crowded? */ - Resize(_numofslots*2); - return t; -} - -void StringTable::Resize(SQInteger size) -{ - SQInteger oldsize=_numofslots; - SQString **oldtable=_strings; - AllocNodes(size); - for (SQInteger i=0; i_next; - SQHash h = p->_hash&(_numofslots-1); - p->_next = _strings[h]; - _strings[h] = p; - p = next; - } - } - SQ_FREE(oldtable,oldsize*sizeof(SQString*)); -} - -void StringTable::Remove(SQString *bs) -{ - SQString *s; - SQString *prev=NULL; - SQHash h = bs->_hash&(_numofslots - 1); - - for (s = _strings[h]; s; ){ - if(s == bs){ - if(prev) - prev->_next = s->_next; - else - _strings[h] = s->_next; - _slotused--; - SQInteger slen = s->_len; - s->~SQString(); - SQ_FREE(s,sizeof(SQString) + rsl(slen)); - return; - } - prev = s; - s = s->_next; - } - assert(0);//if this fail something is wrong -} +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqopcodes.h" +#include "sqvm.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "squserdata.h" +#include "sqclass.h" + +SQObjectPtr _null_; +SQObjectPtr _true_(true); +SQObjectPtr _false_(false); +SQObjectPtr _one_((SQInteger)1); +SQObjectPtr _minusone_((SQInteger)-1); + +SQSharedState::SQSharedState() +{ + _compilererrorhandler = NULL; + _printfunc = NULL; + _debuginfo = false; + _notifyallexceptions = false; +} + +#define newsysstring(s) { \ + _systemstrings->push_back(SQString::Create(this,s)); \ + } + +#define newmetamethod(s) { \ + _metamethods->push_back(SQString::Create(this,s)); \ + _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ + } + +bool CompileTypemask(SQIntVec &res,const SQChar *typemask) +{ + SQInteger i = 0; + + SQInteger mask = 0; + while(typemask[i] != 0) { + + switch(typemask[i]){ + case 'o': mask |= _RT_NULL; break; + case 'i': mask |= _RT_INTEGER; break; + case 'f': mask |= _RT_FLOAT; break; + case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; + case 's': mask |= _RT_STRING; break; + case 't': mask |= _RT_TABLE; break; + case 'a': mask |= _RT_ARRAY; break; + case 'u': mask |= _RT_USERDATA; break; + case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; + case 'b': mask |= _RT_BOOL; break; + case 'g': mask |= _RT_GENERATOR; break; + case 'p': mask |= _RT_USERPOINTER; break; + case 'v': mask |= _RT_THREAD; break; + case 'x': mask |= _RT_INSTANCE; break; + case 'y': mask |= _RT_CLASS; break; + case 'r': mask |= _RT_WEAKREF; break; + case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue; + case ' ': i++; continue; //ignores spaces + default: + return false; + } + i++; + if(typemask[i] == '|') { + i++; + if(typemask[i] == 0) + return false; + continue; + } + res.push_back(mask); + mask = 0; + + } + return true; +} + +SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) +{ + SQInteger i=0; + SQTable *t=SQTable::Create(ss,0); + while(funcz[i].name!=0){ + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); + nc->_nparamscheck = funcz[i].nparamscheck; + nc->_name = SQString::Create(ss,funcz[i].name); + if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) + return NULL; + t->NewSlot(SQString::Create(ss,funcz[i].name),nc); + i++; + } + return t; +} + +void SQSharedState::Init() +{ + _scratchpad=NULL; + _scratchpadsize=0; +#ifndef NO_GARBAGE_COLLECTOR + _gc_chain=NULL; +#endif + sq_new(_stringtable,StringTable); + sq_new(_metamethods,SQObjectPtrVec); + sq_new(_systemstrings,SQObjectPtrVec); + sq_new(_types,SQObjectPtrVec); + _metamethodsmap = SQTable::Create(this,MT_LAST-1); + //adding type strings to avoid memory trashing + //types names + newsysstring(_SC("null")); + newsysstring(_SC("table")); + newsysstring(_SC("array")); + newsysstring(_SC("closure")); + newsysstring(_SC("string")); + newsysstring(_SC("userdata")); + newsysstring(_SC("integer")); + newsysstring(_SC("float")); + newsysstring(_SC("userpointer")); + newsysstring(_SC("function")); + newsysstring(_SC("generator")); + newsysstring(_SC("thread")); + newsysstring(_SC("class")); + newsysstring(_SC("instance")); + newsysstring(_SC("bool")); + //meta methods + newmetamethod(MM_ADD); + newmetamethod(MM_SUB); + newmetamethod(MM_MUL); + newmetamethod(MM_DIV); + newmetamethod(MM_UNM); + newmetamethod(MM_MODULO); + newmetamethod(MM_SET); + newmetamethod(MM_GET); + newmetamethod(MM_TYPEOF); + newmetamethod(MM_NEXTI); + newmetamethod(MM_CMP); + newmetamethod(MM_CALL); + newmetamethod(MM_CLONED); + newmetamethod(MM_NEWSLOT); + newmetamethod(MM_DELSLOT); + newmetamethod(MM_TOSTRING); + newmetamethod(MM_NEWMEMBER); + newmetamethod(MM_INHERITED); + + _constructoridx = SQString::Create(this,_SC("constructor")); + _registry = SQTable::Create(this,0); + _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz); + _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz); + _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz); + _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz); + _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz); + _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz); + _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz); + _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz); + _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz); + _weakref_default_delegate=CreateDefaultDelegate(this,_weakref_default_delegate_funcz); + +} + +SQSharedState::~SQSharedState() +{ + _constructoridx = _null_; + _refs_table.Finalize(); + _table(_registry)->Finalize(); + _table(_metamethodsmap)->Finalize(); +// _refs_table = _null_; + _registry = _null_; + _metamethodsmap = _null_; + while(!_systemstrings->empty()){ + _systemstrings->back()=_null_; + _systemstrings->pop_back(); + } + _thread(_root_vm)->Finalize(); + _root_vm = _null_; + _table_default_delegate=_null_; + _array_default_delegate=_null_; + _string_default_delegate=_null_; + _number_default_delegate=_null_; + _closure_default_delegate=_null_; + _generator_default_delegate=_null_; + _thread_default_delegate=_null_; + _class_default_delegate=_null_; + _instance_default_delegate=_null_; + _weakref_default_delegate=_null_; + +#ifndef NO_GARBAGE_COLLECTOR + + + SQCollectable *t=_gc_chain; + SQCollectable *nx=NULL; + while(t){ + t->_uiRef++; + t->Finalize(); + nx=t->_next; + if(--t->_uiRef==0) + t->Release(); + t=nx; + } + assert(_gc_chain==NULL); //just to proove a theory + while(_gc_chain){ + _gc_chain->_uiRef++; + _gc_chain->Release(); + } +#endif + sq_delete(_types,SQObjectPtrVec); + sq_delete(_systemstrings,SQObjectPtrVec); + sq_delete(_metamethods,SQObjectPtrVec); + sq_delete(_stringtable,StringTable); + if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); +} + + +SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name) +{ + if(type(name) != OT_STRING) + return -1; + SQObjectPtr ret; + if(_table(_metamethodsmap)->Get(name,ret)) { + return _integer(ret); + } + return -1; +} + +#ifndef NO_GARBAGE_COLLECTOR + +void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) +{ + switch(type(o)){ + case OT_TABLE:_table(o)->Mark(chain);break; + case OT_ARRAY:_array(o)->Mark(chain);break; + case OT_USERDATA:_userdata(o)->Mark(chain);break; + case OT_CLOSURE:_closure(o)->Mark(chain);break; + case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break; + case OT_GENERATOR:_generator(o)->Mark(chain);break; + case OT_THREAD:_thread(o)->Mark(chain);break; + case OT_CLASS:_class(o)->Mark(chain);break; + case OT_INSTANCE:_instance(o)->Mark(chain);break; + default: break; //shutup compiler + } +} + + +SQInteger SQSharedState::CollectGarbage(SQVM *vm) +{ + SQInteger n=0; + SQCollectable *tchain=NULL; + SQVM *vms=_thread(_root_vm); + + vms->Mark(&tchain); + SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); + _refs_table.Mark(&tchain); + MarkObject(_registry,&tchain); + MarkObject(_metamethodsmap,&tchain); + MarkObject(_table_default_delegate,&tchain); + MarkObject(_array_default_delegate,&tchain); + MarkObject(_string_default_delegate,&tchain); + MarkObject(_number_default_delegate,&tchain); + MarkObject(_generator_default_delegate,&tchain); + MarkObject(_thread_default_delegate,&tchain); + MarkObject(_closure_default_delegate,&tchain); + MarkObject(_class_default_delegate,&tchain); + MarkObject(_instance_default_delegate,&tchain); + MarkObject(_weakref_default_delegate,&tchain); + + SQCollectable *t=_gc_chain; + SQCollectable *nx=NULL; + while(t){ + t->_uiRef++; + t->Finalize(); + nx=t->_next; + if(--t->_uiRef==0) + t->Release(); + t=nx; + n++; + } + + t=tchain; + while(t){ + t->UnMark(); + t=t->_next; + } + _gc_chain=tchain; + SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); + assert(z == x); + return n; +} +#endif + +#ifndef NO_GARBAGE_COLLECTOR +void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c) +{ + c->_prev=NULL; + c->_next=*chain; + if(*chain) (*chain)->_prev=c; + *chain=c; +} + +void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c) +{ + if(c->_prev) c->_prev->_next=c->_next; + else *chain=c->_next; + if(c->_next) + c->_next->_prev=c->_prev; + c->_next=NULL; + c->_prev=NULL; +} +#endif + +SQChar* SQSharedState::GetScratchPad(SQInteger size) +{ + SQInteger newsize; + if(size>0){ + if(_scratchpadsize>1); + _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize=newsize; + + }else if(_scratchpadsize>=(size<<5)){ + newsize=_scratchpadsize>>1; + _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize=newsize; + } + } + return _scratchpad; +} + +RefTable::RefTable() +{ + AllocNodes(4); +} + +void RefTable::Finalize() +{ + RefNode *nodes = (RefNode *)&_buckets[_numofslots]; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + nodes->obj = _null_; + nodes++; + } +} + +RefTable::~RefTable() +{ + SQ_FREE(_buckets,_buffersize); +} +#ifndef NO_GARBAGE_COLLECTOR +void RefTable::Mark(SQCollectable **chain) +{ + RefNode *nodes = (RefNode *)&_buckets[_numofslots]; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + if(type(nodes->obj) != OT_NULL) { + SQSharedState::MarkObject(nodes->obj,chain); + } + nodes++; + } +} +#endif +void RefTable::AddRef(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + ref->refs++; +} + +SQBool RefTable::Release(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,false); + if(ref) { + if(--ref->refs == 0) { + ref->obj = _null_; + if(prev) { + prev->next = ref->next; + } + else { + _buckets[mainpos] = ref->next; + } + ref->next = _freelist; + _freelist = ref; + _slotused--; + //<>test for shrink? + return SQTrue; + } + } + return SQFalse; +} + +void RefTable::Resize(SQUnsignedInteger size) +{ + RefNode **oldbuffer = _buckets; + RefNode *oldnodes = (RefNode *)&_buckets[_numofslots]; + SQUnsignedInteger oldnumofslots = _numofslots; + SQUnsignedInteger oldbuffersize = _buffersize; + AllocNodes(size); + //rehash + for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { + if(type(oldnodes->obj) != OT_NULL) { + //add back; + assert(oldnodes->refs != 0); + RefNode *nn = Add(::HashObj(oldnodes->obj)&(_numofslots-1),oldnodes->obj); + nn->refs = oldnodes->refs; + oldnodes->obj = _null_; + } + oldnodes++; + } + SQ_FREE(oldbuffer,oldbuffersize); +} + +RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj) +{ + RefNode *t = _buckets[mainpos]; + RefNode *newnode = _freelist; + newnode->obj = obj; + _buckets[mainpos] = newnode; + _freelist = _freelist->next; + newnode->next = t; + assert(newnode->refs == 0); + _slotused++; + return newnode; +} + +RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add) +{ + RefNode *ref; + mainpos = ::HashObj(obj)&(_numofslots-1); + *prev = NULL; + for (ref = _buckets[mainpos]; ref; ) { + if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj)) + break; + *prev = ref; + ref = ref->next; + } + if(ref == NULL && add) { + if(_numofslots == _slotused) { + Resize(_numofslots*2); + } + ref = Add(mainpos,obj); + } + return ref; +} + +void RefTable::AllocNodes(SQUnsignedInteger size) +{ + RefNode **bucks; + RefNode *firstnode; + _buffersize = size * sizeof(RefNode *) + size * sizeof(RefNode); + bucks = (RefNode **)SQ_MALLOC(_buffersize); + firstnode = (RefNode *)&bucks[size]; + RefNode *temp = firstnode; + SQUnsignedInteger n; + for(n = 0; n < size - 1; n++) { + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = temp+1; + temp++; + } + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = NULL; + _freelist = firstnode; + _buckets = bucks; + _slotused = 0; + _numofslots = size; +} +////////////////////////////////////////////////////////////////////////// +//StringTable +/* +* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) +* http://www.lua.org/copyright.html#4 +* http://www.lua.org/source/4.0.1/src_lstring.c.html +*/ + +StringTable::StringTable() +{ + AllocNodes(4); + _slotused = 0; +} + +StringTable::~StringTable() +{ + SQ_FREE(_strings,sizeof(SQString*)*_numofslots); + _strings=NULL; +} + +void StringTable::AllocNodes(SQInteger size) +{ + _numofslots=size; + //_slotused=0; + _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); + memset(_strings,0,sizeof(SQString*)*_numofslots); +} + +SQString *StringTable::Add(const SQChar *news,SQInteger len) +{ + if(len<0) + len = (SQInteger)scstrlen(news); + SQHash h = ::_hashstr(news,len)&(_numofslots-1); + SQString *s; + for (s = _strings[h]; s; s = s->_next){ + if(s->_len == len && (!memcmp(news,s->_val,rsl(len)))) + return s; //found + } + + SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); + new (t) SQString; + memcpy(t->_val,news,rsl(len)); + t->_val[len] = _SC('\0'); + t->_len = len; + t->_hash = ::_hashstr(news,len); + t->_next = _strings[h]; + _strings[h] = t; + _slotused++; + if (_slotused > _numofslots) /* too crowded? */ + Resize(_numofslots*2); + return t; +} + +void StringTable::Resize(SQInteger size) +{ + SQInteger oldsize=_numofslots; + SQString **oldtable=_strings; + AllocNodes(size); + for (SQInteger i=0; i_next; + SQHash h = p->_hash&(_numofslots-1); + p->_next = _strings[h]; + _strings[h] = p; + p = next; + } + } + SQ_FREE(oldtable,oldsize*sizeof(SQString*)); +} + +void StringTable::Remove(SQString *bs) +{ + SQString *s; + SQString *prev=NULL; + SQHash h = bs->_hash&(_numofslots - 1); + + for (s = _strings[h]; s; ){ + if(s == bs){ + if(prev) + prev->_next = s->_next; + else + _strings[h] = s->_next; + _slotused--; + SQInteger slen = s->_len; + s->~SQString(); + SQ_FREE(s,sizeof(SQString) + rsl(slen)); + return; + } + prev = s; + s = s->_next; + } + assert(0);//if this fail something is wrong +} diff --git a/src/squirrel/squirrel/sqstate.h b/src/squirrel/squirrel/sqstate.h index 64892c4ad..fc2981617 100644 --- a/src/squirrel/squirrel/sqstate.h +++ b/src/squirrel/squirrel/sqstate.h @@ -1,142 +1,142 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTATE_H_ -#define _SQSTATE_H_ - -#include "squtils.h" -#include "sqobject.h" -struct SQString; -struct SQTable; -//max number of character for a printed number -#define NUMBER_MAX_CHAR 50 - -struct StringTable -{ - StringTable(); - ~StringTable(); - SQString *Add(const SQChar *,SQInteger len); - void Remove(SQString *); -private: - void Resize(SQInteger size); - void AllocNodes(SQInteger size); - SQString **_strings; - SQUnsignedInteger _numofslots; - SQUnsignedInteger _slotused; -}; - -struct RefTable { - struct RefNode { - SQObjectPtr obj; - SQUnsignedInteger refs; - struct RefNode *next; - }; - RefTable(); - ~RefTable(); - void AddRef(SQObject &obj); - SQBool Release(SQObject &obj); -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); -#endif - void Finalize(); -private: - RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add); - RefNode *Add(SQHash mainpos,SQObject &obj); - void Resize(SQUnsignedInteger size); - void AllocNodes(SQUnsignedInteger size); - SQUnsignedInteger _numofslots; - SQUnsignedInteger _slotused; - SQUnsignedInteger _buffersize; - RefNode *_freelist; - RefNode **_buckets; -}; - -#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len) -#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr) - -struct SQObjectPtr; - -struct SQSharedState -{ - SQSharedState(); - ~SQSharedState(); - void Init(); -public: - SQChar* GetScratchPad(SQInteger size); - SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); -#ifndef NO_GARBAGE_COLLECTOR - SQInteger CollectGarbage(SQVM *vm); - static void MarkObject(SQObjectPtr &o,SQCollectable **chain); -#endif - SQObjectPtrVec *_metamethods; - SQObjectPtr _metamethodsmap; - SQObjectPtrVec *_systemstrings; - SQObjectPtrVec *_types; - StringTable *_stringtable; - RefTable _refs_table; - SQObjectPtr _registry; - SQObjectPtr _constructoridx; -#ifndef NO_GARBAGE_COLLECTOR - SQCollectable *_gc_chain; -#endif - SQObjectPtr _root_vm; - SQObjectPtr _table_default_delegate; - static SQRegFunction _table_default_delegate_funcz[]; - SQObjectPtr _array_default_delegate; - static SQRegFunction _array_default_delegate_funcz[]; - SQObjectPtr _string_default_delegate; - static SQRegFunction _string_default_delegate_funcz[]; - SQObjectPtr _number_default_delegate; - static SQRegFunction _number_default_delegate_funcz[]; - SQObjectPtr _generator_default_delegate; - static SQRegFunction _generator_default_delegate_funcz[]; - SQObjectPtr _closure_default_delegate; - static SQRegFunction _closure_default_delegate_funcz[]; - SQObjectPtr _thread_default_delegate; - static SQRegFunction _thread_default_delegate_funcz[]; - SQObjectPtr _class_default_delegate; - static SQRegFunction _class_default_delegate_funcz[]; - SQObjectPtr _instance_default_delegate; - static SQRegFunction _instance_default_delegate_funcz[]; - SQObjectPtr _weakref_default_delegate; - static SQRegFunction _weakref_default_delegate_funcz[]; - - SQCOMPILERERROR _compilererrorhandler; - SQPRINTFUNCTION _printfunc; - bool _debuginfo; - bool _notifyallexceptions; -private: - SQChar *_scratchpad; - SQInteger _scratchpadsize; -}; - -#define _sp(s) (_sharedstate->GetScratchPad(s)) -#define _spval (_sharedstate->GetScratchPad(-1)) - -#define _table_ddel _table(_sharedstate->_table_default_delegate) -#define _array_ddel _table(_sharedstate->_array_default_delegate) -#define _string_ddel _table(_sharedstate->_string_default_delegate) -#define _number_ddel _table(_sharedstate->_number_default_delegate) -#define _generator_ddel _table(_sharedstate->_generator_default_delegate) -#define _closure_ddel _table(_sharedstate->_closure_default_delegate) -#define _thread_ddel _table(_sharedstate->_thread_default_delegate) -#define _class_ddel _table(_sharedstate->_class_default_delegate) -#define _instance_ddel _table(_sharedstate->_instance_default_delegate) -#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) - -#ifdef SQUNICODE //rsl REAL STRING LEN -#define rsl(l) ((l)<<1) -#else -#define rsl(l) (l) -#endif - -extern SQObjectPtr _null_; -extern SQObjectPtr _true_; -extern SQObjectPtr _false_; -extern SQObjectPtr _one_; -extern SQObjectPtr _minusone_; - -bool CompileTypemask(SQIntVec &res,const SQChar *typemask); - -void *sq_vm_malloc(SQUnsignedInteger size); -void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); -void sq_vm_free(void *p,SQUnsignedInteger size); -#endif //_SQSTATE_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTATE_H_ +#define _SQSTATE_H_ + +#include "squtils.h" +#include "sqobject.h" +struct SQString; +struct SQTable; +//max number of character for a printed number +#define NUMBER_MAX_CHAR 50 + +struct StringTable +{ + StringTable(); + ~StringTable(); + SQString *Add(const SQChar *,SQInteger len); + void Remove(SQString *); +private: + void Resize(SQInteger size); + void AllocNodes(SQInteger size); + SQString **_strings; + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; +}; + +struct RefTable { + struct RefNode { + SQObjectPtr obj; + SQUnsignedInteger refs; + struct RefNode *next; + }; + RefTable(); + ~RefTable(); + void AddRef(SQObject &obj); + SQBool Release(SQObject &obj); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(); +private: + RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add); + RefNode *Add(SQHash mainpos,SQObject &obj); + void Resize(SQUnsignedInteger size); + void AllocNodes(SQUnsignedInteger size); + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; + SQUnsignedInteger _buffersize; + RefNode *_freelist; + RefNode **_buckets; +}; + +#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len) +#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr) + +struct SQObjectPtr; + +struct SQSharedState +{ + SQSharedState(); + ~SQSharedState(); + void Init(); +public: + SQChar* GetScratchPad(SQInteger size); + SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); +#ifndef NO_GARBAGE_COLLECTOR + SQInteger CollectGarbage(SQVM *vm); + static void MarkObject(SQObjectPtr &o,SQCollectable **chain); +#endif + SQObjectPtrVec *_metamethods; + SQObjectPtr _metamethodsmap; + SQObjectPtrVec *_systemstrings; + SQObjectPtrVec *_types; + StringTable *_stringtable; + RefTable _refs_table; + SQObjectPtr _registry; + SQObjectPtr _constructoridx; +#ifndef NO_GARBAGE_COLLECTOR + SQCollectable *_gc_chain; +#endif + SQObjectPtr _root_vm; + SQObjectPtr _table_default_delegate; + static SQRegFunction _table_default_delegate_funcz[]; + SQObjectPtr _array_default_delegate; + static SQRegFunction _array_default_delegate_funcz[]; + SQObjectPtr _string_default_delegate; + static SQRegFunction _string_default_delegate_funcz[]; + SQObjectPtr _number_default_delegate; + static SQRegFunction _number_default_delegate_funcz[]; + SQObjectPtr _generator_default_delegate; + static SQRegFunction _generator_default_delegate_funcz[]; + SQObjectPtr _closure_default_delegate; + static SQRegFunction _closure_default_delegate_funcz[]; + SQObjectPtr _thread_default_delegate; + static SQRegFunction _thread_default_delegate_funcz[]; + SQObjectPtr _class_default_delegate; + static SQRegFunction _class_default_delegate_funcz[]; + SQObjectPtr _instance_default_delegate; + static SQRegFunction _instance_default_delegate_funcz[]; + SQObjectPtr _weakref_default_delegate; + static SQRegFunction _weakref_default_delegate_funcz[]; + + SQCOMPILERERROR _compilererrorhandler; + SQPRINTFUNCTION _printfunc; + bool _debuginfo; + bool _notifyallexceptions; +private: + SQChar *_scratchpad; + SQInteger _scratchpadsize; +}; + +#define _sp(s) (_sharedstate->GetScratchPad(s)) +#define _spval (_sharedstate->GetScratchPad(-1)) + +#define _table_ddel _table(_sharedstate->_table_default_delegate) +#define _array_ddel _table(_sharedstate->_array_default_delegate) +#define _string_ddel _table(_sharedstate->_string_default_delegate) +#define _number_ddel _table(_sharedstate->_number_default_delegate) +#define _generator_ddel _table(_sharedstate->_generator_default_delegate) +#define _closure_ddel _table(_sharedstate->_closure_default_delegate) +#define _thread_ddel _table(_sharedstate->_thread_default_delegate) +#define _class_ddel _table(_sharedstate->_class_default_delegate) +#define _instance_ddel _table(_sharedstate->_instance_default_delegate) +#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) + +#ifdef SQUNICODE //rsl REAL STRING LEN +#define rsl(l) ((l)<<1) +#else +#define rsl(l) (l) +#endif + +extern SQObjectPtr _null_; +extern SQObjectPtr _true_; +extern SQObjectPtr _false_; +extern SQObjectPtr _one_; +extern SQObjectPtr _minusone_; + +bool CompileTypemask(SQIntVec &res,const SQChar *typemask); + +void *sq_vm_malloc(SQUnsignedInteger size); +void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); +void sq_vm_free(void *p,SQUnsignedInteger size); +#endif //_SQSTATE_H_ diff --git a/src/squirrel/squirrel/sqstring.h b/src/squirrel/squirrel/sqstring.h index 235d19059..14f09e1b0 100644 --- a/src/squirrel/squirrel/sqstring.h +++ b/src/squirrel/squirrel/sqstring.h @@ -1,31 +1,31 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQSTRING_H_ -#define _SQSTRING_H_ - -inline SQHash _hashstr (const SQChar *s, size_t l) -{ - SQHash h = (SQHash)l; /* seed */ - size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ - for (; l>=step; l-=step) - h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++)); - return h; -} - -struct SQString : public SQRefCounted -{ - SQString(){} - ~SQString(){} -public: - static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 ); - SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - void Release(); - SQSharedState *_sharedstate; - SQString *_next; //chain for the string table - SQInteger _len; - SQHash _hash; - SQChar _val[1]; -}; - - - -#endif //_SQSTRING_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTRING_H_ +#define _SQSTRING_H_ + +inline SQHash _hashstr (const SQChar *s, size_t l) +{ + SQHash h = (SQHash)l; /* seed */ + size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ + for (; l>=step; l-=step) + h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++)); + return h; +} + +struct SQString : public SQRefCounted +{ + SQString(){} + ~SQString(){} +public: + static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 ); + SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + void Release(); + SQSharedState *_sharedstate; + SQString *_next; //chain for the string table + SQInteger _len; + SQHash _hash; + SQChar _val[1]; +}; + + + +#endif //_SQSTRING_H_ diff --git a/src/squirrel/squirrel/sqtable.cpp b/src/squirrel/squirrel/sqtable.cpp index 4d9608070..71c2c0ed6 100644 --- a/src/squirrel/squirrel/sqtable.cpp +++ b/src/squirrel/squirrel/sqtable.cpp @@ -1,184 +1,184 @@ -/* -see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include "sqvm.h" -#include "sqtable.h" -#include "sqfuncproto.h" -#include "sqclosure.h" - -SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize) -{ - SQInteger pow2size=MINPOWER2; - while(nInitialSize>pow2size)pow2size=pow2size<<1; - AllocNodes(pow2size); - _usednodes = 0; - _delegate = NULL; - INIT_CHAIN(); - ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); -} - -void SQTable::Remove(const SQObjectPtr &key) -{ - - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - n->val = n->key = _null_; - _usednodes--; - Rehash(false); - } -} - -void SQTable::AllocNodes(SQInteger nSize) -{ - _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); - for(SQInteger i=0;i= oldsize-oldsize/4) /* using more than 3/4? */ - AllocNodes(oldsize*2); - else if (nelems <= oldsize/4 && /* less than 1/4? */ - oldsize > MINPOWER2) - AllocNodes(oldsize/2); - else if(force) - AllocNodes(oldsize); - else - return; - _usednodes = 0; - for (SQInteger i=0; ikey) != OT_NULL) - NewSlot(old->key,old->val); - } - for(SQInteger k=0;kNewSlot(key,val); - } - nt->SetDelegate(_delegate); - return nt; -} - -bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val) -{ - if(type(key) == OT_NULL) - return false; - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - val = _realval(n->val); - return true; - } - return false; -} -bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) -{ - assert(type(key) != OT_NULL); - SQHash h = HashObj(key) & (_numofnodes - 1); - _HashNode *n = _Get(key, h); - if (n) { - n->val = val; - return false; - } - _HashNode *mp = &_nodes[h]; - n = mp; - - - //key not found I'll insert it - //main pos is not free - - if(type(mp->key) != OT_NULL) { - n = _firstfree; /* get a free place */ - SQHash mph = HashObj(mp->key) & (_numofnodes - 1); - _HashNode *othern; /* main position of colliding node */ - - if (mp > n && (othern = &_nodes[mph]) != mp){ - /* yes; move colliding node into free position */ - while (othern->next != mp){ - assert(othern->next != NULL); - othern = othern->next; /* find previous */ - } - othern->next = n; /* redo the chain with `n' in place of `mp' */ - n->key = mp->key; - n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ - n->next = mp->next; - mp->key = _null_; - mp->val = _null_; - mp->next = NULL; /* now `mp' is free */ - } - else{ - /* new node will go into free position */ - n->next = mp->next; /* chain new position */ - mp->next = n; - mp = n; - } - } - mp->key = key; - - for (;;) { /* correct `firstfree' */ - if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { - mp->val = val; - _usednodes++; - return true; /* OK; table still has a free place */ - } - else if (_firstfree == _nodes) break; /* cannot decrement from here */ - else (_firstfree)--; - } - Rehash(true); - return NewSlot(key, val); -} - -SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) -{ - SQInteger idx = (SQInteger)TranslateIndex(refpos); - while (idx < _numofnodes) { - if(type(_nodes[idx].key) != OT_NULL) { - //first found - _HashNode &n = _nodes[idx]; - outkey = n.key; - outval = getweakrefs?(SQObject)n.val:_realval(n.val); - //return idx for the next iteration - return ++idx; - } - ++idx; - } - //nothing to iterate anymore - return -1; -} - - -bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) -{ - _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); - if (n) { - n->val = val; - return true; - } - return false; -} - -void SQTable::Finalize() -{ - for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; } - SetDelegate(NULL); -} +/* +see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqtable.h" +#include "sqfuncproto.h" +#include "sqclosure.h" + +SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize) +{ + SQInteger pow2size=MINPOWER2; + while(nInitialSize>pow2size)pow2size=pow2size<<1; + AllocNodes(pow2size); + _usednodes = 0; + _delegate = NULL; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); +} + +void SQTable::Remove(const SQObjectPtr &key) +{ + + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val = n->key = _null_; + _usednodes--; + Rehash(false); + } +} + +void SQTable::AllocNodes(SQInteger nSize) +{ + _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); + for(SQInteger i=0;i= oldsize-oldsize/4) /* using more than 3/4? */ + AllocNodes(oldsize*2); + else if (nelems <= oldsize/4 && /* less than 1/4? */ + oldsize > MINPOWER2) + AllocNodes(oldsize/2); + else if(force) + AllocNodes(oldsize); + else + return; + _usednodes = 0; + for (SQInteger i=0; ikey) != OT_NULL) + NewSlot(old->key,old->val); + } + for(SQInteger k=0;kNewSlot(key,val); + } + nt->SetDelegate(_delegate); + return nt; +} + +bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val) +{ + if(type(key) == OT_NULL) + return false; + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + val = _realval(n->val); + return true; + } + return false; +} +bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) +{ + assert(type(key) != OT_NULL); + SQHash h = HashObj(key) & (_numofnodes - 1); + _HashNode *n = _Get(key, h); + if (n) { + n->val = val; + return false; + } + _HashNode *mp = &_nodes[h]; + n = mp; + + + //key not found I'll insert it + //main pos is not free + + if(type(mp->key) != OT_NULL) { + n = _firstfree; /* get a free place */ + SQHash mph = HashObj(mp->key) & (_numofnodes - 1); + _HashNode *othern; /* main position of colliding node */ + + if (mp > n && (othern = &_nodes[mph]) != mp){ + /* yes; move colliding node into free position */ + while (othern->next != mp){ + assert(othern->next != NULL); + othern = othern->next; /* find previous */ + } + othern->next = n; /* redo the chain with `n' in place of `mp' */ + n->key = mp->key; + n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ + n->next = mp->next; + mp->key = _null_; + mp->val = _null_; + mp->next = NULL; /* now `mp' is free */ + } + else{ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + mp->key = key; + + for (;;) { /* correct `firstfree' */ + if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { + mp->val = val; + _usednodes++; + return true; /* OK; table still has a free place */ + } + else if (_firstfree == _nodes) break; /* cannot decrement from here */ + else (_firstfree)--; + } + Rehash(true); + return NewSlot(key, val); +} + +SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while (idx < _numofnodes) { + if(type(_nodes[idx].key) != OT_NULL) { + //first found + _HashNode &n = _nodes[idx]; + outkey = n.key; + outval = getweakrefs?(SQObject)n.val:_realval(n.val); + //return idx for the next iteration + return ++idx; + } + ++idx; + } + //nothing to iterate anymore + return -1; +} + + +bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) +{ + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val = val; + return true; + } + return false; +} + +void SQTable::Finalize() +{ + for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; } + SetDelegate(NULL); +} diff --git a/src/squirrel/squirrel/sqtable.h b/src/squirrel/squirrel/sqtable.h index be6684348..742074f43 100644 --- a/src/squirrel/squirrel/sqtable.h +++ b/src/squirrel/squirrel/sqtable.h @@ -1,89 +1,89 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQTABLE_H_ -#define _SQTABLE_H_ -/* -* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) -* http://www.lua.org/copyright.html#4 -* http://www.lua.org/source/4.0.1/src_ltable.c.html -*/ - -#include "sqstring.h" - - -#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3)) - -inline SQHash HashObj(const SQObjectPtr &key) -{ - switch(type(key)) { - case OT_STRING: return _string(key)->_hash; - case OT_FLOAT: return (SQHash)((SQInteger)_float(key)); - case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key)); - default: return hashptr(key._unVal.pRefCounted); - } -} - -struct SQTable : public SQDelegable -{ -private: - struct _HashNode - { - _HashNode() { next = NULL; } - SQObjectPtr val; - SQObjectPtr key; - _HashNode *next; - }; - _HashNode *_firstfree; - _HashNode *_nodes; - SQInteger _numofnodes; - SQInteger _usednodes; - -/////////////////////////// - void AllocNodes(SQInteger nSize); - void Rehash(bool force); - SQTable(SQSharedState *ss, SQInteger nInitialSize); -public: - static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize) - { - SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); - new (newtable) SQTable(ss, nInitialSize); - newtable->_delegate = NULL; - return newtable; - } - void Finalize(); - SQTable *Clone(); - ~SQTable() - { - SetDelegate(NULL); - REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); - for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); - SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); - } -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); -#endif - inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) - { - _HashNode *n = &_nodes[hash]; - do{ - if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){ - return n; - } - }while((n = n->next)); - return NULL; - } - bool Get(const SQObjectPtr &key,SQObjectPtr &val); - void Remove(const SQObjectPtr &key); - bool Set(const SQObjectPtr &key, const SQObjectPtr &val); - //returns true if a new slot has been created false if it was already present - bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val); - SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); - - SQInteger CountUsed(){ return _usednodes;} - void Release() - { - sq_delete(this, SQTable); - } - -}; - -#endif //_SQTABLE_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQTABLE_H_ +#define _SQTABLE_H_ +/* +* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) +* http://www.lua.org/copyright.html#4 +* http://www.lua.org/source/4.0.1/src_ltable.c.html +*/ + +#include "sqstring.h" + + +#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3)) + +inline SQHash HashObj(const SQObjectPtr &key) +{ + switch(type(key)) { + case OT_STRING: return _string(key)->_hash; + case OT_FLOAT: return (SQHash)((SQInteger)_float(key)); + case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key)); + default: return hashptr(key._unVal.pRefCounted); + } +} + +struct SQTable : public SQDelegable +{ +private: + struct _HashNode + { + _HashNode() { next = NULL; } + SQObjectPtr val; + SQObjectPtr key; + _HashNode *next; + }; + _HashNode *_firstfree; + _HashNode *_nodes; + SQInteger _numofnodes; + SQInteger _usednodes; + +/////////////////////////// + void AllocNodes(SQInteger nSize); + void Rehash(bool force); + SQTable(SQSharedState *ss, SQInteger nInitialSize); +public: + static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize) + { + SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); + new (newtable) SQTable(ss, nInitialSize); + newtable->_delegate = NULL; + return newtable; + } + void Finalize(); + SQTable *Clone(); + ~SQTable() + { + SetDelegate(NULL); + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); + SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) + { + _HashNode *n = &_nodes[hash]; + do{ + if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){ + return n; + } + }while((n = n->next)); + return NULL; + } + bool Get(const SQObjectPtr &key,SQObjectPtr &val); + void Remove(const SQObjectPtr &key); + bool Set(const SQObjectPtr &key, const SQObjectPtr &val); + //returns true if a new slot has been created false if it was already present + bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val); + SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + + SQInteger CountUsed(){ return _usednodes;} + void Release() + { + sq_delete(this, SQTable); + } + +}; + +#endif //_SQTABLE_H_ diff --git a/src/squirrel/squirrel/squserdata.h b/src/squirrel/squirrel/squserdata.h index 8fe0411ea..8b6b43148 100644 --- a/src/squirrel/squirrel/squserdata.h +++ b/src/squirrel/squirrel/squserdata.h @@ -1,38 +1,38 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQUSERDATA_H_ -#define _SQUSERDATA_H_ - -struct SQUserData : SQDelegable -{ - SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); } - ~SQUserData() - { - REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); - SetDelegate(NULL); - } - static SQUserData* Create(SQSharedState *ss, SQInteger size) - { - SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1)); - new (ud) SQUserData(ss); - ud->_size = size; - ud->_typetag = 0; - return ud; - } -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); - void Finalize(){SetDelegate(NULL);} -#endif - void Release() { - if (_hook) _hook(_val,_size); - SQInteger tsize = _size - 1; - this->~SQUserData(); - SQ_FREE(this, sizeof(SQUserData) + tsize); - } - - SQInteger _size; - SQRELEASEHOOK _hook; - SQUserPointer _typetag; - SQChar _val[1]; -}; - -#endif //_SQUSERDATA_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQUSERDATA_H_ +#define _SQUSERDATA_H_ + +struct SQUserData : SQDelegable +{ + SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); } + ~SQUserData() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); + SetDelegate(NULL); + } + static SQUserData* Create(SQSharedState *ss, SQInteger size) + { + SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1)); + new (ud) SQUserData(ss); + ud->_size = size; + ud->_typetag = 0; + return ud; + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){SetDelegate(NULL);} +#endif + void Release() { + if (_hook) _hook(_val,_size); + SQInteger tsize = _size - 1; + this->~SQUserData(); + SQ_FREE(this, sizeof(SQUserData) + tsize); + } + + SQInteger _size; + SQRELEASEHOOK _hook; + SQUserPointer _typetag; + SQChar _val[1]; +}; + +#endif //_SQUSERDATA_H_ diff --git a/src/squirrel/squirrel/squtils.h b/src/squirrel/squirrel/squtils.h index 86456baf4..3f866210c 100644 --- a/src/squirrel/squirrel/squtils.h +++ b/src/squirrel/squirrel/squtils.h @@ -1,104 +1,104 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQUTILS_H_ -#define _SQUTILS_H_ - -#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;} -#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));} -#define SQ_MALLOC(__size) sq_vm_malloc(__size); -#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size); -#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size); - -//sqvector mini vector class, supports objects by value -template class sqvector -{ -public: - sqvector() - { - _vals = NULL; - _size = 0; - _allocated = 0; - } - sqvector(const sqvector& v) - { - copy(v); - } - void copy(const sqvector& v) - { - resize(v._size); - for(SQUnsignedInteger i = 0; i < v._size; i++) { - new ((void *)&_vals[i]) T(v._vals[i]); - } - _size = v._size; - } - ~sqvector() - { - if(_allocated) { - for(SQUnsignedInteger i = 0; i < _size; i++) - _vals[i].~T(); - SQ_FREE(_vals, (_allocated * sizeof(T))); - } - } - void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } - void resize(SQUnsignedInteger newsize, const T& fill = T()) - { - if(newsize > _allocated) - _realloc(newsize); - if(newsize > _size) { - while(_size < newsize) { - new ((void *)&_vals[_size]) T(fill); - _size++; - } - } - else{ - for(SQUnsignedInteger i = newsize; i < _size; i++) { - _vals[i].~T(); - } - _size = newsize; - } - } - void shrinktofit() { if(_size > 4) { _realloc(_size); } } - T& top() const { return _vals[_size - 1]; } - inline SQUnsignedInteger size() const { return _size; } - bool empty() const { return (_size <= 0); } - inline T &push_back(const T& val = T()) - { - if(_allocated <= _size) - _realloc(_size * 2); - return *(new ((void *)&_vals[_size++]) T(val)); - } - inline void pop_back() - { - _size--; _vals[_size].~T(); - } - void insert(SQUnsignedInteger idx, const T& val) - { - resize(_size + 1); - for(SQUnsignedInteger i = _size - 1; i > idx; i--) { - _vals[i] = _vals[i - 1]; - } - _vals[idx] = val; - } - void remove(SQUnsignedInteger idx) - { - _vals[idx].~T(); - if(idx < (_size - 1)) { - memcpy(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1)); - } - _size--; - } - SQUnsignedInteger capacity() { return _allocated; } - inline T &back() const { return _vals[_size - 1]; } - inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; } - T* _vals; -private: - void _realloc(SQUnsignedInteger newsize) - { - newsize = (newsize > 0)?newsize:4; - _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); - _allocated = newsize; - } - SQUnsignedInteger _size; - SQUnsignedInteger _allocated; -}; - -#endif //_SQUTILS_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQUTILS_H_ +#define _SQUTILS_H_ + +#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;} +#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));} +#define SQ_MALLOC(__size) sq_vm_malloc(__size); +#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size); +#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size); + +//sqvector mini vector class, supports objects by value +template class sqvector +{ +public: + sqvector() + { + _vals = NULL; + _size = 0; + _allocated = 0; + } + sqvector(const sqvector& v) + { + copy(v); + } + void copy(const sqvector& v) + { + resize(v._size); + for(SQUnsignedInteger i = 0; i < v._size; i++) { + new ((void *)&_vals[i]) T(v._vals[i]); + } + _size = v._size; + } + ~sqvector() + { + if(_allocated) { + for(SQUnsignedInteger i = 0; i < _size; i++) + _vals[i].~T(); + SQ_FREE(_vals, (_allocated * sizeof(T))); + } + } + void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } + void resize(SQUnsignedInteger newsize, const T& fill = T()) + { + if(newsize > _allocated) + _realloc(newsize); + if(newsize > _size) { + while(_size < newsize) { + new ((void *)&_vals[_size]) T(fill); + _size++; + } + } + else{ + for(SQUnsignedInteger i = newsize; i < _size; i++) { + _vals[i].~T(); + } + _size = newsize; + } + } + void shrinktofit() { if(_size > 4) { _realloc(_size); } } + T& top() const { return _vals[_size - 1]; } + inline SQUnsignedInteger size() const { return _size; } + bool empty() const { return (_size <= 0); } + inline T &push_back(const T& val = T()) + { + if(_allocated <= _size) + _realloc(_size * 2); + return *(new ((void *)&_vals[_size++]) T(val)); + } + inline void pop_back() + { + _size--; _vals[_size].~T(); + } + void insert(SQUnsignedInteger idx, const T& val) + { + resize(_size + 1); + for(SQUnsignedInteger i = _size - 1; i > idx; i--) { + _vals[i] = _vals[i - 1]; + } + _vals[idx] = val; + } + void remove(SQUnsignedInteger idx) + { + _vals[idx].~T(); + if(idx < (_size - 1)) { + memcpy(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1)); + } + _size--; + } + SQUnsignedInteger capacity() { return _allocated; } + inline T &back() const { return _vals[_size - 1]; } + inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; } + T* _vals; +private: + void _realloc(SQUnsignedInteger newsize) + { + newsize = (newsize > 0)?newsize:4; + _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); + _allocated = newsize; + } + SQUnsignedInteger _size; + SQUnsignedInteger _allocated; +}; + +#endif //_SQUTILS_H_ diff --git a/src/squirrel/squirrel/sqvm.cpp b/src/squirrel/squirrel/sqvm.cpp index b13ae2434..888d34277 100644 --- a/src/squirrel/squirrel/sqvm.cpp +++ b/src/squirrel/squirrel/sqvm.cpp @@ -1,1467 +1,1467 @@ -/* - see copyright notice in squirrel.h -*/ -#include "sqpcheader.h" -#include -#include -#include "sqopcodes.h" -#include "sqfuncproto.h" -#include "sqvm.h" -#include "sqclosure.h" -#include "sqstring.h" -#include "sqtable.h" -#include "squserdata.h" -#include "sqarray.h" -#include "sqclass.h" - -#define TOP() (_stack[_top-1]) - -bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) -{ - SQInteger res; - SQInteger i1 = _integer(o1), i2 = _integer(o2); - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) - { - switch(op) { - case BW_AND: res = i1 & i2; break; - case BW_OR: res = i1 | i2; break; - case BW_XOR: res = i1 ^ i2; break; - case BW_SHIFTL: res = i1 << i2; break; - case BW_SHIFTR: res = i1 >> i2; break; - case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; - default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } - } - } - else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} - trg = res; - return true; -} - -bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) -{ - if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) { - switch(op) { - case '+': trg = _integer(o1) + _integer(o2); break; - case '-': trg = _integer(o1) - _integer(o2); break; - case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; } - trg = _integer(o1) / _integer(o2); - break; - case '*': trg = _integer(o1) * _integer(o2); break; - case '%': trg = _integer(o1) % _integer(o2); break; - } - }else{ - switch(op) { - case '+': trg = tofloat(o1) + tofloat(o2); break; - case '-': trg = tofloat(o1) - tofloat(o2); break; - case '/': trg = tofloat(o1) / tofloat(o2); break; - case '*': trg = tofloat(o1) * tofloat(o2); break; - case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break; - } - } - } else { - if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){ - if(!StringCat(o1, o2, trg)) return false; - } - else if(!ArithMetaMethod(op,o1,o2,trg)) { - Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; - } - } - return true; -} - -SQVM::SQVM(SQSharedState *ss) -{ - _sharedstate=ss; - _suspended = SQFalse; - _suspended_target=-1; - _suspended_root = SQFalse; - _suspended_traps=-1; - _foreignptr=NULL; - _nnativecalls=0; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; - ci = NULL; - INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); -} - -void SQVM::Finalize() -{ - _roottable = _null_; - _lasterror = _null_; - _errorhandler = _null_; - _debughook = _null_; - temp_reg = _null_; - SQInteger size=_stack.size(); - for(SQInteger i=0;i_gc_chain,this); -} - -bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) -{ - SQMetaMethod mm; - switch(op){ - case _SC('+'): mm=MT_ADD; break; - case _SC('-'): mm=MT_SUB; break; - case _SC('/'): mm=MT_DIV; break; - case _SC('*'): mm=MT_MUL; break; - case _SC('%'): mm=MT_MODULO; break; - default: mm = MT_ADD; assert(0); break; //shutup compiler - } - if(is_delegable(o1) && _delegable(o1)->_delegate) { - Push(o1);Push(o2); - return CallMetaMethod(_delegable(o1),mm,2,dest); - } - return false; -} - -bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) -{ - - switch(type(o)) { - case OT_INTEGER: - trg = -_integer(o); - return true; - case OT_FLOAT: - trg = -_float(o); - return true; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) { - trg = temp_reg; - return true; - } - } - default:break; //shutup compiler - } - Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); - return false; -} - -#define _RET_SUCCEED(exp) { result = (exp); return true; } -bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) -{ - if(type(o1)==type(o2)){ - if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0); - SQObjectPtr res; - switch(type(o1)){ - case OT_STRING: - _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); - case OT_INTEGER: - _RET_SUCCEED(_integer(o1)-_integer(o2)); - case OT_FLOAT: - _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - Push(o1);Push(o2); - if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res); - break; - default: break; //shutup compiler - } - if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } - _RET_SUCCEED(_integer(res)); - - } - else{ - if(sq_isnumeric(o1) && sq_isnumeric(o2)){ - if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { - if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } - else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } - _RET_SUCCEED(1); - } - else{ - if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } - else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } - _RET_SUCCEED(1); - } - } - else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);} - else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);} - else { Raise_CompareError(o1,o2); return false; } - - } - assert(0); - _RET_SUCCEED(0); //cannot happen -} - -bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) -{ - SQInteger r; - if(ObjCmp(o1,o2,r)) { - switch(op) { - case CMP_G: res = (r > 0)?_true_:_false_; return true; - case CMP_GE: res = (r >= 0)?_true_:_false_; return true; - case CMP_L: res = (r < 0)?_true_:_false_; return true; - case CMP_LE: res = (r <= 0)?_true_:_false_; return true; - - } - assert(0); - } - return false; -} - -void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) -{ - switch(type(o)) { - case OT_STRING: - res = o; - return; - case OT_FLOAT: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); - break; - case OT_INTEGER: - scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o)); - break; - case OT_BOOL: - scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); - break; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o)->_delegate) { - Push(o); - if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) { - if(type(res) == OT_STRING) - return; - //else keeps going to the default - } - } - default: - scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); - } - res = SQString::Create(_ss(this),_spval); -} - - -bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) -{ - SQObjectPtr a, b; - ToString(str, a); - ToString(obj, b); - SQInteger l = _string(a)->_len , ol = _string(b)->_len; - SQChar *s = _sp(rsl(l + ol + 1)); - memcpy(s, _stringval(a), rsl(l)); - memcpy(s + l, _stringval(b), rsl(ol)); - dest = SQString::Create(_ss(this), _spval, l + ol); - return true; -} - -const SQChar *IdType2Name(SQObjectType type) -{ - switch(_RAW_TYPE(type)) - { - case _RT_NULL:return _SC("null"); - case _RT_INTEGER:return _SC("integer"); - case _RT_FLOAT:return _SC("float"); - case _RT_BOOL:return _SC("bool"); - case _RT_STRING:return _SC("string"); - case _RT_TABLE:return _SC("table"); - case _RT_ARRAY:return _SC("array"); - case _RT_GENERATOR:return _SC("generator"); - case _RT_CLOSURE: - case _RT_NATIVECLOSURE: - return _SC("function"); - case _RT_USERDATA: - case _RT_USERPOINTER: - return _SC("userdata"); - case _RT_THREAD: return _SC("thread"); - case _RT_FUNCPROTO: return _SC("function"); - case _RT_CLASS: return _SC("class"); - case _RT_INSTANCE: return _SC("instance"); - case _RT_WEAKREF: return _SC("weakref"); - default: - return NULL; - } -} - -const SQChar *GetTypeName(const SQObjectPtr &obj1) -{ - return IdType2Name(type(obj1)); -} - -void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) -{ - if(is_delegable(obj1) && _delegable(obj1)->_delegate) { - Push(obj1); - if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest)) - return; - } - dest = SQString::Create(_ss(this),GetTypeName(obj1)); -} - -bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) -{ - _stack.resize(stacksize); - _callsstack.reserve(4); - _stackbase = 0; - _top = 0; - if(!friendvm) - _roottable = SQTable::Create(_ss(this), 0); - else { - _roottable = friendvm->_roottable; - _errorhandler = friendvm->_errorhandler; - _debughook = friendvm->_debughook; - } - - sq_base_register(this); - return true; -} - -extern SQInstructionDesc g_InstrDesc[]; - -bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteger stackbase,bool tailcall) -{ - SQFunctionProto *func = _funcproto(closure->_function); - - const SQInteger paramssize = func->_parameters.size(); - const SQInteger newtop = stackbase + func->_stacksize; - - - if (paramssize != nargs) { - if(func->_varparams) - { - if (nargs < paramssize) { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - for(SQInteger n = 0; n < nargs - paramssize; n++) { - _vargsstack.push_back(_stack[stackbase+paramssize+n]); - _stack[stackbase+paramssize+n] = _null_; - } - } - else { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - } - - if(type(closure->_env) == OT_WEAKREF) { - _stack[stackbase] = _weakref(closure->_env)->_obj; - } - - if (!tailcall) { - CallInfo lc; - lc._etraps = 0; - lc._prevstkbase = stackbase - _stackbase; - lc._target = target; - lc._prevtop = _top - _stackbase; - lc._ncalls = 1; - lc._root = SQFalse; - PUSH_CALLINFO(this, lc); - } - else { - ci->_ncalls++; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); - } - ci->_vargs.size = (nargs - paramssize); - ci->_vargs.base = _vargsstack.size()-(ci->_vargs.size); - ci->_closure._unVal.pClosure = closure; - ci->_closure._type = OT_CLOSURE; - ci->_iv = &func->_instructions; - ci->_literals = &func->_literals; - //grows the stack if needed - if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) { - _stack.resize(_stack.size() + (func->_stacksize<<1)); - } - - _top = newtop; - _stackbase = stackbase; - ci->_ip = ci->_iv->_vals; - return true; -} - -bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) -{ - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - for(SQInteger i=0;i_ncalls;i++) - CallDebugHook(_SC('r')); - - SQBool broot = ci->_root; - SQInteger last_top = _top; - SQInteger target = ci->_target; - SQInteger oldstackbase = _stackbase; - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if (broot) { - if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1]; - else retval = _null_; - } - else { - if(target != -1) { //-1 is when a class contructor ret value has to be ignored - if (_arg0 != MAX_FUNC_STACKSIZE) - STK(target) = _stack[oldstackbase+_arg1]; - else - STK(target) = _null_; - } - } - - while (last_top >= _top) _stack[last_top--].Null(); - assert(oldstackbase >= _stackbase); - return broot?true:false; -} - -#define _RET_ON_FAIL(exp) { if(!exp) return false; } - -bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) -{ - _RET_ON_FAIL(ARITH_OP( op , target, a, incr)); - a = target; - return true; -} - -bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) -{ - SQObjectPtr trg; - _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); - target = a; - a = trg; - return true; -} - -bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix) -{ - SQObjectPtr tmp, tself = self, tkey = key; - if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; } - _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) - Set(tself, tkey, target,true); - if (postfix) target = tmp; - return true; -} - -#define arg0 (_i_._arg0) -#define arg1 (_i_._arg1) -#define sarg1 (*((SQInt32 *)&_i_._arg1)) -#define arg2 (_i_._arg2) -#define arg3 (_i_._arg3) -#define sarg3 ((SQInteger)*((signed char *)&_i_._arg3)) - -SQRESULT SQVM::Suspend() -{ - if (_suspended) - return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); - if (_nnativecalls!=2) - return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); - return SQ_SUSPEND_FLAG; -} - -void SQVM::PopVarArgs(VarArgs &vargs) -{ - for(SQInteger n = 0; n< vargs.size; n++) - _vargsstack.pop_back(); -} - -#define _FINISH(stoploop) {finished = stoploop; return true; } -bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr -&o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished) -{ - SQInteger nrefidx; - switch(type(o1)) { - case OT_TABLE: - if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(true); - o4 = (SQInteger)nrefidx; _FINISH(false); - case OT_ARRAY: - if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(true); - o4 = (SQInteger) nrefidx; _FINISH(false); - case OT_STRING: - if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(true); - o4 = (SQInteger)nrefidx; _FINISH(false); - case OT_CLASS: - if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(true); - o4 = (SQInteger)nrefidx; _FINISH(false); - case OT_USERDATA: - case OT_INSTANCE: - if(_delegable(o1)->_delegate) { - SQObjectPtr itr; - Push(o1); - Push(o4); - if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){ - o4 = o2 = itr; - if(type(itr) == OT_NULL) _FINISH(true); - if(!Get(o1, itr, o3, false,false)) { - Raise_Error(_SC("_nexti returned an invalid idx")); - return false; - } - _FINISH(false); - } - Raise_Error(_SC("_nexti failed")); - return false; - } - break; - case OT_GENERATOR: - if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true); - if(_generator(o1)->_state == SQGenerator::eSuspended) { - SQInteger idx = 0; - if(type(o4) == OT_INTEGER) { - idx = _integer(o4) + 1; - } - o2 = idx; - o4 = idx; - _generator(o1)->Resume(this, arg_2+1); - _FINISH(false); - } - default: - Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); - } - return false; //cannot be hit(just to avoid warnings) -} - -bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) -{ - if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; } - switch(type(o2)) { - case OT_TABLE: - if(!_table(o1)->SetDelegate(_table(o2))){ - Raise_Error(_SC("delegate cycle detected")); - return false; - } - break; - case OT_NULL: - _table(o1)->SetDelegate(NULL); - break; - default: - Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2)); - return false; - break; - } - trg = o1; - return true; -} -#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1)) - -#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} } - -#define SQ_THROW() { goto exception_trap; } - -bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) -{ - SQInteger nouters; - SQClosure *closure = SQClosure::Create(_ss(this), func); - if((nouters = func->_outervalues.size())) { - closure->_outervalues.reserve(nouters); - for(SQInteger i = 0; i_outervalues[i]; - switch(v._type){ - case otSYMBOL: - closure->_outervalues.push_back(_null_); - if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true)) - {Raise_IdxError(v._src); return false; } - break; - case otLOCAL: - closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]); - break; - case otOUTER: - closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]); - break; - } - } - } - target = closure; - return true; - -} - -bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci) -{ - if(ci->_vargs.size == 0) { - Raise_Error(_SC("the function doesn't have var args")); - return false; - } - if(!sq_isnumeric(index)){ - Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index)); - return false; - } - SQInteger idx = tointeger(index); - if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; } - target = _vargsstack[ci->_vargs.base+idx]; - return true; -} - -bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) -{ - SQClass *base = NULL; - SQObjectPtr attrs; - if(baseclass != -1) { - if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } - base = _class(_stack._vals[_stackbase + baseclass]); - } - if(attributes != MAX_FUNC_STACKSIZE) { - attrs = _stack._vals[_stackbase+attributes]; - } - target = SQClass::Create(_ss(this),base); - if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { - int nparams = 2; - SQObjectPtr ret; - Push(target); Push(attrs); - Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false); - Pop(nparams); - } - _class(target)->_attributes = attrs; - return true; -} - - - -bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) -{ - if(type(o1) == type(o2)) { - res = ((_userpointer(o1) == _userpointer(o2)?true:false)); - } - else { - if(sq_isnumeric(o1) && sq_isnumeric(o2)) { - SQInteger cmpres; - if(!ObjCmp(o1, o2,cmpres)) return false; - res = (cmpres == 0); - } - else { - res = false; - } - } - return true; -} - -bool SQVM::IsFalse(SQObjectPtr &o) -{ - if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) ) - || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL - return true; - } - return false; -} - -bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target) -{ - switch(type(o)) { - case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_; - break; - case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_; - break; - default: - Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o)); - return false; - } - return true; -} - -bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) -{ - if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } - _nnativecalls++; - AutoDec ad(&_nnativecalls); - SQInteger traps = 0; - //temp_reg vars for OP_CALL - SQInteger ct_target; - bool ct_tailcall; - - switch(et) { - case ET_CALL: - if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) { - //call the handler if there are no calls in the stack, if not relies on the previous node - if(ci == NULL) CallErrorHandler(_lasterror); - return false; - } - ci->_root = SQTrue; - break; - case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break; - case ET_RESUME_VM: - traps = _suspended_traps; - ci->_root = _suspended_root; - _suspended = SQFalse; - break; - } - -exception_restore: - // - { - for(;;) - { - const SQInstruction &_i_ = *ci->_ip++; - //dumpstack(_stackbase); - //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); - switch(_i_.op) - { - case _OP_LINE: - if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - CallDebugHook(_SC('l'),arg1); - continue; - case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue; - case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; - case _OP_DLOAD: TARGET = (*ci->_literals)[arg1]; STK(arg2) = (*ci->_literals)[arg3];continue; - case _OP_TAILCALL: - temp_reg = STK(arg1); - if (type(temp_reg) == OT_CLOSURE){ - ct_tailcall = true; - if(ci->_vargs.size) PopVarArgs(ci->_vargs); - for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); - ct_target = ci->_target; - goto common_call; - } - case _OP_CALL: { - ct_tailcall = false; - ct_target = arg0; - temp_reg = STK(arg1); -common_call: - SQInteger last_top = _top; - switch (type(temp_reg)) { - case OT_CLOSURE:{ - _GUARD(StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall)); - if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) { - SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg)); - _GUARD(gen->Yield(this)); - Return(1, ct_target, temp_reg); - STK(ct_target) = gen; - while (last_top >= _top) _stack[last_top--].Null(); - continue; - } - if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) - CallDebugHook(_SC('c')); - } - break; - case OT_NATIVECLOSURE: { - bool suspend; - _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend)); - if(suspend){ - _suspended = SQTrue; - _suspended_target = ct_target; - _suspended_root = ci->_root; - _suspended_traps = traps; - outres = temp_reg; - return true; - } - if(ct_target != -1) { //skip return value for contructors - STK(ct_target) = temp_reg; - } - } - break; - case OT_CLASS:{ - SQObjectPtr inst; - _GUARD(CreateClassInstance(_class(temp_reg),inst,temp_reg)); - STK(ct_target) = inst; - ct_target = -1; //fakes return value target so that is not overwritten by the contructor - if(type(temp_reg) != OT_NULL) { - _stack[_stackbase+arg2] = inst; - goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the contructor) - } - } - break; - case OT_TABLE: - case OT_USERDATA: - case OT_INSTANCE: - { - Push(temp_reg); - for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); - if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){ - STK(ct_target) = temp_reg; - break; - } - Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg)); - SQ_THROW(); - } - default: - Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg)); - SQ_THROW(); - } - } - continue; - case _OP_PREPCALL: - if (!Get(STK(arg2), STK(arg1), temp_reg, false,true)) - { Raise_IdxError(STK(arg1)); SQ_THROW(); } - goto common_prepcall; - case _OP_PREPCALLK: - if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) { - if(type(STK(arg2)) == OT_CLASS) { //hack? - if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) { - STK(arg3) = STK(arg2); - TARGET = temp_reg; - continue; - } - } - { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();} - } -common_prepcall: - if(type(STK(arg2)) == OT_CLASS) { - STK(arg3) = STK(0); // this - } - else { - STK(arg3) = STK(arg2); - } - TARGET = temp_reg; - continue; - case _OP_GETK: - if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();} - TARGET = temp_reg; - continue; - case _OP_MOVE: TARGET = STK(arg1); continue; - case _OP_NEWSLOT: - _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); - if(arg0 != arg3) TARGET = STK(arg3); - continue; - case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; - case _OP_SET: - if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - if (arg0 != arg3) TARGET = STK(arg3); - continue; - case _OP_GET: - if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } - TARGET = temp_reg; - continue; - case _OP_EQ:{ - bool res; - if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = res?_true_:_false_; - }continue; - case _OP_NE:{ - bool res; - if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } - TARGET = (!res)?_true_:_false_; - } continue; - case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue; - case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; - case _OP_RETURN: - if(type((ci)->_generator) == OT_GENERATOR) { - _generator((ci)->_generator)->Kill(); - } - if(Return(arg0, arg1, temp_reg)){ - assert(traps==0); - outres = temp_reg; - return true; - } - continue; - case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue; - case _OP_LOADROOTTABLE: TARGET = _roottable; continue; - case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue; - case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; - case _OP_JMP: ci->_ip += (sarg1); continue; - case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; - case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue; - case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue; - case _OP_GETVARGV: - if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } - continue; - case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; - case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; - case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue; - case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue; - case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue; - case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue; - case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue; - case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue; - case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue; - case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue; - case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; - case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue; - case _OP_INSTANCEOF: - if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE) - {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} - TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_; - continue; - case _OP_AND: - if(IsFalse(STK(arg2))) { - TARGET = STK(arg2); - ci->_ip += (sarg1); - } - continue; - case _OP_OR: - if(!IsFalse(STK(arg2))) { - TARGET = STK(arg2); - ci->_ip += (sarg1); - } - continue; - case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; - case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue; - case _OP_BWNOT: - if(type(STK(arg1)) == OT_INTEGER) { - SQInteger t = _integer(STK(arg1)); - TARGET = SQInteger(~t); - continue; - } - Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); - SQ_THROW(); - case _OP_CLOSURE: { - SQClosure *c = ci->_closure._unVal.pClosure; - SQFunctionProto *fp = c->_function._unVal.pFunctionProto; - if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } - continue; - } - case _OP_YIELD:{ - if(type(ci->_generator) == OT_GENERATOR) { - if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); - _GUARD(_generator(ci->_generator)->Yield(this)); - traps -= ci->_etraps; - if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg; - } - else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} - if(Return(arg0, arg1, temp_reg)){ - assert(traps == 0); - outres = temp_reg; - return true; - } - - } - continue; - case _OP_RESUME: - if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} - _GUARD(_generator(STK(arg1))->Resume(this, arg0)); - traps += ci->_etraps; - continue; - case _OP_FOREACH:{ bool finished; - _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished)); - if(finished) ci->_ip += sarg1; } - continue; - case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue; - case _OP_CLONE: - if(!Clone(STK(arg1), TARGET)) - { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();} - continue; - case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue; - case _OP_PUSHTRAP: - _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++; - ci->_etraps++; - continue; - case _OP_POPTRAP: - for(SQInteger i = 0; i < arg0; i++) { - _etraps.pop_back(); traps--; - ci->_etraps--; - } - continue; - case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; - case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; - case _OP_NEWSLOTA: - bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; - if(type(STK(arg1)) == OT_CLASS) { - if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { - Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); - Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_); - int nparams = 4; - if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) { - Pop(nparams); - continue; - } - } - } - _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic)); - if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) { - _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1)); - } - continue; - } - - } - } -exception_trap: - { - SQObjectPtr currerror = _lasterror; -// dumpstack(_stackbase); - SQInteger n = 0; - SQInteger last_top = _top; - if(ci) { - if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror); - - if(traps) { - do { - if(ci->_etraps > 0) { - SQExceptionTrap &et = _etraps.top(); - ci->_ip = et._ip; - _top = et._stacksize; - _stackbase = et._stackbase; - _stack[_stackbase+et._extarget] = currerror; - _etraps.pop_back(); traps--; ci->_etraps--; - while(last_top >= _top) _stack[last_top--].Null(); - goto exception_restore; - } - //if is a native closure - if(type(ci->_closure) != OT_CLOSURE && n) - break; - if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill(); - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - n++; - } while(_callsstack.size()); - } - else { - //call the hook - if(raiseerror && !_ss(this)->_notifyallexceptions) - CallErrorHandler(currerror); - } - //remove call stack until a C function is found or the cstack is empty - if(ci) do { - SQBool exitafterthisone = ci->_root; - if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill(); - _stackbase -= ci->_prevstkbase; - _top = _stackbase + ci->_prevtop; - PopVarArgs(ci->_vargs); - POP_CALLINFO(this); - if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break; - } while(_callsstack.size()); - - while(last_top >= _top) _stack[last_top--].Null(); - } - _lasterror = currerror; - return false; - } - assert(0); -} - -bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) -{ - inst = theclass->CreateInstance(); - if(!theclass->Get(_ss(this)->_constructoridx,constructor)) { - //if(!Call(constr,nargs,stackbase,constr,false)) - // return false; - constructor = _null_; - } - return true; -} - -void SQVM::CallErrorHandler(SQObjectPtr &error) -{ - if(type(_errorhandler) != OT_NULL) { - SQObjectPtr out; - Push(_roottable); Push(error); - Call(_errorhandler, 2, _top-2, out,SQFalse); - Pop(2); - } -} - -void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) -{ - SQObjectPtr temp_reg; - SQInteger nparams=5; - SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function); - Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); - Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse); - Pop(nparams); -} - -bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend) -{ - if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } - SQInteger nparamscheck = nclosure->_nparamscheck; - if(((nparamscheck > 0) && (nparamscheck != nargs)) - || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) { - Raise_Error(_SC("wrong number of parameters")); - return false; - } - - SQInteger tcs; - if((tcs = nclosure->_typecheck.size())) { - for(SQInteger i = 0; i < nargs && i < tcs; i++) - if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) { - Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i])); - return false; - } - } - _nnativecalls++; - if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) { - _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1)); - } - SQInteger oldtop = _top; - SQInteger oldstackbase = _stackbase; - _top = stackbase + nargs; - PUSH_CALLINFO(this, CallInfo()); - ci->_etraps = 0; - ci->_closure._unVal.pNativeClosure = nclosure; - ci->_closure._type = OT_NATIVECLOSURE; - ci->_prevstkbase = stackbase - _stackbase; - ci->_ncalls = 1; - _stackbase = stackbase; - //push free variables - SQInteger outers = nclosure->_outervalues.size(); - for (SQInteger i = 0; i < outers; i++) { - Push(nclosure->_outervalues[i]); - } - - if(type(nclosure->_env) == OT_WEAKREF) { - _stack[stackbase] = _weakref(nclosure->_env)->_obj; - } - - ci->_prevtop = (oldtop - oldstackbase); - SQInteger ret = (nclosure->_function)(this); - _nnativecalls--; - suspend = false; - if( ret == SQ_SUSPEND_FLAG) suspend = true; - else if (ret < 0) { - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); - Raise_Error(_lasterror); - return false; - } - - if (ret != 0){ retval = TOP(); } - else { retval = _null_; } - _stackbase = oldstackbase; - _top = oldtop; - POP_CALLINFO(this); - return true; -} - -bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot) -{ - switch(type(self)){ - case OT_TABLE: - if(_table(self)->Get(key,dest))return true; - break; - case OT_ARRAY: - if(sq_isnumeric(key)){ - return _array(self)->Get(tointeger(key),dest); - } - break; - case OT_INSTANCE: - if(_instance(self)->Get(key,dest)) return true; - break; - default:break; //shut up compiler - } - if(FallBackGet(self,key,dest,raw)) return true; - - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Get(key,dest); - } - } - return false; -} - -bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw) -{ - switch(type(self)){ - case OT_CLASS: - return _class(self)->Get(key,dest); - break; - case OT_TABLE: - case OT_USERDATA: - //delegation - if(_delegable(self)->_delegate) { - if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false)) - return true; - if(raw)return false; - Push(self);Push(key); - if(CallMetaMethod(_delegable(self),MT_GET,2,dest)) - return true; - } - if(type(self) == OT_TABLE) { - if(raw) return false; - return _table_ddel->Get(key,dest); - } - return false; - break; - case OT_ARRAY: - if(raw)return false; - return _array_ddel->Get(key,dest); - case OT_STRING: - if(sq_isnumeric(key)){ - SQInteger n=tointeger(key); - if(abs((int)n)<_string(self)->_len){ - if(n<0)n=_string(self)->_len-n; - dest=SQInteger(_stringval(self)[n]); - return true; - } - return false; - } - else { - if(raw)return false; - return _string_ddel->Get(key,dest); - } - break; - case OT_INSTANCE: - if(raw)return false; - Push(self);Push(key); - if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) { - return _instance_ddel->Get(key,dest); - } - return true; - case OT_INTEGER:case OT_FLOAT:case OT_BOOL: - if(raw)return false; - return _number_ddel->Get(key,dest); - case OT_GENERATOR: - if(raw)return false; - return _generator_ddel->Get(key,dest); - case OT_CLOSURE: case OT_NATIVECLOSURE: - if(raw)return false; - return _closure_ddel->Get(key,dest); - case OT_THREAD: - if(raw)return false; - return _thread_ddel->Get(key,dest); - case OT_WEAKREF: - if(raw)return false; - return _weakref_ddel->Get(key,dest); - default:return false; - } - return false; -} - -bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot) -{ - switch(type(self)){ - case OT_TABLE: - if(_table(self)->Set(key,val)) - return true; - if(_table(self)->_delegate) { - if(Set(_table(self)->_delegate,key,val,false)) { - return true; - } - } - //keeps going - case OT_USERDATA: - if(_delegable(self)->_delegate) { - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } - break; - case OT_INSTANCE:{ - if(_instance(self)->Set(key,val)) - return true; - SQObjectPtr t; - Push(self);Push(key);Push(val); - if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; - } - break; - case OT_ARRAY: - if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } - return _array(self)->Set(tointeger(key),val); - default: - Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); - return false; - } - if(fetchroot) { - if(_rawval(STK(0)) == _rawval(self) && - type(STK(0)) == type(self)) { - return _table(_roottable)->Set(key,val); - } - } - return false; -} - -bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) -{ - SQObjectPtr temp_reg; - SQObjectPtr newobj; - switch(type(self)){ - case OT_TABLE: - newobj = _table(self)->Clone(); - goto cloned_mt; - case OT_INSTANCE: - newobj = _instance(self)->Clone(_ss(this)); -cloned_mt: - if(_delegable(newobj)->_delegate){ - Push(newobj); - Push(self); - CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg); - } - target = newobj; - return true; - case OT_ARRAY: - target = _array(self)->Clone(); - return true; - default: return false; - } -} - -bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) -{ - if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } - switch(type(self)) { - case OT_TABLE: { - bool rawcall = true; - if(_table(self)->_delegate) { - SQObjectPtr res; - if(!_table(self)->Get(key,res)) { - Push(self);Push(key);Push(val); - rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res); - } - } - if(rawcall) _table(self)->NewSlot(key,val); //cannot fail - - break;} - case OT_CLASS: - if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { - if(_class(self)->_locked) { - Raise_Error(_SC("trying to modify a class that has already been instantiated")); - return false; - } - else { - SQObjectPtr oval = PrintObjVal(key); - Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); - return false; - } - } - break; - default: - Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); - return false; - break; - } - return true; -} - -bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) -{ - switch(type(self)) { - case OT_TABLE: - case OT_INSTANCE: - case OT_USERDATA: { - SQObjectPtr t; - bool handled = false; - if(_delegable(self)->_delegate) { - Push(self);Push(key); - handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t); - } - - if(!handled) { - if(type(self) == OT_TABLE) { - if(_table(self)->Get(key,t)) { - _table(self)->Remove(key); - } - else { - Raise_IdxError((SQObject &)key); - return false; - } - } - else { - Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); - return false; - } - } - res = t; - } - break; - default: - Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); - return false; - } - return true; -} - -bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror) -{ -#ifdef _DEBUG -SQInteger prevstackbase = _stackbase; -#endif - switch(type(closure)) { - case OT_CLOSURE: - return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); - break; - case OT_NATIVECLOSURE:{ - bool suspend; - return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend); - - } - break; - case OT_CLASS: { - SQObjectPtr constr; - SQObjectPtr temp; - CreateClassInstance(_class(closure),outres,constr); - if(type(constr) != OT_NULL) { - _stack[stackbase] = outres; - return Call(constr,nparams,stackbase,temp,raiseerror); - } - return true; - } - break; - default: - return false; - } -#ifdef _DEBUG - if(!_suspended) { - assert(_stackbase == prevstackbase); - } -#endif - return true; -} - -bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) -{ - SQObjectPtr closure; - if(del->GetMetaMethod(this, mm, closure)) { - if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { - Pop(nparams); - return true; - } - } - Pop(nparams); - return false; -} - -void SQVM::Remove(SQInteger n) { - n = (n >= 0)?n + _stackbase - 1:_top + n; - for(SQInteger i = n; i < _top; i++){ - _stack[i] = _stack[i+1]; - } - _stack[_top] = _null_; - _top--; -} - -void SQVM::Pop() { - _stack[--_top] = _null_; -} - -void SQVM::Pop(SQInteger n) { - for(SQInteger i = 0; i < n; i++){ - _stack[--_top] = _null_; - } -} - -void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } -SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } -SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } -SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; } -SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } - -#ifdef _DEBUG_DUMP -void SQVM::dumpstack(SQInteger stackbase,bool dumpall) -{ - SQInteger size=dumpall?_stack.size():_top; - SQInteger n=0; - scprintf(_SC("\n>>>>stack dump<<<<\n")); - CallInfo &ci=_callsstack.back(); - scprintf(_SC("IP: %p\n"),ci._ip); - scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); - scprintf(_SC("prev top: %d\n"),ci._prevtop); - for(SQInteger i=0;i"));else scprintf(_SC(" ")); - scprintf(_SC("[%d]:"),n); - switch(type(obj)){ - case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; - case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break; - case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; - case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; - case OT_NULL: scprintf(_SC("NULL")); break; - case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; - case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; - case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; - case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; - case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; - case OT_GENERATOR: scprintf(_SC("GENERATOR"));break; - case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; - case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; - case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; - case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; - case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; - default: - assert(0); - break; - }; - scprintf(_SC("\n")); - ++n; - } -} - - - -#endif +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include +#include +#include "sqopcodes.h" +#include "sqfuncproto.h" +#include "sqvm.h" +#include "sqclosure.h" +#include "sqstring.h" +#include "sqtable.h" +#include "squserdata.h" +#include "sqarray.h" +#include "sqclass.h" + +#define TOP() (_stack[_top-1]) + +bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) +{ + SQInteger res; + SQInteger i1 = _integer(o1), i2 = _integer(o2); + if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) + { + switch(op) { + case BW_AND: res = i1 & i2; break; + case BW_OR: res = i1 | i2; break; + case BW_XOR: res = i1 ^ i2; break; + case BW_SHIFTL: res = i1 << i2; break; + case BW_SHIFTR: res = i1 >> i2; break; + case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; + default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } + } + } + else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} + trg = res; + return true; +} + +bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) +{ + if(sq_isnumeric(o1) && sq_isnumeric(o2)) { + if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) { + switch(op) { + case '+': trg = _integer(o1) + _integer(o2); break; + case '-': trg = _integer(o1) - _integer(o2); break; + case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; } + trg = _integer(o1) / _integer(o2); + break; + case '*': trg = _integer(o1) * _integer(o2); break; + case '%': trg = _integer(o1) % _integer(o2); break; + } + }else{ + switch(op) { + case '+': trg = tofloat(o1) + tofloat(o2); break; + case '-': trg = tofloat(o1) - tofloat(o2); break; + case '/': trg = tofloat(o1) / tofloat(o2); break; + case '*': trg = tofloat(o1) * tofloat(o2); break; + case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break; + } + } + } else { + if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){ + if(!StringCat(o1, o2, trg)) return false; + } + else if(!ArithMetaMethod(op,o1,o2,trg)) { + Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; + } + } + return true; +} + +SQVM::SQVM(SQSharedState *ss) +{ + _sharedstate=ss; + _suspended = SQFalse; + _suspended_target=-1; + _suspended_root = SQFalse; + _suspended_traps=-1; + _foreignptr=NULL; + _nnativecalls=0; + _lasterror = _null_; + _errorhandler = _null_; + _debughook = _null_; + ci = NULL; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); +} + +void SQVM::Finalize() +{ + _roottable = _null_; + _lasterror = _null_; + _errorhandler = _null_; + _debughook = _null_; + temp_reg = _null_; + SQInteger size=_stack.size(); + for(SQInteger i=0;i_gc_chain,this); +} + +bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) +{ + SQMetaMethod mm; + switch(op){ + case _SC('+'): mm=MT_ADD; break; + case _SC('-'): mm=MT_SUB; break; + case _SC('/'): mm=MT_DIV; break; + case _SC('*'): mm=MT_MUL; break; + case _SC('%'): mm=MT_MODULO; break; + default: mm = MT_ADD; assert(0); break; //shutup compiler + } + if(is_delegable(o1) && _delegable(o1)->_delegate) { + Push(o1);Push(o2); + return CallMetaMethod(_delegable(o1),mm,2,dest); + } + return false; +} + +bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) +{ + + switch(type(o)) { + case OT_INTEGER: + trg = -_integer(o); + return true; + case OT_FLOAT: + trg = -_float(o); + return true; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + Push(o); + if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) { + trg = temp_reg; + return true; + } + } + default:break; //shutup compiler + } + Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); + return false; +} + +#define _RET_SUCCEED(exp) { result = (exp); return true; } +bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) +{ + if(type(o1)==type(o2)){ + if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0); + SQObjectPtr res; + switch(type(o1)){ + case OT_STRING: + _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); + case OT_INTEGER: + _RET_SUCCEED(_integer(o1)-_integer(o2)); + case OT_FLOAT: + _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + Push(o1);Push(o2); + if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res); + break; + default: break; //shutup compiler + } + if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } + _RET_SUCCEED(_integer(res)); + + } + else{ + if(sq_isnumeric(o1) && sq_isnumeric(o2)){ + if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { + if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } + else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + else{ + if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } + else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + } + else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);} + else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);} + else { Raise_CompareError(o1,o2); return false; } + + } + assert(0); + _RET_SUCCEED(0); //cannot happen +} + +bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) +{ + SQInteger r; + if(ObjCmp(o1,o2,r)) { + switch(op) { + case CMP_G: res = (r > 0)?_true_:_false_; return true; + case CMP_GE: res = (r >= 0)?_true_:_false_; return true; + case CMP_L: res = (r < 0)?_true_:_false_; return true; + case CMP_LE: res = (r <= 0)?_true_:_false_; return true; + + } + assert(0); + } + return false; +} + +void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) +{ + switch(type(o)) { + case OT_STRING: + res = o; + return; + case OT_FLOAT: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); + break; + case OT_INTEGER: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o)); + break; + case OT_BOOL: + scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + Push(o); + if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) { + if(type(res) == OT_STRING) + return; + //else keeps going to the default + } + } + default: + scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); + } + res = SQString::Create(_ss(this),_spval); +} + + +bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) +{ + SQObjectPtr a, b; + ToString(str, a); + ToString(obj, b); + SQInteger l = _string(a)->_len , ol = _string(b)->_len; + SQChar *s = _sp(rsl(l + ol + 1)); + memcpy(s, _stringval(a), rsl(l)); + memcpy(s + l, _stringval(b), rsl(ol)); + dest = SQString::Create(_ss(this), _spval, l + ol); + return true; +} + +const SQChar *IdType2Name(SQObjectType type) +{ + switch(_RAW_TYPE(type)) + { + case _RT_NULL:return _SC("null"); + case _RT_INTEGER:return _SC("integer"); + case _RT_FLOAT:return _SC("float"); + case _RT_BOOL:return _SC("bool"); + case _RT_STRING:return _SC("string"); + case _RT_TABLE:return _SC("table"); + case _RT_ARRAY:return _SC("array"); + case _RT_GENERATOR:return _SC("generator"); + case _RT_CLOSURE: + case _RT_NATIVECLOSURE: + return _SC("function"); + case _RT_USERDATA: + case _RT_USERPOINTER: + return _SC("userdata"); + case _RT_THREAD: return _SC("thread"); + case _RT_FUNCPROTO: return _SC("function"); + case _RT_CLASS: return _SC("class"); + case _RT_INSTANCE: return _SC("instance"); + case _RT_WEAKREF: return _SC("weakref"); + default: + return NULL; + } +} + +const SQChar *GetTypeName(const SQObjectPtr &obj1) +{ + return IdType2Name(type(obj1)); +} + +void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) +{ + if(is_delegable(obj1) && _delegable(obj1)->_delegate) { + Push(obj1); + if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest)) + return; + } + dest = SQString::Create(_ss(this),GetTypeName(obj1)); +} + +bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) +{ + _stack.resize(stacksize); + _callsstack.reserve(4); + _stackbase = 0; + _top = 0; + if(!friendvm) + _roottable = SQTable::Create(_ss(this), 0); + else { + _roottable = friendvm->_roottable; + _errorhandler = friendvm->_errorhandler; + _debughook = friendvm->_debughook; + } + + sq_base_register(this); + return true; +} + +extern SQInstructionDesc g_InstrDesc[]; + +bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger nargs,SQInteger stackbase,bool tailcall) +{ + SQFunctionProto *func = _funcproto(closure->_function); + + const SQInteger paramssize = func->_parameters.size(); + const SQInteger newtop = stackbase + func->_stacksize; + + + if (paramssize != nargs) { + if(func->_varparams) + { + if (nargs < paramssize) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + for(SQInteger n = 0; n < nargs - paramssize; n++) { + _vargsstack.push_back(_stack[stackbase+paramssize+n]); + _stack[stackbase+paramssize+n] = _null_; + } + } + else { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + } + + if(type(closure->_env) == OT_WEAKREF) { + _stack[stackbase] = _weakref(closure->_env)->_obj; + } + + if (!tailcall) { + CallInfo lc; + lc._etraps = 0; + lc._prevstkbase = stackbase - _stackbase; + lc._target = target; + lc._prevtop = _top - _stackbase; + lc._ncalls = 1; + lc._root = SQFalse; + PUSH_CALLINFO(this, lc); + } + else { + ci->_ncalls++; + if(ci->_vargs.size) PopVarArgs(ci->_vargs); + } + ci->_vargs.size = (nargs - paramssize); + ci->_vargs.base = _vargsstack.size()-(ci->_vargs.size); + ci->_closure._unVal.pClosure = closure; + ci->_closure._type = OT_CLOSURE; + ci->_iv = &func->_instructions; + ci->_literals = &func->_literals; + //grows the stack if needed + if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) { + _stack.resize(_stack.size() + (func->_stacksize<<1)); + } + + _top = newtop; + _stackbase = stackbase; + ci->_ip = ci->_iv->_vals; + return true; +} + +bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) +{ + if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + for(SQInteger i=0;i_ncalls;i++) + CallDebugHook(_SC('r')); + + SQBool broot = ci->_root; + SQInteger last_top = _top; + SQInteger target = ci->_target; + SQInteger oldstackbase = _stackbase; + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + if(ci->_vargs.size) PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + if (broot) { + if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1]; + else retval = _null_; + } + else { + if(target != -1) { //-1 is when a class contructor ret value has to be ignored + if (_arg0 != MAX_FUNC_STACKSIZE) + STK(target) = _stack[oldstackbase+_arg1]; + else + STK(target) = _null_; + } + } + + while (last_top >= _top) _stack[last_top--].Null(); + assert(oldstackbase >= _stackbase); + return broot?true:false; +} + +#define _RET_ON_FAIL(exp) { if(!exp) return false; } + +bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) +{ + _RET_ON_FAIL(ARITH_OP( op , target, a, incr)); + a = target; + return true; +} + +bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) +{ + SQObjectPtr trg; + _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); + target = a; + a = trg; + return true; +} + +bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix) +{ + SQObjectPtr tmp, tself = self, tkey = key; + if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; } + _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) + Set(tself, tkey, target,true); + if (postfix) target = tmp; + return true; +} + +#define arg0 (_i_._arg0) +#define arg1 (_i_._arg1) +#define sarg1 (*((SQInt32 *)&_i_._arg1)) +#define arg2 (_i_._arg2) +#define arg3 (_i_._arg3) +#define sarg3 ((SQInteger)*((signed char *)&_i_._arg3)) + +SQRESULT SQVM::Suspend() +{ + if (_suspended) + return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); + if (_nnativecalls!=2) + return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); + return SQ_SUSPEND_FLAG; +} + +void SQVM::PopVarArgs(VarArgs &vargs) +{ + for(SQInteger n = 0; n< vargs.size; n++) + _vargsstack.pop_back(); +} + +#define _FINISH(stoploop) {finished = stoploop; return true; } +bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr +&o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished) +{ + SQInteger nrefidx; + switch(type(o1)) { + case OT_TABLE: + if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(true); + o4 = (SQInteger)nrefidx; _FINISH(false); + case OT_ARRAY: + if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(true); + o4 = (SQInteger) nrefidx; _FINISH(false); + case OT_STRING: + if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(true); + o4 = (SQInteger)nrefidx; _FINISH(false); + case OT_CLASS: + if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(true); + o4 = (SQInteger)nrefidx; _FINISH(false); + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o1)->_delegate) { + SQObjectPtr itr; + Push(o1); + Push(o4); + if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){ + o4 = o2 = itr; + if(type(itr) == OT_NULL) _FINISH(true); + if(!Get(o1, itr, o3, false,false)) { + Raise_Error(_SC("_nexti returned an invalid idx")); + return false; + } + _FINISH(false); + } + Raise_Error(_SC("_nexti failed")); + return false; + } + break; + case OT_GENERATOR: + if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true); + if(_generator(o1)->_state == SQGenerator::eSuspended) { + SQInteger idx = 0; + if(type(o4) == OT_INTEGER) { + idx = _integer(o4) + 1; + } + o2 = idx; + o4 = idx; + _generator(o1)->Resume(this, arg_2+1); + _FINISH(false); + } + default: + Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); + } + return false; //cannot be hit(just to avoid warnings) +} + +bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) +{ + if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; } + switch(type(o2)) { + case OT_TABLE: + if(!_table(o1)->SetDelegate(_table(o2))){ + Raise_Error(_SC("delegate cycle detected")); + return false; + } + break; + case OT_NULL: + _table(o1)->SetDelegate(NULL); + break; + default: + Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2)); + return false; + break; + } + trg = o1; + return true; +} +#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1)) + +#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} } + +#define SQ_THROW() { goto exception_trap; } + +bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) +{ + SQInteger nouters; + SQClosure *closure = SQClosure::Create(_ss(this), func); + if((nouters = func->_outervalues.size())) { + closure->_outervalues.reserve(nouters); + for(SQInteger i = 0; i_outervalues[i]; + switch(v._type){ + case otSYMBOL: + closure->_outervalues.push_back(_null_); + if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true)) + {Raise_IdxError(v._src); return false; } + break; + case otLOCAL: + closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]); + break; + case otOUTER: + closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]); + break; + } + } + } + target = closure; + return true; + +} + +bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci) +{ + if(ci->_vargs.size == 0) { + Raise_Error(_SC("the function doesn't have var args")); + return false; + } + if(!sq_isnumeric(index)){ + Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index)); + return false; + } + SQInteger idx = tointeger(index); + if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; } + target = _vargsstack[ci->_vargs.base+idx]; + return true; +} + +bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) +{ + SQClass *base = NULL; + SQObjectPtr attrs; + if(baseclass != -1) { + if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } + base = _class(_stack._vals[_stackbase + baseclass]); + } + if(attributes != MAX_FUNC_STACKSIZE) { + attrs = _stack._vals[_stackbase+attributes]; + } + target = SQClass::Create(_ss(this),base); + if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { + int nparams = 2; + SQObjectPtr ret; + Push(target); Push(attrs); + Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false); + Pop(nparams); + } + _class(target)->_attributes = attrs; + return true; +} + + + +bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) +{ + if(type(o1) == type(o2)) { + res = ((_userpointer(o1) == _userpointer(o2)?true:false)); + } + else { + if(sq_isnumeric(o1) && sq_isnumeric(o2)) { + SQInteger cmpres; + if(!ObjCmp(o1, o2,cmpres)) return false; + res = (cmpres == 0); + } + else { + res = false; + } + } + return true; +} + +bool SQVM::IsFalse(SQObjectPtr &o) +{ + if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) ) + || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL + return true; + } + return false; +} + +bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target) +{ + switch(type(o)) { + case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_; + break; + case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_; + break; + default: + Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o)); + return false; + } + return true; +} + +bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) +{ + if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } + _nnativecalls++; + AutoDec ad(&_nnativecalls); + SQInteger traps = 0; + //temp_reg vars for OP_CALL + SQInteger ct_target; + bool ct_tailcall; + + switch(et) { + case ET_CALL: + if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) { + //call the handler if there are no calls in the stack, if not relies on the previous node + if(ci == NULL) CallErrorHandler(_lasterror); + return false; + } + ci->_root = SQTrue; + break; + case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break; + case ET_RESUME_VM: + traps = _suspended_traps; + ci->_root = _suspended_root; + _suspended = SQFalse; + break; + } + +exception_restore: + // + { + for(;;) + { + const SQInstruction &_i_ = *ci->_ip++; + //dumpstack(_stackbase); + //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); + switch(_i_.op) + { + case _OP_LINE: + if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + CallDebugHook(_SC('l'),arg1); + continue; + case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue; + case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; + case _OP_DLOAD: TARGET = (*ci->_literals)[arg1]; STK(arg2) = (*ci->_literals)[arg3];continue; + case _OP_TAILCALL: + temp_reg = STK(arg1); + if (type(temp_reg) == OT_CLOSURE){ + ct_tailcall = true; + if(ci->_vargs.size) PopVarArgs(ci->_vargs); + for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); + ct_target = ci->_target; + goto common_call; + } + case _OP_CALL: { + ct_tailcall = false; + ct_target = arg0; + temp_reg = STK(arg1); +common_call: + SQInteger last_top = _top; + switch (type(temp_reg)) { + case OT_CLOSURE:{ + _GUARD(StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall)); + if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) { + SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg)); + _GUARD(gen->Yield(this)); + Return(1, ct_target, temp_reg); + STK(ct_target) = gen; + while (last_top >= _top) _stack[last_top--].Null(); + continue; + } + if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + CallDebugHook(_SC('c')); + } + break; + case OT_NATIVECLOSURE: { + bool suspend; + _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend)); + if(suspend){ + _suspended = SQTrue; + _suspended_target = ct_target; + _suspended_root = ci->_root; + _suspended_traps = traps; + outres = temp_reg; + return true; + } + if(ct_target != -1) { //skip return value for contructors + STK(ct_target) = temp_reg; + } + } + break; + case OT_CLASS:{ + SQObjectPtr inst; + _GUARD(CreateClassInstance(_class(temp_reg),inst,temp_reg)); + STK(ct_target) = inst; + ct_target = -1; //fakes return value target so that is not overwritten by the contructor + if(type(temp_reg) != OT_NULL) { + _stack[_stackbase+arg2] = inst; + goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the contructor) + } + } + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + { + Push(temp_reg); + for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); + if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){ + STK(ct_target) = temp_reg; + break; + } + Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg)); + SQ_THROW(); + } + default: + Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg)); + SQ_THROW(); + } + } + continue; + case _OP_PREPCALL: + if (!Get(STK(arg2), STK(arg1), temp_reg, false,true)) + { Raise_IdxError(STK(arg1)); SQ_THROW(); } + goto common_prepcall; + case _OP_PREPCALLK: + if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) { + if(type(STK(arg2)) == OT_CLASS) { //hack? + if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) { + STK(arg3) = STK(arg2); + TARGET = temp_reg; + continue; + } + } + { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();} + } +common_prepcall: + if(type(STK(arg2)) == OT_CLASS) { + STK(arg3) = STK(0); // this + } + else { + STK(arg3) = STK(arg2); + } + TARGET = temp_reg; + continue; + case _OP_GETK: + if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();} + TARGET = temp_reg; + continue; + case _OP_MOVE: TARGET = STK(arg1); continue; + case _OP_NEWSLOT: + _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); + if(arg0 != arg3) TARGET = STK(arg3); + continue; + case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; + case _OP_SET: + if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } + if (arg0 != arg3) TARGET = STK(arg3); + continue; + case _OP_GET: + if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } + TARGET = temp_reg; + continue; + case _OP_EQ:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = res?_true_:_false_; + }continue; + case _OP_NE:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = (!res)?_true_:_false_; + } continue; + case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue; + case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; + case _OP_RETURN: + if(type((ci)->_generator) == OT_GENERATOR) { + _generator((ci)->_generator)->Kill(); + } + if(Return(arg0, arg1, temp_reg)){ + assert(traps==0); + outres = temp_reg; + return true; + } + continue; + case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue; + case _OP_LOADROOTTABLE: TARGET = _roottable; continue; + case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue; + case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; + case _OP_JMP: ci->_ip += (sarg1); continue; + case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue; + case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue; + case _OP_GETVARGV: + if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } + continue; + case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; + case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; + case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue; + case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue; + case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue; + case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue; + case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue; + case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue; + case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; + case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue; + case _OP_INSTANCEOF: + if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE) + {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} + TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_; + continue; + case _OP_AND: + if(IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_OR: + if(!IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; + case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue; + case _OP_BWNOT: + if(type(STK(arg1)) == OT_INTEGER) { + SQInteger t = _integer(STK(arg1)); + TARGET = SQInteger(~t); + continue; + } + Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); + SQ_THROW(); + case _OP_CLOSURE: { + SQClosure *c = ci->_closure._unVal.pClosure; + SQFunctionProto *fp = c->_function._unVal.pFunctionProto; + if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } + continue; + } + case _OP_YIELD:{ + if(type(ci->_generator) == OT_GENERATOR) { + if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); + _GUARD(_generator(ci->_generator)->Yield(this)); + traps -= ci->_etraps; + if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg; + } + else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} + if(Return(arg0, arg1, temp_reg)){ + assert(traps == 0); + outres = temp_reg; + return true; + } + + } + continue; + case _OP_RESUME: + if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} + _GUARD(_generator(STK(arg1))->Resume(this, arg0)); + traps += ci->_etraps; + continue; + case _OP_FOREACH:{ bool finished; + _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished)); + if(finished) ci->_ip += sarg1; } + continue; + case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue; + case _OP_CLONE: + if(!Clone(STK(arg1), TARGET)) + { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();} + continue; + case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue; + case _OP_PUSHTRAP: + _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++; + ci->_etraps++; + continue; + case _OP_POPTRAP: + for(SQInteger i = 0; i < arg0; i++) { + _etraps.pop_back(); traps--; + ci->_etraps--; + } + continue; + case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; + case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; + case _OP_NEWSLOTA: + bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; + if(type(STK(arg1)) == OT_CLASS) { + if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { + Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); + Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_); + int nparams = 4; + if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) { + Pop(nparams); + continue; + } + } + } + _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic)); + if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) { + _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1)); + } + continue; + } + + } + } +exception_trap: + { + SQObjectPtr currerror = _lasterror; +// dumpstack(_stackbase); + SQInteger n = 0; + SQInteger last_top = _top; + if(ci) { + if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror); + + if(traps) { + do { + if(ci->_etraps > 0) { + SQExceptionTrap &et = _etraps.top(); + ci->_ip = et._ip; + _top = et._stacksize; + _stackbase = et._stackbase; + _stack[_stackbase+et._extarget] = currerror; + _etraps.pop_back(); traps--; ci->_etraps--; + while(last_top >= _top) _stack[last_top--].Null(); + goto exception_restore; + } + //if is a native closure + if(type(ci->_closure) != OT_CLOSURE && n) + break; + if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill(); + PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + n++; + } while(_callsstack.size()); + } + else { + //call the hook + if(raiseerror && !_ss(this)->_notifyallexceptions) + CallErrorHandler(currerror); + } + //remove call stack until a C function is found or the cstack is empty + if(ci) do { + SQBool exitafterthisone = ci->_root; + if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill(); + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break; + } while(_callsstack.size()); + + while(last_top >= _top) _stack[last_top--].Null(); + } + _lasterror = currerror; + return false; + } + assert(0); +} + +bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) +{ + inst = theclass->CreateInstance(); + if(!theclass->Get(_ss(this)->_constructoridx,constructor)) { + //if(!Call(constr,nargs,stackbase,constr,false)) + // return false; + constructor = _null_; + } + return true; +} + +void SQVM::CallErrorHandler(SQObjectPtr &error) +{ + if(type(_errorhandler) != OT_NULL) { + SQObjectPtr out; + Push(_roottable); Push(error); + Call(_errorhandler, 2, _top-2, out,SQFalse); + Pop(2); + } +} + +void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) +{ + SQObjectPtr temp_reg; + SQInteger nparams=5; + SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function); + Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); + Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse); + Pop(nparams); +} + +bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend) +{ + if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } + SQInteger nparamscheck = nclosure->_nparamscheck; + if(((nparamscheck > 0) && (nparamscheck != nargs)) + || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + + SQInteger tcs; + if((tcs = nclosure->_typecheck.size())) { + for(SQInteger i = 0; i < nargs && i < tcs; i++) + if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) { + Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i])); + return false; + } + } + _nnativecalls++; + if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) { + _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1)); + } + SQInteger oldtop = _top; + SQInteger oldstackbase = _stackbase; + _top = stackbase + nargs; + PUSH_CALLINFO(this, CallInfo()); + ci->_etraps = 0; + ci->_closure._unVal.pNativeClosure = nclosure; + ci->_closure._type = OT_NATIVECLOSURE; + ci->_prevstkbase = stackbase - _stackbase; + ci->_ncalls = 1; + _stackbase = stackbase; + //push free variables + SQInteger outers = nclosure->_outervalues.size(); + for (SQInteger i = 0; i < outers; i++) { + Push(nclosure->_outervalues[i]); + } + + if(type(nclosure->_env) == OT_WEAKREF) { + _stack[stackbase] = _weakref(nclosure->_env)->_obj; + } + + ci->_prevtop = (oldtop - oldstackbase); + SQInteger ret = (nclosure->_function)(this); + _nnativecalls--; + suspend = false; + if( ret == SQ_SUSPEND_FLAG) suspend = true; + else if (ret < 0) { + _stackbase = oldstackbase; + _top = oldtop; + POP_CALLINFO(this); + Raise_Error(_lasterror); + return false; + } + + if (ret != 0){ retval = TOP(); } + else { retval = _null_; } + _stackbase = oldstackbase; + _top = oldtop; + POP_CALLINFO(this); + return true; +} + +bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot) +{ + switch(type(self)){ + case OT_TABLE: + if(_table(self)->Get(key,dest))return true; + break; + case OT_ARRAY: + if(sq_isnumeric(key)){ + return _array(self)->Get(tointeger(key),dest); + } + break; + case OT_INSTANCE: + if(_instance(self)->Get(key,dest)) return true; + break; + default:break; //shut up compiler + } + if(FallBackGet(self,key,dest,raw)) return true; + + if(fetchroot) { + if(_rawval(STK(0)) == _rawval(self) && + type(STK(0)) == type(self)) { + return _table(_roottable)->Get(key,dest); + } + } + return false; +} + +bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw) +{ + switch(type(self)){ + case OT_CLASS: + return _class(self)->Get(key,dest); + break; + case OT_TABLE: + case OT_USERDATA: + //delegation + if(_delegable(self)->_delegate) { + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false)) + return true; + if(raw)return false; + Push(self);Push(key); + if(CallMetaMethod(_delegable(self),MT_GET,2,dest)) + return true; + } + if(type(self) == OT_TABLE) { + if(raw) return false; + return _table_ddel->Get(key,dest); + } + return false; + break; + case OT_ARRAY: + if(raw)return false; + return _array_ddel->Get(key,dest); + case OT_STRING: + if(sq_isnumeric(key)){ + SQInteger n=tointeger(key); + if(abs((int)n)<_string(self)->_len){ + if(n<0)n=_string(self)->_len-n; + dest=SQInteger(_stringval(self)[n]); + return true; + } + return false; + } + else { + if(raw)return false; + return _string_ddel->Get(key,dest); + } + break; + case OT_INSTANCE: + if(raw)return false; + Push(self);Push(key); + if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) { + return _instance_ddel->Get(key,dest); + } + return true; + case OT_INTEGER:case OT_FLOAT:case OT_BOOL: + if(raw)return false; + return _number_ddel->Get(key,dest); + case OT_GENERATOR: + if(raw)return false; + return _generator_ddel->Get(key,dest); + case OT_CLOSURE: case OT_NATIVECLOSURE: + if(raw)return false; + return _closure_ddel->Get(key,dest); + case OT_THREAD: + if(raw)return false; + return _thread_ddel->Get(key,dest); + case OT_WEAKREF: + if(raw)return false; + return _weakref_ddel->Get(key,dest); + default:return false; + } + return false; +} + +bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot) +{ + switch(type(self)){ + case OT_TABLE: + if(_table(self)->Set(key,val)) + return true; + if(_table(self)->_delegate) { + if(Set(_table(self)->_delegate,key,val,false)) { + return true; + } + } + //keeps going + case OT_USERDATA: + if(_delegable(self)->_delegate) { + SQObjectPtr t; + Push(self);Push(key);Push(val); + if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; + } + break; + case OT_INSTANCE:{ + if(_instance(self)->Set(key,val)) + return true; + SQObjectPtr t; + Push(self);Push(key);Push(val); + if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; + } + break; + case OT_ARRAY: + if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } + return _array(self)->Set(tointeger(key),val); + default: + Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); + return false; + } + if(fetchroot) { + if(_rawval(STK(0)) == _rawval(self) && + type(STK(0)) == type(self)) { + return _table(_roottable)->Set(key,val); + } + } + return false; +} + +bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) +{ + SQObjectPtr temp_reg; + SQObjectPtr newobj; + switch(type(self)){ + case OT_TABLE: + newobj = _table(self)->Clone(); + goto cloned_mt; + case OT_INSTANCE: + newobj = _instance(self)->Clone(_ss(this)); +cloned_mt: + if(_delegable(newobj)->_delegate){ + Push(newobj); + Push(self); + CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg); + } + target = newobj; + return true; + case OT_ARRAY: + target = _array(self)->Clone(); + return true; + default: return false; + } +} + +bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) +{ + if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } + switch(type(self)) { + case OT_TABLE: { + bool rawcall = true; + if(_table(self)->_delegate) { + SQObjectPtr res; + if(!_table(self)->Get(key,res)) { + Push(self);Push(key);Push(val); + rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res); + } + } + if(rawcall) _table(self)->NewSlot(key,val); //cannot fail + + break;} + case OT_CLASS: + if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { + if(_class(self)->_locked) { + Raise_Error(_SC("trying to modify a class that has already been instantiated")); + return false; + } + else { + SQObjectPtr oval = PrintObjVal(key); + Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); + return false; + } + } + break; + default: + Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); + return false; + break; + } + return true; +} + +bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) +{ + switch(type(self)) { + case OT_TABLE: + case OT_INSTANCE: + case OT_USERDATA: { + SQObjectPtr t; + bool handled = false; + if(_delegable(self)->_delegate) { + Push(self);Push(key); + handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t); + } + + if(!handled) { + if(type(self) == OT_TABLE) { + if(_table(self)->Get(key,t)) { + _table(self)->Remove(key); + } + else { + Raise_IdxError((SQObject &)key); + return false; + } + } + else { + Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); + return false; + } + } + res = t; + } + break; + default: + Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); + return false; + } + return true; +} + +bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror) +{ +#ifdef _DEBUG +SQInteger prevstackbase = _stackbase; +#endif + switch(type(closure)) { + case OT_CLOSURE: + return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); + break; + case OT_NATIVECLOSURE:{ + bool suspend; + return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend); + + } + break; + case OT_CLASS: { + SQObjectPtr constr; + SQObjectPtr temp; + CreateClassInstance(_class(closure),outres,constr); + if(type(constr) != OT_NULL) { + _stack[stackbase] = outres; + return Call(constr,nparams,stackbase,temp,raiseerror); + } + return true; + } + break; + default: + return false; + } +#ifdef _DEBUG + if(!_suspended) { + assert(_stackbase == prevstackbase); + } +#endif + return true; +} + +bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) +{ + SQObjectPtr closure; + if(del->GetMetaMethod(this, mm, closure)) { + if(Call(closure, nparams, _top - nparams, outres, SQFalse)) { + Pop(nparams); + return true; + } + } + Pop(nparams); + return false; +} + +void SQVM::Remove(SQInteger n) { + n = (n >= 0)?n + _stackbase - 1:_top + n; + for(SQInteger i = n; i < _top; i++){ + _stack[i] = _stack[i+1]; + } + _stack[_top] = _null_; + _top--; +} + +void SQVM::Pop() { + _stack[--_top] = _null_; +} + +void SQVM::Pop(SQInteger n) { + for(SQInteger i = 0; i < n; i++){ + _stack[--_top] = _null_; + } +} + +void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } +SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } +SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } +SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; } +SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } + +#ifdef _DEBUG_DUMP +void SQVM::dumpstack(SQInteger stackbase,bool dumpall) +{ + SQInteger size=dumpall?_stack.size():_top; + SQInteger n=0; + scprintf(_SC("\n>>>>stack dump<<<<\n")); + CallInfo &ci=_callsstack.back(); + scprintf(_SC("IP: %p\n"),ci._ip); + scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); + scprintf(_SC("prev top: %d\n"),ci._prevtop); + for(SQInteger i=0;i"));else scprintf(_SC(" ")); + scprintf(_SC("[%d]:"),n); + switch(type(obj)){ + case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break; + case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break; + case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break; + case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break; + case OT_NULL: scprintf(_SC("NULL")); break; + case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break; + case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break; + case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break; + case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break; + case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break; + case OT_GENERATOR: scprintf(_SC("GENERATOR"));break; + case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break; + case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break; + case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break; + case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break; + case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break; + default: + assert(0); + break; + }; + scprintf(_SC("\n")); + ++n; + } +} + + + +#endif diff --git a/src/squirrel/squirrel/sqvm.h b/src/squirrel/squirrel/sqvm.h index 569bd4329..20a9195b0 100644 --- a/src/squirrel/squirrel/sqvm.h +++ b/src/squirrel/squirrel/sqvm.h @@ -1,190 +1,190 @@ -/* see copyright notice in squirrel.h */ -#ifndef _SQVM_H_ -#define _SQVM_H_ - -#include "sqopcodes.h" -#include "sqobject.h" -#define MAX_NATIVE_CALLS 100 -#define MIN_STACK_OVERHEAD 10 - -#define SQ_SUSPEND_FLAG -666 -//base lib -void sq_base_register(HSQUIRRELVM v); - -struct SQExceptionTrap{ - SQExceptionTrap() {} - SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;} - SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; } - SQInteger _stackbase; - SQInteger _stacksize; - SQInstruction *_ip; - SQInteger _extarget; -}; - -#define _INLINE - -#define STK(a) _stack._vals[_stackbase+(a)] -#define TARGET _stack._vals[_stackbase+arg0] - -typedef sqvector ExceptionsTraps; - -struct SQVM : public CHAINABLE_OBJ -{ - struct VarArgs { - VarArgs() { size = 0; base = 0; } - SQInteger size; - SQInteger base; - }; - - struct CallInfo{ - CallInfo() { _generator._type = OT_NULL;} - //CallInfo(const CallInfo& ci) { } - SQInstructionVec *_iv; - SQObjectPtrVec *_literals; - SQObject _closure; - SQObject _generator; - SQInteger _etraps; - SQInteger _prevstkbase; - SQInteger _prevtop; - SQInteger _target; - SQInstruction *_ip; - SQInteger _ncalls; - SQBool _root; - VarArgs _vargs; - }; - -typedef sqvector CallInfoVec; -public: - enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM }; - SQVM(SQSharedState *ss); - ~SQVM(); - bool Init(SQVM *friendvm, SQInteger stacksize); - bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); - //starts a native call return when the NATIVE closure returns - bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend); - //starts a SQUIRREL call in the same "Execution loop" - bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); - bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); - //call a generic closure pure SQUIRREL or NATIVE - bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror); - SQRESULT Suspend(); - - void CallDebugHook(SQInteger type,SQInteger forcedline=0); - void CallErrorHandler(SQObjectPtr &e); - bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot); - bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw); - bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot); - bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); - bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); - bool Clone(const SQObjectPtr &self, SQObjectPtr &target); - bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); - bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); - bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res); - void ToString(const SQObjectPtr &o,SQObjectPtr &res); - SQString *PrintObjVal(const SQObject &o); - - - void Raise_Error(const SQChar *s, ...); - void Raise_Error(SQObjectPtr &desc); - void Raise_IdxError(SQObject &o); - void Raise_CompareError(const SQObject &o1, const SQObject &o2); - void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); - - void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); - bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); - bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); - bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); - //new stuff - _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); - _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); - _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); - _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); - bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); - bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci); - bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); - bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target); - //return true if the loop is finished - bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished); - bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2); - _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); - _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix); - void PopVarArgs(VarArgs &vargs); -#ifdef _DEBUG_DUMP - void dumpstack(SQInteger stackbase=-1, bool dumpall = false); -#endif - -#ifndef NO_GARBAGE_COLLECTOR - void Mark(SQCollectable **chain); -#endif - void Finalize(); - - void Release(){ sq_delete(this,SQVM); } //does nothing -//////////////////////////////////////////////////////////////////////////// - //stack functions for the api - void Remove(SQInteger n); - - bool IsFalse(SQObjectPtr &o); - - void Pop(); - void Pop(SQInteger n); - void Push(const SQObjectPtr &o); - SQObjectPtr &Top(); - SQObjectPtr &PopGet(); - SQObjectPtr &GetUp(SQInteger n); - SQObjectPtr &GetAt(SQInteger n); - - SQObjectPtrVec _stack; - SQObjectPtrVec _vargsstack; - SQInteger _top; - SQInteger _stackbase; - SQObjectPtr _roottable; - SQObjectPtr _lasterror; - SQObjectPtr _errorhandler; - SQObjectPtr _debughook; - - SQObjectPtr temp_reg; - CallInfoVec _callsstack; - ExceptionsTraps _etraps; - CallInfo *ci; - void *_foreignptr; - //VMs sharing the same state - SQSharedState *_sharedstate; - SQInteger _nnativecalls; - //suspend infos - SQBool _suspended; - SQBool _suspended_root; - SQInteger _suspended_target; - SQInteger _suspended_traps; -}; - -struct AutoDec{ - AutoDec(SQInteger *n) { _n = n; } - ~AutoDec() { (*_n)--; } - SQInteger *_n; -}; - -inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));} -const SQChar *GetTypeName(const SQObjectPtr &obj1); -const SQChar *IdType2Name(SQObjectType type); - -#define _ss(_vm_) (_vm_)->_sharedstate - -#ifndef NO_GARBAGE_COLLECTOR -#define _opt_ss(_vm_) (_vm_)->_sharedstate -#else -#define _opt_ss(_vm_) NULL -#endif - -#define PUSH_CALLINFO(v,nci){ \ - v->ci = &v->_callsstack.push_back(nci); \ -} - -#define POP_CALLINFO(v){ \ - v->_callsstack.pop_back(); \ - if(v->_callsstack.size()) \ - v->ci = &v->_callsstack.back() ; \ - else \ - v->ci = NULL; \ -} -#endif //_SQVM_H_ +/* see copyright notice in squirrel.h */ +#ifndef _SQVM_H_ +#define _SQVM_H_ + +#include "sqopcodes.h" +#include "sqobject.h" +#define MAX_NATIVE_CALLS 100 +#define MIN_STACK_OVERHEAD 10 + +#define SQ_SUSPEND_FLAG -666 +//base lib +void sq_base_register(HSQUIRRELVM v); + +struct SQExceptionTrap{ + SQExceptionTrap() {} + SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;} + SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; } + SQInteger _stackbase; + SQInteger _stacksize; + SQInstruction *_ip; + SQInteger _extarget; +}; + +#define _INLINE + +#define STK(a) _stack._vals[_stackbase+(a)] +#define TARGET _stack._vals[_stackbase+arg0] + +typedef sqvector ExceptionsTraps; + +struct SQVM : public CHAINABLE_OBJ +{ + struct VarArgs { + VarArgs() { size = 0; base = 0; } + SQInteger size; + SQInteger base; + }; + + struct CallInfo{ + CallInfo() { _generator._type = OT_NULL;} + //CallInfo(const CallInfo& ci) { } + SQInstructionVec *_iv; + SQObjectPtrVec *_literals; + SQObject _closure; + SQObject _generator; + SQInteger _etraps; + SQInteger _prevstkbase; + SQInteger _prevtop; + SQInteger _target; + SQInstruction *_ip; + SQInteger _ncalls; + SQBool _root; + VarArgs _vargs; + }; + +typedef sqvector CallInfoVec; +public: + enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM }; + SQVM(SQSharedState *ss); + ~SQVM(); + bool Init(SQVM *friendvm, SQInteger stacksize); + bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); + //starts a native call return when the NATIVE closure returns + bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend); + //starts a SQUIRREL call in the same "Execution loop" + bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); + bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); + //call a generic closure pure SQUIRREL or NATIVE + bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror); + SQRESULT Suspend(); + + void CallDebugHook(SQInteger type,SQInteger forcedline=0); + void CallErrorHandler(SQObjectPtr &e); + bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot); + bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw); + bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot); + bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); + bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); + bool Clone(const SQObjectPtr &self, SQObjectPtr &target); + bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); + bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); + bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res); + void ToString(const SQObjectPtr &o,SQObjectPtr &res); + SQString *PrintObjVal(const SQObject &o); + + + void Raise_Error(const SQChar *s, ...); + void Raise_Error(SQObjectPtr &desc); + void Raise_IdxError(SQObject &o); + void Raise_CompareError(const SQObject &o1, const SQObject &o2); + void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); + + void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); + bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); + bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); + bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); + //new stuff + _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); + _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); + bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); + bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci); + bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); + bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target); + //return true if the loop is finished + bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,bool &finished); + bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2); + _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix); + void PopVarArgs(VarArgs &vargs); +#ifdef _DEBUG_DUMP + void dumpstack(SQInteger stackbase=-1, bool dumpall = false); +#endif + +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(); + + void Release(){ sq_delete(this,SQVM); } //does nothing +//////////////////////////////////////////////////////////////////////////// + //stack functions for the api + void Remove(SQInteger n); + + bool IsFalse(SQObjectPtr &o); + + void Pop(); + void Pop(SQInteger n); + void Push(const SQObjectPtr &o); + SQObjectPtr &Top(); + SQObjectPtr &PopGet(); + SQObjectPtr &GetUp(SQInteger n); + SQObjectPtr &GetAt(SQInteger n); + + SQObjectPtrVec _stack; + SQObjectPtrVec _vargsstack; + SQInteger _top; + SQInteger _stackbase; + SQObjectPtr _roottable; + SQObjectPtr _lasterror; + SQObjectPtr _errorhandler; + SQObjectPtr _debughook; + + SQObjectPtr temp_reg; + CallInfoVec _callsstack; + ExceptionsTraps _etraps; + CallInfo *ci; + void *_foreignptr; + //VMs sharing the same state + SQSharedState *_sharedstate; + SQInteger _nnativecalls; + //suspend infos + SQBool _suspended; + SQBool _suspended_root; + SQInteger _suspended_target; + SQInteger _suspended_traps; +}; + +struct AutoDec{ + AutoDec(SQInteger *n) { _n = n; } + ~AutoDec() { (*_n)--; } + SQInteger *_n; +}; + +inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));} +const SQChar *GetTypeName(const SQObjectPtr &obj1); +const SQChar *IdType2Name(SQObjectType type); + +#define _ss(_vm_) (_vm_)->_sharedstate + +#ifndef NO_GARBAGE_COLLECTOR +#define _opt_ss(_vm_) (_vm_)->_sharedstate +#else +#define _opt_ss(_vm_) NULL +#endif + +#define PUSH_CALLINFO(v,nci){ \ + v->ci = &v->_callsstack.push_back(nci); \ +} + +#define POP_CALLINFO(v){ \ + v->_callsstack.pop_back(); \ + if(v->_callsstack.size()) \ + v->ci = &v->_callsstack.back() ; \ + else \ + v->ci = NULL; \ +} +#endif //_SQVM_H_ diff --git a/src/statistics.cpp b/src/statistics.cpp index aa215389c..5539b723f 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -105,7 +105,7 @@ Statistics::draw_worldmap_info(DrawingContext& context) char caption_buf[128]; char stat_buf[128]; - switch (display_stat) + switch (display_stat) { case 0: snprintf(caption_buf, sizeof(caption_buf), _("Max coins collected:")); @@ -121,7 +121,7 @@ Statistics::draw_worldmap_info(DrawingContext& context) int csecs = (int)(time * 100); int mins = (int)(csecs / 6000); int secs = (csecs % 6000) / 100; - snprintf(stat_buf, sizeof(stat_buf), "%02d:%02d", mins,secs); + snprintf(stat_buf, sizeof(stat_buf), "%02d:%02d", mins,secs); } break; case 3: @@ -165,30 +165,30 @@ Statistics::draw_message_info(DrawingContext& context, std::string title) int py = 450 + 18; snprintf(stat_buf, sizeof(stat_buf), "%d/%d", coins, total_coins); - context.draw_text(white_small_text, _("Max coins collected:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); - context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, _("Max coins collected:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); py+=18; snprintf(stat_buf, sizeof(stat_buf), "%d/%d", badguys, total_badguys); - context.draw_text(white_small_text, _("Max fragging:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); - context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, _("Max fragging:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); py+=18; int csecs = (int)(time * 100); int mins = (int)(csecs / 6000); int secs = (csecs % 6000) / 100; - snprintf(stat_buf, sizeof(stat_buf), "%02d:%02d", mins,secs); - context.draw_text(white_small_text, _("Min time needed:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); - context.draw_text(white_small_text, "%02d:%02d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); + snprintf(stat_buf, sizeof(stat_buf), "%02d:%02d", mins,secs); + context.draw_text(white_small_text, _("Min time needed:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, "%02d:%02d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); py+=18; - + snprintf(stat_buf, sizeof(stat_buf), "%d/%d", secrets, total_secrets); - context.draw_text(white_small_text, _("Max secrets found:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); - context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, _("Max secrets found:"), Vector(left, py), LEFT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, "%d / %d", Vector(right, py), RIGHT_ALLIGN, LAYER_GUI); py+=18; } -void +void Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, Surface* backdrop) { // skip draw if level was never played @@ -260,10 +260,10 @@ Statistics::draw_endseq_panel(DrawingContext& context, Statistics* best_stats, S void Statistics::reset() { - coins = 0; - badguys = 0; - time = 0; - secrets = 0; + coins = 0; + badguys = 0; + time = 0; + secrets = 0; } void @@ -297,4 +297,3 @@ Statistics::declare_invalid() { valid = false; } - diff --git a/src/statistics.hpp b/src/statistics.hpp index 5419f5bca..a7b194f94 100644 --- a/src/statistics.hpp +++ b/src/statistics.hpp @@ -32,7 +32,7 @@ * track of stuff like scores, and minor, but funny things, like * number of jumps and stuff */ class Statistics -{ +{ public: int coins; /**< coins collected */ int total_coins; /**< coins in level */ diff --git a/src/textscroller.cpp b/src/textscroller.cpp index b2d60bf91..972a29d5e 100644 --- a/src/textscroller.cpp +++ b/src/textscroller.cpp @@ -45,7 +45,7 @@ TextScroller::TextScroller(const std::string& filename) { defaultspeed = DEFAULT_SPEED; speed = defaultspeed; - + std::string text; std::string background_file; @@ -56,7 +56,7 @@ TextScroller::TextScroller(const std::string& filename) const lisp::Lisp* text_lisp = root->get_lisp("supertux-text"); if(!text_lisp) throw std::runtime_error("File isn't a supertux-text file"); - + if(!text_lisp->get("text", text)) throw std::runtime_error("file doesn't contain a text field"); if(!text_lisp->get("background", background_file)) @@ -104,13 +104,13 @@ TextScroller::update(float elapsed_time) if(main_controller->pressed(Controller::JUMP) || main_controller->pressed(Controller::ACTION) || main_controller->pressed(Controller::MENU_SELECT)) - scroll += SCROLL; + scroll += SCROLL; if(main_controller->pressed(Controller::PAUSE_MENU)) { main_loop->exit_screen(new FadeOut(0.5)); } scroll += speed * elapsed_time; - + if(scroll < 0) scroll = 0; } @@ -154,7 +154,9 @@ InfoBox::InfoBox(const std::string& text) InfoBox::~InfoBox() { - for(std::vector::iterator i = lines.begin(); i != lines.end(); i++) delete *i; + for(std::vector::iterator i = lines.begin(); + i != lines.end(); i++) + delete *i; delete arrow_scrollup; delete arrow_scrolldown; } @@ -219,27 +221,27 @@ InfoBoxLine::InfoBoxLine(char format_char, const std::string& text) : lineType(N { switch(format_char) { - case ' ': + case ' ': lineType = SMALL; font = white_small_text; break; - case '\t': + case '\t': lineType = NORMAL; font = white_text; break; - case '-': + case '-': lineType = HEADING; font = white_big_text; break; - case '*': + case '*': lineType = REFERENCE; font = blue_text; break; - case '#': + case '#': lineType = NORMAL_LEFT; font = white_text; break; - case '!': + case '!': lineType = IMAGE; image = new Surface(text); break; @@ -254,7 +256,7 @@ InfoBoxLine::~InfoBoxLine() delete image; } -const std::vector +const std::vector InfoBoxLine::split(const std::string& text, int line_length) { std::vector lines; @@ -285,12 +287,12 @@ InfoBoxLine::split(const std::string& text, int line_length) if (format_char == '!') { lines.push_back(new InfoBoxLine(format_char, s)); continue; - } + } // append wrapped parts of line into list std::string overflow; - do { - lines.push_back(new InfoBoxLine(format_char, Font::wrap_to_chars(s, line_length, &overflow))); + do { + lines.push_back(new InfoBoxLine(format_char, Font::wrap_to_chars(s, line_length, &overflow))); s = overflow; } while (s.length() > 0); @@ -299,7 +301,7 @@ InfoBoxLine::split(const std::string& text, int line_length) return lines; } -void +void InfoBoxLine::draw(DrawingContext& context, const Vector& position, int layer) { switch (lineType) { @@ -309,7 +311,7 @@ InfoBoxLine::draw(DrawingContext& context, const Vector& position, int layer) case NORMAL_LEFT: context.draw_text(font, text, Vector(position.x, position.y), LEFT_ALLIGN, layer); break; - default: + default: context.draw_text(font, text, Vector(SCREEN_WIDTH/2, position.y), CENTER_ALLIGN, layer); break; } @@ -323,8 +325,7 @@ InfoBoxLine::get_height() return image->get_height() + ITEMS_SPACE; case NORMAL_LEFT: return font->get_height() + ITEMS_SPACE; - default: + default: return font->get_height() + ITEMS_SPACE; } } - diff --git a/src/textscroller.hpp b/src/textscroller.hpp index b9c534c8e..ad7f39790 100644 --- a/src/textscroller.hpp +++ b/src/textscroller.hpp @@ -41,7 +41,7 @@ private: LineType lineType; Font* font; std::string text; - Surface* image; + Surface* image; public: InfoBoxLine(char format_char, const std::string& text); @@ -66,7 +66,7 @@ public: void scrollup(); void pagedown(); void pageup(); - + private: size_t firstline; std::vector lines; @@ -96,4 +96,3 @@ private: }; #endif - diff --git a/src/tile.cpp b/src/tile.cpp index c402cf454..fa0b8349d 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -59,7 +59,7 @@ Tile::parse(const lisp::Lisp& reader) if(!reader.get("id", id)) { throw std::runtime_error("Missing tile-id."); } - + bool value = false; if(reader.get("solid", value) && value) attributes |= SOLID; @@ -86,10 +86,10 @@ Tile::parse(const lisp::Lisp& reader) data |= WORLDMAP_SOUTH; if(reader.get("west", value) && value) data |= WORLDMAP_WEST; - if(reader.get("east", value) && value) + if(reader.get("east", value) && value) data |= WORLDMAP_EAST; if(reader.get("stop", value) && value) - data |= WORLDMAP_STOP; + data |= WORLDMAP_STOP; reader.get("data", data); reader.get("anim-fps", anim_fps); @@ -97,7 +97,7 @@ Tile::parse(const lisp::Lisp& reader) if(reader.get("slope-type", data)) { attributes |= SOLID | SLOPE; } - + const lisp::Lisp* images = reader.get_lisp("images"); if(images) parse_images(*images); @@ -113,7 +113,7 @@ Tile::parse_images(const lisp::Lisp& images_lisp) std::string file; cur->get(file); imagespecs.push_back(ImageSpec(file, Rect(0, 0, 0, 0))); - } else if(cur->get_type() == lisp::Lisp::TYPE_CONS && + } else if(cur->get_type() == lisp::Lisp::TYPE_CONS && cur->get_car()->get_type() == lisp::Lisp::TYPE_SYMBOL) { const lisp::Lisp* ptr = cur->get_cdr(); @@ -129,7 +129,7 @@ Tile::parse_images(const lisp::Lisp& images_lisp) log_warning << "Expected string or list in images tag" << std::endl; continue; } - + list = list->get_cdr(); } } @@ -166,4 +166,3 @@ Tile::draw(DrawingContext& context, const Vector& pos, int z_pos) const context.draw_surface(images[0], pos, z_pos); } } - diff --git a/src/tile.hpp b/src/tile.hpp index d7e3d233f..c03154f8e 100644 --- a/src/tile.hpp +++ b/src/tile.hpp @@ -38,7 +38,7 @@ class Tile public: /// bitset for tile attributes enum { - /** solid tile that is indestructable by Tux */ + /** solid tile that is indestructable by Tux */ SOLID = 0x0001, /** uni-directional solid tile */ UNISOLID = 0x0002, @@ -58,10 +58,10 @@ public: /* interesting flags (the following are passed to gameobjects) */ FIRST_INTERESTING_FLAG = 0x0100, - + /** an ice brick that makes tux sliding more than usual */ ICE = 0x0100, - /** a water tile in which tux starts to swim */ + /** a water tile in which tux starts to swim */ WATER = 0x0200, /** a tile that hurts the player if he touches it */ HURTS = 0x0400, @@ -83,7 +83,7 @@ public: WORLDMAP_CSEW = WORLDMAP_SOUTH | WORLDMAP_EAST | WORLDMAP_WEST, WORLDMAP_CNSEW = WORLDMAP_NORTH | WORLDMAP_SOUTH | WORLDMAP_EAST | WORLDMAP_WEST }; - + struct ImageSpec { ImageSpec(const std::string& newfile, const Rect& newrect) : file(newfile), rect(newrect) @@ -101,15 +101,15 @@ private: /// tile attributes uint32_t attributes; - + /** General purpose data attached to a tile (content of a box, type of coin)*/ int data; - + float anim_fps; public: ~Tile(); - + /** Draw a tile on the screen */ void draw(DrawingContext& context, const Vector& pos, int z_pos) const; @@ -124,7 +124,7 @@ public: /// returns the width of the tile in pixels int getWidth() const - { + { if(!images.size()) return 0; return (int) images[0]->get_width(); diff --git a/src/tile_manager.cpp b/src/tile_manager.cpp index 309311e3e..bbc3cffe7 100644 --- a/src/tile_manager.cpp +++ b/src/tile_manager.cpp @@ -67,7 +67,7 @@ void TileManager::load_tileset(std::string filename) } else { tiles_path = filename.substr(0, t+1); } - + lisp::Parser parser; std::auto_ptr root (parser.parse(filename)); @@ -101,7 +101,7 @@ void TileManager::load_tileset(std::string filename) std::string image; // width and height of the image in tile units, this is used for two - // purposes: + // purposes: // a) so we don't have to load the image here to know its dimensions // b) so that the resulting 'tiles' entry is more robust, // ie. enlarging the image won't break the tile id mapping @@ -137,7 +137,7 @@ void TileManager::load_tileset(std::string filename) tiles[ids[i]] = tile; } } - + } else if(iter.item() == "properties") { // deprecated } else { @@ -145,4 +145,3 @@ void TileManager::load_tileset(std::string filename) } } } - diff --git a/src/tile_manager.hpp b/src/tile_manager.hpp index 319b81910..64906cf09 100644 --- a/src/tile_manager.hpp +++ b/src/tile_manager.hpp @@ -53,7 +53,7 @@ private: std::set tilegroups; std::string tiles_path; - + void load_tileset(std::string filename); public: @@ -77,7 +77,7 @@ public: if(tile->images.size() == 0 && tile->imagespecs.size() != 0) tile->load_images(tiles_path); - + return tile; } diff --git a/src/timer.cpp b/src/timer.cpp index 105ce7520..9c94f581c 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -47,7 +47,7 @@ Timer::check() { if(period == 0) return false; - + if(game_time - cycle_start >= period) { if(cyclic) { cycle_start = game_time - fmodf(game_time - cycle_start, period); @@ -59,4 +59,3 @@ Timer::check() return false; } - diff --git a/src/timer.hpp b/src/timer.hpp index 903ffa8e4..8dd9400f9 100644 --- a/src/timer.hpp +++ b/src/timer.hpp @@ -62,4 +62,3 @@ private: }; #endif - diff --git a/src/tinygettext/findlocale.cpp b/src/tinygettext/findlocale.cpp index 04d1fb4b8..e7deb55b2 100644 --- a/src/tinygettext/findlocale.cpp +++ b/src/tinygettext/findlocale.cpp @@ -1,6 +1,6 @@ /* findlocale-0.46.tar.gz from http://icculus.org/~aspirin/findlocale/ - + Copyright (C) 2004 Adam D. Moss (the "Author"). All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/tinygettext/tinygettext.cpp b/src/tinygettext/tinygettext.cpp index d51f62738..a9bb9641f 100644 --- a/src/tinygettext/tinygettext.cpp +++ b/src/tinygettext/tinygettext.cpp @@ -45,7 +45,7 @@ std::string convert(const std::string& text, 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 @@ -174,7 +174,7 @@ get_language_def(const std::string& name) 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; + else return lang_en; } DictionaryManager::DictionaryManager() @@ -186,7 +186,7 @@ DictionaryManager::DictionaryManager() if( lang ){ set_language( lang ); return; - } + } // use findlocale to setup language FL_Locale *locale; FL_FindLocale( &locale, FL_MESSAGES ); @@ -200,18 +200,18 @@ 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; @@ -230,7 +230,7 @@ DictionaryManager::parseLocaleAliases() set_language_alias(alias, language); } } - + Dictionary& DictionaryManager::get_dictionary(const std::string& spec) { @@ -252,7 +252,7 @@ DictionaryManager::get_dictionary(const std::string& spec) for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p) { char** files = PHYSFS_enumerateFiles(p->c_str()); - if(!files) + if(!files) { log_warning << "Error: enumerateFiles() failed on " << *p << std::endl; } @@ -301,7 +301,7 @@ DictionaryManager::get_languages() } PHYSFS_freeList(files); } - } + } return languages; } @@ -341,12 +341,12 @@ DictionaryManager::get_language_from_spec(const std::string& spec) 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); + return std::string(lang, 0, s); } void @@ -388,7 +388,7 @@ Dictionary::set_language(const LanguageDef& lang) } std::string -Dictionary::translate(const std::string& msgid, const std::string& msgid2, int num) +Dictionary::translate(const std::string& msgid, const std::string& msgid2, int num) { PluralEntries::iterator i = plural_entries.find(msgid); std::map& msgstrs = i->second; @@ -441,7 +441,7 @@ Dictionary::translate(const char* msgid) } std::string -Dictionary::translate(const std::string& msgid) +Dictionary::translate(const std::string& msgid) { Entries::iterator i = entries.find(msgid); if (i != entries.end() && !i->second.empty()) @@ -456,7 +456,7 @@ Dictionary::translate(const std::string& msgid) return msgid; } } - + void Dictionary::add_translation(const std::string& msgid, const std::string& , const std::map& msgstrs) @@ -466,8 +466,8 @@ Dictionary::add_translation(const std::string& msgid, const std::string& , plural_entries[msgid] = msgstrs; } -void -Dictionary::add_translation(const std::string& msgid, const std::string& msgstr) +void +Dictionary::add_translation(const std::string& msgid, const std::string& msgstr) { entries[msgid] = msgstr; } @@ -515,7 +515,7 @@ public: // Seperate the header in lines typedef std::vector Lines; Lines lines; - + std::string::size_type start = 0; for(std::string::size_type i = 0; i < header.length(); ++i) { @@ -549,10 +549,10 @@ public: void add_token(const Token& token) { - switch(state) + switch(state) { case WANT_MSGID: - if (token.keyword == "msgid") + if (token.keyword == "msgid") { current_msgid = token.content; state = WANT_MSGID_PLURAL; @@ -566,13 +566,13 @@ public: log_warning << "tinygettext: expected 'msgid' keyword, got " << token.keyword << " at line " << line_num << std::endl; } break; - + case WANT_MSGID_PLURAL: - if (token.keyword == "msgid_plural") + if (token.keyword == "msgid_plural") { current_msgid_plural = token.content; state = WANT_MSGSTR_PLURAL; - } + } else { state = WANT_MSGSTR; @@ -581,9 +581,9 @@ public: break; case WANT_MSGSTR: - if (token.keyword == "msgstr") + if (token.keyword == "msgstr") { - if (current_msgid == "") + if (current_msgid == "") { // .po Header is hidden in the msgid with the empty string parse_header(token.content); } @@ -592,7 +592,7 @@ public: dict.add_translation(current_msgid, convert(token.content, from_charset, to_charset)); } state = WANT_MSGID; - } + } else { log_warning << "tinygettext: expected 'msgstr' keyword, got " << token.keyword << " at line " << line_num << std::endl; @@ -600,19 +600,19 @@ public: break; case WANT_MSGSTR_PLURAL: - if (has_prefix(token.keyword, "msgstr[")) + if (has_prefix(token.keyword, "msgstr[")) { int num; - if (sscanf(token.keyword.c_str(), "msgstr[%d]", &num) != 1) + if (sscanf(token.keyword.c_str(), "msgstr[%d]", &num) != 1) { log_warning << "Error: Couldn't parse: " << token.keyword << std::endl; - } - else + } + else { msgstr_plural[num] = convert(token.content, from_charset, to_charset); } } - else + else { dict.add_translation(current_msgid, current_msgid_plural, msgstr_plural); @@ -622,18 +622,18 @@ public: break; } } - - inline int getchar(std::istream& in) + + 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, + enum State { READ_KEYWORD, READ_CONTENT, READ_CONTENT_IN_STRING, SKIP_COMMENT }; @@ -656,8 +656,8 @@ public: { // Read a new token token = Token(); - - do { // Read keyword + + do { // Read keyword token.keyword += c; } while((c = getchar(in)) != EOF && !isspace(c)); in.unget(); @@ -669,7 +669,7 @@ public: case READ_CONTENT: while((c = getchar(in)) != EOF) { - if (c == '"') { + if (c == '"') { // Found start of content state = READ_CONTENT_IN_STRING; break; @@ -719,7 +719,7 @@ public: } }; -void read_po_file(Dictionary& dict_, std::istream& in) +void read_po_file(Dictionary& dict_, std::istream& in) { POFileReader reader(in, dict_); } diff --git a/src/tinygettext/tinygettext.hpp b/src/tinygettext/tinygettext.hpp index ca731b9ac..fe0dff0b8 100644 --- a/src/tinygettext/tinygettext.hpp +++ b/src/tinygettext/tinygettext.hpp @@ -81,7 +81,7 @@ public: std::string translate(const std::string& msgid); /** Translate the string \a msgid. */ const char* translate(const char* 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 @@ -137,7 +137,7 @@ public: /** 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 get_languages(); diff --git a/src/title.cpp b/src/title.cpp index 395836a90..4b4d62ac8 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -102,7 +102,7 @@ void TitleScreen::generate_contrib_menu() { /** Generating contrib levels list by making use of Level Subset */ - std::vector level_worlds; + std::vector level_worlds; char** files = PHYSFS_enumerateFiles("levels/"); for(const char* const* filename = files; *filename != 0; ++filename) { std::string filepath = std::string("levels/") + *filename; @@ -116,7 +116,7 @@ TitleScreen::generate_contrib_menu() contrib_menu->add_label(_("Contrib Levels")); contrib_menu->add_hl(); - + int i = 0; for (std::vector::iterator it = level_worlds.begin(); it != level_worlds.end(); ++it) { @@ -203,7 +203,7 @@ TitleScreen::check_contrib_world_menu() new GameSession(current_world->get_level_filename(index)); main_loop->push_screen(session); } - } + } } void @@ -223,17 +223,17 @@ TitleScreen::make_tux_jump() controller->press(Controller::RIGHT); // Determine how far we moved since last frame - float dx = fabsf(last_tux_x_pos - tux->get_pos().x); - float dy = fabsf(last_tux_y_pos - tux->get_pos().y); - - // Calculate space to check for obstacles + float dx = fabsf(last_tux_x_pos - tux->get_pos().x); + float dy = fabsf(last_tux_y_pos - tux->get_pos().y); + + // Calculate space to check for obstacles Rect lookahead = tux->get_bbox(); lookahead.move(Vector(96, 0)); - + // Check if we should press the jump button bool randomJump = !randomWaitTimer.started(); bool notMoving = (fabsf(dx) + fabsf(dy)) < 0.1; - bool pathBlocked = !sector->is_free_space(lookahead); + bool pathBlocked = !sector->is_free_space(lookahead); if (!controller->released(Controller::JUMP) && (notMoving || pathBlocked || randomJump)) { float jumpDuration; @@ -308,7 +308,7 @@ TitleScreen::draw(DrawingContext& context) { Sector* sector = titlesession->get_current_sector(); sector->draw(context); - + context.draw_text(white_small_text, " SuperTux " PACKAGE_VERSION "\n", Vector(0, SCREEN_HEIGHT - 50), LEFT_ALLIGN, LAYER_FOREGROUND1); context.draw_text(white_small_text, @@ -329,11 +329,11 @@ TitleScreen::update(float elapsed_time) sector->update(elapsed_time); make_tux_jump(); - + Menu* menu = Menu::current(); if(menu) { menu->update(); - + if(menu == main_menu.get()) { switch (main_menu->check()) { case MNID_STARTGAME: @@ -366,7 +366,7 @@ TitleScreen::update(float elapsed_time) std::stringstream stream; stream << slot; std::string str = _("Are you sure you want to delete slot") + stream.str() + "?"; - + if(confirm_dialog(bkg_title, str.c_str())) { str = "save/slot" + stream.str() + ".stsg"; log_debug << "Removing: " << str << std::endl; @@ -451,4 +451,3 @@ TitleScreen::process_load_game_menu() return true; } - diff --git a/src/title.hpp b/src/title.hpp index 746bce7ae..39d0abf08 100644 --- a/src/title.hpp +++ b/src/title.hpp @@ -61,10 +61,9 @@ private: std::auto_ptr main_world; std::vector contrib_worlds; World* current_world; - + std::auto_ptr controller; std::auto_ptr titlesession; }; #endif - diff --git a/src/trigger/door.cpp b/src/trigger/door.cpp index bd38c1b98..f8d2b7286 100644 --- a/src/trigger/door.cpp +++ b/src/trigger/door.cpp @@ -40,7 +40,7 @@ Door::Door(const lisp::Lisp& reader) sprite = sprite_manager->create("images/objects/door/door.sprite"); sprite->set_action("closed"); - bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); + bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); } Door::Door(int x, int y, std::string sector, std::string spawnpoint) @@ -52,7 +52,7 @@ Door::Door(int x, int y, std::string sector, std::string spawnpoint) sprite = sprite_manager->create("images/objects/door/door.sprite"); sprite->set_action("closed"); - bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); + bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height()); } Door::~Door() @@ -69,7 +69,7 @@ Door::write(lisp::Writer& writer) writer.write_float("y", bbox.p1.y); writer.write_float("width", bbox.get_width()); writer.write_float("height", bbox.get_height()); - + writer.write_string("sector", target_sector); writer.write_string("spawnpoint", target_spawnpoint); sound_manager->preload("sounds/door.wav"); diff --git a/src/trigger/door.hpp b/src/trigger/door.hpp index 9186129c7..925edd642 100644 --- a/src/trigger/door.hpp +++ b/src/trigger/door.hpp @@ -37,12 +37,12 @@ public: virtual ~Door(); virtual void write(lisp::Writer& writer); - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); virtual void event(Player& player, EventType type); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); - + private: enum DoorState { CLOSED, diff --git a/src/trigger/scripttrigger.cpp b/src/trigger/scripttrigger.cpp index cc330a237..afac8aeb9 100644 --- a/src/trigger/scripttrigger.cpp +++ b/src/trigger/scripttrigger.cpp @@ -1,93 +1,92 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2006 Matthias Braun -// -// 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 - -#include -#include -#include - -#include "scripttrigger.hpp" -#include "game_session.hpp" -#include "lisp/lisp.hpp" -#include "lisp/writer.hpp" -#include "object_factory.hpp" -#include "sector.hpp" - -ScriptTrigger::ScriptTrigger(const lisp::Lisp& reader) -{ - bool must_activate = false; - - reader.get("x", bbox.p1.x); - reader.get("y", bbox.p1.y); - float w = 0, h = 0; - reader.get("width", w); - reader.get("height", h); - bbox.set_size(w, h); - reader.get("script", script); - reader.get("button", must_activate); - if(script == "") { - throw std::runtime_error("Need to specify a script for trigger object"); - } - - if (must_activate) - triggerevent = EVENT_ACTIVATE; - else - triggerevent = EVENT_TOUCH; -} - -ScriptTrigger::ScriptTrigger(const Vector& pos, const std::string& script) -{ - bbox.set_pos(pos); - bbox.set_size(32, 32); - this->script = script; - triggerevent = EVENT_TOUCH; -} - -ScriptTrigger::~ScriptTrigger() -{ -} - -void -ScriptTrigger::write(lisp::Writer& writer) -{ - writer.start_list("scripttrigger"); - - writer.write_float("x", bbox.p1.x); - writer.write_float("y", bbox.p1.y); - writer.write_float("width", bbox.get_width()); - writer.write_float("height", bbox.get_height()); - writer.write_string("script", script); - writer.write_bool("button", (triggerevent == EVENT_ACTIVATE) ? true : false); - - writer.end_list("scripttrigger"); -} - -void -ScriptTrigger::event(Player& , EventType type) -{ - if(type != triggerevent) - return; - - std::istringstream stream(script); - Sector::current()->run_script(stream, "ScriptTrigger"); -} - -IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger"); - +// $Id$ +// +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 + +#include +#include +#include + +#include "scripttrigger.hpp" +#include "game_session.hpp" +#include "lisp/lisp.hpp" +#include "lisp/writer.hpp" +#include "object_factory.hpp" +#include "sector.hpp" + +ScriptTrigger::ScriptTrigger(const lisp::Lisp& reader) +{ + bool must_activate = false; + + reader.get("x", bbox.p1.x); + reader.get("y", bbox.p1.y); + float w = 0, h = 0; + reader.get("width", w); + reader.get("height", h); + bbox.set_size(w, h); + reader.get("script", script); + reader.get("button", must_activate); + if(script == "") { + throw std::runtime_error("Need to specify a script for trigger object"); + } + + if (must_activate) + triggerevent = EVENT_ACTIVATE; + else + triggerevent = EVENT_TOUCH; +} + +ScriptTrigger::ScriptTrigger(const Vector& pos, const std::string& script) +{ + bbox.set_pos(pos); + bbox.set_size(32, 32); + this->script = script; + triggerevent = EVENT_TOUCH; +} + +ScriptTrigger::~ScriptTrigger() +{ +} + +void +ScriptTrigger::write(lisp::Writer& writer) +{ + writer.start_list("scripttrigger"); + + writer.write_float("x", bbox.p1.x); + writer.write_float("y", bbox.p1.y); + writer.write_float("width", bbox.get_width()); + writer.write_float("height", bbox.get_height()); + writer.write_string("script", script); + writer.write_bool("button", (triggerevent == EVENT_ACTIVATE) ? true : false); + + writer.end_list("scripttrigger"); +} + +void +ScriptTrigger::event(Player& , EventType type) +{ + if(type != triggerevent) + return; + + std::istringstream stream(script); + Sector::current()->run_script(stream, "ScriptTrigger"); +} + +IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger"); diff --git a/src/trigger/scripttrigger.hpp b/src/trigger/scripttrigger.hpp index edf03946e..739473448 100644 --- a/src/trigger/scripttrigger.hpp +++ b/src/trigger/scripttrigger.hpp @@ -29,10 +29,10 @@ public: ScriptTrigger(const lisp::Lisp& reader); ScriptTrigger(const Vector& pos, const std::string& script); ~ScriptTrigger(); - + void write(lisp::Writer& writer); void event(Player& player, EventType type); - + private: EventType triggerevent; std::string script; diff --git a/src/trigger/secretarea_trigger.hpp b/src/trigger/secretarea_trigger.hpp index 993f1f436..da8423fea 100644 --- a/src/trigger/secretarea_trigger.hpp +++ b/src/trigger/secretarea_trigger.hpp @@ -32,15 +32,14 @@ public: SecretAreaTrigger(const lisp::Lisp& reader); SecretAreaTrigger(const Rect& area); ~SecretAreaTrigger(); - + void write(lisp::Writer& writer); void event(Player& player, EventType type); void draw(DrawingContext& context); - + private: Timer message_timer; bool message_displayed; }; #endif - diff --git a/src/trigger/sequence_trigger.hpp b/src/trigger/sequence_trigger.hpp index 46f18c256..5b8c02205 100644 --- a/src/trigger/sequence_trigger.hpp +++ b/src/trigger/sequence_trigger.hpp @@ -30,14 +30,13 @@ public: SequenceTrigger(const lisp::Lisp& reader); SequenceTrigger(const Vector& pos, const std::string& sequence); ~SequenceTrigger(); - + void write(lisp::Writer& writer); void event(Player& player, EventType type); - + private: EventType triggerevent; std::string sequence_name; }; #endif - diff --git a/src/trigger/switch.cpp b/src/trigger/switch.cpp index e11a5b68b..49205fb25 100644 --- a/src/trigger/switch.cpp +++ b/src/trigger/switch.cpp @@ -111,4 +111,3 @@ Switch::event(Player& , EventType type) } IMPLEMENT_FACTORY(Switch, "switch"); - diff --git a/src/trigger/switch.hpp b/src/trigger/switch.hpp index d7e68952b..8742f804a 100644 --- a/src/trigger/switch.hpp +++ b/src/trigger/switch.hpp @@ -36,7 +36,7 @@ public: virtual ~Switch(); virtual void write(lisp::Writer& writer); - + virtual void update(float elapsed_time); virtual void draw(DrawingContext& context); virtual void event(Player& player, EventType type); @@ -52,7 +52,7 @@ private: std::string sprite_name; Sprite* sprite; std::string script; - + SwitchState state; }; diff --git a/src/trigger/trigger_base.cpp b/src/trigger/trigger_base.cpp index d60e14ea7..480cd90eb 100644 --- a/src/trigger/trigger_base.cpp +++ b/src/trigger/trigger_base.cpp @@ -61,4 +61,3 @@ TriggerBase::collision(GameObject& other, const CollisionHit& ) return ABORT_MOVE; } - diff --git a/src/trigger/trigger_base.hpp b/src/trigger/trigger_base.hpp index f4c47955d..887f413a5 100644 --- a/src/trigger/trigger_base.hpp +++ b/src/trigger/trigger_base.hpp @@ -35,14 +35,14 @@ public: enum EventType { EVENT_TOUCH, EVENT_ACTIVATE }; - + TriggerBase(); ~TriggerBase(); void update(float elapsed_time); void draw(DrawingContext& context); HitResponse collision(GameObject& other, const CollisionHit& hit); - + /** * Receive trigger events */ @@ -55,4 +55,3 @@ private: }; #endif /*SUPERTUX_INTERACTIVE_OBJECT_H*/ - diff --git a/src/video/color.hpp b/src/video/color.hpp index dc912f735..1178fabe9 100644 --- a/src/video/color.hpp +++ b/src/video/color.hpp @@ -62,4 +62,3 @@ public: }; #endif - diff --git a/src/video/drawing_context.cpp b/src/video/drawing_context.cpp index 1214c20a6..7bb36e41b 100644 --- a/src/video/drawing_context.cpp +++ b/src/video/drawing_context.cpp @@ -41,7 +41,7 @@ static inline int next_po2(int val) int result = 1; while(result < val) result *= 2; - + return result; } @@ -70,19 +70,19 @@ DrawingContext::~DrawingContext() } void -DrawingContext::draw_surface(const Surface* surface, const Vector& position, +DrawingContext::draw_surface(const Surface* surface, const Vector& position, float angle, const Color& color, const Blend& blend, int layer) { assert(surface != 0); - + DrawingRequest request; request.type = SURFACE; request.pos = transform.apply(position); if(request.pos.x >= SCREEN_WIDTH || request.pos.y >= SCREEN_HEIGHT - || request.pos.x + surface->get_width() < 0 + || request.pos.x + surface->get_width() < 0 || request.pos.y + surface->get_height() < 0) return; @@ -93,13 +93,13 @@ DrawingContext::draw_surface(const Surface* surface, const Vector& position, request.color = color; request.blend = blend; - request.request_data = const_cast (surface); + request.request_data = const_cast (surface); requests->push_back(request); } void -DrawingContext::draw_surface(const Surface* surface, const Vector& position, +DrawingContext::draw_surface(const Surface* surface, const Vector& position, int layer) { draw_surface(surface, position, 0.0f, Color(1.0f, 1.0f, 1.0f), Blend(), layer); @@ -118,7 +118,7 @@ DrawingContext::draw_surface_part(const Surface* surface, const Vector& source, request.layer = layer; request.drawing_effect = transform.drawing_effect; request.alpha = transform.alpha; - + SurfacePartRequest* surfacepartrequest = new SurfacePartRequest(); surfacepartrequest->size = size; surfacepartrequest->source = source; @@ -204,7 +204,7 @@ DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size, request.layer = layer; request.drawing_effect = transform.drawing_effect; - request.alpha = transform.alpha; + request.alpha = transform.alpha; FillRectRequest* fillrectrequest = new FillRectRequest; fillrectrequest->size = size; @@ -226,7 +226,7 @@ DrawingContext::draw_filled_rect(const Rect& rect, const Color& color, request.layer = layer; request.drawing_effect = transform.drawing_effect; - request.alpha = transform.alpha; + request.alpha = transform.alpha; FillRectRequest* fillrectrequest = new FillRectRequest; fillrectrequest->size = Vector(rect.get_width(), rect.get_height()); @@ -258,7 +258,7 @@ DrawingContext::draw_gradient(DrawingRequest& request) GradientRequest* gradientrequest = (GradientRequest*) request.request_data; const Color& top = gradientrequest->top; const Color& bottom = gradientrequest->bottom; - + glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glColor4f(top.red, top.green, top.blue, top.alpha); @@ -297,7 +297,7 @@ DrawingContext::draw_filled_rect(DrawingRequest& request) glDisable(GL_TEXTURE_2D); glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, fillrectrequest->color.blue, fillrectrequest->color.alpha); - + glBegin(GL_QUADS); glVertex2f(x, y); glVertex2f(x+w, y); @@ -320,12 +320,12 @@ DrawingContext::do_drawing() target_stack.clear(); bool use_lightmap = lightmap_requests.size() != 0; - + // PART1: create lightmap if(use_lightmap) { glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height); glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + glLoadIdentity(); glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -335,16 +335,16 @@ DrawingContext::do_drawing() glClear(GL_COLOR_BUFFER_BIT); handle_drawing_requests(lightmap_requests); lightmap_requests.clear(); - + glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, lightmap->get_handle()); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height); glViewport(0, 0, screen->w, screen->h); glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + glLoadIdentity(); glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_BLEND); } @@ -356,7 +356,7 @@ DrawingContext::do_drawing() if(use_lightmap) { // multiple the lightmap with the framebuffer glBlendFunc(GL_DST_COLOR, GL_ZERO); - + glBindTexture(GL_TEXTURE_2D, lightmap->get_handle()); glBegin(GL_QUADS); @@ -371,7 +371,7 @@ DrawingContext::do_drawing() glTexCoord2f(0, 0); glVertex2f(0, SCREEN_HEIGHT); - + glEnd(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -386,7 +386,7 @@ void DrawingContext::handle_drawing_requests(DrawingRequests& requests) { std::stable_sort(requests.begin(), requests.end()); - + for(DrawingRequests::iterator i = requests.begin(); i != requests.end(); ++i) { switch(i->type) { @@ -476,4 +476,3 @@ DrawingContext::set_target(Target target) else requests = &drawing_requests; } - diff --git a/src/video/drawing_context.hpp b/src/video/drawing_context.hpp index a8c7e5680..df312256d 100644 --- a/src/video/drawing_context.hpp +++ b/src/video/drawing_context.hpp @@ -57,7 +57,7 @@ class Blend public: GLenum sfactor; GLenum dfactor; - + Blend() : sfactor(GL_SRC_ALPHA), dfactor(GL_ONE_MINUS_SRC_ALPHA) {} @@ -78,10 +78,10 @@ public: ~DrawingContext(); /// Adds a drawing request for a surface into the request list. - void draw_surface(const Surface* surface, const Vector& position, + void draw_surface(const Surface* surface, const Vector& position, int layer); /// Adds a drawing request for a surface into the request list. - void draw_surface(const Surface* surface, const Vector& position, + void draw_surface(const Surface* surface, const Vector& position, float angle, const Color& color, const Blend& blend, int layer); /// Adds a drawing request for part of a surface. @@ -90,7 +90,7 @@ public: /// Draws a text. void draw_text(const Font* font, const std::string& text, const Vector& position, FontAlignment alignment, int layer); - + /// Draws text on screen center (feed Vector.x with a 0). /// This is the same as draw_text() with a SCREEN_WIDTH/2 position and /// alignment set to LEFT_ALLIGN @@ -102,19 +102,19 @@ public: void draw_filled_rect(const Vector& topleft, const Vector& size, const Color& color, int layer); void draw_filled_rect(const Rect& rect, const Color& color, int layer); - + /// Processes all pending drawing requests and flushes the list. void do_drawing(); - + const Vector& get_translation() const { return transform.translation; } - + void set_translation(const Vector& newtranslation) { transform.translation = newtranslation; } - + void push_transform(); void pop_transform(); - + /// Apply that effect in the next draws (effects are listed on surface.h). void set_drawing_effect(DrawingEffect effect); /// return currently applied drawing effect @@ -130,7 +130,7 @@ public: void push_target(); void pop_target(); void set_target(Target target); - + private: class Transform { @@ -138,17 +138,17 @@ private: Vector translation; DrawingEffect drawing_effect; float alpha; - + Transform() : drawing_effect(NO_EFFECT), alpha(1.0f) { } - + Vector apply(const Vector& v) const { return v - translation; } }; - + /// the transform stack std::vector transformstack; /// the currently active transform @@ -156,42 +156,42 @@ private: std::vector blend_stack; Blend blend_mode; - + enum RequestType { SURFACE, SURFACE_PART, TEXT, GRADIENT, FILLRECT }; - + struct SurfacePartRequest { const Surface* surface; Vector source, size; }; - + struct TextRequest { const Font* font; std::string text; FontAlignment alignment; }; - + struct GradientRequest { Color top, bottom; Vector size; }; - + struct FillRectRequest { Color color; Vector size; }; - + struct DrawingRequest { RequestType type; - Vector pos; - + Vector pos; + int layer; DrawingEffect drawing_effect; float alpha; @@ -205,7 +205,7 @@ private: : angle(0.0f), color(1.0f, 1.0f, 1.0f, 1.0f) {} - + bool operator<(const DrawingRequest& other) const { return layer < other.layer; @@ -213,14 +213,14 @@ private: }; typedef std::vector DrawingRequests; - + void handle_drawing_requests(DrawingRequests& requests); void draw_surface_part(DrawingRequest& request); void draw_text(DrawingRequest& request); void draw_text_center(DrawingRequest& request); void draw_gradient(DrawingRequest& request); void draw_filled_rect(DrawingRequest& request); - + DrawingRequests drawing_requests; DrawingRequests lightmap_requests; diff --git a/src/video/font.cpp b/src/video/font.cpp index 5e844df00..c61ee431e 100644 --- a/src/video/font.cpp +++ b/src/video/font.cpp @@ -36,7 +36,7 @@ Font::Font(const std::string& file, const std::string& shadowfile, { chars = new Surface(file); shadow_chars = new Surface(shadowfile); - + first_char = 32; char_count = ((int) chars->get_height() / h) * 16; } @@ -145,9 +145,9 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment, if(l > sizeof(temp)-1) l = sizeof(temp)-1; - + temp[text.copy(temp, l - i, i)] = '\0'; - + // calculate X positions based on the alignment type Vector pos = Vector(pos_); if(alignment == CENTER_ALLIGN) @@ -163,7 +163,7 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment, } void -Font::draw_text(const std::string& text, const Vector& pos, +Font::draw_text(const std::string& text, const Vector& pos, DrawingEffect drawing_effect, float alpha) const { if(shadowsize > 0) @@ -182,7 +182,7 @@ bool has_multibyte_mark(unsigned char c) { return ((c & 0300) == 0200); } -/** +/** * gets unicode character at byte position @a p of UTF-8 encoded @a text, then advances @a p to the next character. * @throws std::runtime_error if decoding fails. * See unicode standard section 3.10 table 3-5 and 3-6 for details. @@ -197,7 +197,7 @@ uint32_t decode_utf8(const std::string& text, size_t& p) // 0xxx.xxxx: 1 byte sequence p+=1; return c1; - } + } else if ((c1 & 0340) == 0300) { // 110x.xxxx: 2 byte sequence if(p+1 >= text.size()) throw std::range_error("Malformed utf-8 sequence"); @@ -243,7 +243,7 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos, uint32_t c; try { c = decode_utf8(text, i); - } + } catch (std::runtime_error) { log_debug << "Malformed utf-8 sequence beginning with " << *((uint32_t*)(text.c_str() + i)) << " found " << std::endl; c = 0; @@ -252,7 +252,7 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos, ssize_t font_index; // a non-printable character? - if(c == '\n') { + if(c == '\n') { p.x = pos.x; p.y += h + 2; continue; @@ -271,11 +271,11 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos, font_index = 0; } } - + if(font_index < 0 || font_index >= (ssize_t) char_count) { log_debug << "Unsupported utf-8 character found" << std::endl; font_index = 0; - } + } int source_x = (font_index % 16) * w; int source_y = (font_index / 16) * h; diff --git a/src/video/font.hpp b/src/video/font.hpp index c39df1aaa..fffcc1fa4 100644 --- a/src/video/font.hpp +++ b/src/video/font.hpp @@ -38,14 +38,14 @@ public: Font(const std::string& file, const std::string& shadowfile, int w, int h, int shadowsize = 2); ~Font(); - + /** returns the width of a given text. (Note that I won't add a normal * get_width function here, as we might switch to variable width fonts in the * future.) * Supports breaklines. */ float get_text_width(const std::string& text) const; - + /** returns the height of a given text. This function supports breaklines. * In case, you are positive that your text doesn't use break lines, you can * just use get_height(). @@ -53,7 +53,7 @@ public: float get_text_height(const std::string& text) const; /// returns the height of the font. float get_height() const; - + /** * returns the given string, truncated (preferrably at whitespace) to be at most max_width pixels long */ @@ -63,31 +63,31 @@ public: * returns the given string, truncated (preferrably at whitespace) to be at most max_chars characters long */ static std::string wrap_to_chars(const std::string& text, int max_chars, std::string* overflow); - + /** Draws the given text to the screen. Also needs the position. * Type of alignment, drawing effect and alpha are optional. */ void draw(const std::string& text, const Vector& pos, FontAlignment allignment = LEFT_ALLIGN, DrawingEffect drawing_effect = NO_EFFECT, float alpha = 1.0f) const; - + private: friend class DrawingContext; - + void draw_text(const std::string& text, const Vector& pos, DrawingEffect drawing_effect = NO_EFFECT, float alpha = 1.0f) const; - + void draw_chars(Surface* pchars, const std::string& text, const Vector& position, DrawingEffect drawing_effect, float alpha) const; - + Surface* chars; Surface* shadow_chars; int w; int h; int shadowsize; - + /// the number of the first character that is represented in the font uint32_t first_char; /// the number of the last character that is represented in the font diff --git a/src/video/glutil.hpp b/src/video/glutil.hpp index 0ccb63006..6c2122fe0 100644 --- a/src/video/glutil.hpp +++ b/src/video/glutil.hpp @@ -56,11 +56,11 @@ static inline void check_gl_error(const char* message) case GL_TABLE_TOO_LARGE: msg << "TABLE_TOO_LARGE: table is too large"; break; -#endif +#endif default: msg << "Unknown error (code " << error << ")"; } - + throw std::runtime_error(msg.str()); } #endif diff --git a/src/video/image_texture.hpp b/src/video/image_texture.hpp index ef8019c06..dccc9bfcc 100644 --- a/src/video/image_texture.hpp +++ b/src/video/image_texture.hpp @@ -42,12 +42,12 @@ public: { return image_height; } - + float get_uv_right() const { return image_width / static_cast (get_width()); } - + float get_uv_bottom() const { return image_height / static_cast (get_height()); @@ -68,7 +68,7 @@ public: private: friend class TextureManager; - + ImageTexture(SDL_Surface* surface); virtual ~ImageTexture(); @@ -76,4 +76,3 @@ private: }; #endif - diff --git a/src/video/surface.cpp b/src/video/surface.cpp index ff89f8c6f..23ff69389 100644 --- a/src/video/surface.cpp +++ b/src/video/surface.cpp @@ -116,11 +116,11 @@ static inline void intern_draw(float left, float top, float right, float bottom, if(effect & VERTICAL_FLIP) { std::swap(uv_top, uv_bottom); } - + glBegin(GL_QUADS); glTexCoord2f(uv_left, uv_top); glVertex2f(left, top); - + glTexCoord2f(uv_right, uv_top); glVertex2f(right, top); @@ -145,10 +145,10 @@ static inline void intern_draw2(float left, float top, float right, float bottom if(effect & VERTICAL_FLIP) { std::swap(uv_top, uv_bottom); } - + float center_x = (left + right) / 2; float center_y = (top + bottom) / 2; - + float sa = sinf(angle/180.0f*M_PI); float ca = cosf(angle/180.0f*M_PI); @@ -164,7 +164,7 @@ static inline void intern_draw2(float left, float top, float right, float bottom glTexCoord2f(uv_left, uv_top); glVertex2f(left*ca - top*sa + center_x, left*sa + top*ca + center_y); - + glTexCoord2f(uv_right, uv_top); glVertex2f(right*ca - top*sa + center_x, right*sa + top*ca + center_y); @@ -177,7 +177,7 @@ static inline void intern_draw2(float left, float top, float right, float bottom glVertex2f(left*ca - bottom*sa + center_x, left*sa + bottom*ca + center_y); glEnd(); - + // FIXME: find a better way to restore the blend mode glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -191,10 +191,10 @@ Surface::draw(float x, float y, float alpha, float angle, const Color& color, co intern_draw2(x, y, x + width, y + height, - uv_left, uv_top, uv_right, uv_bottom, + uv_left, uv_top, uv_right, uv_bottom, angle, color, - blend, + blend, effect); } @@ -216,17 +216,16 @@ Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y, { float uv_width = uv_right - uv_left; float uv_height = uv_bottom - uv_top; - + float uv_left = this->uv_left + (uv_width * src_x) / this->width; float uv_top = this->uv_top + (uv_height * src_y) / this->height; float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width; float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height; - + glColor4f(1.0f, 1.0f, 1.0f, alpha); - glBindTexture(GL_TEXTURE_2D, texture->get_handle()); - + glBindTexture(GL_TEXTURE_2D, texture->get_handle()); + intern_draw(dst_x, dst_y, dst_x + width, dst_y + height, uv_left, uv_top, uv_right, uv_bottom, effect); } - diff --git a/src/video/surface.hpp b/src/video/surface.hpp index 0945253ed..650f93169 100644 --- a/src/video/surface.hpp +++ b/src/video/surface.hpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux // Copyright (C) 2006 Matthias Braun // @@ -12,7 +12,7 @@ // 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 @@ -69,7 +69,7 @@ public: /** flip the surface horizontally */ void hflip(); - + const Surface& operator= (const Surface& other); float get_width() const diff --git a/src/video/texture.cpp b/src/video/texture.cpp index 8e792b814..9c41ddde9 100644 --- a/src/video/texture.cpp +++ b/src/video/texture.cpp @@ -37,10 +37,10 @@ Texture::Texture(unsigned int w, unsigned int h, GLenum glformat) this->width = w; this->height = h; - + assert_gl("before creating texture"); glGenTextures(1, &handle); - + try { glBindTexture(GL_TEXTURE_2D, handle); @@ -61,13 +61,13 @@ Texture::Texture(SDL_Surface* image, GLenum glformat) throw std::runtime_error("image has no power of 2 size"); if(format->BitsPerPixel != 24 && format->BitsPerPixel != 32) throw std::runtime_error("image has no 24 or 32 bit color depth"); - + this->width = image->w; this->height = image->h; assert_gl("before creating texture"); glGenTextures(1, &handle); - + try { GLenum sdl_format; if(format->BytesPerPixel == 3) @@ -85,7 +85,7 @@ Texture::Texture(SDL_Surface* image, GLenum glformat) assert_gl("creating texture"); - set_texture_params(); + set_texture_params(); } catch(...) { glDeleteTextures(1, &handle); throw; @@ -107,4 +107,3 @@ Texture::set_texture_params() assert_gl("set texture params"); } - diff --git a/src/video/texture.hpp b/src/video/texture.hpp index 0e4dd89d2..bf87c65df 100644 --- a/src/video/texture.hpp +++ b/src/video/texture.hpp @@ -40,7 +40,7 @@ public: Texture(unsigned int width, unsigned int height, GLenum glformat); Texture(SDL_Surface* surface, GLenum glformat); virtual ~Texture(); - + GLuint get_handle() const { return handle; @@ -61,4 +61,3 @@ private: }; #endif - diff --git a/src/video/texture_manager.cpp b/src/video/texture_manager.cpp index 1f78be0f3..d45eb84f8 100644 --- a/src/video/texture_manager.cpp +++ b/src/video/texture_manager.cpp @@ -137,7 +137,7 @@ TextureManager::create_image_texture(const std::string& filename) SDL_FreeSurface(convert); throw; } - + SDL_FreeSurface(convert); return result; } @@ -183,7 +183,7 @@ TextureManager::save_texture(Texture* texture) size_t pixelssize = saved_texture.width * saved_texture.height * 4; saved_texture.pixels = new char[pixelssize]; - + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, saved_texture.pixels); @@ -204,11 +204,11 @@ TextureManager::reload_textures() glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + for(std::vector::iterator i = saved_textures.begin(); i != saved_textures.end(); ++i) { SavedTexture& saved_texture = *i; - + GLuint handle; glGenTextures(1, &handle); assert_gl("creating texture handle"); @@ -236,4 +236,3 @@ TextureManager::reload_textures() saved_textures.clear(); } - diff --git a/src/video/texture_manager.hpp b/src/video/texture_manager.hpp index 32280f431..ee75655ed 100644 --- a/src/video/texture_manager.hpp +++ b/src/video/texture_manager.hpp @@ -36,7 +36,7 @@ public: ~TextureManager(); ImageTexture* get(const std::string& filename); - + void register_texture(Texture* texture); void remove_texture(Texture* texture); @@ -46,7 +46,7 @@ public: private: friend class ImageTexture; void release(ImageTexture* texture); - + typedef std::map ImageTextures; ImageTextures image_textures; @@ -61,7 +61,7 @@ private: GLint width; GLint height; char* pixels; - GLint border; + GLint border; GLint min_filter; GLint mag_filter; @@ -76,4 +76,3 @@ private: extern TextureManager* texture_manager; #endif - diff --git a/src/world.cpp b/src/world.cpp index 8b68b0847..121718e34 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -72,7 +72,7 @@ World::set_savegame_filename(const std::string& filename) throw std::runtime_error(msg.str()); } } - + if(!PHYSFS_isDirectory(dirname.c_str())) { std::ostringstream msg; msg << "Savegame path '" << dirname << "' is not a directory"; @@ -84,7 +84,7 @@ void World::load(const std::string& filename) { basedir = FileSystem::dirname(filename); - + lisp::Parser parser; std::auto_ptr root (parser.parse(filename)); @@ -105,7 +105,7 @@ World::load(const std::string& filename) // Level info file doesn't define any levels, so read the // directory to see what we can find - + std::string path = basedir + "/"; char** files = PHYSFS_enumerateFiles(path.c_str()); if(!files) { @@ -127,7 +127,7 @@ World::run() using namespace Scripting; current_ = this; - + // create new squirrel table for persisten game state HSQUIRRELVM vm = Scripting::global_vm; @@ -139,7 +139,7 @@ World::run() sq_pop(vm, 1); load_state(); - + std::string filename = basedir + "/world.nut"; try { IFileStream in(filename); @@ -163,12 +163,12 @@ World::save_state() writer.start_list("supertux-savegame"); writer.write_int("version", 1); - + using namespace WorldMapNS; if(WorldMap::current() != NULL) { std::ostringstream title; title << WorldMap::current()->get_title(); - title << " (" << WorldMap::current()->solved_level_count() + title << " (" << WorldMap::current()->solved_level_count() << "/" << WorldMap::current()->level_count() << ")"; writer.write_string("title", title.str()); } @@ -178,7 +178,7 @@ World::save_state() writer.end_list("tux"); writer.start_list("state"); - + sq_pushroottable(global_vm); sq_pushstring(global_vm, "state", -1); if(SQ_SUCCEEDED(sq_get(global_vm, -2))) { @@ -187,7 +187,7 @@ World::save_state() } sq_pop(global_vm, 1); writer.end_list("state"); - + writer.end_list("supertux-savegame"); } @@ -217,18 +217,18 @@ World::load_state() const lisp::Lisp* state = lisp->get_lisp("state"); if(state == NULL) throw std::runtime_error("No state section in savegame"); - + sq_pushroottable(global_vm); sq_pushstring(global_vm, "state", -1); if(SQ_FAILED(sq_deleteslot(global_vm, -2, SQFalse))) sq_pop(global_vm, 1); - + sq_pushstring(global_vm, "state", -1); sq_newtable(global_vm); load_squirrel_table(global_vm, -1, state); if(SQ_FAILED(sq_createslot(global_vm, -3))) throw std::runtime_error("Couldn't create state table"); - sq_pop(global_vm, 1); + sq_pop(global_vm, 1); } catch(std::exception& e) { log_debug << "Couldn't load savegame: " << e.what() << std::endl; } diff --git a/src/world.hpp b/src/world.hpp index 71095b8e3..f59e5cca8 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -43,7 +43,7 @@ public: void save_state(); void load_state(); - + const std::string& get_level_filename(unsigned int i) const; unsigned int get_num_levels() const; @@ -63,4 +63,3 @@ public: }; #endif - diff --git a/src/worldmap/level.cpp b/src/worldmap/level.cpp index fbc6b0bdb..b6aa12c35 100644 --- a/src/worldmap/level.cpp +++ b/src/worldmap/level.cpp @@ -36,17 +36,17 @@ LevelTile::LevelTile(const std::string& basedir, const lisp::Lisp* lisp) { lisp->get("x", pos.x); lisp->get("y", pos.y); - + std::string spritefile = "images/worldmap/common/leveldot.sprite"; lisp->get("sprite", spritefile); sprite.reset(sprite_manager->create(spritefile)); lisp->get("extro-script", extro_script); lisp->get("name", name); - + if (!PHYSFS_exists((basedir + name).c_str())) { - log_warning << "level file '" << name + log_warning << "level file '" << name << "' does not exist and will not be added to the worldmap" << std::endl; return; } diff --git a/src/worldmap/level.hpp b/src/worldmap/level.hpp index d8a48e92f..be081c940 100644 --- a/src/worldmap/level.hpp +++ b/src/worldmap/level.hpp @@ -40,7 +40,7 @@ public: virtual void draw(DrawingContext& context); virtual void update(float elapsed_time); - + Vector pos; std::string name; std::string title; @@ -70,4 +70,3 @@ private: } #endif - diff --git a/src/worldmap/special_tile.cpp b/src/worldmap/special_tile.cpp index ea2bd2032..a8e561610 100644 --- a/src/worldmap/special_tile.cpp +++ b/src/worldmap/special_tile.cpp @@ -35,7 +35,7 @@ SpecialTile::SpecialTile(const lisp::Lisp* lisp) lisp->get("x", pos.x); lisp->get("y", pos.y); lisp->get("invisible-tile", invisible); - + if(!invisible) { std::string spritefile = ""; lisp->get("sprite", spritefile); @@ -83,4 +83,3 @@ SpecialTile::update(float ) } } - diff --git a/src/worldmap/special_tile.hpp b/src/worldmap/special_tile.hpp index a7948e3f6..f32b7b0fb 100644 --- a/src/worldmap/special_tile.hpp +++ b/src/worldmap/special_tile.hpp @@ -41,7 +41,7 @@ public: virtual void update(float elapsed_time); Vector pos; - + /** Sprite to render instead of guessing what image to draw */ std::auto_ptr sprite; @@ -65,4 +65,3 @@ public: } #endif - diff --git a/src/worldmap/sprite_change.cpp b/src/worldmap/sprite_change.cpp index b4db66de7..4cffd9cfe 100644 --- a/src/worldmap/sprite_change.cpp +++ b/src/worldmap/sprite_change.cpp @@ -32,7 +32,7 @@ SpriteChange::SpriteChange(const lisp::Lisp* lisp) lisp->get("x", pos.x); lisp->get("y", pos.y); lisp->get("change-on-touch", change_on_touch); - + std::string spritefile = ""; lisp->get("sprite", spritefile); sprite.reset(sprite_manager->create(spritefile)); diff --git a/src/worldmap/sprite_change.hpp b/src/worldmap/sprite_change.hpp index b48787db5..4754e279f 100644 --- a/src/worldmap/sprite_change.hpp +++ b/src/worldmap/sprite_change.hpp @@ -53,10 +53,10 @@ public: std::string stay_action; /** - * name of a group in which only one SpriteChange will ever have its stay_action displayed. - * Leave empty if you don't care. + * name of a group in which only one SpriteChange will ever have its stay_action displayed. + * Leave empty if you don't care. */ - std::string stay_group; + std::string stay_group; virtual void draw(DrawingContext& context); virtual void update(float elapsed_time); @@ -84,4 +84,3 @@ private: } #endif - diff --git a/src/worldmap/teleporter.cpp b/src/worldmap/teleporter.cpp index 26dbeca60..d1a7ffbbb 100644 --- a/src/worldmap/teleporter.cpp +++ b/src/worldmap/teleporter.cpp @@ -31,12 +31,12 @@ Teleporter::Teleporter(const lisp::Lisp* lisp) { lisp->get("x", pos.x); lisp->get("y", pos.y); - + std::string spritefile = ""; if (lisp->get("sprite", spritefile)) { sprite.reset(sprite_manager->create(spritefile)); } - + lisp->get("worldmap", worldmap); lisp->get("spawnpoint", spawnpoint); lisp->get("automatic", automatic); @@ -55,4 +55,3 @@ Teleporter::update(float ) } } - diff --git a/src/worldmap/teleporter.hpp b/src/worldmap/teleporter.hpp index 4b3b55579..0e5cff30b 100644 --- a/src/worldmap/teleporter.hpp +++ b/src/worldmap/teleporter.hpp @@ -40,7 +40,7 @@ public: /** Position (in tiles, not pixels) */ Vector pos; - + /** Sprite to render, or 0 for no sprite */ std::auto_ptr sprite; @@ -61,4 +61,3 @@ public: } #endif - diff --git a/src/worldmap/tux.cpp b/src/worldmap/tux.cpp index 7f5c50a1f..2e89f0480 100644 --- a/src/worldmap/tux.cpp +++ b/src/worldmap/tux.cpp @@ -34,14 +34,14 @@ namespace WorldMapNS { -static const float TUXSPEED = 200; +static const float TUXSPEED = 200; static const float map_message_TIME = 2.8; Tux::Tux(WorldMap* worldmap_) : worldmap(worldmap_) { sprite.reset(sprite_manager->create("images/worldmap/common/tux.sprite")); - + offset = 0; moving = false; direction = D_NONE; @@ -98,7 +98,7 @@ Tux::get_pos() case D_NONE: break; } - + return Vector(x, y); } @@ -117,11 +117,11 @@ Tux::set_direction(Direction dir) input_direction = dir; } -void -Tux::tryStartWalking() +void +Tux::tryStartWalking() { if (moving) - return; + return; if (input_direction == D_NONE) return; @@ -143,7 +143,7 @@ Tux::tryStartWalking() } } -bool +bool Tux::canWalk(const Tile* tile, Direction dir) { return ((tile->getData() & Tile::WORLDMAP_NORTH && dir == D_NORTH) || @@ -152,7 +152,7 @@ Tux::canWalk(const Tile* tile, Direction dir) (tile->getData() & Tile::WORLDMAP_WEST && dir == D_WEST)); } -void +void Tux::tryContinueWalking(float elapsed_time) { if (!moving) @@ -176,7 +176,7 @@ Tux::tryContinueWalking(float elapsed_time) // if this is a special_tile with passive_message, display it SpecialTile* special_tile = worldmap->at_special_tile(); if(special_tile) - { + { // direction and the apply_action_ are opposites, since they "see" // directions in a different way if((direction == D_NORTH && special_tile->apply_action_south) || @@ -217,8 +217,8 @@ Tux::tryContinueWalking(float elapsed_time) // if user wants to change direction, try changing, else guess the direction in which to walk next const Tile* tile = worldmap->at(tile_pos); - if (direction != input_direction) { - if(canWalk(tile, input_direction)) { + if (direction != input_direction) { + if(canWalk(tile, input_direction)) { direction = input_direction; back_direction = reverse_dir(direction); } @@ -248,7 +248,7 @@ Tux::tryContinueWalking(float elapsed_time) // Walk automatically to the next tile if(direction == D_NONE) return; - + Vector next_tile; if (!worldmap->path_ok(direction, tile_pos, &next_tile)) { log_warning << "Tilemap data is buggy" << std::endl; @@ -286,7 +286,7 @@ Tux::updateInputDirection() void Tux::update(float elapsed_time) { - updateInputDirection(); + updateInputDirection(); if (moving) tryContinueWalking(elapsed_time); else diff --git a/src/worldmap/tux.hpp b/src/worldmap/tux.hpp index 6519785e2..67ec76d4f 100644 --- a/src/worldmap/tux.hpp +++ b/src/worldmap/tux.hpp @@ -55,10 +55,10 @@ private: void tryStartWalking(); /**< try starting to walk in input_direction */ void tryContinueWalking(float elapsed_time); /**< try to continue walking in current direction */ -public: +public: Tux(WorldMap* worldmap_); ~Tux(); - + void setup(); /**< called prior to first update */ void draw(DrawingContext& context); void update(float elapsed_time); @@ -67,11 +67,10 @@ public: bool is_moving() const { return moving; } Vector get_pos(); - Vector get_tile_pos() const { return tile_pos; } - void set_tile_pos(Vector p) { tile_pos = p; } + Vector get_tile_pos() const { return tile_pos; } + void set_tile_pos(Vector p) { tile_pos = p; } }; } #endif - diff --git a/src/worldmap/worldmap.cpp b/src/worldmap/worldmap.cpp index b34e881ed..0d21134b0 100644 --- a/src/worldmap/worldmap.cpp +++ b/src/worldmap/worldmap.cpp @@ -132,10 +132,10 @@ WorldMap::WorldMap(const std::string& filename, const std::string& force_spawnpo : tux(0), solids(0), force_spawnpoint(force_spawnpoint) { tile_manager.reset(new TileManager("images/worldmap.strf")); - + tux = new Tux(this); add_object(tux); - + name = ""; music = "music/salcon.ogg"; @@ -165,7 +165,7 @@ WorldMap::WorldMap(const std::string& filename, const std::string& force_spawnpo throw Scripting::SquirrelError(global_vm, "Couldn't get table from stack"); sq_addref(global_vm, &worldmap_table); - sq_pop(global_vm, 1); + sq_pop(global_vm, 1); } WorldMap::~WorldMap() @@ -180,7 +180,7 @@ WorldMap::~WorldMap() sq_release(global_vm, &worldmap_table); sq_collectgarbage(global_vm); - + if(current_ == this) current_ = NULL; @@ -247,11 +247,11 @@ WorldMap::load(const std::string& filename) throw std::runtime_error("file isn't a supertux-level file."); lisp->get("name", name); - + const lisp::Lisp* sector = lisp->get_lisp("sector"); if(!sector) throw std::runtime_error("No sector sepcified in worldmap file."); - + lisp::ListIterator iter(sector); while(iter.next()) { if(iter.item() == "tilemap") { @@ -290,7 +290,7 @@ WorldMap::load(const std::string& filename) if(solids == 0) throw std::runtime_error("No solid tilemap specified"); - move_to_spawnpoint("main"); + move_to_spawnpoint("main"); } catch(std::exception& e) { std::stringstream msg; @@ -313,7 +313,7 @@ WorldMap::get_level_title(LevelTile& level) const lisp::Lisp* level_lisp = root->get_lisp("supertux-level"); if(!level_lisp) return; - + level_lisp->get("name", level.title); } catch(std::exception& e) { log_warning << "Problem when reading leveltitle: " << e.what() << std::endl; @@ -425,7 +425,7 @@ WorldMap::finished_level(Level* gamelevel) // Try to detect the next direction to which we should walk // FIXME: Mostly a hack Direction dir = D_NONE; - + const Tile* tile = at(tux->get_tile_pos()); // first, test for crossroads @@ -471,7 +471,7 @@ WorldMap::update(float delta) if(menu == worldmap_menu.get()) { switch (worldmap_menu->check()) { - case MNID_RETURNWORLDMAP: // Return to game + case MNID_RETURNWORLDMAP: // Return to game Menu::set_current(0); break; case MNID_QUITWORLDMAP: // Quit Worldmap @@ -524,7 +524,7 @@ WorldMap::update(float delta) enter_level = true; if(main_controller->pressed(Controller::PAUSE_MENU)) on_escape_press(); - + // check for teleporters Teleporter* teleporter = at_teleporter(tux->get_tile_pos()); if (teleporter && (teleporter->automatic || (enter_level && (!tux->is_moving())))) { @@ -591,7 +591,7 @@ WorldMap::at_special_tile() i != special_tiles.end(); ++i) { SpecialTile* special_tile = *i; if (special_tile->pos == tux->get_tile_pos()) - return special_tile; + return special_tile; } return NULL; @@ -626,13 +626,13 @@ WorldMap::draw(DrawingContext& context) { context.push_transform(); context.set_translation(camera_offset); - + for(GameObjects::iterator i = game_objects.begin(); i != game_objects.end(); ++i) { GameObject* object = *i; object->draw(context); } - + draw_status(context); context.pop_transform(); } @@ -642,13 +642,13 @@ WorldMap::draw_status(DrawingContext& context) { context.push_transform(); context.set_translation(Vector(0, 0)); - + player_status->draw(context); if (!tux->is_moving()) { for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) { LevelTile* level = *i; - + if (level->pos == tux->get_tile_pos()) { if(level->title == "") get_level_title(*level); @@ -657,7 +657,7 @@ WorldMap::draw_status(DrawingContext& context) Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 30), CENTER_ALLIGN, LAYER_FOREGROUND1); - + // if level is solved, draw level picture behind stats /* if (level->solved) { @@ -670,7 +670,7 @@ WorldMap::draw_status(DrawingContext& context) } } */ - + level->statistics.draw_worldmap_info(context); break; } @@ -679,11 +679,11 @@ WorldMap::draw_status(DrawingContext& context) for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) { SpecialTile* special_tile = *i; - + if (special_tile->pos == tux->get_tile_pos()) { /* Display an in-map message in the map, if any as been selected */ if(!special_tile->map_message.empty() && !special_tile->passive_message) - context.draw_text(gold_text, special_tile->map_message, + context.draw_text(gold_text, special_tile->map_message, Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 60), CENTER_ALLIGN, LAYER_FOREGROUND1); @@ -699,10 +699,10 @@ WorldMap::draw_status(DrawingContext& context) } } - + /* Display a passive message in the map, if needed */ if(passive_message_timer.started()) - context.draw_text(gold_text, passive_message, + context.draw_text(gold_text, passive_message, Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 60), CENTER_ALLIGN, LAYER_FOREGROUND1); @@ -728,7 +728,7 @@ WorldMap::setup() // register worldmap_table as worldmap in scripting using namespace Scripting; - + sq_pushroottable(global_vm); sq_pushstring(global_vm, "worldmap", -1); sq_pushobject(global_vm, worldmap_table); @@ -797,7 +797,7 @@ static float read_float(HSQUIRRELVM vm, const char* name) msg << "Couldn't get float value for '" << name << "' from table"; throw Scripting::SquirrelError(vm, msg.str()); } - + float result; if(SQ_FAILED(sq_getfloat(vm, -1, &result))) { std::ostringstream msg; @@ -817,7 +817,7 @@ static std::string read_string(HSQUIRRELVM vm, const char* name) msg << "Couldn't get string value for '" << name << "' from table"; throw Scripting::SquirrelError(vm, msg.str()); } - + const char* result; if(SQ_FAILED(sq_getstring(vm, -1, &result))) { std::ostringstream msg; @@ -836,8 +836,8 @@ static bool read_bool(HSQUIRRELVM vm, const char* name) std::ostringstream msg; msg << "Couldn't get bool value for '" << name << "' from table"; throw Scripting::SquirrelError(vm, msg.str()); - } - + } + SQBool result; if(SQ_FAILED(sq_getbool(vm, -1, &result))) { std::ostringstream msg; @@ -853,7 +853,7 @@ void WorldMap::save_state() { using namespace Scripting; - + HSQUIRRELVM vm = global_vm; int oldtop = sq_gettop(vm); @@ -876,7 +876,7 @@ WorldMap::save_state() if(SQ_FAILED(sq_get(vm, -2))) throw Scripting::SquirrelError(vm, "Couldn't create.get state.worlds"); } - + sq_pushstring(vm, map_filename.c_str(), map_filename.length()); if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) sq_pop(vm, 1); @@ -888,32 +888,32 @@ WorldMap::save_state() // store tux sq_pushstring(vm, "tux", -1); sq_newtable(vm); - + store_float(vm, "x", tux->get_tile_pos().x); store_float(vm, "y", tux->get_tile_pos().y); store_string(vm, "back", direction_to_string(tux->back_direction)); sq_createslot(vm, -3); - + // levels... sq_pushstring(vm, "levels", -1); sq_newtable(vm); for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) { LevelTile* level = *i; - + if (level->solved) { sq_pushstring(vm, level->name.c_str(), -1); sq_newtable(vm); - store_bool(vm, "solved", true); + store_bool(vm, "solved", true); // TODO write statistics // i->statistics.write(writer); sq_createslot(vm, -3); } } - + sq_createslot(vm, -3); // push world into worlds table @@ -929,10 +929,10 @@ void WorldMap::load_state() { using namespace Scripting; - + HSQUIRRELVM vm = global_vm; int oldtop = sq_gettop(vm); - + try { // get state table sq_pushroottable(vm); @@ -999,7 +999,7 @@ WorldMap::solved_level_count() size_t count = 0; for(LevelTiles::iterator i = levels.begin(); i != levels.end(); ++i) { LevelTile* level = *i; - + if(level->solved) count++; } @@ -1040,5 +1040,5 @@ WorldMap::run_script(std::istream& in, const std::string& sourcename) return vm; } - + } // namespace WorldMapNS diff --git a/src/worldmap/worldmap.hpp b/src/worldmap/worldmap.hpp index ea847054b..9263307eb 100644 --- a/src/worldmap/worldmap.hpp +++ b/src/worldmap/worldmap.hpp @@ -86,9 +86,9 @@ private: typedef std::vector GameObjects; GameObjects game_objects; TileMap* solids; - + std::auto_ptr tile_manager; - + public: /** Variables to deal with the passive map messages */ Timer passive_message_timer; @@ -112,7 +112,7 @@ private: HSQOBJECT worldmap_table; typedef std::vector ScriptList; - ScriptList scripts; + ScriptList scripts; std::string force_spawnpoint; /**< if set, spawnpoint will be forced to this value */ @@ -168,7 +168,7 @@ public: { return name; } /** - * runs a script in the context of the worldmap (and keeps a reference to + * runs a script in the context of the worldmap (and keeps a reference to * the script (so the script gets destroyed when the worldmap is destroyed) */ HSQUIRRELVM run_script(std::istream& in, const std::string& sourcename); @@ -189,7 +189,7 @@ private: void draw_status(DrawingContext& context); void calculate_total_stats(); - void load(const std::string& filename); + void load(const std::string& filename); void on_escape_press(); }; diff --git a/tools/miniswig/create_docu.cpp b/tools/miniswig/create_docu.cpp index 821dedb29..d7d8d345d 100644 --- a/tools/miniswig/create_docu.cpp +++ b/tools/miniswig/create_docu.cpp @@ -11,7 +11,7 @@ void DocuCreator::create_docu(Namespace* ns) { std::string fromfile = original_file != "" ? original_file : inputfile; - + writer.openTag("documentation"); writer.openTag("namespace"); writer.writeAttribute("name", ns->name); @@ -42,7 +42,7 @@ DocuCreator::create_class_docu(Class* _class) writer.writeTag("documentation"); writer.write(_class->docu_comment); } - + for(std::vector::iterator i = _class->members.begin(); i != _class->members.end(); ++i) { ClassMember* member = *i; @@ -63,7 +63,7 @@ void DocuCreator::create_function_docu(Class* _class, Function* function) { writer.openTag("function"); - + writer.writeAttribute("return_type", get_type(function->return_type)); writer.writeAttribute("name", function->name); @@ -72,10 +72,10 @@ DocuCreator::create_function_docu(Class* _class, Function* function) writer.writeTag("documentation"); writer.write(function->docu_comment); } - + for(std::vector::iterator p = function->parameters.begin(); p != function->parameters.end(); ++p) { - if(p == function->parameters.begin() + if(p == function->parameters.begin() && p->type.atomic_type == HSQUIRRELVMType::instance()) continue; @@ -104,10 +104,9 @@ DocuCreator::get_type(const Type& type) return "bool"; } else if(type.atomic_type == StringType::instance()) { return "string"; - } - + } + std::ostringstream msg; msg << "Type '" << type.atomic_type->name << "' not supported yet."; throw std::runtime_error(msg.str()); } - diff --git a/tools/miniswig/create_wrapper.cpp b/tools/miniswig/create_wrapper.cpp index fafe124ab..64318fd76 100644 --- a/tools/miniswig/create_wrapper.cpp +++ b/tools/miniswig/create_wrapper.cpp @@ -40,7 +40,7 @@ WrapperCreator::create_wrapper(Namespace* ns) for(std::vector::iterator i = ns->types.begin(); i != ns->types.end(); ++i) { AtomicType* type = *i; - Class* _class = dynamic_cast (type); + Class* _class = dynamic_cast (type); if(_class == 0) continue; @@ -53,7 +53,7 @@ WrapperCreator::create_wrapper(Namespace* ns) << "\n" << "#endif\n" << "\n"; - + // cpp header out << "/**\n" << " * WARNING: This file is automatically generated from:\n" @@ -92,13 +92,13 @@ WrapperCreator::create_wrapper(Namespace* ns) out << "\n"; for(std::vector::iterator i = ns->types.begin(); - i != ns->types.end(); ++i) { + i != ns->types.end(); ++i) { AtomicType* type = *i; Class* _class = dynamic_cast (type); if(_class != 0) create_squirrel_instance(_class); } - + out << "void register_" << modulename << "_wrapper(HSQUIRRELVM v)\n" << "{\n" << ind << "using namespace Wrapper;\n" @@ -119,13 +119,13 @@ WrapperCreator::create_register_function_code(Function* function, Class* _class) { if(function->type == Function::DESTRUCTOR) return; - + out << ind << "sq_pushstring(v, \"" << function->name << "\", -1);\n"; - out << ind << "sq_newclosure(v, &" - << (_class != 0 ? _class->name + "_" : "") << function->name + out << ind << "sq_newclosure(v, &" + << (_class != 0 ? _class->name + "_" : "") << function->name << "_wrapper, 0);\n"; create_register_slot_code("function", function->name); - out << "\n"; + out << "\n"; } void @@ -144,7 +144,7 @@ WrapperCreator::create_register_classes_code(Namespace* ns) for(std::vector::iterator i = ns->types.begin(); i != ns->types.end(); ++i) { AtomicType* type = *i; - Class* _class = dynamic_cast (type); + Class* _class = dynamic_cast (type); if(_class == 0) continue; if(_class->super_classes.size() > 0) @@ -158,9 +158,9 @@ void WrapperCreator::create_register_class_code(Class* _class) { out << ind << "// Register class " << _class->name << "\n"; - out << ind << "sq_pushstring(v, \"" - << _class->name << "\", -1);\n"; - + out << ind << "sq_pushstring(v, \"" + << _class->name << "\", -1);\n"; + if(_class->super_classes.size() > 0) { if(_class->super_classes.size() > 1) { std::ostringstream msg; @@ -168,7 +168,7 @@ WrapperCreator::create_register_class_code(Class* _class) << _class->name << "')"; throw std::runtime_error(msg.str()); } - + out << ind << "sq_pushstring(v, \"" << _class->super_classes[0]->name << "\", -1);\n"; out << ind << "sq_get(v, -3);\n"; @@ -177,7 +177,7 @@ WrapperCreator::create_register_class_code(Class* _class) << (_class->super_classes.size() > 0 ? "SQTrue" : "SQFalse") << ") < 0) {\n"; out << ind << ind << "std::ostringstream msg;\n"; - out << ind << ind << "msg << \"Couldn't create new class '" + out << ind << ind << "msg << \"Couldn't create new class '" << _class->name << "'\";\n"; out << ind << ind << "throw SquirrelError(v, msg.str());\n"; out << ind << "}\n"; @@ -199,7 +199,7 @@ WrapperCreator::create_register_class_code(Class* _class) create_register_slot_code("class", _class->name); out << "\n"; - + for(std::vector::iterator i = _class->sub_classes.begin(); i != _class->sub_classes.end(); ++i) { Class* _class = *i; @@ -266,12 +266,12 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) out << function->name << "_wrapper(HSQUIRRELVM vm)\n" << "{\n"; // avoid warning... - if(_class == 0 && function->parameters.empty() + if(_class == 0 && function->parameters.empty() && function->return_type.is_void() && function->type != Function::CONSTRUCTOR) { out << ind << "(void) vm;\n"; } - + // retrieve pointer to class instance if(_class != 0 && function->type != Function::CONSTRUCTOR) { out << ind << "SQUserPointer data;\n"; @@ -303,7 +303,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) out << "\n"; return; } - + // declare and retrieve arguments int i = 0; int arg_offset = 2; @@ -319,7 +319,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) } ++i; } - + // call function out << ind << "\n"; out << ind << "try {\n"; @@ -365,7 +365,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) out << ind << ind << "sq_throwerror(vm, _SC(\"Couldn't setup instance of '" << _class->name << "' class\"));\n"; out << ind << ind << "return SQ_ERROR;\n"; out << ind << "}\n"; - out << ind << "sq_setreleasehook(vm, 1, " + out << ind << "sq_setreleasehook(vm, 1, " << _class->name << "_release_hook);\n"; } out << ind << "\n"; @@ -394,7 +394,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function) out << ind << ind << "return SQ_ERROR;\n"; out << ind << "}\n"; out << ind << "\n"; - + out << "}\n"; out << "\n"; } @@ -453,7 +453,7 @@ WrapperCreator::push_to_stack(const Type& type, const std::string& var) } else if(type.atomic_type == &BasicType::BOOL) { out << "sq_pushbool(vm, " << var << ");\n"; } else if(type.atomic_type == StringType::instance()) { - out << "sq_pushstring(vm, " << var << ".c_str(), " + out << "sq_pushstring(vm, " << var << ".c_str(), " << var << ".size());\n"; } else { std::ostringstream msg; @@ -485,7 +485,7 @@ void WrapperCreator::create_squirrel_instance(Class* _class) { out << "void create_squirrel_instance(HSQUIRRELVM v, " - << ns_prefix << _class->name + << ns_prefix << _class->name << "* object, bool setup_releasehook)\n" << "{\n" << ind << "using namespace Wrapper;\n" @@ -523,12 +523,11 @@ WrapperCreator::create_class_release_hook(Class* _class) { out << "static SQInteger " << _class->name << "_release_hook(SQUserPointer ptr, SQInteger )\n" << "{\n" - << ind << ns_prefix << _class->name - << "* _this = reinterpret_cast<" << ns_prefix << _class->name + << ind << ns_prefix << _class->name + << "* _this = reinterpret_cast<" << ns_prefix << _class->name << "*> (ptr);\n" << ind << "delete _this;\n" << ind << "return 0;\n" << "}\n" << "\n"; } - diff --git a/tools/miniswig/create_wrapper.hpp b/tools/miniswig/create_wrapper.hpp index ec9842940..a2e5395d6 100644 --- a/tools/miniswig/create_wrapper.hpp +++ b/tools/miniswig/create_wrapper.hpp @@ -22,7 +22,7 @@ public: private: std::string ns_prefix; - + void create_register_functions_code(Namespace* ns); void create_register_function_code(Function* function, Class* _class); void create_register_classes_code(Namespace* ns); @@ -31,7 +31,7 @@ private: void create_register_constants_code(Namespace* ns); void create_register_slot_code(const std::string& what, const std::string& name); - + void create_function_list(Namespace* ns); void create_const_lists(Namespace* ns); void create_class_const_lists(Class* _class); @@ -44,4 +44,3 @@ private: }; #endif - diff --git a/tools/miniswig/globals.hpp b/tools/miniswig/globals.hpp index 9f6f65d46..13e6a8ce3 100644 --- a/tools/miniswig/globals.hpp +++ b/tools/miniswig/globals.hpp @@ -27,4 +27,3 @@ extern std::string modulename; extern std::string selected_namespace; #endif - diff --git a/tools/miniswig/main.cpp b/tools/miniswig/main.cpp index 646180394..46c5fa047 100644 --- a/tools/miniswig/main.cpp +++ b/tools/miniswig/main.cpp @@ -85,7 +85,7 @@ int main(int argc, char** argv) usage(); return 1; } - + try { input = new std::ifstream(inputfile.c_str()); if(!input->good()) { @@ -100,24 +100,24 @@ int main(int argc, char** argv) unit->namespaces.push_back(std_namespace); unit->types.push_back(new HSQUIRRELVMType()); unit->types.push_back(new SQIntegerType()); - + yyparse(); Namespace* ns = unit; if(selected_namespace != "") { ns = ns->findNamespace(selected_namespace); - } + } if(outputcpp != "") { std::ofstream cppout(outputcpp.c_str()); if(!cppout.good()) { - std::cerr << "Couldn't open file '" + std::cerr << "Couldn't open file '" << outputcpp << "' for writing.\n"; return 1; } std::ofstream hppout(outputhpp.c_str()); if(!hppout.good()) { - std::cerr << "Couldn't open file '" << outputhpp + std::cerr << "Couldn't open file '" << outputhpp << "' for writing.\n"; return 1; } @@ -129,7 +129,7 @@ int main(int argc, char** argv) if(output_doc != "") { std::ofstream dout(output_doc.c_str()); if(!dout.good()) { - std::cerr << "Couldn't open file '" + std::cerr << "Couldn't open file '" << output_doc << "' for writing.\n"; return 1; } @@ -143,4 +143,3 @@ int main(int argc, char** argv) return 0; } - diff --git a/tools/miniswig/tree.hpp b/tools/miniswig/tree.hpp index 19ed320f0..2c398c9d3 100644 --- a/tools/miniswig/tree.hpp +++ b/tools/miniswig/tree.hpp @@ -40,14 +40,14 @@ public: private: BasicType(const std::string& name) - { + { this->name = name; - } + } }; class Type { public: - Type() + Type() : atomic_type(0), _unsigned(false), _const(false), _static(false), pointer(0), ref(0) { } @@ -55,7 +55,7 @@ public: void write_c_type(std::ostream& out) { if(_static) - out << "static "; + out << "static "; if(_const) out << "const "; atomic_type->write_c(out); @@ -97,7 +97,7 @@ public: assert(_instance == this); _instance = NULL; } - + static SQIntegerType* instance() { return _instance; @@ -153,7 +153,7 @@ public: } private: - static StringType* _instance; + static StringType* _instance; }; class Parameter { @@ -182,7 +182,7 @@ public: suspend = false; custom = false; } - + enum FuncType { FUNCTION, CONSTRUCTOR, @@ -205,7 +205,7 @@ public: { has_const_value = false; } - + Type* type; std::string docu_comment; std::string name; @@ -225,7 +225,7 @@ public: i != members.end(); ++i) delete *i; } - + std::vector members; std::vector super_classes; std::vector sub_classes; @@ -294,7 +294,7 @@ public: return ret; } - + std::vector functions; std::vector fields; std::vector types; @@ -309,4 +309,3 @@ public: }; #endif - diff --git a/tools/miniswig/xmlwriter.cpp b/tools/miniswig/xmlwriter.cpp index b44635f17..459c22066 100644 --- a/tools/miniswig/xmlwriter.cpp +++ b/tools/miniswig/xmlwriter.cpp @@ -45,7 +45,7 @@ void XmlWriter::closeTag(const char* name) throw std::runtime_error(msg.str()); } sections.pop_back(); - + indent--; newLine(); // XXX: We should check for consistency here @@ -75,4 +75,3 @@ void XmlWriter::closeTag() if (closetag != "") out << closetag << "\n"; } - diff --git a/tools/miniswig/xmlwriter.hpp b/tools/miniswig/xmlwriter.hpp index 97e43445a..ad243f313 100644 --- a/tools/miniswig/xmlwriter.hpp +++ b/tools/miniswig/xmlwriter.hpp @@ -26,7 +26,7 @@ class XmlWriter { public: XmlWriter(std::ostream& out); ~XmlWriter(); - + /** Start a xml tag which contains subtags */ void openTag(const char* name); /** Closes an xml tag with subtags */ @@ -34,7 +34,7 @@ public: void writeTag(const char* name); - template + template void comment(const T& outp) { // This routine writes just about anything as an XML comment. newLine(); @@ -67,7 +67,7 @@ public: private: void newLine(); void closeTag(); - + std::ostream& out; int indent; std::string closetag; @@ -76,4 +76,3 @@ private: }; #endif -