tuxjumps <- 2;
while(true) {
wait(0.8);
- Sound.play_sound(\"jump\");
+ Sound.play(\"jump\");
if(tuxjumps >= 0) {
TUX.set_velocity(50, 300);
} else {
} else if(PENNY.get_animation() == \"jump\") {
PENNY.set_animation(\"dead\");
} else {
- Sound.play_sound(\"grow\");
+ Sound.play(\"grow\");
PENNY.set_animation(\"stand\");
PENNY.set_velocity(0, 900);
}
(x 2)
(y 177)
(dead-script "
-Sound.play_sound(\"invincible\");
+Sound.play(\"sounds/invincible.wav\");
Text.set_text(\"You made it!\");
Text.set_font(\"big\");
Text.fade_in(1.5);
}
void
-SoundManager::play(const std::string& soundname, const Vector& pos)
+SoundManager::play(const std::string& filename, const Vector& pos)
{
- std::string filename = "sounds/";
- filename += soundname;
- filename += ".wav";
try {
SoundSource* source = create_sound_source(filename);
if(source == 0)
SoundSource* create_sound_source(const std::string& filename);
/**
* Convenience function to simply play a sound at a given position.
- * This functions constructs prepends sounds/ to the name and adds .wav
+ * This functions prepends sounds/ to the name and adds .wav
*/
void play(const std::string& name, const Vector& pos = Vector(-1, -1));
void
BadGuy::kill_squished(Player& player)
{
- sound_manager->play("squish", get_pos());
+ sound_manager->play("sounds/squish.wav", get_pos());
physic.enable_gravity(true);
physic.set_velocity_x(0);
physic.set_velocity_y(0);
void
BadGuy::kill_fall()
{
- sound_manager->play("fall", get_pos());
+ sound_manager->play("sounds/fall.wav", get_pos());
global_stats.add_points(BADGUYS_KILLED_STAT, 1);
physic.set_velocity_y(0);
physic.enable_gravity(true);
{
state = 1;
sprite->set_action("explosion");
- sound_manager->play("explosion", get_pos());
+ sound_manager->play("sounds/explosion.wav", get_pos());
timer.start(EXPLOSIONTIME);
}
physic.set_velocity_y(JUMPSPEED);
// TODO create a nice sound for this...
- //sound_manager->play("skid");
+ //sound_manager->play("sounds/skid.wav");
} else if(chit.normal.y < .5) { // bumped on roof
physic.set_velocity_y(0);
}
dir = dir == LEFT ? RIGHT : LEFT;
sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
physic.set_velocity_x(-physic.get_velocity_x());
- sound_manager->play("ricochet", get_pos());
+ sound_manager->play("sounds/ricochet.wav", get_pos());
break;
}
case ICESTATE_FLAT:
}
// flatten
- sound_manager->play("stomp", get_pos());
+ sound_manager->play("sounds/stomp.wav", get_pos());
physic.set_velocity_x(0);
physic.set_velocity_y(0);
break;
case ICESTATE_FLAT:
// kick
- sound_manager->play("kick", get_pos());
+ sound_manager->play("sounds/kick.wav", get_pos());
if(player.get_pos().x < get_pos().x) {
dir = RIGHT;
mystate = STATE_NORMAL;
activate();
- sound_manager->play("squish", get_pos());
+ sound_manager->play("sounds/squish.wav", get_pos());
player.bounce(*this);
} else {
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
bullet_hitpoints--;
if (bullet_hitpoints <= 0) {
hitpoints = 0;
- sound_manager->play("fall", this,
+ sound_manager->play("sounds/fall.wav", this,
Sector::current()->player->get_pos());
physic.set_velocity_y(0);
physic.enable_gravity(true);
RocketExplosion::explode()
{
sprite->set_action(dir == LEFT ? "explosion-left" : "explosion-right");
- sound_manager->play("explosion", get_pos());
+ sound_manager->play("sounds/explosion.wav", get_pos());
timer.start(EXPLOSIONTIME, true);
}
case ANGRY_JUMPING:
if(timer.check()) {
// jump
- sound_manager->play("yeti_gna");
+ sound_manager->play("sounds/yeti_gna.wav");
physic.set_velocity_y(JUMP_VEL1);
}
break;
return true;
player.bounce(*this);
- sound_manager->play("yeti_roar");
+ sound_manager->play("sounds/yeti_roar.wav");
hit_points--;
if(hit_points <= 0) {
sprite->set_action("dead");
BonusBlock::try_open()
{
if(sprite->get_action_name() == "empty") {
- sound_manager->play("brick");
+ sound_manager->play("sounds/brick.wav");
return;
}
get_pos(), new Flower(Flower::FIREFLOWER));
sector->add_object(riser);
}
- sound_manager->play("upgrade");
+ sound_manager->play("sounds/upgrade.wav");
break;
case CONTENT_ICEGROW:
get_pos(), new Flower(Flower::ICEFLOWER));
sector->add_object(riser);
}
- sound_manager->play("upgrade");
+ sound_manager->play("sounds/upgrade.wav");
break;
case CONTENT_STAR:
SpecialRiser* riser = new SpecialRiser(get_pos(), object);
object = 0;
sector->add_object(riser);
- sound_manager->play("upgrade");
+ sound_manager->play("sounds/upgrade.wav");
break;
//default:
if(sprite->get_action_name() == "empty")
return;
- sound_manager->play("brick");
+ sound_manager->play("sounds/brick.wav");
Sector* sector = Sector::current();
Player& player = *(sector->player);
if(coin_counter > 0) {
sector->add_object(new Particles(pos, 0, 360, Vector(140, 140),
Vector(0, 0), 45, Color(red, green, 0), 3, 1.3,
LAYER_FOREGROUND1+1));
- sound_manager->play("fireworks");
+ sound_manager->play("sounds/fireworks.wav");
timer.start(((float) rand() / RAND_MAX) + .5);
}
}
else
player->set_bonus(ICE_BONUS, true);
- sound_manager->play("fire-flower");
+ sound_manager->play("sounds/fire-flower.wav");
remove_me();
return ABORT_MOVE;
}
Player* player = dynamic_cast<Player*>(&other);
if(player != 0) {
player->set_bonus(GROWUP_BONUS, true);
- sound_manager->play("grow");
+ sound_manager->play("sounds/grow.wav");
remove_me();
return ABORT_MOVE;
return;
sprite->set_action("empty");
- sound_manager->play("brick");
+ sound_manager->play("sounds/brick.wav");
start_bounce();
flags |= FLAG_SOLID;
visible = true;
// let's skid!
if(fabs(vx)>SKID_XM && !skidding_timer.started()) {
skidding_timer.start(SKID_TIME);
- sound_manager->play("skid");
+ sound_manager->play("sounds/skid.wav");
// dust some partcles
Sector::current()->add_object(
new Particles(
can_flap = false;
flaps_nb = 0; // Ricardo's flapping
if (is_big())
- sound_manager->play("bigjump");
+ sound_manager->play("sounds/bigjump.wav");
else
- sound_manager->play("jump");
+ sound_manager->play("sounds/jump.wav");
} else if(!controller->hold(Controller::JUMP)) { // Let go of jump key
if (!flapping && !duck && !falling_from_flap && !on_ground()) {
can_flap = true;
void
Player::make_invincible()
{
- sound_manager->play("invincible");
+ sound_manager->play("sounds/invincible.wav");
invincible_timer.start(TUX_INVINCIBLE_TIME);
Sector::current()->play_music(HERRING_MUSIC);
}
safe_timer.get_timeleft() > 0 || invincible_timer.get_timeleft() > 0)
return;
- sound_manager->play("hurt");
+ sound_manager->play("sounds/hurt.wav");
physic.set_velocity_x(0);
// some defaults if no script has been set
if (sprite->get_name() == "egg") {
player->set_bonus(GROWUP_BONUS, true);
- sound_manager->play("grow");
+ sound_manager->play("sounds/grow.wav");
} else if (sprite->get_name() == "fireflower") {
player->set_bonus(FIRE_BONUS, true);
- sound_manager->play("fire-flower");
+ sound_manager->play("sounds/fire-flower.wav");
} else if (sprite->get_name() == "star") {
player->make_invincible();
} else if (sprite->get_name() == "1up") {
{
if(lives < MAX_LIVES)
++lives;
- sound_manager->play("lifeup");
+ sound_manager->play("sounds/lifeup.wav");
}
void
incLives();
coins = 0;
}
- sound_manager->play("coin");
+ sound_manager->play("sounds/coin.wav");
}
void
}
add_object(new_bullet);
- sound_manager->play("shoot");
+ sound_manager->play("sounds/shoot.wav");
return true;
}
[ Wildcard sqstdlib : *.cpp *.c *.h ]
: noinstall
;
+CXXFLAGS on $(squirrel_OBJECTS)
+ = [ Filter [ on $(squirrel_OBJECTS) GetVar CXXFLAGS ] : -Wall -W -Werror ] ;
+CFLAGS on $(squirrel_OBJECTS)
+ = [ Filter [ on $(squirrel_OBJECTS) GetVar CFLAGS ] : -Wall -W -Werror ] ;
IncludeDir squirrel : include ;
#define SQSTD_STREAM_TYPE_TAG 0x80000000
struct SQStream {
- virtual ~SQStream()
- {}
+ virtual ~SQStream() {}
+
virtual SQInteger Read(void *buffer, SQInteger size) = 0;
virtual SQInteger Write(void *buffer, SQInteger size) = 0;
virtual int Flush() = 0;
#define MAX_CHAR 0xFF
#endif
-#define SQUIRREL_VERSION _SC("Squirrel 2.0.1 stable")
+#define SQUIRREL_VERSION _SC("Squirrel 2.0.3 stable")
#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2005 Alberto Demichelis")
#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
#define SQ_BYTECODE_STREAM_TAG 0xFAFA
#define SQOBJECT_REF_COUNTED 0x00800000
-#define SQOBJECT_NUMERIC 0x00080000
-#define SQOBJECT_DELEGABLE 0x08000000
-#define SQOBJECT_CANBEFALSE 0x80000000
-//typedef unsigned int SQObjectType;
+#define SQOBJECT_NUMERIC 0x00400000
+#define SQOBJECT_DELEGABLE 0x00200000
+#define SQOBJECT_CANBEFALSE 0x00100000
+
+#define SQ_MATCHTYPEMASKSTRING (-99999)
#define _RT_MASK 0x0000FFFF
#define _RAW_TYPE(type) (type&_RT_MASK)
-#define _RT_NULL 0x00000000
-#define _RT_INTEGER 0x00000001
-#define _RT_FLOAT 0x00000002
-#define _RT_BOOL 0x00000004
-#define _RT_STRING 0x00000008
-#define _RT_TABLE 0x00000010
-#define _RT_ARRAY 0x00000020
-#define _RT_USERDATA 0x00000040
-#define _RT_CLOSURE 0x00000080
-#define _RT_NATIVECLOSURE 0x00000100
-#define _RT_GENERATOR 0x00000200
-#define _RT_USERPOINTER 0x00000400
-#define _RT_THREAD 0x00000800
-#define _RT_FUNCPROTO 0x00001000
-#define _RT_CLASS 0x00002000
-#define _RT_INSTANCE 0x00004000
+#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
typedef enum {
OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE),
for(level=0;level<10;level++){
seq=0;
- while( (name=sq_getlocal(v,level,seq)) )
+ while(name=sq_getlocal(v,level,seq))
{
seq++;
switch(sq_gettype(v,-1))
case OT_INSTANCE:
pf(v,_SC("[%s] INSTANCE\n"),name);
break;
- default:
- break;
}
sq_pop(v,1);
}
return 1;
}
-static int _blob_releasehook(SQUserPointer p, int )
+static int _blob_releasehook(SQUserPointer p, int size)
{
SQBlob *self = (SQBlob*)p;
delete self;
_DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
_DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
_DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
- {0,0,0,0}
+ {0,0}
};
SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr)
struct SQFile : public SQStream {
SQFile() { _handle = NULL; _owns = false;}
SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
- virtual ~SQFile() { Close(); }
+ ~SQFile() { Close(); }
bool Open(const SQChar *filename ,const SQChar *mode) {
Close();
- if( (_handle = sqstd_fopen(filename,mode)) ) {
+ if(_handle = sqstd_fopen(filename,mode)) {
_owns = true;
return true;
}
static int _file_releasehook(SQUserPointer p, int size)
{
- (void) size;
SQFile *self = (SQFile*)p;
delete self;
return 1;
}
+
static SQInteger _io_file_lexfeedASCII(SQUserPointer file)
{
int ret;
return 0;
}
-static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)
+static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
+{
+#define READ() \
+ if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \
+ return 0;
+
+ static const int 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;
+ int c = 0;
+ READ();
+ c = inchar;
+ //
+ if(c >= 0x80) {
+ int tmp;
+ int codelen = utf8_lengths[c>>4];
+ if(codelen == 0)
+ return 0;
+ //"invalid UTF-8 stream";
+ tmp = c&byte_masks[codelen];
+ for(int 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)
{
int ret;
wchar_t c;
return 0;
}
+static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file)
+{
+ int 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;
+}
+
int file_read(SQUserPointer file,SQUserPointer buf,int size)
{
int ret;
{
SQFILE file = sqstd_fopen(filename,_SC("rb"));
int ret;
- unsigned short uc;
- SQLEXREADFUNC func = _io_file_lexfeedASCII;
- if(file && (ret=sqstd_fread(&uc,1,2,file))){
- if(ret!=2) {
+ unsigned short us;
+ unsigned char uc;
+ SQLEXREADFUNC func = _io_file_lexfeed_UTF8;
+ if(file && (ret = sqstd_fread(&us,1,2,file))){
+ if(ret != 2) {
sqstd_fclose(file);
return sq_throwerror(v,_SC("io error"));
}
- if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE
+ 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);
}
}
else { //SCRIPT
- if(uc==0xFEFF)
- func = _io_file_lexfeedWCHAR;
- else
- sqstd_fseek(file,0,SQ_SEEK_SET);
+ 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);
{
if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {
sq_push(v,-2);
- //int ntop = sq_gettop(v);
+ int ntop = sq_gettop(v);
if(SQ_SUCCEEDED(sq_call(v,1,retval))) {
sq_remove(v,retval?-2:-1); //removes the closure
return 1;
static SQRegFunction iolib_funcs[]={
_DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
_DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
- {0,0,0,0}
+ {0,0}
};
SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
//create delegate
declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
sq_pushstring(v,_SC("stdout"),-1);
- sqstd_createfile(v,stdout,0);
+ sqstd_createfile(v,stdout,SQFalse);
sq_createslot(v,-3);
sq_pushstring(v,_SC("stdin"),-1);
- sqstd_createfile(v,stdin,0);
+ sqstd_createfile(v,stdin,SQFalse);
sq_createslot(v,-3);
sq_pushstring(v,_SC("stderr"),-1);
- sqstd_createfile(v,stderr,0);
+ sqstd_createfile(v,stderr,SQFalse);
sq_createslot(v,-3);
sq_settop(v,top);
return SQ_OK;
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=sqstdlib - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "sqstdlib.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "sqstdlib - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x410 /d "NDEBUG"
-# ADD RSC /l 0x410 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
-
-!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x410 /d "_DEBUG"
-# ADD RSC /l 0x410 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
-
-!ENDIF
-
-# Begin Target
-
-# Name "sqstdlib - Win32 Release"
-# Name "sqstdlib - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\sqstdblob.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdio.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdmath.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdrex.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdstream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdstring.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdaux.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdsystem.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\sqstdblobimpl.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqstdstream.h
-# End Source File
-# End Group
-# End Target
-# End Project
_DECL_FUNC(rand,1,NULL),
_DECL_FUNC(fabs,2,_SC(".n")),
_DECL_FUNC(abs,2,_SC(".n")),
- {0,0,0,0},
+ {0,0},
};
#ifndef M_PI
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <string.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include "sqstdstring.h"
-
-#ifdef _DEBUG
-#include <stdio.h>
-
-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;
- long left;
- long right;
- int next;
-}SQRexNode;
-
-struct SQRex{
- const SQChar *_eol;
- const SQChar *_bol;
- const SQChar *_p;
- int _first;
- int _op;
- SQRexNode *_nodes;
- int _nallocated;
- int _nsize;
- int _nsubexpr;
- SQRexMatch *_matches;
- int _currsubexp;
- void *_jmpbuf;
- const SQChar **_error;
-};
-
-static int sqstd_rex_list(SQRex *exp);
-
-static int 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)) {
- int 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 (int)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, int 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(!sqstd_rex_ischar(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
- return (*exp->_p++);
-}
-
-static int sqstd_rex_charclass(SQRex *exp,int classid)
-{
- int n = sqstd_rex_newnode(exp,OP_CCLASS);
- exp->_nodes[n].left = classid;
- return n;
-}
-
-static int 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) {
- int 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(!sqstd_rex_ischar(*exp->_p)) {
-
- sqstd_rex_error(exp,_SC("letter expected"));
- }
- return sqstd_rex_newnode(exp,*exp->_p++);
-}
-static int sqstd_rex_class(SQRex *exp)
-{
- int ret = -1;
- int 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 == ']' || *exp->_p == '-'){
- first = *exp->_p;
- exp->_p++;
- }
- chain = ret;
- while(*exp->_p != ']' && exp->_p != exp->_eol) {
- if(*exp->_p == '-' && first != -1){
- int 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){
- int 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){
- int 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 int sqstd_rex_parsenumber(SQRex *exp)
-{
- int ret = *exp->_p-'0';
- int 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 int sqstd_rex_element(SQRex *exp)
-{
- int ret;
- switch(*exp->_p)
- {
- case '(': {
- int 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 */
- {
- int 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 = sqstd_rex_parsenumber(exp);
- switch(*exp->_p) {
- case '}':
- p1 = p0; exp->_p++;
- goto __end;
- case ',':
- exp->_p++;
- p1 = 0xFFFF;
- if(isdigit(*exp->_p)){
- p1 = sqstd_rex_parsenumber(exp);
- }
- sqstd_rex_expect(exp,'}');
- goto __end;
- default:
- sqstd_rex_error(exp,_SC(", or } expected"));
- }
- }
- __end: {
- int 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 int sqstd_rex_list(SQRex *exp)
-{
- int 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) {
- int 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(int 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)
-{
- SQRexNodeType type = node->type;
- switch(type) {
- case OP_GREEDY: {
- int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
- const SQChar *s=str, *good = str;
- while((nmaches == 0xFFFF || nmaches < p1)
- && (s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s))) {
- good=s;
- nmaches++;
- 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)) ) {
- 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)) ) {
- 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;
- int capture = -1;
- if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
- capture = exp->_currsubexp;
- exp->_matches[capture].begin = cur;
- exp->_currsubexp++;
- }
-
- do {
- if(!(cur = sqstd_rex_matchnode(exp,n,cur))) {
- 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->_p = pattern;
- exp->_nallocated = (int)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
- {
- int 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);
- 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;
- int 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);
- 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);
-}
-
-int sqstd_rex_getsubexpcount(SQRex* exp)
-{
- return exp->_nsubexpr;
-}
-
-SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp)
-{
- if( n<0 || n >= exp->_nsubexpr) return SQFalse;
- *subexp = exp->_matches[n];
- return SQTrue;
-}
-
+/* see copyright notice in squirrel.h */\r
+#include <squirrel.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <setjmp.h>\r
+#include "sqstdstring.h"\r
+\r
+#ifdef _DEBUG\r
+#include <stdio.h>\r
+\r
+static const SQChar *g_nnames[] =\r
+{\r
+ _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),\r
+ _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),\r
+ _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),\r
+ _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")\r
+};\r
+\r
+#endif\r
+\r
+#define OP_GREEDY MAX_CHAR+1 // * + ? {n}\r
+#define OP_OR MAX_CHAR+2\r
+#define OP_EXPR MAX_CHAR+3 //parentesis ()\r
+#define OP_NOCAPEXPR MAX_CHAR+4 //parentesis (?:)\r
+#define OP_DOT MAX_CHAR+5\r
+#define OP_CLASS MAX_CHAR+6\r
+#define OP_CCLASS MAX_CHAR+7\r
+#define OP_NCLASS MAX_CHAR+8 //negates class the [^\r
+#define OP_RANGE MAX_CHAR+9\r
+#define OP_CHAR MAX_CHAR+10\r
+#define OP_EOL MAX_CHAR+11\r
+#define OP_BOL MAX_CHAR+12\r
+#define OP_WB MAX_CHAR+13\r
+\r
+#define SQREX_SYMBOL_ANY_CHAR '.'\r
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+'\r
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*'\r
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?'\r
+#define SQREX_SYMBOL_BRANCH '|'\r
+#define SQREX_SYMBOL_END_OF_STRING '$'\r
+#define SQREX_SYMBOL_BEGINNING_OF_STRING '^'\r
+#define SQREX_SYMBOL_ESCAPE_CHAR '\\'\r
+\r
+\r
+typedef int SQRexNodeType;\r
+\r
+typedef struct tagSQRexNode{\r
+ SQRexNodeType type;\r
+ long left;\r
+ long right;\r
+ int next;\r
+}SQRexNode;\r
+\r
+struct SQRex{\r
+ const SQChar *_eol;\r
+ const SQChar *_bol;\r
+ const SQChar *_p;\r
+ int _first;\r
+ int _op;\r
+ SQRexNode *_nodes;\r
+ int _nallocated;\r
+ int _nsize;\r
+ int _nsubexpr;\r
+ SQRexMatch *_matches;\r
+ int _currsubexp;\r
+ void *_jmpbuf;\r
+ const SQChar **_error;\r
+};\r
+\r
+static int sqstd_rex_list(SQRex *exp);\r
+\r
+static int sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)\r
+{\r
+ SQRexNode n;\r
+ n.type = type;\r
+ n.next = n.right = n.left = -1;\r
+ if(type == OP_EXPR)\r
+ n.right = exp->_nsubexpr++;\r
+ if(exp->_nallocated < (exp->_nsize + 1)) {\r
+ int oldsize = exp->_nallocated;\r
+ exp->_nallocated *= 2;\r
+ exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));\r
+ }\r
+ exp->_nodes[exp->_nsize++] = n;\r
+ return (int)exp->_nsize - 1;\r
+}\r
+\r
+static void sqstd_rex_error(SQRex *exp,const SQChar *error)\r
+{\r
+ if(exp->_error) *exp->_error = error;\r
+ longjmp(*((jmp_buf*)exp->_jmpbuf),-1);\r
+}\r
+\r
+static void sqstd_rex_expect(SQRex *exp, int n){\r
+ if((*exp->_p) != n) \r
+ sqstd_rex_error(exp, _SC("expected paren"));\r
+ exp->_p++;\r
+}\r
+\r
+static SQBool sqstd_rex_ischar(SQChar c)\r
+{\r
+ switch(c) {\r
+ case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE:\r
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE:\r
+ case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING:\r
+ case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}':\r
+ return SQFalse;\r
+ }\r
+ return SQTrue;\r
+}\r
+\r
+static SQChar sqstd_rex_escapechar(SQRex *exp)\r
+{\r
+ if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){\r
+ exp->_p++;\r
+ switch(*exp->_p) {\r
+ case 'v': exp->_p++; return '\v';\r
+ case 'n': exp->_p++; return '\n';\r
+ case 't': exp->_p++; return '\t';\r
+ case 'r': exp->_p++; return '\r';\r
+ case 'f': exp->_p++; return '\f';\r
+ default: return (*exp->_p++);\r
+ }\r
+ } else if(!sqstd_rex_ischar(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));\r
+ return (*exp->_p++);\r
+}\r
+\r
+static int sqstd_rex_charclass(SQRex *exp,int classid)\r
+{\r
+ int n = sqstd_rex_newnode(exp,OP_CCLASS);\r
+ exp->_nodes[n].left = classid;\r
+ return n;\r
+}\r
+\r
+static int sqstd_rex_charnode(SQRex *exp,SQBool isclass)\r
+{\r
+ if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {\r
+ exp->_p++;\r
+ switch(*exp->_p) {\r
+ case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');\r
+ case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');\r
+ case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');\r
+ case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');\r
+ case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');\r
+ case 'a': case 'A': case 'w': case 'W': case 's': case 'S': \r
+ case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': \r
+ case 'p': case 'P': case 'l': case 'u': \r
+ {\r
+ SQChar t = *exp->_p;\r
+ exp->_p++; \r
+ return sqstd_rex_charclass(exp,t);\r
+ }\r
+ case 'b': \r
+ case 'B':\r
+ if(!isclass) {\r
+ int node = sqstd_rex_newnode(exp,OP_WB);\r
+ exp->_nodes[node].left = *exp->_p;\r
+ exp->_p++; \r
+ return node;\r
+ } //else default\r
+ default: return sqstd_rex_newnode(exp,(*exp->_p++));\r
+ }\r
+ }\r
+ else if(!sqstd_rex_ischar(*exp->_p)) {\r
+ \r
+ sqstd_rex_error(exp,_SC("letter expected"));\r
+ }\r
+ return sqstd_rex_newnode(exp,*exp->_p++);\r
+}\r
+static int sqstd_rex_class(SQRex *exp)\r
+{\r
+ int ret = -1;\r
+ int first = -1,chain;\r
+ if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){\r
+ ret = sqstd_rex_newnode(exp,OP_NCLASS);\r
+ exp->_p++;\r
+ }else ret = sqstd_rex_newnode(exp,OP_CLASS);\r
+ \r
+ if(*exp->_p == ']' || *exp->_p == '-'){\r
+ first = *exp->_p;\r
+ exp->_p++;\r
+ }\r
+ chain = ret;\r
+ while(*exp->_p != ']' && exp->_p != exp->_eol) {\r
+ if(*exp->_p == '-' && first != -1){ \r
+ int r;\r
+ if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));\r
+ r = sqstd_rex_newnode(exp,OP_RANGE);\r
+ if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));\r
+ if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));\r
+ exp->_nodes[r].left = exp->_nodes[first].type;\r
+ exp->_nodes[r].right = sqstd_rex_escapechar(exp);\r
+ exp->_nodes[chain].next = r;\r
+ chain = r;\r
+ first = -1;\r
+ }\r
+ else{\r
+ if(first!=-1){\r
+ int c = first;\r
+ exp->_nodes[chain].next = c;\r
+ chain = c;\r
+ first = sqstd_rex_charnode(exp,SQTrue);\r
+ }\r
+ else{\r
+ first = sqstd_rex_charnode(exp,SQTrue);\r
+ }\r
+ }\r
+ }\r
+ if(first!=-1){\r
+ int c = first;\r
+ exp->_nodes[chain].next = c;\r
+ chain = c;\r
+ first = -1;\r
+ }\r
+ /* hack? */\r
+ exp->_nodes[ret].left = exp->_nodes[ret].next;\r
+ exp->_nodes[ret].next = -1;\r
+ return ret;\r
+}\r
+\r
+static int sqstd_rex_parsenumber(SQRex *exp)\r
+{\r
+ int ret = *exp->_p-'0';\r
+ int positions = 10;\r
+ exp->_p++;\r
+ while(isdigit(*exp->_p)) {\r
+ ret = ret*10+(*exp->_p++-'0');\r
+ if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));\r
+ positions *= 10;\r
+ };\r
+ return ret;\r
+}\r
+\r
+static int sqstd_rex_element(SQRex *exp)\r
+{\r
+ int ret;\r
+ switch(*exp->_p)\r
+ {\r
+ case '(': {\r
+ int expr;\r
+ exp->_p++;\r
+ \r
+ \r
+ if(*exp->_p =='?') {\r
+ exp->_p++;\r
+ sqstd_rex_expect(exp,':');\r
+ expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);\r
+ }\r
+ else\r
+ expr = sqstd_rex_newnode(exp,OP_EXPR);\r
+ exp->_nodes[expr].left = sqstd_rex_list(exp);\r
+ ret = expr;\r
+ sqstd_rex_expect(exp,')');\r
+ }\r
+ break;\r
+ case '[':\r
+ exp->_p++;\r
+ ret = sqstd_rex_class(exp);\r
+ sqstd_rex_expect(exp,']');\r
+ break;\r
+ case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;\r
+ case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;\r
+ default:\r
+ ret = sqstd_rex_charnode(exp,SQFalse);\r
+ break;\r
+ }\r
+ /* scope block */\r
+ {\r
+ int op;\r
+ unsigned short p0 = 0, p1 = 0;\r
+ switch(*exp->_p){\r
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end;\r
+ case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end;\r
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end;\r
+ case '{':{\r
+ exp->_p++;\r
+ if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));\r
+ p0 = sqstd_rex_parsenumber(exp);\r
+ switch(*exp->_p) {\r
+ case '}':\r
+ p1 = p0; exp->_p++;\r
+ goto __end;\r
+ case ',':\r
+ exp->_p++;\r
+ p1 = 0xFFFF;\r
+ if(isdigit(*exp->_p)){\r
+ p1 = sqstd_rex_parsenumber(exp);\r
+ }\r
+ sqstd_rex_expect(exp,'}');\r
+ goto __end;\r
+ default:\r
+ sqstd_rex_error(exp,_SC(", or } expected"));\r
+ }\r
+ }\r
+ __end: {\r
+ int nnode = sqstd_rex_newnode(exp,OP_GREEDY);\r
+ op = OP_GREEDY;\r
+ exp->_nodes[nnode].left = ret;\r
+ exp->_nodes[nnode].right = ((p0)<<16)|p1;\r
+ ret = nnode;\r
+ }\r
+ }\r
+ }\r
+ if(*exp->_p != SQREX_SYMBOL_BRANCH && *exp->_p != ')' && *exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE && *exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE && *exp->_p != '\0')\r
+ exp->_nodes[ret].next = sqstd_rex_element(exp);\r
+ return ret;\r
+}\r
+\r
+static int sqstd_rex_list(SQRex *exp)\r
+{\r
+ int ret=-1,e;\r
+ if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {\r
+ exp->_p++;\r
+ ret = sqstd_rex_newnode(exp,OP_BOL);\r
+ }\r
+ e = sqstd_rex_element(exp);\r
+ if(ret != -1) {\r
+ exp->_nodes[ret].next = e;\r
+ }\r
+ else ret = e;\r
+\r
+ if(*exp->_p == SQREX_SYMBOL_BRANCH) {\r
+ int temp;\r
+ exp->_p++;\r
+ temp = sqstd_rex_newnode(exp,OP_OR);\r
+ exp->_nodes[temp].left = ret;\r
+ exp->_nodes[temp].right = sqstd_rex_list(exp);\r
+ ret = temp;\r
+ }\r
+ return ret;\r
+}\r
+\r
+static SQBool sqstd_rex_matchcclass(int cclass,SQChar c)\r
+{\r
+ switch(cclass) {\r
+ case 'a': return isalpha(c)?SQTrue:SQFalse;\r
+ case 'A': return !isalpha(c)?SQTrue:SQFalse;\r
+ case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;\r
+ case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;\r
+ case 's': return isspace(c)?SQTrue:SQFalse;\r
+ case 'S': return !isspace(c)?SQTrue:SQFalse;\r
+ case 'd': return isdigit(c)?SQTrue:SQFalse;\r
+ case 'D': return !isdigit(c)?SQTrue:SQFalse;\r
+ case 'x': return isxdigit(c)?SQTrue:SQFalse;\r
+ case 'X': return !isxdigit(c)?SQTrue:SQFalse;\r
+ case 'c': return iscntrl(c)?SQTrue:SQFalse;\r
+ case 'C': return !iscntrl(c)?SQTrue:SQFalse;\r
+ case 'p': return ispunct(c)?SQTrue:SQFalse;\r
+ case 'P': return !ispunct(c)?SQTrue:SQFalse;\r
+ case 'l': return islower(c)?SQTrue:SQFalse;\r
+ case 'u': return isupper(c)?SQTrue:SQFalse;\r
+ }\r
+ return SQFalse; /*cannot happen*/\r
+}\r
+\r
+static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)\r
+{\r
+ do {\r
+ switch(node->type) {\r
+ case OP_RANGE:\r
+ if(c >= node->left && c <= node->right) return SQTrue;\r
+ break;\r
+ case OP_CCLASS:\r
+ if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;\r
+ break;\r
+ default:\r
+ if(c == node->type)return SQTrue;\r
+ }\r
+ } while((node->next != -1) && (node = &exp->_nodes[node->next]));\r
+ return SQFalse;\r
+}\r
+\r
+static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str)\r
+{\r
+ SQRexNodeType type = node->type;\r
+ switch(type) {\r
+ case OP_GREEDY: {\r
+ int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;\r
+ const SQChar *s=str, *good = str;\r
+ while((nmaches == 0xFFFF || nmaches < p1) \r
+ && (s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s))) {\r
+ good=s;\r
+ nmaches++;\r
+ if(s >= exp->_eol)\r
+ break;\r
+ }\r
+ if(p0 == p1 && p0 == nmaches) return good;\r
+ else if(nmaches >= p0 && p1 == 0xFFFF) return good;\r
+ else if(nmaches >= p0 && nmaches <= p1) return good;\r
+ return NULL;\r
+ }\r
+ case OP_OR: {\r
+ const SQChar *asd = str;\r
+ SQRexNode *temp=&exp->_nodes[node->left];\r
+ while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
+ if(temp->next != -1)\r
+ temp = &exp->_nodes[temp->next];\r
+ else\r
+ return asd;\r
+ }\r
+ asd = str;\r
+ temp = &exp->_nodes[node->right];\r
+ while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
+ if(temp->next != -1)\r
+ temp = &exp->_nodes[temp->next];\r
+ else\r
+ return asd;\r
+ }\r
+ return NULL;\r
+ break;\r
+ }\r
+ case OP_EXPR:\r
+ case OP_NOCAPEXPR:{\r
+ SQRexNode *n = &exp->_nodes[node->left];\r
+ const SQChar *cur = str;\r
+ int capture = -1;\r
+ if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {\r
+ capture = exp->_currsubexp;\r
+ exp->_matches[capture].begin = cur;\r
+ exp->_currsubexp++;\r
+ }\r
+\r
+ do {\r
+ if(!(cur = sqstd_rex_matchnode(exp,n,cur))) {\r
+ if(capture != -1){\r
+ exp->_matches[capture].begin = 0;\r
+ exp->_matches[capture].len = 0;\r
+ }\r
+ return NULL;\r
+ }\r
+ } while((n->next != -1) && (n = &exp->_nodes[n->next]));\r
+\r
+ if(capture != -1) \r
+ exp->_matches[capture].len = cur - exp->_matches[capture].begin;\r
+ return cur;\r
+ } \r
+ case OP_WB:\r
+ if(str == exp->_bol && !isspace(*str)\r
+ || (str == exp->_eol && !isspace(*(str-1)))\r
+ || (!isspace(*str) && isspace(*(str+1)))\r
+ || (isspace(*str) && !isspace(*(str+1))) ) {\r
+ return (node->left == 'b')?str:NULL;\r
+ }\r
+ return (node->left == 'b')?NULL:str;\r
+ case OP_BOL:\r
+ if(str == exp->_bol) return str;\r
+ return NULL;\r
+ case OP_EOL:\r
+ if(str == exp->_eol) return str;\r
+ return NULL;\r
+ case OP_DOT:\r
+ *str++;\r
+ return str;\r
+ case OP_NCLASS:\r
+ case OP_CLASS:\r
+ if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {\r
+ *str++;\r
+ return str;\r
+ }\r
+ return NULL;\r
+ case OP_CCLASS:\r
+ if(sqstd_rex_matchcclass(node->left,*str)) {\r
+ *str++;\r
+ return str;\r
+ }\r
+ return NULL;\r
+ default: /* char */\r
+ if(*str != node->type) return NULL;\r
+ *str++;\r
+ return str;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+/* public api */\r
+SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)\r
+{\r
+ SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));\r
+ exp->_p = pattern;\r
+ exp->_nallocated = (int)scstrlen(pattern) * sizeof(SQChar);\r
+ exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));\r
+ exp->_nsize = 0;\r
+ exp->_matches = 0;\r
+ exp->_nsubexpr = 0;\r
+ exp->_first = sqstd_rex_newnode(exp,OP_EXPR);\r
+ exp->_error = error;\r
+ exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));\r
+ if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {\r
+ exp->_nodes[exp->_first].left=sqstd_rex_list(exp);\r
+ if(*exp->_p!='\0')\r
+ sqstd_rex_error(exp,_SC("unexpected character"));\r
+#ifdef _DEBUG\r
+ {\r
+ int nsize,i;\r
+ SQRexNode *t;\r
+ nsize = exp->_nsize;\r
+ t = &exp->_nodes[0];\r
+ scprintf(_SC("\n"));\r
+ for(i = 0;i < nsize; i++) {\r
+ if(exp->_nodes[i].type>MAX_CHAR)\r
+ scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);\r
+ else\r
+ scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);\r
+ scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);\r
+ }\r
+ scprintf(_SC("\n"));\r
+ }\r
+#endif\r
+ exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));\r
+ memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));\r
+ }\r
+ else{\r
+ sqstd_rex_free(exp);\r
+ return NULL;\r
+ }\r
+ return exp;\r
+}\r
+\r
+void sqstd_rex_free(SQRex *exp)\r
+{\r
+ if(exp) {\r
+ if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));\r
+ if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));\r
+ if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));\r
+ sq_free(exp,sizeof(SQRex));\r
+ }\r
+}\r
+\r
+SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)\r
+{\r
+ const SQChar* res = NULL;\r
+ exp->_bol = text;\r
+ exp->_eol = text + scstrlen(text);\r
+ exp->_currsubexp = 0;\r
+ res = sqstd_rex_matchnode(exp,exp->_nodes,text);\r
+ if(res == NULL || res != exp->_eol)\r
+ return SQFalse;\r
+ return SQTrue;\r
+}\r
+\r
+SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)\r
+{\r
+ const SQChar *cur = NULL;\r
+ int node = exp->_first;\r
+ if(text_begin >= text_end) return SQFalse;\r
+ exp->_bol = text_begin;\r
+ exp->_eol = text_end;\r
+ do {\r
+ cur = text_begin;\r
+ while(node != -1) {\r
+ exp->_currsubexp = 0;\r
+ cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur);\r
+ if(!cur)\r
+ break;\r
+ node = exp->_nodes[node].next;\r
+ }\r
+ *text_begin++;\r
+ } while(cur == NULL && text_begin != text_end);\r
+\r
+ if(cur == NULL)\r
+ return SQFalse;\r
+\r
+ --text_begin;\r
+\r
+ if(out_begin) *out_begin = text_begin;\r
+ if(out_end) *out_end = cur;\r
+ return SQTrue;\r
+}\r
+\r
+SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)\r
+{\r
+ return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);\r
+}\r
+\r
+int sqstd_rex_getsubexpcount(SQRex* exp)\r
+{\r
+ return exp->_nsubexpr;\r
+}\r
+\r
+SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp)\r
+{\r
+ if( n<0 || n >= exp->_nsubexpr) return SQFalse;\r
+ *subexp = exp->_matches[n];\r
+ return SQTrue;\r
+}\r
+\r
break;
case _SC('u'): {
wchar_t *temp;
- if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)), size * sizeof(wchar_t)) != (int) (size * sizeof(wchar_t)))
+ if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)),size * sizeof(wchar_t)) != (size * sizeof(wchar_t)))
return sq_throwerror(v, _SC("io failure"));
#ifdef _UNICODE
_DECL_STREAM_FUNC(len,1,_SC("x")),
_DECL_STREAM_FUNC(eos,1,_SC("x")),
_DECL_STREAM_FUNC(flush,1,_SC("x")),
- {0,0,0,0}
+ {0,0}
};
void init_streamclass(HSQUIRRELVM v)
static int _rexobj_releasehook(SQUserPointer p, int size)
{
- (void) size;
SQRex *self = ((SQRex *)p);
sqstd_rex_free(self);
return 1;
_DECL_REX_FUNC(capture,-2,_SC("xsn")),
_DECL_REX_FUNC(subexpcount,1,_SC("x")),
_DECL_REX_FUNC(_typeof,1,_SC("x")),
- {0,0,0,0}
+ {0,0}
};
#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
static SQRegFunction stringlib_funcs[]={
_DECL_FUNC(format,-2,_SC(".s")),
- {0,0,0,0}
+ {0,0}
};
_DECL_FUNC(date,-1,_SC(".nn")),
_DECL_FUNC(remove,2,_SC(".s")),
_DECL_FUNC(rename,3,_SC(".ss")),
- {0,0,0,0}
+ {0,0}
};
#include "sqfuncproto.h"
#include "sqclosure.h"
#include "squserdata.h"
-#include "sqfuncstate.h"
#include "sqcompiler.h"
+#include "sqfuncstate.h"
#include "sqclass.h"
bool sq_aux_gettypedarg(HSQUIRRELVM v,int idx,SQObjectType type,SQObjectPtr **o)
else {
nc->_typecheck.resize(0);
}
+ if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
+ nc->_nparamscheck = nc->_typecheck.size();
+ }
return SQ_OK;
}
v->Push(SQObjectPtr(_userdata(self)->_delegate));
return SQ_OK;
break;
- default:
- break;
}
return sq_throwerror(v,_SC("wrong type"));
}
case OT_INSTANCE:
_instance(ud)->_hook = hook;
break;
- default:
- break;
}
}
}
{
SQObjectPtr *o = NULL;
_GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
- //SQClosure *c=_closure(*o);
+ SQClosure *c=_closure(*o);
unsigned short tag = SQ_BYTECODE_STREAM_TAG;
if(w(up,&tag,2) != 2)
return sq_throwerror(v,_SC("io error"));
sq_pushstring(v, _SC("locals"), -1);
sq_newtable(v);
seq=0;
- while ( (name = sq_getlocal(v, level, seq)) ) {
+ while (name = sq_getlocal(v, level, seq)) {
sq_pushstring(v, name, -1);
sq_push(v, -2);
sq_createslot(v, -4);
#ifndef NO_GARBAGE_COLLECTOR
{_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
#endif
- {0,0,0,0}
+ {0,0}
};
void sq_base_register(HSQUIRRELVM v)
{_SC("rawset"),table_rawset,3, _SC("t")},
{_SC("rawdelete"),table_rawdelete,2, _SC("t")},
{_SC("rawin"),container_rawexists,2, _SC("t")},
- {0,0,0,0}
+ {0,0}
};
//ARRAY DEFAULT DELEGATE///////////////////////////////////////
//QSORT ala Sedgewick
bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,int func,int &ret)
{
- (void) arr;
-
if(func < 0) {
if(!v->ObjCmp(a,b,ret)) return false;
}
{_SC("reverse"),array_reverse,1, _SC("a")},
{_SC("sort"),array_sort,-1, _SC("ac")},
{_SC("slice"),array_slice,-1, _SC("ann")},
- {0,0,0,0}
+ {0,0}
};
//STRING DEFAULT DELEGATE//////////////////////////
{_SC("find"),string_find,-2, _SC("s s n ")},
{_SC("tolower"),string_tolower,1, _SC("s")},
{_SC("toupper"),string_toupper,1, _SC("s")},
- {0,0,0,0}
+ {0,0}
};
//INTEGER DEFAULT DELEGATE//////////////////////////
{_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
{_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},
{_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
- {0,0,0,0}
+ {0,0}
};
//CLOSURE DEFAULT DELEGATE//////////////////////////
SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
{_SC("call"),closure_call,-1, _SC("c")},
{_SC("acall"),closure_acall,2, _SC("ca")},
- {0,0,0,0}
+ {0,0}
};
//GENERATOR DEFAULT DELEGATE
SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
{_SC("getstatus"),generator_getstatus,1, _SC("g")},
- {0,0,0,0}
+ {0,0}
};
//THREAD DEFAULT DELEGATE
{_SC("call"), thread_call, -1, _SC("v")},
{_SC("wakeup"), thread_wakeup, -1, _SC("v")},
{_SC("getstatus"), thread_getstatus, 1, _SC("v")},
- {0,0,0,0},
+ {0,0},
};
static int class_getattributes(HSQUIRRELVM v)
{_SC("getattributes"), class_getattributes, 2, _SC("y.")},
{_SC("setattributes"), class_setattributes, 3, _SC("y..")},
{_SC("rawin"),container_rawexists,2, _SC("y")},
- {0,0,0,0}
+ {0,0}
};
static int instance_getclass(HSQUIRRELVM v)
SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
{_SC("getclass"), instance_getclass, 1, _SC("x")},
{_SC("rawin"),container_rawexists,2, _SC("x")},
- {0,0,0,0}
+ {0,0}
};
}
else {
if(type(temp) == OT_NULL) {
- SQClassMember m;
+ SQClassMemeber m;
m.val = val;
- _members->NewSlot(key, SQObjectPtr((SQUserPointer)_methods.size()));
+ _members->NewSlot(key,SQObjectPtr((SQUserPointer)_methods.size()));
_methods.push_back(m);
}
else {
- _methods[_integer(temp)].val = val;
+ _methods[(int)_userpointer(temp)].val = val;
}
}
return true;
}
- SQClassMember m;
+ SQClassMemeber m;
m.val = val;
_members->NewSlot(key,SQObjectPtr((SQInteger)_defaultvalues.size()));
_defaultvalues.push_back(m);
int idx = _members->Next(refpos,outkey,oval);
if(idx != -1) {
if(type(oval) != OT_INTEGER) {
- outval = _methods[_integer(oval)].val;
+ outval = _methods[(int)_userpointer(oval)].val;
}
else {
outval = _defaultvalues[_integer(oval)].val;
if(type(idx) == OT_INTEGER)
_defaultvalues[_integer(idx)].attrs = val;
else
- _methods[_integer(idx)].attrs = val;
+ _methods[(int)_userpointer(idx)].attrs = val;
return true;
}
return false;
struct SQInstance;
-struct SQClassMember {
- SQClassMember(){}
- SQClassMember(const SQClassMember &o) {
+struct SQClassMemeber {
+ SQClassMemeber(){}
+ SQClassMemeber(const SQClassMemeber &o) {
val = o.val;
attrs = o.attrs;
}
SQObjectPtr attrs;
};
-typedef sqvector<SQClassMember> SQClassMemberVec;
+typedef sqvector<SQClassMemeber> SQClassMemeberVec;
struct SQClass : public CHAINABLE_OBJ
{
bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
if(_members->Get(key,val)) {
- val = (type(val) == OT_INTEGER?_defaultvalues[_integer(val)].val:_methods[_integer(val)].val);
+ val = (type(val) == OT_INTEGER?_defaultvalues[_integer(val)].val:_methods[(int)_userpointer(val)].val);
return true;
}
return false;
SQTable *_members;
//SQTable *_properties;
SQClass *_base;
- SQClassMemberVec _defaultvalues;
- SQClassMemberVec _methods;
+ SQClassMemeberVec _defaultvalues;
+ SQClassMemeberVec _methods;
SQObjectPtrVec _metamethods;
SQObjectPtr _attributes;
unsigned int _typetag;
~SQInstance();
bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
if(_class->_members->Get(key,val)) {
- val = (type(val) == OT_INTEGER?_values[_integer(val)]:_class->_methods[_integer(val)].val);
+ val = (type(val) == OT_INTEGER?_values[_integer(val)]:_class->_methods[(int)_userpointer(val)].val);
return true;
}
return false;
*/
#include "sqpcheader.h"
#include <stdarg.h>
+#include <setjmp.h>
#include "sqopcodes.h"
#include "sqstring.h"
#include "sqfuncproto.h"
-#include "sqfuncstate.h"
#include "sqcompiler.h"
+#include "sqfuncstate.h"
#include "sqlexer.h"
#include "sqvm.h"
SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
{
_vm=v;
- _lex.Init(_ss(v), rg, up);
+ _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, ...)
{
va_start(vl, s);
scvsprintf(temp, s, vl);
va_end(vl);
- throw ParserException(temp);
+ compilererror = temp;
+ longjmp(_errorjmp,1);
}
void Lex(){ _token = _lex.Lex();}
void PushExpState(){ _expstates.push_back(ExpState()); }
_expstates.pop_back();
return ret;
}
- SQObjectPtr Expect(int tok)
+ SQObject Expect(int tok)
{
- SQObjectPtr ret;
+
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:
- ret = SQString::Create(_ss(_vm), _SC("IDENTIFIER"));
+ etypename = _SC("IDENTIFIER");
break;
case TK_STRING_LITERAL:
- ret = SQString::Create(_ss(_vm), _SC("STRING_LITERAL"));
+ etypename = _SC("STRING_LITERAL");
break;
case TK_INTEGER:
- ret = SQString::Create(_ss(_vm), _SC("INTEGER"));
+ etypename = _SC("INTEGER");
break;
case TK_FLOAT:
- ret = SQString::Create(_ss(_vm), _SC("FLOAT"));
+ etypename = _SC("FLOAT");
break;
default:
- ret = _lex.Tok2Str(tok);
+ etypename = _lex.Tok2Str(tok);
}
- Error(_SC("expected '%s'"), _stringval(ret));
+ Error(_SC("expected '%s'"), etypename);
}
Error(_SC("expected '%c'"), tok);
}
}
+ SQObjectPtr ret;
switch(tok)
{
case TK_IDENTIFIER:
- ret = SQString::Create(_ss(_vm), _lex._svalue);
+ ret = _fs->CreateString(_lex._svalue);
break;
case TK_STRING_LITERAL:
- ret = SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1);
+ ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
break;
case TK_INTEGER:
- ret = _lex._nvalue;
+ ret = SQObjectPtr(_lex._nvalue);
break;
case TK_FLOAT:
- ret = _lex._fvalue;
+ ret = SQObjectPtr(_lex._fvalue);
break;
}
Lex();
}
bool Compile(SQObjectPtr &o)
{
- SQ_TRY {
- _debugline = 1;
- _debugop = 0;
+ _debugline = 1;
+ _debugop = 0;
+
+ SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), NULL,ThrowError,this);
+ _funcproto(funcstate._func)->_name = SQString::Create(_ss(_vm), _SC("main"));
+ _fs = &funcstate;
+ _fs->AddParameter(_fs->CreateString(_SC("this")));
+ _funcproto(_fs->_func)->_sourcename = _sourcename;
+ int stacksize = _fs->GetStackSize();
+ if(setjmp(_errorjmp) == 0) {
Lex();
- SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), NULL);
- _funcproto(funcstate._func)->_name = SQString::Create(_ss(_vm), _SC("main"));
- _fs = &funcstate;
- _fs->AddParameter(SQString::Create(_ss(_vm), _SC("this")));
- _funcproto(_fs->_func)->_sourcename = _sourcename;
- int stacksize = _fs->GetStackSize();
while(_token > 0){
Statement();
if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
_fs->Dump();
#endif
}
- SQ_CATCH(ParserException,ex){
- if(_raiseerror && _ss(_vm)->_compilererrorhandler){
- SQObjectPtr ret;
- _ss(_vm)->_compilererrorhandler(_vm, ex.desc, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
+ 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), ex.desc, -1);
+ _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
return false;
}
return true;
case TK_MULEQ: oper = '*'; break;
case TK_DIVEQ: oper = '/'; break;
case TK_MODEQ: oper = '%'; break;
- default: oper = 0; assert(0); break;
+ default: assert(0); break;
};
if(deref) {
int val = _fs->PopTarget();
switch(_token) {
case _SC('.'): {
pos = -1;
- SQObjectPtr idx;
Lex();
if(_token == TK_PARENT) {
Lex();
_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
}
else {
- idx = Expect(TK_IDENTIFIER);
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(idx)));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
if(NeedGet()) Emit2ArgsOP(_OP_GET);
}
_exst._deref = DEREF_FIELD;
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->GetStringConstant(_stringval(id)));
+ //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_CONSTRUCTOR:
case TK_THIS:{
_exst._freevar = false;
- SQObjectPtr id;
+ SQObject id;
switch(_token) {
- case TK_IDENTIFIER: id = SQString::Create(_ss(_vm), _lex._svalue); break;
- case TK_THIS: id = SQString::Create(_ss(_vm), _SC("this")); break;
- case TK_CONSTRUCTOR: id = SQString::Create(_ss(_vm), _SC("constructor")); break;
+ 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;
}
int pos = -1;
Lex();
_exst._freevar = true;
} else {
_fs->PushTarget(0);
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
if(NeedGet()) Emit2ArgsOP(_OP_GET);
_exst._deref = DEREF_FIELD;
}
case TK_CONSTRUCTOR:{
int tk = _token;
Lex();
- SQObjectPtr id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : SQString::Create(_ss(_vm),_SC("constructor"));
+ SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
Expect(_SC('('));
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
CreateFunction(id);
_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
}
Expect(_SC('=')); Expression();
break;
default :
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(Expect(TK_IDENTIFIER))));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
Expect(_SC('=')); Expression();
}
}
void LocalDeclStatement()
{
- SQObjectPtr varname;
+ SQObject varname;
do {
Lex(); varname = Expect(TK_IDENTIFIER);
if(_token == _SC('=')) {
}
void ForEachStatement()
{
- SQObjectPtr idxname, valname;
+ SQObject idxname, valname;
Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
if(_token == _SC(',')) {
idxname = valname;
Lex(); valname = Expect(TK_IDENTIFIER);
}
else{
- idxname = SQString::Create(_ss(_vm), _SC("@INDEX@"));
+ idxname = _fs->CreateString(_SC("@INDEX@"));
}
Expect(TK_IN);
int valuepos = _fs->PushLocalVariable(valname);
_fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
//push reference index
- int itrpos = _fs->PushLocalVariable(SQString::Create(_ss(_vm), _SC("@ITERATOR@"))); //use invalid id to make it inaccessible
+ int itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
_fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
int jmppos = _fs->GetCurrentPos();
_fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
}
void FunctionStatement()
{
- SQObjectPtr id;
+ SQObject id;
Lex(); id = Expect(TK_IDENTIFIER);
_fs->PushTarget(0);
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ _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->GetStringConstant(_stringval(id)));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
}
Expect(_SC('('));
}
void TryCatchStatement()
{
- SQObjectPtr exid;
+ SQObject exid;
Lex();
_fs->AddInstruction(_OP_PUSHTRAP,0,0);
_fs->_traps++;
_fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
}
}
- void CreateFunction(SQObjectPtr name)
+ void CreateFunction(SQObject &name)
{
- SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), _fs);
- _funcproto(funcstate._func)->_name = name;
- SQObjectPtr paramname;
- funcstate.AddParameter(SQString::Create(_ss(_vm), _SC("this")));
- _funcproto(funcstate._func)->_sourcename = _sourcename;
+
+ SQFuncState *funcstate = _fs->PushChildState(_ss(_vm), SQFunctionProto::Create());
+ _funcproto(funcstate->_func)->_name = name;
+ SQObject paramname;
+ funcstate->AddParameter(_fs->CreateString(_SC("this")));
+ _funcproto(funcstate->_func)->_sourcename = _sourcename;
while(_token!=_SC(')')) {
if(_token == TK_VARPARAMS) {
- funcstate._varparams = true;
+ funcstate->_varparams = true;
Lex();
if(_token != _SC(')')) Error(_SC("expected ')'"));
break;
}
else {
paramname = Expect(TK_IDENTIFIER);
- funcstate.AddParameter(paramname);
+ funcstate->AddParameter(paramname);
if(_token == _SC(',')) Lex();
else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
}
while(_token != _SC(')')) {
paramname = Expect(TK_IDENTIFIER);
//outers are treated as implicit local variables
- funcstate.AddOuterValue(paramname);
+ funcstate->AddOuterValue(paramname);
if(_token == _SC(',')) Lex();
else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
}
}
SQFuncState *currchunk = _fs;
- _fs = &funcstate;
+ _fs = funcstate;
Statement();
- funcstate.AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
- funcstate.AddInstruction(_OP_RETURN, -1);
- funcstate.SetStackSize(0);
+ funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
+ funcstate->AddInstruction(_OP_RETURN, -1);
+ funcstate->SetStackSize(0);
_funcproto(_fs->_func)->_stacksize = _fs->_stacksize;
- funcstate.Finalize();
+ funcstate->Finalize();
#ifdef _DEBUG_DUMP
- funcstate.Dump();
+ funcstate->Dump();
#endif
_fs = currchunk;
- _fs->_functions.push_back(funcstate._func);
+ _fs->_functions.push_back(funcstate->_func);
+ _fs->PopChildState();
}
void CleanStack(int stacksize)
{
int _debugline;
int _debugop;
ExpStateVec _expstates;
+ SQChar *compilererror;
+ jmp_buf _errorjmp;
SQVM *_vm;
};
#define TK_ATTR_CLOSE 321
-struct ParserException{ SQChar *desc; ParserException(SQChar *err):desc(err) {} };
+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_
si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
si->line = -1;
break;
- default:
- break;
}
return SQ_OK;
}
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: break;
}
}
-SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)
+SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
{
_nliterals = 0;
_literals = SQTable::Create(ss,0);
+ _strings = SQTable::Create(ss,0);
_sharedstate = ss;
_lastline = 0;
_optimization = true;
_traps = 0;
_returnexp = 0;
_varparams = false;
+ _errfunc = efunc;
+ _errtarget = ed;
+
+}
+
+void SQFuncState::Error(const SQChar *err)
+{
+ _errfunc(_errtarget,err);
}
#ifdef _DEBUG_DUMP
scprintf(_SC("--------------------------------------------------------------------\n\n"));
}
#endif
-int SQFuncState::GetStringConstant(const SQChar *cons)
+/*int SQFuncState::GetStringConstant(SQObjectPtr &cons)
{
- return GetConstant(SQString::Create(_sharedstate,cons));
-}
+ return GetConstant(cons);
+}*/
int SQFuncState::GetNumericConstant(const SQInteger cons)
{
- return GetConstant(cons);
+ return GetConstant(SQObjectPtr(cons));
}
int SQFuncState::GetNumericConstant(const SQFloat cons)
{
- return GetConstant(cons);
+ return GetConstant(SQObjectPtr(cons));
}
-int SQFuncState::GetConstant(SQObjectPtr cons)
+int SQFuncState::GetConstant(const SQObject &cons)
{
- // int n=0;
+ int n=0;
SQObjectPtr val;
if(!_table(_literals)->Get(cons,val))
{
val = _nliterals;
_table(_literals)->NewSlot(cons,val);
_nliterals++;
- if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));
+ if(_nliterals > MAX_LITERALS) {
+ val.Null();
+ Error(_SC("internal compiler error: too many literals"));
+ }
}
return _integer(val);
}
int npos=_vlocals.size();
_vlocals.push_back(SQLocalVarInfo());
if(_vlocals.size()>((unsigned int)_stacksize)) {
- if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));
+ if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
_stacksize=_vlocals.size();
}
return npos;
return false;
}
-int SQFuncState::PushLocalVariable(const SQObjectPtr &name)
+int SQFuncState::PushLocalVariable(const SQObject &name)
{
int pos=_vlocals.size();
SQLocalVarInfo lvi;
return pos;
}
-int SQFuncState::GetLocalVariable(const SQObjectPtr &name)
+int SQFuncState::GetLocalVariable(const SQObject &name)
{
int locals=_vlocals.size();
while(locals>=1){
return -1;
}
-int SQFuncState::GetOuterVariable(const SQObjectPtr &name)
+int SQFuncState::GetOuterVariable(const SQObject &name)
{
int outers = _outervalues.size();
for(int i = 0; i<outers; i++) {
return -1;
}
-void SQFuncState::AddOuterValue(const SQObjectPtr &name)
+void SQFuncState::AddOuterValue(const SQObject &name)
{
//AddParameter(name);
int pos=-1;
_outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
}
-void SQFuncState::AddParameter(const SQObjectPtr &name)
+void SQFuncState::AddParameter(const SQObject &name)
{
PushLocalVariable(name);
_parameters.push_back(name);
_instructions.push_back(i);
}
-SQObject SQFuncState::CreateString(const SQChar *s)
+SQObject SQFuncState::CreateString(const SQChar *s,int len)
{
- SQObjectPtr ns(SQString::Create(_sharedstate,s));
- _stringrefs.push_back(ns);
+ SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
+ _table(_strings)->NewSlot(ns,1);
return ns;
}
f->_lineinfos.copy(_lineinfos);
f->_varparams = _varparams;
}
+
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss,SQFunctionProto *func)
+{
+ SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
+ new (child) SQFuncState(ss,func,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();
+ }
+}
///////////////////////////////////
#include "squtils.h"
-
-
struct SQFuncState
{
- SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent);
+ SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
+ ~SQFuncState();
#ifdef _DEBUG_DUMP
void Dump();
#endif
+ void Error(const SQChar *err);
+ SQFuncState *PushChildState(SQSharedState *ss,SQFunctionProto *func);
+ void PopChildState();
void AddInstruction(SQOpcode _op,int arg0=0,int arg1=0,int arg2=0,int arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
void AddInstruction(SQInstruction &i);
void SetIntructionParams(int pos,int arg0,int arg1,int arg2=0,int arg3=0);
void SetStackSize(int n);
void SnoozeOpt(){_optimization=false;}
int GetCurrentPos(){return _instructions.size()-1;}
- int GetStringConstant(const SQChar *cons);
+ //int GetStringConstant(const SQChar *cons);
int GetNumericConstant(const SQInteger cons);
int GetNumericConstant(const SQFloat cons);
- int PushLocalVariable(const SQObjectPtr &name);
- void AddParameter(const SQObjectPtr &name);
- void AddOuterValue(const SQObjectPtr &name);
- int GetLocalVariable(const SQObjectPtr &name);
- int GetOuterVariable(const SQObjectPtr &name);
+ int PushLocalVariable(const SQObject &name);
+ void AddParameter(const SQObject &name);
+ void AddOuterValue(const SQObject &name);
+ int GetLocalVariable(const SQObject &name);
+ int GetOuterVariable(const SQObject &name);
int GenerateCode();
int GetStackSize();
int CalcStackFrameSize();
int TopTarget();
int GetUpTarget(int n);
bool IsLocal(unsigned int stkpos);
- SQObject CreateString(const SQChar *s);
+ SQObject CreateString(const SQChar *s,int len = -1);
int _returnexp;
SQLocalVarInfoVec _vlocals;
SQIntVec _targetstack;
SQIntVec _unresolvedcontinues;
SQObjectPtrVec _functions;
SQObjectPtrVec _parameters;
- SQObjectPtrVec _stringrefs;
SQOuterVarVec _outervalues;
SQInstructionVec _instructions;
SQLocalVarInfoVec _localvarinfos;
SQObjectPtr _literals;
+ SQObjectPtr _strings;
SQInteger _nliterals;
SQLineInfoVec _lineinfos;
SQObjectPtr _func;
int _traps;
bool _optimization;
SQSharedState *_sharedstate;
+ sqvector<SQFuncState*> _childstates;
+ int GetConstant(const SQObject &cons);
private:
- int GetConstant(SQObjectPtr cons);
+ CompilerErrorFunc _errfunc;
+ void *_errtarget;
};
_keywords->Release();
}
-void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)
+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);
Next();
}
+void SQLexer::Error(const SQChar *err)
+{
+ _errfunc(_errtarget,err);
+}
+
void SQLexer::Next()
{
SQInteger t = _readf(_up);
- if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));
+ if(t > MAX_CHAR) Error(_SC("Invalid character"));
if(t != 0) {
_currdata = t;
return;
_currdata = SQUIRREL_EOB;
}
-SQObjectPtr SQLexer::Tok2Str(int tok)
+const SQChar *SQLexer::Tok2Str(int tok)
{
SQObjectPtr itr, key, val;
int nitr;
while((nitr = _keywords->Next(itr, key, val)) != -1) {
itr = (SQInteger)nitr;
if(((int)_integer(val)) == tok)
- return key;
+ return _stringval(key);
}
- return SQObjectPtr();
+ return NULL;
}
void SQLexer::LexBlockComment()
case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
//case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;
case _SC('\n'): _currentline++; NEXT(); continue;
- case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));
+ case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
default: NEXT();
}
}
int stype;
NEXT();
if(CUR_CHAR != _SC('"'))
- throw ParserException(_SC("string expected"));
+ Error(_SC("string expected"));
if((stype=ReadString('"',true))!=-1) {
RETURN_TOKEN(stype);
}
- throw ParserException(_SC("error parsing the string"));
+ Error(_SC("error parsing the string"));
}
case _SC('"'):
case _SC('\''): {
if((stype=ReadString(CUR_CHAR,false))!=-1){
RETURN_TOKEN(stype);
}
- throw ParserException(_SC("error parsing the string"));
+ 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('~'):
NEXT();
if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
NEXT();
- if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }
+ if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
NEXT();
RETURN_TOKEN(TK_VARPARAMS);
case _SC('&'):
}
else {
int c = CUR_CHAR;
- if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));
+ if (sciscntrl(c)) Error(_SC("unexpected character(control)"));
NEXT();
RETURN_TOKEN(c);
}
while(CUR_CHAR != ndelim) {
switch(CUR_CHAR) {
case SQUIRREL_EOB:
- throw ParserException(_SC("unfinished string"));
+ Error(_SC("unfinished string"));
return -1;
case _SC('\n'):
- if(!verbatim) throw ParserException(_SC("newline in a constant"));
+ if(!verbatim) Error(_SC("newline in a constant"));
APPEND_CHAR(CUR_CHAR); NEXT();
break;
case _SC('\\'):
APPEND_CHAR('\\'); NEXT();
}
else {
-
NEXT();
switch(CUR_CHAR) {
+ case _SC('x'): NEXT(); {
+ if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
+ const int maxdigits = 4;
+ SQChar temp[maxdigits+1];
+ int 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('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
default:
- throw ParserException(_SC("unrecognised escaper char"));
+ Error(_SC("unrecognised escaper char"));
break;
}
}
TERMINATE_BUFFER();
int len = _longstr.size()-1;
if(ndelim == _SC('\'')) {
- if(len == 0) throw ParserException(_SC("empty constant"));
- if(len > 1) throw ParserException(_SC("constant too long"));
+ if(len == 0) Error(_SC("empty constant"));
+ if(len > 1) Error(_SC("constant too long"));
_nvalue = _longstr[0];
return TK_INTEGER;
}
#define THEX 3
#define TSCIENTIFIC 4
int type = TINT, firstchar = CUR_CHAR;
- //bool isfloat = false;
+ bool isfloat = false;
SQChar *sTemp;
INIT_TEMP_STRING();
NEXT();
APPEND_CHAR(CUR_CHAR);
NEXT();
}
- if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));
+ if(_longstr.size() > 8) Error(_SC("Hex number over 8 digits"));
}
else {
APPEND_CHAR(firstchar);
while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
if(CUR_CHAR == _SC('.')) type = TFLOAT;
if(isexponent(CUR_CHAR)) {
- if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));
+ if(type != TFLOAT) Error(_SC("invalid numeric format"));
type = TSCIENTIFIC;
APPEND_CHAR(CUR_CHAR);
NEXT();
APPEND_CHAR(CUR_CHAR);
NEXT();
}
- if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));
+ if(!scisdigit(CUR_CHAR)) Error(_SC("exponent expected"));
}
APPEND_CHAR(CUR_CHAR);
int SQLexer::ReadID()
{
- int res;
- // int size = 0;
+ int res, size = 0;
INIT_TEMP_STRING();
do {
APPEND_CHAR(CUR_CHAR);
#define MAX_STRING 2024
+
+
struct SQLexer
{
SQLexer();
~SQLexer();
- void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);
+ void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);
+ void Error(const SQChar *err);
int Lex();
- SQObjectPtr Tok2Str(int tok);
+ const SQChar *Tok2Str(int tok);
private:
int GetIDType(SQChar *s);
int ReadString(int ndelim,bool verbatim);
#endif
SQSharedState *_sharedstate;
sqvector<SQChar> _longstr;
+ CompilerErrorFunc _errfunc;
+ void *_errtarget;
};
#endif
#include "sqpcheader.h"
void *sq_vm_malloc(unsigned int size){ return malloc(size); }
-void *sq_vm_realloc(void *p, unsigned int , unsigned int size){ return realloc(p, size); }
+void *sq_vm_realloc(void *p, unsigned int oldsize, unsigned int size){ return realloc(p, size); }
-void sq_vm_free(void *p, unsigned int ){ free(p); }
+void sq_vm_free(void *p, unsigned int size){ free(p); }
return 0;
case OT_INTEGER:
return (unsigned int)_integer(idx);
- default:
- break;
}
assert(0);
return 0;
#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
-#define SQ_TRY try
-#define SQ_CATCH(type, ex) catch(type &ex)
-
struct SQSharedState;
enum SQMetaMethod{
struct SQRefCounted
{
- virtual ~SQRefCounted()
- {}
unsigned int _uiRef;
virtual void Release()=0;
};
{
__Release(_type,_unVal);
}
- void Null()
+ inline void Null()
{
__Release(_type,_unVal);
_type=OT_NULL;
_unVal.pUserPointer=NULL;
}
- SQObjectPtr& operator=(const SQObjectPtr& obj)
+ inline SQObjectPtr& operator=(const SQObjectPtr& obj)
{
SQObjectType tOldType;
SQObjectValue unOldVal;
__Release(tOldType,unOldVal);
return *this;
}
- SQObjectPtr& operator=(const SQObject& obj)
+ inline SQObjectPtr& operator=(const SQObject& obj)
{
SQObjectType tOldType;
SQObjectValue unOldVal;
#ifndef _SQOPCODES_H_
#define _SQOPCODES_H_
-#include <limits.h>
-
#define MAX_FUNC_STACKSIZE 0xFF
-#define MAX_LITERALS INT_MAX
+#define MAX_LITERALS 0xFFFFFFFF
enum BitWiseOP {
BW_AND = 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 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;
}
}
int SQSharedState::CollectGarbage(SQVM *vm)
{
- (void) vm;
int n=0;
SQCollectable *tchain=NULL;
SQVM *vms=_thread(_root_vm);
default: return hashptr(key._unVal.pRefCounted);
}
}
- _HashNode *_Get(const SQObjectPtr &key,unsigned long hash)
+ inline _HashNode *_Get(const SQObjectPtr &key,unsigned long hash)
{
_HashNode *n = &_nodes[hash];
do{
if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
return n;
}
- }while( (n = n->next) );
+ }while(n = n->next);
return NULL;
}
bool Get(const SQObjectPtr &key,SQObjectPtr &val);
T& top() const { return _vals[_size - 1]; }
inline unsigned int size() const { return _size; }
bool empty() const { return (_size <= 0); }
- inline void push_back(const T& val = T())
+ inline T &push_back(const T& val = T())
{
if(_allocated <= _size)
_realloc(_size * 2);
- new ((void *)&_vals[_size++]) T(val);
+ return *(new ((void *)&_vals[_size++]) T(val));
}
inline void pop_back()
{
}
unsigned int capacity() { return _allocated; }
inline T &back() const { return _vals[_size - 1]; }
- T& operator[](unsigned int pos) const{ return _vals[pos]; }
+ inline T& operator[](unsigned int pos) const{ return _vals[pos]; }
T* _vals;
private:
void _realloc(unsigned int newsize)
#include "sqpcheader.h"
#include <math.h>
#include <stdlib.h>
-#include <assert.h>
#include "sqopcodes.h"
#include "sqfuncproto.h"
#include "sqvm.h"
SQVM::SQVM(SQSharedState *ss)
{
_sharedstate=ss;
- _suspended=false;
+ _suspended = SQFalse;
_suspended_target=-1;
- _suspended_root=false;
+ _suspended_root = SQFalse;
_suspended_traps=-1;
_foreignptr=NULL;
_nnativecalls=0;
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;
}
if(is_delegable(o1) && _delegable(o1)->_delegate) {
Push(o1);Push(o2);
}
}
return true;
- default:
- break;
+
}
Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
return false;
Push(o1);Push(o2);
if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);
break;
- default:
- break;
}
if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
_RET_SUCCEED(_integer(res));
//const int outerssize = func->_outervalues.size();
const int paramssize = func->_parameters.size();
- // const int oldtop = _top;
+ const int oldtop = _top;
const int newtop = stackbase + func->_stacksize;
ci->_target = target;
ci->_prevtop = _top - _stackbase;
ci->_ncalls = 1;
- ci->_root = false;
+ ci->_root = SQFalse;
}
else {
ci->_ncalls++;
for(int i=0;i<ci->_ncalls;i++)
CallDebugHook(_SC('r'));
- bool broot = ci->_root;
+ SQBool broot = ci->_root;
int last_top = _top;
int target = ci->_target;
int oldstackbase = _stackbase;
_stackbase -= ci->_prevstkbase;
_top = _stackbase + ci->_prevtop;
- PopVarArgs(ci->_vargs);
+ if(ci->_vargs.size) PopVarArgs(ci->_vargs);
POP_CALLINFO(this);
if (broot) {
if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1];
while (last_top >= _top) _stack[last_top--].Null();
assert(oldstackbase >= _stackbase);
- return broot;
+ return broot?true:false;
}
#define _RET_ON_FAIL(exp) { if(!exp) return false; }
_generator(o1)->Resume(this, arg_2+1);
_FINISH(false);
}
- default:
- break;
}
Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
return false; //cannot be hit(just to avoid warnings)
{
int nouters;
SQClosure *closure = SQClosure::Create(_ss(this), func);
- if( (nouters = func->_outervalues.size()) ) {
+ if(nouters = func->_outervalues.size()) {
closure->_outervalues.reserve(nouters);
for(int i = 0; i<nouters; i++) {
SQOuterVar &v = func->_outervalues[i];
if(ci == NULL) CallErrorHandler(_lasterror);
return false;
}
- ci->_root = true;
+ ci->_root = SQTrue;
break;
- case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = true; traps += ci->_etraps; 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 = false;
+ _suspended = SQFalse;
break;
}
exception_restore:
- //SQ_TRY
+ //
{
for(;;)
{
temp_reg = STK(arg1);
if (type(temp_reg) == OT_CLOSURE){
ct_tailcall = true;
- PopVarArgs(ci->_vargs);
+ if(ci->_vargs.size) PopVarArgs(ci->_vargs);
for (int i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
ct_target = ci->_target;
goto common_call;
int last_top = _top;
switch (type(temp_reg)) {
case OT_CLOSURE:{
- StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall);
+ _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));
bool suspend;
_GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend));
if(suspend){
- _suspended = true;
+ _suspended = SQTrue;
_suspended_target = ct_target;
_suspended_root = ci->_root;
_suspended_traps = traps;
continue;
case OT_CLASS: TARGET = _class(STK(arg1))->_base?_class(STK(arg1))->_base:_null_;
continue;
- default:
- break;
}
Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(STK(arg1)));
SQ_THROW();
CallErrorHandler(currerror);
//remove call stack until a C function is found or the cstack is empty
if(ci) do{
- bool exitafterthisone = ci->_root;
+ SQBool exitafterthisone = ci->_root;
if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();
_stackbase -= ci->_prevstkbase;
_top = _stackbase + ci->_prevtop;
bool SQVM::CallNative(SQNativeClosure *nclosure,int nargs,int stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend)
{
- (void) tailcall;
if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
int nparamscheck = nclosure->_nparamscheck;
if(((nparamscheck > 0) && (nparamscheck != nargs))
}
int tcs;
- if( (tcs = nclosure->_typecheck.size()) ) {
+ if(tcs = nclosure->_typecheck.size()) {
for(int 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]));
case OT_INSTANCE:
if(_instance(self)->Get(key,dest)) return true;
break;
- default:
- break;
}
if(FallBackGet(self,key,dest,raw)) return true;
return false;
}
-void SQVM::Pop() {
- _stack[--_top] = _null_;
-}
-void SQVM::Pop(int n) {
- for(int i = 0; i < n; i++){
- _stack[--_top] = _null_;
- }
-}
-
void SQVM::Remove(int n) {
n = (n >= 0)?n + _stackbase - 1:_top + n;
for(int i = n; i < _top; i++){
_top--;
}
-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(int n) { return _stack[_top+n]; }
-SQObjectPtr &SQVM::GetAt(int n) { return _stack[n]; }
#ifdef _DEBUG_DUMP
void SQVM::dumpstack(int stackbase,bool dumpall)
int _target;
SQInstruction *_ip;
int _ncalls;
- bool _root;
+ SQBool _root;
VarArgs _vargs;
};
void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, int nparams, SQObjectPtr &outres);
bool ArithMetaMethod(int op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
- //void Modulo(const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
bool Return(int _arg0, int _arg1, SQObjectPtr &retval);
//new stuff
- bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
- bool BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
- bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
- bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
+ inline bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
+ inline bool BW_OP(unsigned int 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,int base,int attrs);
//return true if the loop is finished
bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,int arg_2,bool &finished);
bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
- bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
- bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
- bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
+ inline bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+ inline bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+ inline bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
void PopVarArgs(VarArgs &vargs);
#ifdef _DEBUG_DUMP
void dumpstack(int stackbase=-1, bool dumpall = false);
void Release(){ sq_delete(this,SQVM); } //does nothing
////////////////////////////////////////////////////////////////////////////
//stack functions for the api
- void Pop();
- void Pop(int n);
void Remove(int n);
- void Push(const SQObjectPtr &o);
- SQObjectPtr &Top();
- SQObjectPtr &PopGet();
- SQObjectPtr &GetUp(int n);
- SQObjectPtr &GetAt(int n);
+ inline void Pop() {
+ _stack[--_top] = _null_;
+ }
+
+ inline void Pop(int n) {
+ for(int i = 0; i < n; i++){
+ _stack[--_top] = _null_;
+ }
+ }
+
+ inline void Push(const SQObjectPtr &o) { _stack[_top++] = o; }
+ inline SQObjectPtr &Top() { return _stack[_top-1]; }
+ inline SQObjectPtr &PopGet() { return _stack[--_top]; }
+ inline SQObjectPtr &GetUp(int n) { return _stack[_top+n]; }
+ inline SQObjectPtr &GetAt(int n) { return _stack[n]; }
SQObjectPtrVec _stack;
SQObjectPtrVec _vargsstack;
SQSharedState *_sharedstate;
int _nnativecalls;
//suspend infos
- bool _suspended;
- bool _suspended_root;
+ SQBool _suspended;
+ SQBool _suspended_root;
int _suspended_target;
int _suspended_traps;
};
#endif
#define PUSH_CALLINFO(v,nci){ \
- v->_callsstack.push_back(nci); \
- v->ci = &v->_callsstack.back(); \
+ v->ci = &v->_callsstack.push_back(nci); \
}
#define POP_CALLINFO(v){ \
if (special_tile->teleport_dest != Vector(-1,-1))
{
// TODO: an animation, camera scrolling or a fading would be a nice touch
- sound_manager->play("warp");
+ sound_manager->play("sounds/warp.wav");
tux->back_direction = D_NONE;
tux->set_tile_pos(special_tile->teleport_dest);
SDL_Delay(1000);