[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/Makefile.am server/named...
From: |
Chad Musick |
Subject: |
[Gnash-commit] gnash ChangeLog server/Makefile.am server/named... |
Date: |
Sat, 29 Sep 2007 08:24:22 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Chad Musick <cmusick> 07/09/29 08:24:22
Modified files:
. : ChangeLog
server : Makefile.am namedStrings.cpp namedStrings.h
server/asobj : ClassHierarchy.cpp ClassHierarchy.h Global.cpp
server/parser : Namespace.h abc_block.cpp abc_block.h
server/vm : VM.cpp
testsuite/samples: .cvsignore
Added files:
extensions/dbus: .cvsignore
extensions/lirc: .cvsignore
libmedia : .cvsignore
server : asClass.cpp asClass.h
Log message:
Add some .cvsignore files
New type library system for (so far) ActionScript 3.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4472&r2=1.4473
http://cvs.savannah.gnu.org/viewcvs/gnash/extensions/dbus/.cvsignore?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/extensions/lirc/.cvsignore?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/.cvsignore?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.126&r2=1.127
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asClass.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asClass.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ClassHierarchy.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ClassHierarchy.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Global.cpp?cvsroot=gnash&r1=1.71&r2=1.72
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/Namespace.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/abc_block.cpp?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/abc_block.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/VM.cpp?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/samples/.cvsignore?cvsroot=gnash&r1=1.6&r2=1.7
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4472
retrieving revision 1.4473
diff -u -b -r1.4472 -r1.4473
--- ChangeLog 29 Sep 2007 06:33:25 -0000 1.4472
+++ ChangeLog 29 Sep 2007 08:24:20 -0000 1.4473
@@ -1,3 +1,22 @@
+2007-09-29 Chad Musick <address@hidden>
+
+ * New: server/asClass.h,.cpp: Several different classes which work
+ together to construct a type library for ActionScript 3. Work is
+ in progress to make this glean the same information from the current
+ ActionScript 2 information (through the Global object, as well
+ as hand coding) so that the 'implements' op can be written and so
+ that various AS2 things will work better. This is not yet complete.
+ Because this code is in flux (though currently not broken), it is
+ not yet extensively commented.
+ * server/Makefile.am: Add new files
+ * server/namedStrings.h,.cpp: New strings for the AS3 namespaces.
+ * server/parser/Namespace.h: Add resource marking -- this file is
+ going to be obsolete as soon as dependencies are verified.
+ * server/parser/abc_block.h,.cpp: Update to be more modular, and to
+ build a type library from AS3 tag.
+ * server/vm/VM.cpp: Change to registration method for new types.
+ * New: Various .cvsignore files
+
2007-09-29 Sandro Santilli <address@hidden>
* testsuite/misc-swfc.all/: Dejagnu.sc, check.sc,
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.126
retrieving revision 1.127
diff -u -b -r1.126 -r1.127
--- server/Makefile.am 27 Sep 2007 23:59:55 -0000 1.126
+++ server/Makefile.am 29 Sep 2007 08:24:21 -0000 1.127
@@ -18,7 +18,7 @@
#
#
-# $Id: Makefile.am,v 1.126 2007/09/27 23:59:55 tgc Exp $
+# $Id: Makefile.am,v 1.127 2007/09/29 08:24:21 cmusick Exp $
AUTOMAKE_OPTIONS =
@@ -65,6 +65,7 @@
as_function.cpp \
as_object.cpp \
as_value.cpp \
+ asClass.cpp \
character.cpp \
cxform.cpp \
DynamicShape.cpp \
@@ -129,6 +130,7 @@
as_object.h \
as_prop_flags.h \
as_value.h \
+ asClass.h \
bitmap_info.h \
BitmapMovieInstance.h \
builtin_function.h \
Index: server/namedStrings.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/namedStrings.cpp 23 Sep 2007 22:33:56 -0000 1.2
+++ server/namedStrings.cpp 29 Sep 2007 08:24:21 -0000 1.3
@@ -125,6 +125,18 @@
{ "ContextMenu", NSV::CLASS_CONTEXT_MENU },
{ "MovieClipLoader", NSV::CLASS_MOVIE_CLIP_LOADER },
{ "Error", NSV::CLASS_ERROR },
+ { "flash.display", NSV::NS_FLASH_DISPLAY },
+ { "flash.text", NSV::NS_FLASH_TEXT },
+ { "flash.geom", NSV::NS_FLASH_GEOM },
+ { "flash.net", NSV::NS_FLASH_NET },
+ { "flash.system", NSV::NS_FLASH_SYSTEM },
+ { "flash.utils", NSV::NS_FLASH_UTILS },
+ { "flash.events", NSV::NS_FLASH_EVENTS },
+ { "flash.accessibility", NSV::NS_FLASH_ACCESSIBILITY },
+ { "flash.media", NSV::NS_FLASH_MEDIA },
+ { "flash.xml", NSV::NS_FLASH_XML },
+ { "flash.ui", NSV::NS_FLASH_UI },
+ { "adobe.utils", NSV::NS_ADOBE_UTILS },
};
void load_strings(string_table *table, int version)
Index: server/namedStrings.h
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/namedStrings.h 23 Sep 2007 22:46:30 -0000 1.4
+++ server/namedStrings.h 29 Sep 2007 08:24:21 -0000 1.5
@@ -142,7 +142,19 @@
CLASS_NET_STREAM,
CLASS_CONTEXT_MENU,
CLASS_MOVIE_CLIP_LOADER,
- CLASS_ERROR
+ CLASS_ERROR,
+ NS_FLASH_DISPLAY,
+ NS_FLASH_TEXT,
+ NS_FLASH_GEOM,
+ NS_FLASH_NET,
+ NS_FLASH_SYSTEM,
+ NS_FLASH_UTILS,
+ NS_FLASH_EVENTS,
+ NS_FLASH_ACCESSIBILITY,
+ NS_FLASH_MEDIA,
+ NS_FLASH_XML,
+ NS_FLASH_UI,
+ NS_ADOBE_UTILS
} named_strings;
/// Load the prenamed strings.
Index: server/asobj/ClassHierarchy.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ClassHierarchy.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/asobj/ClassHierarchy.cpp 24 Sep 2007 15:39:31 -0000 1.2
+++ server/asobj/ClassHierarchy.cpp 29 Sep 2007 08:24:21 -0000 1.3
@@ -63,6 +63,7 @@
#include "xmlsocket.h"
#include "xml.h"
#include "xmlnode.h"
+#include "asClass.h"
namespace gnash {
@@ -189,7 +190,9 @@
if (mExtension == NULL)
return false; // Extensions can't be loaded.
- mGlobalNamespace.stubPrototype(c.name);
+ mGlobalNamespace->stubPrototype(c.name);
+ mGlobalNamespace->getClass(c.name)->setDeclared();
+ mGlobalNamespace->getClass(c.name)->setSystem();
boost::intrusive_ptr<as_function> getter =
new declare_extension_function(c, mGlobal, mExtension);
@@ -203,7 +206,14 @@
bool
ClassHierarchy::declareClass(nativeClass& c)
{
- mGlobalNamespace.stubPrototype(c.name);
+ // For AS2 and below, registering with mGlobal _should_ make it
equivalent
+ // to being in the global namespace, since everything is global there.
+ asNamespace *nso = findNamespace(c.namespace_name);
+ if (!nso)
+ nso = addNamespace(c.namespace_name);
+ nso->stubPrototype(c.name);
+ nso->getClass(c.name)->setDeclared();
+ nso->getClass(c.name)->setSystem();
boost::intrusive_ptr<as_function> getter =
new declare_native_function(c, mGlobal, mExtension);
@@ -216,40 +226,45 @@
static ClassHierarchy::nativeClass knownClasses[] =
{
+// This makes it clear the difference between "We don't know where the
+// class belongs" and "it belongs in the global namespace", even though
+// the result is the same.
+#define NS_GLOBAL 0
+#define NS_UNKNOWN 0
/* { function_name, name key, super name key, lowest version }, */
-// { object_class_init, NSV::CLASS_OBJECT, 0, 5 }, // Object is special
-// { function_class_init, NSV::CLASS_FUNCTION, NSV::CLASS_OBJECT, 6 }, //
Function is special
-// { array_class_init, NSV::CLASS_ARRAY, NSV::CLASS_OBJECT, 5 }, // Array
is special
- { system_class_init, NSV::CLASS_SYSTEM, 0, 1 },
- { stage_class_init, NSV::CLASS_STAGE, 0, 1 },
- { movieclip_class_init, NSV::CLASS_MOVIE_CLIP, 0, 3 },
- { textfield_class_init, NSV::CLASS_TEXT_FIELD, 0, 3 },
- { math_class_init, NSV::CLASS_MATH, 0, 4 },
- { boolean_class_init, NSV::CLASS_BOOLEAN, NSV::CLASS_OBJECT, 5 },
- { color_class_init, NSV::CLASS_COLOR, NSV::CLASS_OBJECT, 5 },
- { selection_class_init, NSV::CLASS_SELECTION, NSV::CLASS_OBJECT, 5 },
- { sound_class_init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT, 5 },
- { xmlsocket_class_init, NSV::CLASS_X_M_L_SOCKET, NSV::CLASS_OBJECT, 5 },
- { date_class_init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, 5 },
- { xml_class_init, NSV::CLASS_X_M_L, NSV::CLASS_OBJECT, 5 },
- { xmlnode_class_init, NSV::CLASS_X_M_L_NODE, NSV::CLASS_OBJECT, 5 },
- { mouse_class_init, NSV::CLASS_MOUSE, NSV::CLASS_OBJECT, 5 },
- { number_class_init, NSV::CLASS_NUMBER, NSV::CLASS_OBJECT, 5 },
- { string_class_init, NSV::CLASS_STRING, NSV::CLASS_OBJECT, 5 },
- { key_class_init, NSV::CLASS_KEY, NSV::CLASS_OBJECT, 5 },
- { AsBroadcaster_init, NSV::CLASS_AS_BROADCASTER, NSV::CLASS_OBJECT, 5 },
- { textsnapshot_class_init, NSV::CLASS_TEXT_SNAPSHOT, NSV::CLASS_OBJECT,
6 },
- { video_class_init, NSV::CLASS_VIDEO, NSV::CLASS_OBJECT, 6 },
- { camera_class_init, NSV::CLASS_CAMERA, NSV::CLASS_OBJECT, 6 },
- { microphone_class_init, NSV::CLASS_MICROPHONE, NSV::CLASS_OBJECT, 6 },
- { sharedobject_class_init, NSV::CLASS_SHARED_OBJECT, NSV::CLASS_OBJECT,
6 },
- { loadvars_class_init, NSV::CLASS_LOAD_VARS, NSV::CLASS_OBJECT, 6 },
- { customactions_class_init, NSV::CLASS_CUSTOM_ACTIONS,
NSV::CLASS_OBJECT, 6 },
- { netconnection_class_init, NSV::CLASS_NET_CONNECTION,
NSV::CLASS_OBJECT, 7 },
- { netstream_class_init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT, 7 },
- { contextmenu_class_init, NSV::CLASS_CONTEXT_MENU, NSV::CLASS_OBJECT, 7
},
- { moviecliploader_class_init, NSV::CLASS_MOVIE_CLIP_LOADER,
NSV::CLASS_OBJECT, 7 },
- { error_class_init, NSV::CLASS_ERROR, NSV::CLASS_OBJECT, 7 },
+// { object_class_init, NSV::CLASS_OBJECT, 0, NS_GLOBAL, 5 }, // Object is
special
+// { function_class_init, NSV::CLASS_FUNCTION, NSV::CLASS_OBJECT,
NS_GLOBAL, 6 }, // Function is special
+// { array_class_init, NSV::CLASS_ARRAY, NSV::CLASS_OBJECT, NS_GLOBAL, 5
}, // Array is special
+ { system_class_init, NSV::CLASS_SYSTEM, 0, NSV::NS_FLASH_SYSTEM, 1 },
+ { stage_class_init, NSV::CLASS_STAGE, 0, NSV::NS_FLASH_DISPLAY, 1 },
+ { movieclip_class_init, NSV::CLASS_MOVIE_CLIP, 0,
NSV::NS_FLASH_DISPLAY, 3 },
+ { textfield_class_init, NSV::CLASS_TEXT_FIELD, 0, NSV::NS_FLASH_TEXT, 3
},
+ { math_class_init, NSV::CLASS_MATH, 0, NS_GLOBAL, 4 },
+ { boolean_class_init, NSV::CLASS_BOOLEAN, NSV::CLASS_OBJECT, NS_GLOBAL,
5 },
+ { color_class_init, NSV::CLASS_COLOR, NSV::CLASS_OBJECT, NS_GLOBAL, 5 },
+ { selection_class_init, NSV::CLASS_SELECTION, NSV::CLASS_OBJECT,
NS_UNKNOWN, 5 },
+ { sound_class_init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT,
NSV::NS_FLASH_MEDIA, 5 },
+ { xmlsocket_class_init, NSV::CLASS_X_M_L_SOCKET, NSV::CLASS_OBJECT,
NSV::NS_FLASH_NET, 5 },
+ { date_class_init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, NS_GLOBAL, 5 },
+ { xml_class_init, NSV::CLASS_X_M_L, NSV::CLASS_OBJECT, NS_GLOBAL, 5 },
+ { xmlnode_class_init, NSV::CLASS_X_M_L_NODE, NSV::CLASS_OBJECT,
NSV::NS_FLASH_XML, 5 },
+ { mouse_class_init, NSV::CLASS_MOUSE, NSV::CLASS_OBJECT,
NSV::NS_FLASH_UI, 5 },
+ { number_class_init, NSV::CLASS_NUMBER, NSV::CLASS_OBJECT, NS_GLOBAL, 5
},
+ { string_class_init, NSV::CLASS_STRING, NSV::CLASS_OBJECT, NS_GLOBAL, 5
},
+ { key_class_init, NSV::CLASS_KEY, NSV::CLASS_OBJECT, NS_GLOBAL, 5 },
+ { AsBroadcaster_init, NSV::CLASS_AS_BROADCASTER, NSV::CLASS_OBJECT,
NS_GLOBAL, 5 },
+ { textsnapshot_class_init, NSV::CLASS_TEXT_SNAPSHOT, NSV::CLASS_OBJECT,
NSV::NS_FLASH_TEXT, 6 },
+ { video_class_init, NSV::CLASS_VIDEO, NSV::CLASS_OBJECT,
NSV::NS_FLASH_MEDIA, 6 },
+ { camera_class_init, NSV::CLASS_CAMERA, NSV::CLASS_OBJECT,
NSV::NS_FLASH_UI, 6 },
+ { microphone_class_init, NSV::CLASS_MICROPHONE, NSV::CLASS_OBJECT,
NSV::NS_FLASH_UI, 6 },
+ { sharedobject_class_init, NSV::CLASS_SHARED_OBJECT, NSV::CLASS_OBJECT,
NSV::NS_FLASH_NET, 6 },
+ { loadvars_class_init, NSV::CLASS_LOAD_VARS, NSV::CLASS_OBJECT,
NS_GLOBAL, 6 },
+ { customactions_class_init, NSV::CLASS_CUSTOM_ACTIONS,
NSV::CLASS_OBJECT, NSV::NS_ADOBE_UTILS, 6 },
+ { netconnection_class_init, NSV::CLASS_NET_CONNECTION,
NSV::CLASS_OBJECT, NSV::NS_FLASH_NET, 7 },
+ { netstream_class_init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT,
NSV::NS_FLASH_NET, 7 },
+ { contextmenu_class_init, NSV::CLASS_CONTEXT_MENU, NSV::CLASS_OBJECT,
NSV::NS_FLASH_UI, 7 },
+ { moviecliploader_class_init, NSV::CLASS_MOVIE_CLIP_LOADER,
NSV::CLASS_OBJECT, NS_GLOBAL, 7 },
+ { error_class_init, NSV::CLASS_ERROR, NSV::CLASS_OBJECT, NS_GLOBAL, 7 },
};
void
@@ -273,4 +288,22 @@
}
}
+void
+ClassHierarchy::markReachableResources() const
+{
+ // TODO
+}
+
+void
+ClassHierarchy::dump()
+{
+ namespacesContainer::iterator i;
+
+ for (i = mNamespaces.begin(); i != mNamespaces.end(); ++i)
+ {
+ (i->second).dump();
+ }
+ getGlobalNs()->dump();
+}
+
} /* namespace gnash */
Index: server/asobj/ClassHierarchy.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ClassHierarchy.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/asobj/ClassHierarchy.h 24 Sep 2007 15:39:31 -0000 1.2
+++ server/asobj/ClassHierarchy.h 29 Sep 2007 08:24:21 -0000 1.3
@@ -19,12 +19,64 @@
#ifndef GNASH_CLASS_HIERARCHY_H
#define GNASH_CLASS_HIERARCHY_H
+#include <list>
+#include <vector>
+
#include "as_object.h"
-#include "Namespace.h"
+#include "asClass.h"
namespace gnash {
class Extension;
+class asClass;
+class asMethod;
+class asNamespace;
+class asException;
+class asMethodBody;
+class asBoundValue;
+class asBoundAccessor;
+
+template <class T> class memoryDispenser
+{
+private:
+ typedef std::vector<T> block;
+ typedef std::list<block*> blocks;
+ blocks mMemory;
+ block *mCurrent;
+ std::size_t mBlockSize;
+ std::size_t mLeftInBlock;
+
+ void grow()
+ {
+ mLeftInBlock = mBlockSize;
+ mCurrent = new block(mBlockSize);
+ mCurrent->resize(mBlockSize);
+ mMemory.push_back(mCurrent);
+ }
+
+public:
+ memoryDispenser(std::size_t allocSize) : mBlockSize(allocSize),
+ mLeftInBlock(0)
+ {/**/}
+
+ T* newMemory()
+ {
+ if (!mLeftInBlock)
+ grow();
+ --mLeftInBlock;
+ return &(*mCurrent)[mLeftInBlock];
+ }
+
+ // Done this way because an iterator won't compile right.
+ ~memoryDispenser()
+ {
+ while (!mMemory.empty())
+ {
+ delete mMemory.front();
+ mMemory.pop_front();
+ }
+ }
+};
/// Register all of the ActionScript classes, with their dependencies.
class ClassHierarchy
@@ -56,6 +108,10 @@
string_table::key super_name;
/// \brief
+ /// The name of the namespace in which this belongs.
+ string_table::key namespace_name;
+
+ /// \brief
/// The version at which this should be added.
int version;
};
@@ -80,6 +136,10 @@
string_table::key super_name;
/// \brief
+ /// The name of the namespace in which this belongs.
+ string_table::key namespace_name;
+
+ /// \brief
/// The version at which this should be added.
int version;
};
@@ -115,31 +175,45 @@
/// Get the global namespace. This is not the Global object -- it only
/// contains the classes, not any globally available functions or
anything
/// else.
- Namespace *getGlobalNs() { return &mGlobalNamespace; }
+ asNamespace* getGlobalNs() { return mGlobalNamespace; }
/// Find a namespace with the given uri.
///
/// @return
/// The namespace with the given uri or NULL if it doesn't exist.
- Namespace *findNamespace(string_table::key uri)
+ asNamespace *findNamespace(string_table::key uri)
{
- if (uri == 0)
- return getGlobalNs();
-
- std::map<string_table::key, Namespace>::iterator i;
+ namespacesContainer::iterator i;
+ if (mNamespaces.empty())
+ return NULL;
i = mNamespaces.find(uri);
if (i == mNamespaces.end())
return NULL;
- return &(i->second);
+ return &i->second;
}
/// \brief
+ /// Obtain a new anonymous namespace. Use this to let the object keep
track
+ /// of all namespaces, even private ones. Namespaces obtained in this
way
+ /// can't ever be found. (They must be kept and passed to the
appropriate
+ /// objects.)
+ ///
+ asNamespace* anonNamespace(string_table::key uri)
+ { asNamespace* n = mAnonNamespaces.newMemory(); n->setURI(uri); return
n; }
+
+ /// \brief
/// Add a namespace to the set. Don't use to add unnamed namespaces.
/// Will overwrite existing namespaces 'kind' and 'prefix' values.
/// Returns the added space.
- Namespace* addNamespace(string_table::key uri, Namespace::kinds kind)
- { Namespace &n = mNamespaces[uri]; n.initialize(uri, 0, kind);
- return &mNamespaces[uri];}
+ asNamespace* addNamespace(string_table::key uri)
+ {
+ asNamespace *n = findNamespace(uri);
+ if (n)
+ return n;
+ mNamespaces[uri] = asNamespace();
+ mNamespaces[uri].setURI(uri);
+ return &mNamespaces[uri];
+ }
/// Set the extension object, since it wasn't set on construction.
void setExtension(Extension *e) { mExtension = e; }
@@ -147,19 +221,61 @@
/// Set the global object, for registrations.
void setGlobal(as_object *g) { mGlobal = g; }
+ /// Mark objects for garbage collector.
+ void markReachableResources() const;
+
+ /// Create a new asClass object for use.
+ asClass *newClass()
+ { return mClassMemory.newMemory(); }
+
+ asException *newException()
+ { return mExceptionMemory.newMemory(); }
+
+ /// Create a new asMethod object for use.
+ asMethod *newMethod()
+ { return mMethodMemory.newMemory(); }
+
+ /// Create a new asMethodBody
+ asMethodBody *newMethodBody()
+ { return mMethodBodyMemory.newMemory(); }
+
+ asBoundValue *newBoundValue()
+ { return mBoundValueMemory.newMemory(); }
+
+ asBoundAccessor *newBoundAccessor()
+ { return mBoundAccessorMemory.newMemory(); }
+
/// \brief
/// Construct the declaration object. Later set the global and
/// extension objects using setGlobal and setExtension
ClassHierarchy() :
- mGlobal(NULL), mGlobalNamespace(), mExtension(NULL)
- {/**/}
+ mGlobal(NULL), mGlobalNamespace(NULL), mExtension(NULL),
+ mAnonNamespaces(100),
+ mClassMemory(100), mExceptionMemory(100),
+ mMethodMemory(100), mMethodBodyMemory(100),
+ mBoundValueMemory(100), mBoundAccessorMemory(100)
+ { mGlobalNamespace = anonNamespace(0); }
+
+ /// \brief
+ /// Delete our private namespaces.
+ ~ClassHierarchy();
+
+ void dump();
private:
as_object *mGlobal;
- Namespace mGlobalNamespace;
+ asNamespace *mGlobalNamespace;
Extension *mExtension;
- std::map<string_table::key, Namespace> mNamespaces;
+ typedef std::map<string_table::key, asNamespace> namespacesContainer;
+ namespacesContainer mNamespaces;
+ memoryDispenser<asNamespace> mAnonNamespaces;
+ memoryDispenser<asClass> mClassMemory;
+ memoryDispenser<asException> mExceptionMemory;
+ memoryDispenser<asMethod> mMethodMemory;
+ memoryDispenser<asMethodBody> mMethodBodyMemory;
+ memoryDispenser<asBoundValue> mBoundValueMemory;
+ memoryDispenser<asBoundAccessor> mBoundAccessorMemory;
};
} /* namespace gnash */
Index: server/asobj/Global.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Global.cpp,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -b -r1.71 -r1.72
--- server/asobj/Global.cpp 27 Sep 2007 15:42:11 -0000 1.71
+++ server/asobj/Global.cpp 29 Sep 2007 08:24:21 -0000 1.72
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/* $Id: Global.cpp,v 1.71 2007/09/27 15:42:11 strk Exp $ */
+/* $Id: Global.cpp,v 1.72 2007/09/29 08:24:21 cmusick Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -404,13 +404,16 @@
{
object_class_init(*this);
ch->getGlobalNs()->stubPrototype(NSV::CLASS_OBJECT);
+ ch->getGlobalNs()->getClass(NSV::CLASS_OBJECT)->setDeclared();
array_class_init(*this);
ch->getGlobalNs()->stubPrototype(NSV::CLASS_ARRAY);
+ ch->getGlobalNs()->getClass(NSV::CLASS_ARRAY)->setDeclared();
}
if (vm.getSWFVersion() >= 6)
{
function_class_init(*this);
ch->getGlobalNs()->stubPrototype(NSV::CLASS_FUNCTION);
+ ch->getGlobalNs()->getClass(NSV::CLASS_FUNCTION)->setDeclared();
}
if ( vm.getSWFVersion() < 3 ) goto extscan;
Index: server/parser/Namespace.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/Namespace.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/parser/Namespace.h 24 Sep 2007 15:39:31 -0000 1.2
+++ server/parser/Namespace.h 29 Sep 2007 08:24:21 -0000 1.3
@@ -27,11 +27,11 @@
#include <map>
#include "string_table.h"
+#include "as_object.h"
namespace gnash {
class abc_block;
-class as_object;
/// A namespace for ActionScript. Not really functional in AS2.
///
@@ -166,6 +166,10 @@
return i->second;
}
+ /// \brief
+ /// Mark reachable resources for GC.
+ void markReachableResources() const;
+
private:
string_table::key mUri;
string_table::key mPrefix;
@@ -174,5 +178,18 @@
std::map<string_table::key, as_object*> mMembers;
};
+inline void
+Namespace::markReachableResources() const
+{
+ std::map<string_table::key, as_object*>::const_iterator i =
+ mMembers.begin();
+
+ for ( ; i != mMembers.end(); ++i)
+ {
+ if (i->second != NULL)
+ i->second->setReachable();
+ }
+}
+
}; /* namespace gnash */
#endif /* GNASH_NAMESPACE_H */
Index: server/parser/abc_block.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/parser/abc_block.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- server/parser/abc_block.cpp 24 Sep 2007 15:39:31 -0000 1.6
+++ server/parser/abc_block.cpp 29 Sep 2007 08:24:21 -0000 1.7
@@ -23,18 +23,156 @@
#include "VM.h"
#include "log.h"
#include "ClassHierarchy.h"
+#include "asClass.h"
+#include "namedStrings.h"
-#define ERR(x) IF_VERBOSE_MALFORMED_SWF(log_swferror x;);
-//#define ERR(x) printf x
+//#define ERR(x) IF_VERBOSE_MALFORMED_SWF(log_swferror x;);
+#define ERR(x) printf x; fflush(stdout);
namespace gnash {
namespace abc_parsing {
bool
-abc_Trait::read(stream* in)
+abc_Trait::finalize(abc_block *pBlock, asClass *pClass, bool do_static)
{
- mNameIndex = in->read_V32();
+ switch (mKind)
+ {
+ case KIND_SLOT:
+ case KIND_CONST:
+ {
+ // Validate the type.
+ asClass *pType;
+ if (mTypeIndex)
+ pType =
pBlock->locateClass(pBlock->mMultinamePool[mTypeIndex]);
+ else
+ pType = pBlock->mTheObject;
+ if (!pType)
+ {
+ ERR((_("ABC: Finalizing trait yielded bad type for
slot.\n")));
+ return false;
+ }
+ // The name has been validated in read.
+ if (mHasValue)
+ pClass->addValue(mName, mNamespace, mSlotId, pType,
+ mValue, mKind == KIND_CONST, do_static,
pBlock->mCH);
+ else
+ pClass->addSlot(mName, mNamespace, mSlotId, pType,
+ do_static, pBlock->mCH);
+ break;
+ }
+ case KIND_METHOD:
+ {
+ pClass->addMethod(mName, mNamespace, mMethod, do_static);
+ break;
+ }
+ case KIND_GETTER:
+ {
+ pClass->addGetter(mName, mNamespace, mMethod, do_static,
pBlock->mCH);
+ break;
+ }
+ case KIND_SETTER:
+ {
+ pClass->addSetter(mName, mNamespace, mMethod, do_static,
pBlock->mCH);
+ break;
+ }
+ case KIND_CLASS:
+ {
+ pClass->addMemberClass(mName, mNamespace, mSlotId,
+ pBlock->mClasses[mClassInfoIndex], do_static);
+ break;
+ }
+ case KIND_FUNCTION:
+ {
+ pClass->addSlotFunction(mName, mNamespace, mSlotId, mMethod,
do_static);
+ break;
+ }
+ default:
+ // Not here -- validated already in read.
+ return false;
+ break;
+ } // end of switch
+ return true;
+}
+
+bool
+abc_Trait::finalize_mbody(abc_block *pBlock, asMethod *pMethod)
+{
+ switch (mKind)
+ {
+ case KIND_SLOT:
+ case KIND_CONST:
+ {
+ // Validate the type.
+ asClass *pType;
+ if (mTypeIndex)
+ pType =
pBlock->locateClass(pBlock->mMultinamePool[mTypeIndex]);
+ else
+ pType = pBlock->mTheObject;
+ if (!pType)
+ {
+ ERR((_("ABC: Finalizing trait yielded bad type for
slot.\n")));
+ return false;
+ }
+ // The name has been validated in read.
+ if (mHasValue)
+ pMethod->addValue(mName, mNamespace, mSlotId, pType,
+ mValue, mKind == KIND_CONST, pBlock->mCH);
+ else
+ pMethod->addSlot(mName, mNamespace, mSlotId, pType,
pBlock->mCH);
+ break;
+ }
+ case KIND_METHOD:
+ {
+ pMethod->addMethod(mName, mNamespace, mMethod);
+ break;
+ }
+ case KIND_GETTER:
+ {
+ pMethod->addGetter(mName, mNamespace, mMethod, pBlock->mCH);
+ break;
+ }
+ case KIND_SETTER:
+ {
+ pMethod->addSetter(mName, mNamespace, mMethod, pBlock->mCH);
+ break;
+ }
+ case KIND_CLASS:
+ {
+ pMethod->addMemberClass(mName, mNamespace, mSlotId,
+ pBlock->mClasses[mClassInfoIndex]);
+ break;
+ }
+ case KIND_FUNCTION:
+ {
+ pMethod->addSlotFunction(mName, mNamespace, mSlotId, mMethod);
+ break;
+ }
+ default:
+ // Not here -- validated already in read.
+ return false;
+ break;
+ } // end of switch
+ return true;
+}
+
+/// Read an AS3 'trait'
+bool
+abc_Trait::read(stream* in, abc_block *pBlock)
+{
+ uint32_t name = in->read_V32();
+ if (name >= pBlock->mMultinamePool.size())
+ {
+ ERR((_("ABC: Bad name for trait.\n")));
+ return false;
+ }
+ if (!(pBlock->mMultinamePool[name].mFlags & abc_Multiname::FLAG_QNAME))
+ {
+ ERR((_("ABC: Trait name must be fully qualified.\n")));
+ return false;
+ }
+ mName = pBlock->mMultinamePool[name].mName;
+ mNamespace = pBlock->mMultinamePool[name].mNamespace;
uint8_t kind = in->read_u8();
mKind = static_cast<kinds> (kind & 0x0F);
@@ -46,11 +184,15 @@
{
mSlotId = in->read_V32();
mTypeIndex = in->read_V32();
- mValueIndex = in->read_V32();
- if (mValueIndex)
- mValueIndexTypeIndex = in->read_u8();
+ uint32_t vindex = in->read_V32();
+ if (vindex)
+ {
+ if (!pBlock->pool_value(vindex, in->read_u8(), mValue))
+ return false; // Message done by pool_value
+ mHasValue = true;
+ }
else
- mValueIndexTypeIndex = 0;
+ mHasValue = false;
break;
}
case KIND_METHOD:
@@ -60,203 +202,289 @@
// Ignore the 'disp_id'
in->skip_V32();
- mMethodInfoIndex = in->read_V32();
+ uint32_t moffset = in->read_V32();
+ if (moffset >= pBlock->mMethods.size())
+ {
+ ERR((_("Bad method id in trait.\n")));
+ return false;
+ }
+ mMethod = pBlock->mMethods[moffset];
break;
}
case KIND_CLASS:
{
mSlotId = in->read_V32();
mClassInfoIndex = in->read_V32();
+ if (mClassInfoIndex >= pBlock->mClasses.size())
+ {
+ ERR((_("Bad Class id in trait.\n")));
+ return false;
+ }
break;
}
case KIND_FUNCTION:
{
mSlotId = in->read_V32();
- mMethodInfoIndex = in->read_V32();
+ uint32_t moffset = in->read_V32();
+ if (moffset >= pBlock->mMethods.size())
+ {
+ ERR((_("Bad method id in trait.\n")));
+ return false;
+ }
+ mMethod = pBlock->mMethods[moffset];
break;
}
default:
{
- ERR((_("Action Block: Unknown trait kind (%d).\n"), mKind));
+ ERR((_("ABC: Unknown type of trait.\n")));
return false;
}
- } // end of switch
+ } // end of switch statement
- // Ignore the metadata, but it must be read to know how long it is.
+ // Ignore the metadata, but it must be read to know how to ignore it.
if ((kind >> 4) & 0x04) // has metadata
{
- uint32_t metaCount = in->read_V32();
- for (unsigned int k = 0; k < metaCount; ++k)
+ uint32_t mcount = in->read_V32();
+ for (unsigned int i = 0; i < mcount; ++i)
{
in->skip_V32();
}
}
-
- return true; // Here, we were successful.
+ return true;
}
}; // namespace abc_parsing
-// Load up all of the data.
-bool
-abc_block::read(stream* in)
+using namespace abc_parsing;
+
+asClass *
+abc_block::locateClass(abc_Multiname &m)
{
- using namespace abc_parsing;
- ClassHierarchy *ch = VM::get().getClassHierarchy();
+ asClass *found = NULL;
+
+ if (m.mNamespace)
+ {
+ found = m.mNamespace->getClass(m.mName);
+ if (found)
+ return found;
+ }
+ if (m.mNamespaceSet && !m.mNamespaceSet->empty())
+ {
+ std::vector<asNamespace*>::iterator i;
+ for (i = m.mNamespaceSet->begin(); i != m.mNamespaceSet->end();
++i)
+ {
+ found = (*i)->getClass(m.mName);
+ if (found)
+ return found;
+ }
+ }
+ // One last chance: Look globally.
+ found = mCH->getGlobalNs()->getClass(m.mName);
+ if (found)
+ return found;
+
+ // Fake it here for a while.
+ if (m.mNamespace)
+ {
+ m.mNamespace->stubPrototype(m.mName);
+ found = m.mNamespace->getClass(m.mName);
+ return found;
+ }
+ else
+ {
+ // Fake in global.
+ mCH->getGlobalNs()->stubPrototype(m.mName);
+ found = mCH->getGlobalNs()->getClass(m.mName);
+ return found;
+ }
+ return NULL;
+}
+/// Read the ActionBlock version number.
+bool
+abc_block::read_version()
+{
// Minor version, major version.
- uint32_t version = (in->read_u16()) | (in->read_u16() << 16);
- ERR((_("Abc Version: %d.%d\n"), (version & 0xFFFF0000) >> 16, (version
& 0x0000FFFF)));
+ mVersion = (mS->read_u16()) | (mS->read_u16() << 16);
+ ERR((_("Abc Version: %d.%d\n"), (mVersion & 0xFFFF0000) >> 16,
+ (mVersion & 0x0000FFFF)));
+ return true;
+}
- // A block of signed integers. Count overshoots by 1,
- // and the 0 is used to signal a no-op.
- uint32_t intPoolCount = in->read_V32();
- mIntegerPool.resize(intPoolCount);
- if (intPoolCount)
+/// Read the pool of integer constants.
+bool
+abc_block::read_integer_constants()
+{
+ // count overestimates by 1.
+ uint32_t count = mS->read_V32();
+ mIntegerPool.resize(count);
+ if (count)
mIntegerPool[0] = 0;
- for (unsigned int i = 1; i < intPoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- mIntegerPool[i] = static_cast<int32_t> (in->read_V32());
+ mIntegerPool[i] = static_cast<int32_t> (mS->read_V32());
}
+ return true;
+}
- // A block of unsigned integers. Count overshoots by 1,
- // and the 0 is used to signal a no-op.
- uint32_t uIntPoolCount = in->read_V32();
- mUIntegerPool.resize(uIntPoolCount);
- if (uIntPoolCount)
+/// Read the pool of unsigned integer constants.
+bool
+abc_block::read_unsigned_integer_constants()
+{
+ // count overestimates by 1.
+ uint32_t count = mS->read_V32();
+ mUIntegerPool.resize(count);
+ if (count)
mUIntegerPool[0] = 0;
- for (unsigned int i = 1; i < uIntPoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- mUIntegerPool[i] = in->read_V32();
+ mUIntegerPool[i] = mS->read_V32();
}
+ return true;
+}
- // A block of 64 bit doubles. Counter overshoots by 1,
- // and the 0 is used to signal a no-op.
- uint32_t doublePoolCount = in->read_V32();
- mDoublePool.resize(doublePoolCount);
- if (doublePoolCount)
+/// Read the pool of 64-bit double constants.
+bool
+abc_block::read_double_constants()
+{
+ uint32_t count = mS->read_V32();
+ mDoublePool.resize(count);
+ if (count)
mDoublePool[0] = 0.0;
- for (unsigned int i = 1; i < doublePoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- mDoublePool[i] = in->read_d64();
+ mDoublePool[i] = mS->read_d64();
}
+ return true;
+}
- // A block of strings. Counter overshoots by 1, with the 0th
- // entry used to signal a no-op.
- uint32_t stringPoolCount = in->read_V32();
- mStringPool.resize(stringPoolCount);
- mStringPoolTableIds.resize(stringPoolCount);
- if (stringPoolCount)
+/// Read the pool of string constants.
+bool
+abc_block::read_string_constants()
+{
+ uint32_t count = mS->read_V32();
+ mStringPool.resize(count);
+ mStringPoolTableIds.resize(count);
+ if (count)
{
mStringPool[0] = "";
mStringPoolTableIds[0] = 0;
}
- for (unsigned int i = 1; i < stringPoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- uint32_t length = in->read_V32();
- in->read_string_with_length(length, mStringPool[i]);
+ uint32_t length = mS->read_V32();
+ mS->read_string_with_length(length, mStringPool[i]);
mStringPoolTableIds[i] = 0;
}
+ return true;
+}
- // These are namespaces, individually. The counter overshoots by
- // 1, with the 0th entry used to signal a wildcard.
- uint32_t namespacePoolCount = in->read_V32();
- mNamespacePool.resize(namespacePoolCount);
- if (namespacePoolCount)
+/// Read the pool of namespaces
+/// Any two namespaces with the same uri here are the same namespace,
+/// excepting private namespaces.
+bool
+abc_block::read_namespaces()
+{
+ uint32_t count = mS->read_V32();
+ mNamespacePool.resize(count);
+ if (count)
{
- mNamespacePool[0] = ch->getGlobalNs();
+ mNamespacePool[0] = mCH->getGlobalNs();
}
- for (unsigned int i = 1; i < namespacePoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- uint8_t kind = in->read_u8();
- if (kind == Namespace::KIND_PACKAGE)
- kind = Namespace::KIND_NORMAL;
- // All namespaces have the same structure, though the usage
differs.
+ uint8_t kind = mS->read_u8();
+ uint32_t nameIndex = mS->read_V32();
- uint32_t nameIndex = in->read_V32();
- // Set the name of the namespace.
if (nameIndex && nameIndex < mStringPool.size())
{
- // If we don't have an index for this yet, do so now.
if (mStringPoolTableIds[nameIndex] == 0)
mStringPoolTableIds[nameIndex] =
mStringTable->find(mStringPool[nameIndex]);
- // And reset the nameIndex for the uri.
nameIndex = mStringPoolTableIds[nameIndex];
}
else if (nameIndex >= mStringPool.size())
{
- ERR((_("Action Block: Out of Bound string for
namespace.\n")));
+ ERR((_("ABC: Out of bounds string given for
namespace.\n")));
return false;
}
- // If this is a private namespace, it is special.
- if (kind == Namespace::KIND_PRIVATE)
+ if (kind == PRIVATE_NS)
{
- // TODO: This is a leak. Plug it.
- mNamespacePool[i] = new Namespace(nameIndex, 0,
static_cast<Namespace::kinds>(kind));
+ mNamespacePool[i] = mCH->anonNamespace(nameIndex);
+ mNamespacePool[i]->setPrivate();
}
else
{
- // And do the Namespace itself.
- Namespace *n = ch->findNamespace(nameIndex);
+ asNamespace *n = mCH->findNamespace(nameIndex);
if (n == NULL)
- n = ch->addNamespace(nameIndex,
- static_cast<Namespace::kinds>(kind));
+ n = mCH->addNamespace(nameIndex);
mNamespacePool[i] = n;
}
+ if (kind == PROTECTED_NS)
+ {
+ mNamespacePool[i]->setProtected();
}
+ }
+ return true;
+}
- // These are sets of namespaces, which use the individual ones above.
- uint32_t namespaceSetPoolCount = in->read_V32();
- mNamespaceSetPool.resize(namespaceSetPoolCount);
- if (namespaceSetPoolCount)
+/// Read the set of sets of namespaces.
+bool
+abc_block::read_namespace_sets()
+{
+ uint32_t count = mS->read_V32();
+ mNamespaceSetPool.resize(count);
+ if (count)
{
- // The base namespace set is empty.
mNamespaceSetPool[0].resize(0);
}
- for (unsigned int i = 1; i < namespaceSetPoolCount; ++i)
+ for (unsigned int i = 1; i < count; ++i)
{
- // These counts are not inflated the way the others are.
- uint32_t count = in->read_V32();
- mNamespaceSetPool[i].resize(count);
- for (unsigned int j = 0; j < count; ++j)
+ uint32_t icount = mS->read_V32();
+ mNamespaceSetPool[i].resize(icount);
+ for (unsigned int j = 0; j < icount; ++j)
{
- uint32_t selection = in->read_V32();
- if (!selection || selection >= namespacePoolCount)
+ uint32_t selection = mS->read_V32();
+ if (!selection || selection >= mNamespacePool.size())
{
- // Reached a bad selection.
- ERR((_("Action Block: Out of Bound namespace in
namespace set.\n")));
+ ERR((_("ABC: Out of bounds namespace for
namespace set.\n")));
return false;
}
mNamespaceSetPool[i][j] = mNamespacePool[selection];
}
}
+ return true;
+}
- // A list of the multinames. The counter overestimates by 1, and the
- // 0th is used as a no-op.
- uint32_t multinamePoolCount = in->read_V32();
-
- // Any two namespaces with the same uri here are the same namespace,
- // excepting private nameSpaces.
- mMultinamePool.resize(multinamePoolCount);
- for (unsigned int i = 1; i < multinamePoolCount; ++i)
+/// Read the multinames.
+bool
+abc_block::read_multinames()
+{
+ uint32_t count = mS->read_V32();
+ mMultinamePool.resize(count);
+ if (count)
{
- uint8_t kind = in->read_u8();
+ mMultinamePool[0].mName = 0;
+ mMultinamePool[0].mNamespace = mCH->getGlobalNs();
+ }
+ for (unsigned int i = 1; i < count; ++i)
+ {
+ uint8_t kind = mS->read_u8();
uint32_t ns = 0;
uint32_t name = 0;
uint32_t nsset = 0;
mMultinamePool[i].mFlags = 0;
- // Read, but don't upper validate until after the switch
+ // Read, but don't upper validate until after the switch.
switch (kind)
{
case abc_Multiname::KIND_Qname:
case abc_Multiname::KIND_QnameA:
{
- ns = in->read_V32();
- name = in->read_V32();
+ ns = mS->read_V32();
+ name = mS->read_V32();
mMultinamePool[i].mFlags |= abc_Multiname::FLAG_QNAME;
if (kind == abc_Multiname::KIND_QnameA)
mMultinamePool[i].mFlags |=
abc_Multiname::FLAG_ATTR;
@@ -265,7 +493,7 @@
case abc_Multiname::KIND_RTQname:
case abc_Multiname::KIND_RTQnameA:
{
- name = in->read_V32();
+ name = mS->read_V32();
mMultinamePool[i].mFlags |= abc_Multiname::FLAG_QNAME
| abc_Multiname::FLAG_RTNS;
if (kind == abc_Multiname::KIND_RTQnameA)
@@ -285,12 +513,12 @@
case abc_Multiname::KIND_Multiname:
case abc_Multiname::KIND_MultinameA:
{
- name = in->read_V32();
- nsset = in->read_V32();
+ name = mS->read_V32();
+ nsset = mS->read_V32();
// 0 is not a valid nsset.
if (!nsset)
{
- ERR((_("Action Block: 0 selection for namespace
set is invalid.\n")));
+ ERR((_("ABC: 0 selection for namespace set is invalid.\n")));
return false;
}
mMultinamePool[i].mFlags |= abc_Multiname::FLAG_NSSET;
@@ -301,11 +529,11 @@
case abc_Multiname::KIND_MultinameL:
case abc_Multiname::KIND_MultinameLA:
{
- nsset = in->read_V32();
+ nsset = mS->read_V32();
// 0 is not a valid nsset.
if (!nsset)
{
- ERR((_("Action Block: 0 selection for namespace
set is invalid.\n")));
+ ERR((_("ABC: 0 selection for namespace set is invalid.\n")));
return false;
}
mMultinamePool[i].mFlags |= abc_Multiname::FLAG_RTNAME
@@ -324,21 +552,21 @@
if (name >= mStringPool.size())
{
- ERR((_("Action Block: Out of Bound string for
Multiname.\n")));
- return false; // Bad name.
+ ERR((_("ABC: Out of bounds string for Multiname.\n")));
+ return false;
}
if (ns >= mNamespacePool.size())
{
- ERR((_("Action Block: Out of Bound namespace for
Multiname.\n")));
- return false; // Bad namespace.
+ ERR((_("ABC: Out of bounds namespace for
Multiname.\n")));
+ return false;
}
if (nsset >= mNamespaceSetPool.size())
{
- ERR((_("Action Block: Out of Bound namespace set for
Multiname.\n")));
- return false; // Bad namespace set.
+ ERR((_("ABC: Out of bounds namespace set for
Multiname.\n")));
+ return false;
}
- // The name should be in the string table.
+ // Load the string table with the name if not already there.
if (name && mStringPoolTableIds[name] == 0)
{
mStringPoolTableIds[name] =
mStringTable->find(mStringPool[name]);
@@ -349,372 +577,585 @@
mMultinamePool[i].mNamespace = mNamespacePool[ns];
if (nsset)
mMultinamePool[i].mNamespaceSet =
&mNamespaceSetPool[nsset];
+ } // End of main loop.
+ return true;
+}
- } // End of multiname loop.
+bool
+abc_block::pool_value(uint32_t index, uint8_t type, as_value &v)
+{
+ if (!index)
+ return true;
+
+ switch (type)
+ {
+ case POOL_STRING:
+ {
+ if (index >= mStringPool.size())
+ {
+ ERR((_("Action Block: Bad index in optional
argument.\n")));
+ return false;
+ }
+ v.set_string(mStringPool[index]);
+ break;
+ }
+ case POOL_INTEGER:
+ {
+ if (index >= mIntegerPool.size())
+ {
+ ERR((_("Action Block: Bad index in optional
argument.\n")));
+ return false;
+ }
+ v.set_int(mIntegerPool[index]);
+ break;
+ }
+ case POOL_UINTEGER:
+ {
+ if (index >= mUIntegerPool.size())
+ {
+ ERR((_("Action Block: Bad index in optional
argument.\n")));
+ return false;
+ }
+ v.set_int(mUIntegerPool[index]);
+ break;
+ }
+ case POOL_DOUBLE:
+ {
+ if (index >= mDoublePool.size())
+ {
+ ERR((_("Action Block: Bad index in optional
argument.\n")));
+ return false;
+ }
+ v.set_double(static_cast<double>(mDoublePool[index]));
+ break;
+ }
+ case POOL_NAMESPACE: // Namespace
+ {
+ if (index >= mNamespacePool.size())
+ {
+ ERR((_("ABC: Bad index in optional argument,
namespaces.\n")));
+ return false;
+ }
+ break;
+ }
+ case POOL_FALSE: // False value
+ {
+ v.set_bool(false);
+ break;
+ }
+ case POOL_TRUE: // True value
+ {
+ v.set_bool(true);
+ break;
+ }
+ case POOL_NULL: // NULL value
+ {
+ v.set_null();
+ break;
+ }
+ default: // All others are bogus.
+ {
+ ERR((_("ABC: Bad default value type (%X), but continuing.\n"),
type));
+ return true;
+ break;
+ }
+ } // end of switch
+ return true;
+}
- uint32_t methodCount = in->read_V32();
- mMethods.resize(methodCount);
- for (unsigned int i = 0; i < methodCount; ++i)
+/// Read the method infos.
+bool
+abc_block::read_method_infos()
+{
+ uint32_t count = mS->read_V32();
+ mMethods.resize(count);
+ for (unsigned int i = 0; i < count; ++i)
{
- abc_Method& method = mMethods[i];
+ asMethod *pMethod = mCH->newMethod();
+ mMethods[i] = pMethod;
- uint32_t param_count = in->read_V32();
- uint32_t return_type = in->read_V32();
+ uint32_t param_count = mS->read_V32();
+ uint32_t return_type = mS->read_V32();
+
+ pMethod->setMinArgumentCount(param_count);
+ pMethod->setMaxArgumentCount(param_count);
if (return_type >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound return type for "
- "method info (%d).\n"), return_type));
+ ERR((_("ABC: Out of bounds return type for method
info.\n")));
+ return false;
+ }
+
+ asClass *rtClass = locateClass(mMultinamePool[return_type]);
+ if (!rtClass)
+ {
+ ERR((_("ABC: Unknown return type.\n")));
return false;
}
- method.mReturnType = &mMultinamePool[return_type];
+ pMethod->setReturnType(rtClass);
- method.mParameters.resize(param_count);
for (unsigned int j = 0; j < param_count; ++j)
{
// The parameter type.
- uint32_t ptype = in->read_V32();
+ uint32_t ptype = mS->read_V32();
if (ptype >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound parameter
type "
- "for method info (%d).\n"), ptype));
+ ERR((_("ABC: Out of bounds parameter type in
method.\n")));
+ return false;
+ }
+ asClass *param_type =
locateClass(mMultinamePool[ptype]);
+ if (!param_type)
+ {
+ ERR((_("ABC: Unknown parameter type.\n")));
return false;
}
- method.mParameters[j] = &mMultinamePool[ptype];
+ pMethod->pushArgument(param_type);
}
- // We ignore the name_index
- in->skip_V32();
- uint8_t flags = in->read_u8();
- method.mFlags = flags;
+ // A skippable name index.
+ mS->skip_V32();
+
+ uint8_t flags = mS->read_u8();
- // Some parameters have default values.
- if (flags & abc_Method::FLAG_OPTIONAL)
+ // If there are default parameters, read them now.
+ // Runtime will do validation of whether or not these can
actually
+ // be assigned to the corresponding parameters.
+ if (flags & METHOD_OPTIONAL_ARGS)
{
- uint32_t count = in->read_V32();
- method.mOptionalParameters.resize(count);
- for (unsigned int j = 0; j < count; ++j)
+ uint32_t ocount = mS->read_V32();
+
pMethod->setMinArgumentCount(pMethod->maxArgumentCount() - ocount);
+ for (unsigned int j = 0; j < ocount; ++j)
{
- // The value index.
- method.mOptionalParameters[j].mIndex =
in->read_V32();
- // The value kind.
- method.mOptionalParameters[j].mKind =
in->read_u8();
+ uint32_t index = mS->read_V32();
+ uint8_t kindof = mS->read_u8();
+ as_value v;
+ if (!pool_value(index, kindof, v))
+ return false; // message done by
pool_value
+ pMethod->pushOptional(v);
}
}
- // The parameters are given names, which AS3 can't use. We don't
- // either, since we're not a development environment.
- if (flags & abc_Method::FLAG_PARAM_NAMES)
+ // If there are names present for the parameters, skip them.
+ if (flags & METHOD_ARG_NAMES)
{
for (unsigned int j = 0; j < param_count; ++j)
{
- in->skip_V32();
+ mS->skip_V32();
}
}
} // End of method loop.
+ return true;
+}
- // Following is MetaData, which we will ignore.
- uint32_t metaCount = in->read_V32();
- for (unsigned int i = 0; i < metaCount; ++i)
- {
- in->skip_V32(); // A name index.
- uint32_t metaInternalCount = in->read_V32();
- for (unsigned int j = 0; j < metaInternalCount; ++j)
+/// Skip the metadata, which is useless to us.
+bool
+abc_block::skip_metadata()
+{
+ uint32_t count = mS->read_V32();
+ for (unsigned int i = 0; i < count; ++i)
{
- // key and values are _not_ in this order (they group
together), but
- // we are just skipping anyway.
- in->skip_V32();
- in->skip_V32();
+ mS->skip_V32(); // A name index.
+ uint32_t icount = mS->read_V32();
+ for (unsigned int j = 0; j < icount; ++j)
+ {
+ // key/values may not be stored together, but this
still works.
+ mS->skip_V32();
+ mS->skip_V32();
}
}
+ return true;
+}
- // Classes count.
- uint32_t classCount = in->read_V32();
- mClasses.resize(classCount);
-
- // But first, instances, which uses classCount
- mInstances.resize(classCount);
- for (unsigned int i = 0; i < classCount; ++i)
+/// Load the instances from the block.
+bool
+abc_block::read_instances()
+{
+ uint32_t count = mS->read_V32();
+ mClasses.resize(count);
+ for (unsigned int i = 0; i < count; ++i)
{
- abc_Instance& instance = mInstances[i];
- uint32_t index = in->read_V32();
+ asClass *pClass;
+
+ uint32_t index = mS->read_V32();
// 0 is allowed as a name, typically for the last entry.
if (index >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound instance name
(%d).\n"), index));
- return false; // Name out of bounds.
+ ERR((_("ABC: Out of bounds instance name.\n")));
+ return false;
}
- instance.mName = &mMultinamePool[index];
- // This must be a QName, not some other type.
- if (!(instance.mName->mFlags & abc_Multiname::FLAG_QNAME))
+ // This must be a QName.
+ if (!(mMultinamePool[index].mFlags & abc_Multiname::FLAG_QNAME))
{
- ERR((_("Action Block: Qname required for
instance.\n")));
- return false; // Name not Qname
+ ERR((_("ABC: QName required for instance.\n")));
+ return false;
}
-
- uint32_t super_index = in->read_V32();
- if (!super_index)
- instance.mSuperType = NULL;
- else if (super_index >= mMultinamePool.size())
+ if (mMultinamePool[index].mNamespace == NULL)
{
- ERR((_("Action Block: Out of Bound super type
(%d).\n"), super_index));
- return false; // Bad index.
+ ERR((_("ABC: No namespace to use for storing
class.\n")));
+ return false;
}
- else
- instance.mSuperType = &mMultinamePool[super_index];
- int found = 0;
- // If there is a super_index, we ought to be able to find this
thing.
- if (super_index)
- {
- if (!instance.mSuperType->mNamespace)
- {
- if (instance.mSuperType->mNamespaceSet)
+ pClass = locateClass(mMultinamePool[index]);
+ if (!pClass)
{
- int found = 0;
- for (std::vector<Namespace*>::iterator
i =
-
instance.mSuperType->mNamespaceSet->begin();
- i !=
instance.mSuperType->mNamespaceSet->end();
- ++i)
+ pClass = mCH->newClass();
+ if (!mMultinamePool[index].mNamespace->addClass(
+ mMultinamePool[index].mName, pClass))
{
- if
((*i)->prototypeExists(super_index))
- ++found;
+ ERR((_("Duplicate class registration.\n")));
+ return false;
}
}
+ pClass->setDeclared();
+ mClasses[i] = pClass;
+ uint32_t super_index = mS->read_V32();
+
+ if (super_index && super_index >= mMultinamePool.size())
+ {
+ ERR((_("ABC: Out of bounds super type.\n")));
+ return false;
}
- else if
(instance.mSuperType->mNamespace->prototypeExists(
- instance.mSuperType->mName))
+ if (!super_index)
{
- ++found;
+ pClass->setSuper(mTheObject);
}
-
- if (found == 0)
+ else
{
- if
(!ch->getGlobalNs()->prototypeExists(instance.mSuperType->mName))
+ asClass *pSuper =
locateClass(mMultinamePool[super_index]);
+ if (!pSuper)
{
- ERR((_("Action Block: Super type not
found (%s), faking.\n"),
-
mStringTable->value(instance.mSuperType->mName).c_str()));
- // While testing, we will add the super
to the global object to fake.
-
ch->getGlobalNs()->stubPrototype(instance.mSuperType->mName);
- //return false;
+ ERR((_("ABC: Super type not found (%s),
faking.\n"),
+
mStringTable->value(mMultinamePool[super_index].mName).c_str()));
+ // While testing, we will add a fake type,
rather than abort.
+ pSuper = mCH->newClass();
+
pSuper->setName(mMultinamePool[super_index].mName);
+
mCH->getGlobalNs()->addClass(mMultinamePool[super_index].mName, pSuper);
+ // return false;
}
+
+ if (pSuper->isFinal())
+ {
+ ERR((_("ABC: Can't extend a class which is
final.\n")));
+ return false;
+ }
+
+ if (pSuper->isInterface())
+ {
+ ERR((_("ABC: Can't extend an interface
type.\n")));
+ return false;
}
- else if (found > 1)
+
+ if (pSuper == pClass)
{
- ERR((_("Action Block: Ambiguous declaration
(%s)\n"),
-
mStringTable->value(instance.mSuperType->mName).c_str()));
+ ERR((_("ABC: Class cannot be its own
supertype.\n")));
return false;
}
+ pClass->setSuper(pSuper);
+ pSuper->setInherited();
}
- uint8_t flags = in->read_u8();
- instance.mFlags = static_cast<abc_Instance::flags> (flags);
+ uint8_t flags = mS->read_u8();
- instance.mProtectedNamespace = NULL;
- if (flags & abc_Instance::FLAG_PROTECTED_NS) // Protected
namespace
+ if (flags & INSTANCE_SEALED)
+ pClass->setSealed();
+ if (flags & INSTANCE_FINAL)
+ pClass->setFinal();
+ if (flags & INSTANCE_INTERFACE)
+ pClass->setInterface();
+ if ((flags & 7) == INSTANCE_DYNAMIC)
+ pClass->setDynamic();
+
+ if (flags & INSTANCE_PROTECTED_NS) // Protected Namespace
{
- uint32_t ns_index = in->read_V32();
+ uint32_t ns_index = mS->read_V32();
if (ns_index >= mNamespacePool.size())
{
- ERR((_("Action Block: Out of Bound namespace
for "
- "instance protected namespace
(%d).\n"), ns_index));
+ ERR((_("ABC: Out of bounds namespace for
protected.\n")));
return false;
}
- if (ns_index)
- instance.mProtectedNamespace =
mNamespacePool[ns_index];
+ // Set the protected namespace's parent, if it exists.
+ if (pClass->getSuper()->hasProtectedNs())
+
mNamespacePool[ns_index]->setParent(pClass->getSuper()->getProtectedNs());
+ pClass->setProtectedNs(mNamespacePool[ns_index]);
}
- // Get the interfaces.
- uint32_t interfaceCount = in->read_V32();
- instance.mInterfaces.resize(interfaceCount);
- for (unsigned int j = 0; j < interfaceCount; ++j)
+ // This is the list of interfaces which the instances has
agreed to
+ // implement. They must be interfaces, and they must exist.
+ uint32_t intcount = mS->read_V32();
+
+ for (unsigned int j = 0; j < intcount; ++j)
{
- uint32_t i_index = in->read_V32();
+ uint32_t i_index = mS->read_V32();
// 0 is allowed as an interface, typically for the last
one.
if (i_index >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound name for
interface. "
- "(%d)\n"), i_index));
- return false; // Bad read.
- }
- instance.mInterfaces[j] = &mMultinamePool[i_index];
+ ERR((_("ABC: Out of bounds name for
interface.\n")));
+ return false;
}
-
- // Reach into the methods list.
- uint32_t methodsOffset = in->read_V32();
- if (methodsOffset >= mMethods.size())
+ asClass *pInterface =
locateClass(mMultinamePool[i_index]);
+ // These may be undefined still, so don't check
interface just yet.
+ if (0) //!pInterface || !pInterface->isInterface())
{
- ERR((_("Action Block: Out of Bound method for
interface. (%d)\n"),
- methodsOffset));
- return false; // Bad method.
+ ERR((_("ABC: Can't implement a non-interface
type.\n")));
+ return false;
+ }
+ pClass->pushInterface(pInterface);
}
- instance.mMethod = &mMethods[methodsOffset];
- // Now parse the traits.
- // How many of them.
- uint32_t traitsCount = in->read_V32();
- instance.mTraits.resize(traitsCount);
- for (unsigned int j = 0; j < traitsCount; ++j)
+ // The next thing should be the constructor.
+ // TODO: What does this mean exactly? How does it differ from
the one in
+ // the class info block?
+ uint32_t moffset = mS->read_V32();
+ if (moffset >= mMethods.size())
{
- if (!instance.mTraits[j].read(in))
+ ERR((_("ABC: Out of bounds method for
initializer.\n")));
return false;
}
-
- if (instance.mName->mNamespace == NULL)
+ if (mMethods[moffset]->getOwner())
{
- ERR((_("Action Block: No namespace to use for storing
class.\n")));
+ ERR((_("ABC: Initializer method already bound.\n")));
return false;
}
- if
(!instance.mName->mNamespace->stubPrototype(instance.mName->mName))
- {
- ERR((_("Duplicate class registration for type %s.\n"),
-
mStringTable->value(instance.mName->mName).c_str()));
+ pClass->setConstructor(mMethods[moffset]);
+ mMethods[moffset]->setOwner(pClass);
+
+ // Next come the 'traits' of the instance. (The members.)
+ uint32_t tcount = mS->read_V32();
+ for (unsigned int j = 0; j < tcount; ++j)
+ {
+ abc_Trait &aTrait = newTrait();
+ aTrait.set_target(pClass, false);
+ if (!aTrait.read(mS, this))
return false;
}
- } // end of instances list
+ } // End of instances loop.
+ return true;
+}
- // Now the classes are read. TODO: Discover what these do.
- for (unsigned int i = 0; i < classCount; ++i)
+/// Read the class data
+bool
+abc_block::read_classes()
+{
+ // Count was found in read_instances().
+ uint32_t count = mClasses.size();
+
+ for (unsigned int i = 0; i < count; ++i)
{
- abc_Class& cClass = mClasses[i];
- uint32_t method_offset = in->read_V32();
- if (method_offset >= mMethods.size())
+ asClass *pClass = mClasses[i];
+ uint32_t moffset = mS->read_V32();
+ if (moffset >= mMethods.size())
+ {
+ ERR((_("ABC: Out of bound static constructor for
class.\n")));
+ return false;
+ }
+ if (mMethods[moffset]->getOwner())
{
- ERR((_("Action Block: Out of Bound method for class
(%d).\n"),
- method_offset));
+ ERR((_("ABC: Static constructor method already
bound.\n")));
return false;
}
- cClass.mMethod = &mMethods[method_offset];
+ pClass->setStaticConstructor(mMethods[moffset]);
+ mMethods[moffset]->setOwner(pClass);
- uint32_t traitsCount = in->read_V32();
- cClass.mTraits.resize(traitsCount);
- for (unsigned int j = 0; j < traitsCount; ++j)
+ uint32_t tcount = mS->read_V32();
+ for (unsigned int j = 0; j < tcount; ++j)
{
- if (!cClass.mTraits[j].read(in))
+ abc_Trait &aTrait = newTrait();
+ aTrait.set_target(pClass, true);
+ if (!(aTrait.read(mS, this)))
return false;
}
- } // end of classes list
+ } // end of classes loop
+ return true;
+}
+
+/// Read the scripts (global functions)
+/// The final script is the entry point for the block.
+bool
+abc_block::read_scripts()
+{
+ uint32_t count = mS->read_V32();
- // The scripts. TODO: Discover what these do.
- uint32_t scriptCount = in->read_V32();
- mScripts.resize(scriptCount);
- for (unsigned int i = 0; i < scriptCount; ++i)
+ mScripts.resize(count);
+ for (unsigned int i = 0; i < count; ++i)
{
- abc_Script& script = mScripts[i];
- uint32_t method_offset = in->read_V32();
- if (method_offset >= mMethods.size())
+ asClass *pScript = mCH->newClass();
+ mScripts[i] = pScript;
+
+ uint32_t moffset = mS->read_V32();
+ if (moffset >= mMethods.size())
{
- ERR((_("Action Block: Out of Bound method for script
(%d).\n"),
- method_offset));
+ ERR((_("ABC: Out of bounds method for script.\n")));
return false;
}
- script.mMethod = &mMethods[method_offset];
-
- uint32_t traitsCount = in->read_V32();
- script.mTraits.resize(traitsCount);
- for (unsigned int j = 0; j < traitsCount; ++j)
+ if (mMethods[moffset]->getOwner())
{
- if (!script.mTraits[j].read(in))
+ ERR((_("ABC: Global script initializer is already
bound.\n")));
return false;
}
+ mMethods[moffset]->setOwner(pScript);
+ pScript->setConstructor(mMethods[moffset]);
+ pScript->setSuper(mTheObject);
+
+ uint32_t tcount = mS->read_V32();
+ for (unsigned int j = 0; j < tcount; ++j)
+ {
+ abc_Trait &aTrait = newTrait();
+ aTrait.set_target(pScript, false);
+ if (!(aTrait.read(mS, this)))
+ return false;
}
+ } // end of scripts loop
+ return true;
+}
- // The method bodies. TODO: Use these.
- uint32_t methodBodyCount = in->read_V32();
- mBodies.resize(methodBodyCount);
- for (unsigned int i = 0; i < methodBodyCount; ++i)
+/// Read the method bodies and attach them to the methods.
+bool
+abc_block::read_method_bodies()
+{
+ uint32_t count = mS->read_V32();
+
+ for (unsigned int i = 0; i < count; ++i)
{
- abc_MethodBody& method = mBodies[i];
+ asMethodBody *pBody = mCH->newMethodBody();
- uint32_t method_info = in->read_V32();
- if (method_info >= mMethods.size())
+ uint32_t moffset = mS->read_V32();
+ if (moffset >= mMethods.size())
+ {
+ ERR((_("ABC: Out of bounds for method body.\n")));
+ return false;
+ }
+ if (mMethods[moffset]->getBody())
{
- ERR((_("Action Block: Out of Bound method for method
body. "
- "(%d)\n"), method_info));
- return false; // Too big.
+ ERR((_("ABC: Only one body per method.\n")));
+ return false;
}
- method.mMethod = &mMethods[method_info];
+ mMethods[moffset]->setBody(pBody);
- // We don't care about the maximum stack size. Discard it.
- in->skip_V32();
- // We don't care about the maximum register size. Discard it.
- in->skip_V32();
- // What to do with the scope depth?
- in->skip_V32();
- // What to do with the max scope depth?
- in->skip_V32();
- // How long is the code?
- uint32_t code_length = in->read_V32();
- // And the code:
- method.mCode.resize(code_length);
+ // Maximum stack size.
+ mS->skip_V32();
+ // Maximum register size.
+ mS->skip_V32();
+ // Scope depth.
+ mS->skip_V32();
+ // Max scope depth.
+ mS->skip_V32();
+ // Code length
+ uint32_t clength = mS->read_V32();
+ // The code.
+ pBody->setSize(clength);
unsigned int got_length;
- if ((got_length = in->read(&method.mCode.front(), code_length))
!= code_length)
+ if ((got_length = mS->read(pBody->getRaw(), clength)) !=
clength)
{
- ERR((_("Action Block: Not enough body. Wanted %d but
got %d.\n"),
- code_length, got_length));
- return false; // Not enough bytes.
+ ERR((_("ABC: Not enough method body. Wanted %d but got
%d.\n"),
+ pBody->getSize(), got_length));
+ return false;
}
- // TODO: Grab code_length bytes for the code.
- uint32_t exceptions_count = in->read_V32();
- method.mExceptions.resize(exceptions_count);
- for (unsigned int j = 0; j < exceptions_count; ++j)
+ uint32_t ecount = mS->read_V32();
+ for (unsigned int j = 0; j < ecount; ++j)
{
- abc_Exception& exceptor = method.mExceptions[j];
+ asException *pExcept = mCH->newException();
// Where the try block begins and ends.
- exceptor.mStart = in->read_V32();
- exceptor.mEnd = in->read_V32();
+ pExcept->setStart(mS->read_V32());
+ pExcept->setEnd(mS->read_V32());
- // Where to go if this exception is activated.
- exceptor.mCatch = in->read_V32();
+ // Where to go when the exception is activated.
+ pExcept->setCatch(mS->read_V32());
// What types should be caught.
- uint32_t catch_type = in->read_V32();
+ uint32_t catch_type = mS->read_V32();
if (catch_type >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound type for
exception "
- "(%d).\n"), catch_type));
- return false; // Bad type.
+ ERR((_("ABC: Out of bound type for
exception.\n")));
+ return false;
+ }
+ if (!catch_type)
+ {
+ pExcept->catchAny();
+ }
+ else
+ {
+ asClass *pType =
locateClass(mMultinamePool[catch_type]);
+ if (!pType)
+ {
+ ERR((_("ABC: Unknown type of object to
catch. (%s)\n"),
+
mStringTable->value(mMultinamePool[catch_type].mName).c_str()));
+ // return false;
+ // Fake it, for now:
+ pExcept->catchAny();
+ }
+ else
+ {
+ pExcept->setCatchType(pType);
+ }
}
- exceptor.mType = catch_type ?
&mMultinamePool[catch_type] : NULL;
- // If caught, what is the variable name.
- if (version != (46 << 16) | 15) // In version 46.15, no
names.
+ // A variable name for the catch type.
+ // In version 46.15, no names.
+ if (mVersion != (46 << 16) | 15)
{
- uint32_t cvn = in->read_V32();
+ uint32_t cvn = mS->read_V32();
if (cvn >= mMultinamePool.size())
{
- ERR((_("Action Block: Out of Bound name
for caught "
- "exception. (%d)\n"), cvn));
- return false; // Bad name
+ ERR((_("ABC: Out of bound name for
caught exception.\n")));
+ return false;
}
- exceptor.mName = cvn ? &mMultinamePool[cvn] :
NULL;
+ pExcept->setName(mMultinamePool[cvn].mName);
+
pExcept->setNamespace(mMultinamePool[cvn].mNamespace);
}
- else
- exceptor.mName = NULL;
- } // End of exceptions
+ } // end of exceptions
- uint32_t traitsCount = in->read_V32();
- method.mTraits.resize(traitsCount);
- for (unsigned int j = 0; j < traitsCount; ++j)
+ uint32_t tcount = mS->read_V32();
+ for (unsigned int j = 0; j < tcount; ++j)
{
- if (!method.mTraits[j].read(in))
+ abc_Trait &aTrait = newTrait();
+ aTrait.set_target(mMethods[moffset]);
+ if (!aTrait.read(mS, this)) // TODO: 'method body
activation traits'
return false;
}
- } // End of method bodies
+ } // end of bodies loop
+ return true;
+}
- // Everything has been read. It needs to be verified, with symbol tables
- // built to make it all run.
+// Load up all of the data.
+bool
+abc_block::read(stream* in)
+{
+ mS = in;
+ if (!read_version()) return false;
+ if (!read_integer_constants()) return false;
+ if (!read_unsigned_integer_constants()) return false;
+ if (!read_double_constants()) return false;
+ if (!read_string_constants()) return false;
+ if (!read_namespaces()) return false;
+ if (!read_namespace_sets()) return false;
+ if (!read_multinames()) return false;
+ if (!read_method_infos()) return false;
+ if (!skip_metadata()) return false;
+ if (!read_instances()) return false;
+ if (!read_classes()) return false;
+ if (!read_scripts()) return false;
+ if (!read_method_bodies()) return false;
- // If flow reaches here, everything went fine.
+ std::vector<abc_Trait*>::iterator i = mTraits.begin();
+ for ( ; i != mTraits.end(); ++i)
+ {
+ if (!(*i)->finalize(this))
+ return false;
+ }
+ mTraits.clear();
+ mCH->dump();
return true;
}
abc_block::abc_block() : mStringTable(&VM::get().getStringTable())
{
- /**/
+ mCH = VM::get().getClassHierarchy();
+ // TODO: Make this the real 'Object' prototype.
+ mCH->getGlobalNs()->stubPrototype(NSV::CLASS_OBJECT);
+ mTheObject = mCH->getGlobalNs()->getClass(NSV::CLASS_OBJECT);
}
}; /* namespace gnash */
Index: server/parser/abc_block.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/abc_block.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/parser/abc_block.h 24 Sep 2007 15:39:31 -0000 1.4
+++ server/parser/abc_block.h 29 Sep 2007 08:24:21 -0000 1.5
@@ -28,13 +28,14 @@
#include "gnash.h"
#include "stream.h"
#include "string_table.h"
-#include "Namespace.h"
+#include "asClass.h"
namespace gnash {
-typedef std::vector<Namespace *> abcNamespaceSet;
+typedef std::vector<asNamespace *> abcNamespaceSet;
class abc_block;
+class ClassHierarchy;
namespace abc_parsing {
@@ -67,57 +68,11 @@
uint8_t mFlags;
string_table::key mName;
- Namespace* mNamespace;
- std::vector<Namespace*> *mNamespaceSet;
-};
-
-class abc_Method
-{
-public:
- typedef enum
- {
- FLAG_ARGS = 0x01,
- FLAG_ACTIVATION = 0x02,
- FLAG_MORE = 0x04,
- FLAG_OPTIONAL = 0x08,
- FLAG_IGNORE = 0x10,
- FLAG_NATIVE = 0x20,
- FLAG_DEFAULT_NS = 0x40,
- FLAG_PARAM_NAMES = 0x80
- } flags;
-
- class optional_parameter
- {
- public:
- uint32_t mIndex;
- uint8_t mKind;
- };
+ asNamespace* mNamespace;
+ std::vector<asNamespace*> *mNamespaceSet;
- abc_Multiname *mReturnType;
- std::vector<abc_Multiname*> mParameters; // The types, not the names.
- uint8_t mFlags;
- std::vector<optional_parameter> mOptionalParameters;
-};
-
-class abc_Instance
-{
-public:
- typedef enum
- {
- FLAG_SEALED = 0x01,
- FLAG_FINAL = 0x02,
- FLAG_INTERFACE = 0x04,
- FLAG_PROTECTED_NS = 0x08,
- FLAG_DYNAMIC = 0x00 // No other flags set
- } flags;
-
- abc_Multiname *mName;
- abc_Multiname *mSuperType;
- flags mFlags;
- Namespace *mProtectedNamespace;
- std::vector<abc_Multiname*> mInterfaces;
- abc_Method *mMethod;
- std::vector<abc_Trait> mTraits;
+ abc_Multiname() : mFlags(0), mName(0), mNamespace(NULL),
mNamespaceSet(NULL)
+ {/**/}
};
class abc_Trait
@@ -134,79 +89,128 @@
KIND_FUNCTION = 5
} kinds;
+ bool mHasValue;
kinds mKind;
- uint32_t mNameIndex;
- uint32_t mNamespaceIndex;
- uint32_t mNamespaceSetIndex;
uint32_t mSlotId;
uint32_t mTypeIndex;
- uint32_t mValueIndex;
- uint8_t mValueIndexTypeIndex;
uint32_t mClassInfoIndex;
- uint32_t mMethodInfoIndex;
-
- bool read(stream* in);
-};
-
-class abc_Class
-{
-public:
- abc_Method *mMethod;
- std::vector<abc_Trait> mTraits;
-};
-
-class abc_Script
-{
-public:
- abc_Method *mMethod;
- std::vector<abc_Trait> mTraits;
-};
-
-class abc_Exception
-{
-public:
- uint32_t mStart;
- uint32_t mEnd;
- uint32_t mCatch;
- abc_Multiname* mType;
- abc_Multiname* mName;
-};
-
-class abc_MethodBody
-{
-public:
- abc_Method *mMethod;
- std::vector<abc_Exception> mExceptions;
- std::vector<abc_Trait> mTraits;
- std::vector<char> mCode;
+ as_value mValue;
+ string_table::key mName;
+ asNamespace *mNamespace;
+ asMethod *mMethod;
+ bool mValueSet;
+
+ asClass *mCTarget;
+ asMethod *mMTarget;
+ bool mStatic;
+
+ abc_Trait() : mHasValue(false), mKind(KIND_SLOT), mSlotId(0),
+ mTypeIndex(0), mClassInfoIndex(0), mValue(), mName(0),
+ mNamespace(NULL), mMethod(NULL), mValueSet(false)
+ {/**/}
+
+ bool read(stream* in, abc_block *pBlock);
+ bool finalize(abc_block *pBlock, asClass *pClass, bool do_static);
+ bool finalize_mbody(abc_block *pBlock, asMethod *pMethod);
+
+ void set_target(asClass *pClass, bool do_static)
+ { mCTarget = pClass; mStatic = do_static; }
+ void set_target(asMethod *pMethod)
+ { mCTarget = NULL; mMTarget = pMethod; }
+
+ bool finalize(abc_block *pBlock)
+ {
+ if (mCTarget)
+ return finalize(pBlock, mCTarget, mStatic);
+ return finalize_mbody(pBlock, mMTarget);
+ }
};
}; // namespace abc_parsing
-typedef std::vector<Namespace*> NamespaceSet;
+typedef std::vector<asNamespace*> NamespaceSet;
class abc_block
{
private:
+ friend class abc_parsing::abc_Trait;
+ typedef enum
+ {
+ PRIVATE_NS = 0x05,
+ PROTECTED_NS = 0x18,
+ METHOD_ARGS = 0x01,
+ METHOD_ACTIVATION = 0x02,
+ METHOD_MORE = 0x04,
+ METHOD_OPTIONAL_ARGS = 0x08,
+ METHOD_IGNORE = 0x10,
+ METHOD_NATIVE = 0x20,
+ METHOD_DEFAULT_NS = 0x40,
+ METHOD_ARG_NAMES = 0x80,
+ INSTANCE_SEALED = 0x01,
+ INSTANCE_FINAL = 0x02,
+ INSTANCE_INTERFACE = 0x04,
+ INSTANCE_DYNAMIC = 0x00,
+ INSTANCE_PROTECTED_NS = 0x08,
+ POOL_STRING = 0x01,
+ POOL_INTEGER = 0x03,
+ POOL_UINTEGER = 0x04,
+ POOL_DOUBLE = 0x06,
+ POOL_NAMESPACE = 0x08,
+ POOL_FALSE = 0x0A,
+ POOL_TRUE = 0x0B,
+ POOL_NULL = 0x0C
+ } constants;
+
std::vector<int32_t> mIntegerPool;
std::vector<uint32_t> mUIntegerPool;
std::vector<long double> mDoublePool;
std::vector<std::string> mStringPool;
std::vector<string_table::key> mStringPoolTableIds;
- std::vector<Namespace*> mNamespacePool;
+ std::vector<asNamespace*> mNamespacePool;
std::vector<NamespaceSet> mNamespaceSetPool;
- std::vector<abc_parsing::abc_Method> mMethods;
+ std::vector<asMethod*> mMethods;
std::vector<abc_parsing::abc_Multiname> mMultinamePool;
- std::vector<abc_parsing::abc_Instance> mInstances;
- std::vector<abc_parsing::abc_Class> mClasses;
- std::vector<abc_parsing::abc_Script> mScripts;
- std::vector<abc_parsing::abc_MethodBody> mBodies;
+ std::vector<asClass*> mClasses;
+ std::vector<asClass*> mScripts;
+ std::vector<abc_parsing::abc_Trait*> mTraits;
string_table* mStringTable;
+ stream *mS; // Not stored beyond one read.
+
+ asClass *mTheObject;
+ ClassHierarchy *mCH;
+
+ uint32_t mVersion;
+
+ asClass *locateClass(abc_parsing::abc_Multiname &m);
+
+ abc_parsing::abc_Trait &newTrait()
+ {
+ abc_parsing::abc_Trait *p = new abc_parsing::abc_Trait;
+ mTraits.push_back(p);
+ return *p;
+ }
+
+public:
+ bool read_version();
+ bool read_integer_constants();
+ bool read_unsigned_integer_constants();
+ bool read_double_constants();
+ bool read_string_constants();
+ bool read_namespaces();
+ bool read_namespace_sets();
+ bool read_multinames();
+ bool read_method_infos();
+ bool skip_metadata();
+ bool read_instances();
+ bool read_classes();
+ bool read_scripts();
+ bool read_method_bodies();
-public:
bool read(stream* in);
+ bool pool_value(uint32_t index, uint8_t type, as_value &v);
+
abc_block();
};
Index: server/vm/VM.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/VM.cpp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/vm/VM.cpp 24 Sep 2007 15:39:31 -0000 1.21
+++ server/vm/VM.cpp 29 Sep 2007 08:24:22 -0000 1.22
@@ -16,7 +16,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-/* $Id: VM.cpp,v 1.21 2007/09/24 15:39:31 cmusick Exp $ */
+/* $Id: VM.cpp,v 1.22 2007/09/29 08:24:22 cmusick Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -155,6 +155,8 @@
{
(*i)->setReachable();
}
+
+ mClassHierarchy->markReachableResources();
#endif
}
Index: testsuite/samples/.cvsignore
===================================================================
RCS file: /sources/gnash/gnash/testsuite/samples/.cvsignore,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- testsuite/samples/.cvsignore 4 May 2007 09:49:00 -0000 1.6
+++ testsuite/samples/.cvsignore 29 Sep 2007 08:24:22 -0000 1.7
@@ -13,3 +13,6 @@
GotoAndPlayTestRunner
gotoFrameOnKeyEvent-TestRunner
gmon.out
+subshapes-TestRunner
+BitsReaderTest
+StreamTest
Index: extensions/dbus/.cvsignore
===================================================================
RCS file: extensions/dbus/.cvsignore
diff -N extensions/dbus/.cvsignore
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ extensions/dbus/.cvsignore 29 Sep 2007 08:24:20 -0000 1.1
@@ -0,0 +1,3 @@
+.deps
+Makefile
+Makefile.in
Index: extensions/lirc/.cvsignore
===================================================================
RCS file: extensions/lirc/.cvsignore
diff -N extensions/lirc/.cvsignore
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ extensions/lirc/.cvsignore 29 Sep 2007 08:24:20 -0000 1.1
@@ -0,0 +1,3 @@
+.deps
+Makefile
+Makefile.in
Index: libmedia/.cvsignore
===================================================================
RCS file: libmedia/.cvsignore
diff -N libmedia/.cvsignore
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/.cvsignore 29 Sep 2007 08:24:21 -0000 1.1
@@ -0,0 +1,5 @@
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
Index: server/asClass.cpp
===================================================================
RCS file: server/asClass.cpp
diff -N server/asClass.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asClass.cpp 29 Sep 2007 08:24:21 -0000 1.1
@@ -0,0 +1,339 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "asClass.h"
+#include "ClassHierarchy.h"
+#include "VM.h"
+
+namespace gnash {
+
+#define STV(x) VM::get().getStringTable().value(x).c_str()
+
+void
+asNamespace::stubPrototype(string_table::key name)
+{
+ asClass *pClass = VM::get().getClassHierarchy()->newClass();
+ pClass->setName(name);
+ addClass(name, pClass);
+}
+
+bool
+asMethod::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, as_value& val, bool isconst, ClassHierarchy *CH)
+{
+ asBoundValue *bv = CH->newBoundValue();
+ bv->setType(type);
+ bv->setValue(val);
+ return addBinding(name, asBinding(ns, bv, slotId, isconst, false));
+}
+
+bool
+asMethod::addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, ClassHierarchy *CH)
+{
+ asBoundValue *bv = CH->newBoundValue();
+ bv->setType(type);
+ return addBinding(name, asBinding(ns, bv, slotId, false));
+}
+
+bool
+asMethod::addMethod(string_table::key name, asNamespace *ns, asMethod *method)
+{
+ return addBinding(name, asBinding(ns, method, false));
+}
+
+bool
+asMethod::addGetter(string_table::key name, asNamespace *ns, asMethod *method,
+ ClassHierarchy *CH)
+{
+ asBinding *bv = getBinding(name);
+ if (bv)
+ {
+ asBoundAccessor *a = bv->getAccessor();
+ if (!a)
+ {
+ // Okay if this is already bound to a value.
+ asBoundValue *v = bv->getValue();
+ if (!v)
+ {
+ // Let caller do the logging.
+ return false;
+ }
+ a = CH->newBoundAccessor();
+ a->setValue(v);
+ bv->reset(a, bv->isStatic());
+ }
+ return a->setGetter(method);
+ }
+ asBoundAccessor *a = CH->newBoundAccessor();
+ a->setGetter(method);
+ return addBinding(name, asBinding(ns, a, false));
+}
+
+bool
+asMethod::addSetter(string_table::key name, asNamespace *ns, asMethod *method,
+ ClassHierarchy *CH)
+{
+ asBinding *bv = getBinding(name);
+ if (bv)
+ {
+ asBoundAccessor *a = bv->getAccessor();
+ if (!a)
+ {
+ asBoundValue *v = bv->getValue();
+ if (!v)
+ {
+ // Let caller do the logging.
+ return false;
+ }
+ a = CH->newBoundAccessor();
+ a->setValue(v);
+ bv->reset(a, bv->isStatic());
+ }
+ return a->setSetter(method);
+ }
+ asBoundAccessor *a = CH->newBoundAccessor();
+ addBinding(name, asBinding(ns, a, false));
+ return a->setSetter(method);
+}
+
+bool
+asMethod::addMemberClass(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asClass *type)
+{
+ return addBinding(name, asBinding(ns, type, slotId, false));
+}
+
+// TODO: Figure out how this differs from addMethod
+bool
+asMethod::addSlotFunction(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asMethod *method)
+{
+ return addBinding(name, asBinding(ns, method, slotId, false));
+}
+
+bool
+asClass::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, as_value& val, bool isconst, bool isstatic,
+ ClassHierarchy *CH)
+{
+ asBoundValue *bv = CH->newBoundValue();
+ bv->setType(type);
+ bv->setValue(val);
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, bv, slotId, isconst,
isstatic));
+ return addStaticBinding(name, asBinding(ns, bv, slotId, isconst,
isstatic));
+}
+
+bool
+asClass::addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, bool isstatic, ClassHierarchy *CH)
+{
+ asBoundValue *bv = CH->newBoundValue();
+ bv->setType(type);
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, bv, slotId, isstatic));
+ return addStaticBinding(name, asBinding(ns, bv, slotId, isstatic));
+}
+
+bool
+asClass::addMethod(string_table::key name, asNamespace *ns, asMethod *method,
+ bool isstatic)
+{
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, method, isstatic));
+ else
+ return addStaticBinding(name, asBinding(ns, method, isstatic));
+}
+
+bool
+asClass::addGetter(string_table::key name, asNamespace *ns, asMethod *method,
+ bool isstatic, ClassHierarchy *CH)
+{
+ asBinding *bv;
+ if (!isstatic)
+ bv = getBinding(name);
+ else
+ bv = getStaticBinding(name);
+ if (bv)
+ {
+ asBoundAccessor *a = bv->getAccessor();
+ if (!a)
+ {
+ // Okay if this is already bound to a value.
+ asBoundValue *v = bv->getValue();
+ if (!v)
+ {
+ // Let caller do the logging.
+ return false;
+ }
+ a = CH->newBoundAccessor();
+ a->setValue(v);
+ bv->reset(a, bv->isStatic());
+ }
+ return a->setGetter(method);
+ }
+ asBoundAccessor *a = CH->newBoundAccessor();
+ a->setGetter(method);
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, a, isstatic));
+ return addStaticBinding(name, asBinding(ns, a, isstatic));
+}
+
+bool
+asClass::addSetter(string_table::key name, asNamespace *ns, asMethod *method,
+ bool isstatic, ClassHierarchy *CH)
+{
+ asBinding *bv;
+ if (!isstatic)
+ bv = getBinding(name);
+ else
+ bv = getStaticBinding(name);
+
+ if (bv)
+ {
+ asBoundAccessor *a = bv->getAccessor();
+ if (!a)
+ {
+ asBoundValue *v = bv->getValue();
+ if (!v)
+ {
+ // Let caller do the logging.
+ return false;
+ }
+ a = CH->newBoundAccessor();
+ a->setValue(v);
+ bv->reset(a, bv->isStatic());
+ }
+ return a->setSetter(method);
+ }
+ asBoundAccessor *a = CH->newBoundAccessor();
+ a->setSetter(method);
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, a, isstatic));
+ else
+ return addStaticBinding(name, asBinding(ns, a, isstatic));
+}
+
+bool
+asClass::addMemberClass(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asClass *type, bool isstatic)
+{
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, type, slotId, isstatic));
+ return addStaticBinding(name, asBinding(ns, type, slotId, isstatic));
+}
+
+// TODO: Figure out how this differs from addMethod
+bool
+asClass::addSlotFunction(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asMethod *method, bool isstatic)
+{
+ if (!isstatic)
+ return addBinding(name, asBinding(ns, method, slotId,
isstatic));
+ return addStaticBinding(name, asBinding(ns, method, slotId, isstatic));
+}
+
+void
+asNamespace::dump()
+{
+ container::iterator i;
+ for (i = mClasses.begin(); i != mClasses.end(); ++i)
+ {
+ if (!((*i->second).isDeclared()))
+ {
+ if (i->second->isSystem())
+ fprintf(stderr, "(Known to internals) ");
+ fprintf(stderr, "%s.%s\n", STV(getURI()),
+ STV(i->second->getName()));
+// else
+// (*i->second).dump();
+ }
+ }
+}
+
+void
+asClass::dump()
+{
+ binding_container::iterator i;
+ fprintf(stderr, "Class: %s\n", STV(getName()));
+ for (i = mBindings.begin(); i != mBindings.end(); ++i)
+ {
+ fprintf(stderr, " ");
+ i->second.dump(i->first);
+ }
+}
+
+void
+asBinding::dump(string_table::key name)
+{
+ if (mNamespace->isProtected())
+ fprintf(stderr, "+");
+ if (mNamespace->isPrivate())
+ fprintf(stderr, "#");
+ if (mConst)
+ fprintf(stderr, "@");
+ fprintf(stderr, "%s: ", STV(name));
+ switch (mType)
+ {
+ case T_CLASS:
+ {
+ fprintf(stderr, "Class %s", STV(mClass->getName()));
+ break;
+ }
+ case T_METHOD:
+ {
+// if (mConst)
+ fprintf(stderr, "Member Function: %s",
STV(mMethod->getReturnType()->getName()));
+// else
+// fprintf(stderr, "Function Slot");
+ break;
+ }
+ case T_VALUE:
+ {
+ if (mValue->getType())
+ fprintf(stderr, "Value of type %s",
STV(mValue->getType()->getName()));
+ else
+ fprintf(stderr, "Value of unknown type.");
+ break;
+ }
+ case T_ACCESS:
+ {
+ fprintf(stderr, "GetSet: ");
+ if (mAccess->getGetter())
+ {
+ fprintf(stderr, "g:%s ",
STV(mAccess->getGetter()->getReturnType()->getName()));
+ }
+ if (mAccess->getSetter())
+ {
+ fprintf(stderr, "s ");
+ }
+ if (mAccess->getValue())
+ {
+ fprintf(stderr, "dv: ");
+ if (mAccess->getValue()->getType())
+ fprintf(stderr, "%s ",
STV(mAccess->getValue()->getType()->getName()));
+ else
+ fprintf(stderr, "(unknown type)");
+ }
+ break;
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+} /* namespace gnash */
Index: server/asClass.h
===================================================================
RCS file: server/asClass.h
diff -N server/asClass.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asClass.h 29 Sep 2007 08:24:21 -0000 1.1
@@ -0,0 +1,661 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#ifndef GNASH_AS_CLASS_H
+#define GNASH_AS_CLASS_H
+
+#include <list>
+#include <map>
+#include <vector>
+#include "string_table.h"
+#include "as_value.h"
+
+namespace gnash {
+
+class as_function;
+class asNamespace;
+class asMethod;
+class asClass;
+class asException;
+class asBinding;
+class asBoundValue;
+class asBoundAccessor;
+class ClassHierarchy;
+
+class asException
+{
+public:
+ void setStart(uint32_t i) { mStart = i; }
+ void setEnd(uint32_t i) { mEnd = i; }
+ void setCatch(uint32_t i) { mCatch = i; }
+ void catchAny() { mCatchAny = true; }
+ void setCatchType(asClass* p) { mCatchType = p; }
+ void setNamespace(asNamespace* n) { mNamespace = n; }
+ void setName(string_table::key name) { mName = name; }
+
+private:
+ uint32_t mStart;
+ uint32_t mEnd;
+ uint32_t mCatch;
+ bool mCatchAny;
+ asClass *mCatchType;
+ asNamespace *mNamespace;
+ string_table::key mName;
+};
+
+/// An abstract binding for ActionScript.
+class asBinding
+{
+public:
+ void dump(string_table::key name);
+
+ void setConst() { mConst = true; }
+ void unsetConst() { mConst = false; }
+ bool isConst() { return mConst; }
+
+ void setStatic() { mStatic = true; }
+ void unsetStatic() { mStatic = false; }
+ bool isStatic() { return mStatic; }
+
+ uint32_t getSlotId() { return mSlotId; }
+ void setSlotId(uint32_t s) { mSlotId = s; }
+
+ // As a member method.
+ asBinding(asNamespace *ns, asMethod *pMethod, bool isstatic = false) :
+ mNamespace(ns), mType(T_METHOD), mSlotId(0), mConst(true),
+ mStatic(isstatic), mMethod(pMethod)
+ {/**/}
+
+ // As an assignable function.
+ asBinding(asNamespace *ns, asMethod *pMethod, uint32_t sid, bool
isstatic) :
+ mNamespace(ns), mType(T_METHOD), mSlotId(sid), mConst(false),
+ mStatic(isstatic), mMethod(pMethod)
+ {/**/}
+
+ asBinding(asNamespace *ns, asBoundValue *pValue, uint32_t sid, bool
isconstant,
+ bool isstatic) : mNamespace(ns), mType(T_VALUE), mSlotId(sid),
mConst(isconstant),
+ mStatic(isstatic), mValue(pValue)
+ {/**/}
+
+ asBinding(asNamespace *ns, asBoundValue *pValue, uint32_t sid, bool
isstatic) :
+ mNamespace(ns), mType(T_VALUE), mSlotId(sid), mConst(false),
mStatic(isstatic),
+ mValue(pValue)
+ {/**/}
+
+ asBinding(asNamespace *ns, asBoundAccessor *pAccess, bool isstatic) :
+ mNamespace(ns), mType(T_ACCESS), mSlotId(0), mConst(true),
mStatic(isstatic),
+ mAccess(pAccess)
+ {/**/}
+
+ asBinding(asNamespace *ns, asClass *pClass, uint32_t sid, bool
isstatic) :
+ mNamespace(ns), mType(T_CLASS), mSlotId(sid), mConst(true),
mStatic(isstatic),
+ mClass(pClass)
+ {/**/}
+
+ asBinding() : mNamespace(NULL), mType(T_CLASS), mSlotId(0),
mConst(false), mStatic(false),
+ mClass(NULL)
+ {/**/}
+
+ void reset(asBoundAccessor *pAccess, bool isstatic)
+ {
+ mType = T_ACCESS;
+ mAccess = pAccess;
+ mConst = true;
+ mStatic = isstatic;
+ }
+
+ asBoundAccessor* getAccessor()
+ { return mType == T_ACCESS ? mAccess : NULL; }
+
+ asBoundValue* getValue()
+ { return mType == T_VALUE ? mValue : NULL; }
+
+ asMethod* getMethod()
+ { return mType == T_METHOD ? mMethod : NULL; }
+
+ asClass* getClass()
+ { return mType == T_CLASS ? mClass : NULL; }
+
+private:
+ asNamespace *mNamespace;
+
+ typedef enum
+ {
+ T_CLASS,
+ T_METHOD,
+ T_VALUE,
+ T_ACCESS
+ } types;
+ types mType;
+
+ uint32_t mSlotId;
+ bool mConst;
+ bool mStatic;
+
+ union
+ {
+ asClass *mClass;
+ asMethod *mMethod;
+ asBoundValue *mValue;
+ asBoundAccessor *mAccess;
+ };
+};
+
+class asMethodBody
+{
+public:
+ void setSize(std::size_t s) { mData.resize(s); }
+ std::size_t getSize() { return mData.size(); }
+ char *getRaw() { return &mData.front(); }
+private:
+ std::vector<char> mData;
+};
+
+/// Represent an ActionScript namespace
+class asNamespace
+{
+public:
+ void markReachableResources() const { /* TODO */ }
+
+ /// Our parent (for protected)
+ void setParent(asNamespace* p) { mParent = p; }
+
+ asNamespace* getParent() { return mParent; }
+
+ /// Set the uri
+ void setURI(string_table::key name) { mUri = name; }
+
+ /// What is the Uri of the namespace?
+ string_table::key getURI() const { return mUri; }
+
+ /// What is the XML prefix?
+ string_table::key getPrefix() const { return mPrefix; }
+
+ /// Create an empty namespace
+ asNamespace() : mParent(NULL), mUri(0), mPrefix(0), mClasses(),
+ mRecursePrevent(false), mPrivate(false), mProtected(false)
+ {/**/}
+
+ /// Add a class to the namespace. The namespace stores this, but
+ /// does not take ownership. (So don't delete it.)
+ bool addClass(string_table::key name, asClass *a)
+ {
+ if (getClassInternal(name))
+ return false;
+ mClasses[name] = a;
+ return true;
+ }
+
+ void stubPrototype(string_table::key name);
+
+ /// Get the named class. Returns NULL if information is not known
+ /// about the class. (Stubbed classes still return NULL here.)
+ asClass *getClass(string_table::key name)
+ {
+ if (mRecursePrevent)
+ return NULL;
+
+ asClass *found = getClassInternal(name);
+ if (found || !getParent())
+ return found;
+
+ mRecursePrevent = true;
+ found = getParent()->getClass(name);
+ mRecursePrevent = false;
+ return found;
+ }
+
+ void dump();
+
+ void setPrivate() { mPrivate = true; }
+ void unsetPrivate() { mPrivate = false; }
+ bool isPrivate() { return mPrivate; }
+
+ void setProtected() { mProtected = true; }
+ void unsetProtected() { mProtected = false; }
+ bool isProtected() { return mProtected; }
+
+private:
+ asNamespace *mParent;
+ string_table::key mUri;
+ string_table::key mPrefix;
+
+ typedef std::map<string_table::key, asClass*> container;
+ container mClasses;
+ mutable bool mRecursePrevent;
+
+ bool mPrivate;
+ bool mProtected;
+
+ asClass *getClassInternal(string_table::key name) const
+ {
+ container::const_iterator i;
+ if (mClasses.empty())
+ return NULL;
+
+ i = mClasses.find(name);
+ if (i == mClasses.end())
+ return NULL;
+ return i->second;
+ }
+};
+
+class asBoundValue;
+class asBoundAccessor;
+
+class asBoundAccessor
+{
+public:
+ bool setGetter(asMethod *p) { mGetter = p; return true; }
+ bool setSetter(asMethod *p) { mSetter = p; return true; }
+ bool setValue(asBoundValue *p) { mValue = p; return true; }
+
+ asBoundValue* getValue() { return mValue; }
+ asMethod *getGetter() { return mGetter; }
+ asMethod *getSetter() { return mSetter; }
+
+private:
+ asMethod *mGetter;
+ asMethod *mSetter;
+ asBoundValue *mValue;
+};
+
+class asBoundValue
+{
+public:
+ asBoundValue() : mConst(false), mValue()
+ { mValue.set_undefined(); }
+ void setValue(as_value &v) { mValue = v; }
+ as_value& getCurrentValue() { return mValue; }
+
+ void setType(asClass *t) { mType = t; }
+ asClass *getType() { return mType; }
+
+private:
+ bool mConst;
+ asClass *mType;
+ as_value mValue;
+};
+
+/// A class to represent, abstractly, an ActionScript method.
+///
+/// Methods are unnamed until they are bound to an object.
+class asMethod
+{
+private:
+ typedef enum
+ {
+ FLAGS_FINAL = 0x01,
+ FLAGS_PROTECTED = 0x02,
+ FLAGS_PUBLIC = 0x04,
+ FLAGS_PRIVATE = 0x08
+ } flags;
+ /// A list of type identifiers
+ typedef std::list<asClass*> argumentList;
+ typedef std::map<string_table::key, asBinding> binding_container;
+
+ binding_container mBindings;
+ asClass *mReturnType;
+ asClass* mOwner;
+ asMethod* mSuper;
+ int mMinArguments;
+ int mMaxArguments;
+ argumentList mArguments;
+ std::list<as_value> mOptionalArguments;
+ as_function *mImplementation;
+ unsigned char mFlags;
+ asMethodBody *mBody;
+
+ bool addBinding(string_table::key name, asBinding b)
+ { mBindings[name] = b; return true; }
+
+ asBinding *getBinding(string_table::key name)
+ {
+ binding_container::iterator i;
+ if (mBindings.empty())
+ return NULL;
+ i = mBindings.find(name);
+ if (i == mBindings.end())
+ return NULL;
+ return &i->second;
+ }
+
+public:
+ asMethod() : mBindings(), mReturnType(NULL),
+ mOwner(NULL), mSuper(NULL), mMinArguments(-1),
mMaxArguments(-1),
+ mArguments(), mOptionalArguments(), mImplementation(NULL),
mFlags(0),
+ mBody(NULL)
+ {/**/}
+
+ bool hasActivation() { return !mBindings.empty(); }
+
+ asMethodBody *getBody() { return mBody; }
+ void setBody(asMethodBody* b) { mBody = b; }
+
+ bool addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, as_value& val, bool isconst, ClassHierarchy *CH);
+
+ bool addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, ClassHierarchy *CH);
+
+ bool addMethod(string_table::key name, asNamespace *ns, asMethod
*method);
+
+ bool addGetter(string_table::key name, asNamespace *ns, asMethod
*method,
+ ClassHierarchy *CH);
+
+ bool addSetter(string_table::key name, asNamespace *ns, asMethod
*method,
+ ClassHierarchy *CH);
+
+ bool addMemberClass(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asClass *type);
+
+ bool addSlotFunction(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asMethod *method);
+
+ /// \brief
+ /// Get the unique identifier of the owning class.
+ /// 0 indicates that no class owns this.
+ asClass* getOwner() const { return mOwner; }
+
+ /// \brief
+ /// Set the owner of this method.
+ void setOwner(asClass* s) { mOwner = s; }
+
+ /// \brief
+ /// Get the unique identifier for the return type. 0 is 'anything'.
+ /// (This is the value of any dynamic property.)
+ /// Id reference: Type
+ asClass* getReturnType() const { return mReturnType; }
+
+ /// Set the return type
+ void setReturnType(asClass* t) { mReturnType = t; }
+
+ asMethod *getSuper() { return mSuper; }
+
+ void setSuper(asMethod* s) { mSuper = s; }
+
+ /// \brief
+ /// Is the method final? If so, it may not be overridden.
+ bool isFinal() const { return mFlags & FLAGS_FINAL; }
+
+ /// \brief
+ /// Set the method as final.
+ void setFinal() { mFlags = mFlags | FLAGS_FINAL; }
+
+ /// \brief
+ /// Unset the method as final. Not final anymore.
+ void unsetFinal() { mFlags = mFlags & ~FLAGS_FINAL; }
+
+ /// \brief
+ /// Is the method private?
+ bool isPrivate() const { return mFlags & FLAGS_PRIVATE; }
+
+ /// \brief
+ /// Make the method private.
+ void setPrivate()
+ { mFlags = (mFlags & ~(FLAGS_PUBLIC | FLAGS_PROTECTED)) |
FLAGS_PRIVATE; }
+
+ /// \brief
+ /// Is the method protected?
+ bool isProtected() const { return mFlags & FLAGS_PROTECTED; }
+
+ /// \brief
+ /// Make the method protected.
+ void setProtected()
+ { mFlags = (mFlags & ~(FLAGS_PUBLIC | FLAGS_PRIVATE)) |
FLAGS_PROTECTED; }
+
+ /// \brief
+ /// Is the method public?
+ bool isPublic() const { return mFlags & FLAGS_PUBLIC; }
+
+ /// \brief
+ /// Make the method public.
+ void setPublic()
+ { mFlags = (mFlags & ~(FLAGS_PRIVATE | FLAGS_PROTECTED)) |
FLAGS_PUBLIC; }
+
+ /// \brief
+ /// How many arguments are required? -1 means unknown.
+ int minArgumentCount() const { return mMinArguments; }
+
+ /// \brief
+ /// Set the required minimum arguments.
+ void setMinArgumentCount(int i) { mMinArguments = i; }
+
+ /// \brief
+ /// How many arguments are allowed? -1 means unknown.
+ int maxArgumentCount() const { return mMaxArguments; }
+
+ /// Set the required maximum arguments.
+ void setMaxArgumentCount(int i) { mMaxArguments = i; }
+
+ /// \brief
+ /// Push an argument of type t into the method definition
+ void pushArgument(asClass *t) { mArguments.push_back(t); }
+
+ /// \brief
+ /// Push an optional argument's default value.
+ void pushOptional(const as_value& v) { mOptionalArguments.push_back(v);
}
+
+ /// \brief
+ /// Are any of the arguments optional?
+ bool optionalArguments() const
+ { return minArgumentCount() != maxArgumentCount(); }
+
+ /// \brief
+ /// Get a reference to a list of argument types.
+ argumentList& getArgumentList() { return mArguments; }
+
+ /// \brief
+ /// Get an object capable of executing this function.
+ /// Note: This may be NULL, because we might have information about this
+ /// function but not actually have it yet.
+ as_function* getImplementation() { return mImplementation; }
+
+ /// \brief
+ /// Check to see whether m could override this.
+ ///
+ /// Check to see whether m could override this. This means:
+ /// Same return type. Same parameter types. Same access. At least as
many
+ /// default arguments. this is not final or private. Should check, but
+ /// does not for information storing reasons: they are not in the same
+ /// override chain. (Can be checked in management object.)
+ /// have a super.
+ bool isOkayAsSuper(const asMethod &m) const
+ {
+ if (mMinArguments < m.mMinArguments
+ || m.mMaxArguments < mMaxArguments
+ || isFinal()
+ || mFlags != m.mFlags
+ || isPrivate())
+ return false;
+ for (argumentList::const_iterator i, j; /**/; ++i, ++j)
+ {
+ if (i == mArguments.end())
+ return (j == mArguments.end());
+ if (j == mArguments.end())
+ return false;
+ if (*i != *j)
+ return false;
+ }
+ return true;
+ }
+};
+
+/// A class to represent, abstractly, ActionScript prototypes.
+///
+/// This class is intended to be able to capture the structure of an
+/// ActionScript prototype as a type, rather than as an object. This is
+/// contrary to the spirit of ActionScript as a dynamic language, but it is
+/// incredibly helpful to an interpreter for that language.
+class asClass
+{
+public:
+ void dump();
+
+ bool addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, as_value& val, bool isconst, bool isstatic,
+ ClassHierarchy *CH);
+
+ bool addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
+ asClass *type, bool isstatic, ClassHierarchy *CH);
+
+ bool addMethod(string_table::key name, asNamespace *ns, asMethod
*method,
+ bool isstatic);
+
+ bool addGetter(string_table::key name, asNamespace *ns, asMethod
*method,
+ bool isstatic, ClassHierarchy *CH);
+
+ bool addSetter(string_table::key name, asNamespace *ns, asMethod
*method,
+ bool isstatic, ClassHierarchy *CH);
+
+ bool addMemberClass(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asClass *type, bool isstatic);
+
+ // TODO: Figure out how this differs from addMethod
+ bool addSlotFunction(string_table::key name, asNamespace *ns,
+ uint32_t slotId, asMethod *method, bool isstatic);
+
+ /// Is the class final?
+ bool isFinal() const { return mFinal; }
+
+ /// Set the class as final.
+ void setFinal() { mFinal = true; }
+
+ /// Set the class as not final.
+ void unsetFinal() { mFinal = false; }
+
+ /// Is the class sealed?
+ bool isSealed() const { return mSealed; }
+
+ /// Set the class as sealed.
+ void setSealed() { mSealed = true; }
+
+ // Set the class as not sealed.
+ void unsetSealed() { mSealed = false; }
+
+ /// Is the class an interface type?
+ bool isInterface() const { return mInterface; }
+
+ /// Set the class as an interface.
+ void setInterface() { mInterface = true; }
+
+ /// Set the class as not an interface.
+ void unsetInterface() { mInterface = false; }
+
+ /// Is the class dynamic?
+ bool isDynamic() const { return mDynamic; }
+
+ /// Set the class as dynamic.
+ void setDynamic() { mDynamic = true; }
+
+ /// Set the class as not dynamic.
+ void unsetDynamic() { mDynamic = false; }
+
+ /// Does the class have a protected namespace to be inherited?
+ bool hasProtectedNs() const { return mProtectedNs != NULL; }
+
+ /// Get the protected namespace.
+ asNamespace *getProtectedNs() { return mProtectedNs; }
+
+ /// Set the protected namespace.
+ void setProtectedNs(asNamespace *n) { mProtectedNs = n; }
+
+ string_table::key getName() const { return mName; }
+
+ /// Set our Name
+ void setName(string_table::key name) { mName = name; }
+
+ /// What is the type of our parent class?
+ asClass* getSuper() const { return mSuper; }
+
+ /// We implement this interface.
+ void pushInterface(asClass* p) { mInterfaces.push_back(p); }
+
+ /// This is our constructor.
+ void setConstructor(asMethod *m) { mConstructor = m; }
+
+ void setStaticConstructor(asMethod *m) { mStaticConstructor = m; }
+
+ void setSuper(asClass *p) { mSuper = p; }
+
+ void setDeclared() { mDeclared = true; }
+ bool isDeclared() { return mDeclared; }
+ void setInherited() { mInherited = true; }
+ bool isInherited() { return mInherited; }
+
+ void setSystem() { mSystem = true; }
+ void unsetSystem() { mSystem = false; }
+ bool isSystem() { return mSystem; }
+
+ asClass() : mFinal(false), mSealed(false), mDynamic(false),
+ mInterface(false), mName(0), mInterfaces(), mProtectedNs(NULL),
+ mSuper(NULL), mConstructor(NULL), mStaticConstructor(NULL),
+ mBindings(), mStaticBindings(), mDeclared(false),
mInherited(false),
+ mSystem(false)
+ {/**/}
+
+private:
+ bool addBinding(string_table::key name, asBinding b)
+ { mBindings[name] = b; return true; }
+ bool addStaticBinding(string_table::key name, asBinding b)
+ { mStaticBindings[name] = b; return true; }
+
+ asBinding *getStaticBinding(string_table::key name)
+ {
+ binding_container::iterator i;
+ if (mStaticBindings.empty())
+ return NULL;
+ i = mStaticBindings.find(name);
+ if (i == mStaticBindings.end())
+ return NULL;
+ return &i->second;
+ }
+
+ asBinding *getBinding(string_table::key name)
+ {
+ binding_container::iterator i;
+ if (mBindings.empty())
+ return NULL;
+ i = mBindings.find(name);
+ if (i == mBindings.end())
+ return NULL;
+ return &i->second;
+ }
+
+ bool mFinal;
+ bool mSealed;
+ bool mDynamic;
+ bool mInterface;
+ string_table::key mName;
+ std::list<asClass*> mInterfaces;
+ asNamespace *mProtectedNs;
+ asClass *mSuper;
+ asMethod *mConstructor;
+ asMethod *mStaticConstructor;
+
+ typedef std::map<string_table::key, asBinding> binding_container;
+
+ binding_container mBindings;
+ binding_container mStaticBindings;
+ bool mDeclared;
+ bool mInherited;
+ bool mSystem;
+};
+
+} /* namespace gnash */
+
+#endif /* GNASH_AS_CLASS_H */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog server/Makefile.am server/named...,
Chad Musick <=