C:\gnash\libcore\abc\AbcBlock.h C:\gnash\libcore\abc\Copy of AbcBlock.h
// //
//   Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. //   Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// //
// This program is free software; you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or // the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   
// The AS3 abc block format reader. // The AS3 abc block format reader.
// //
   
#ifndef GNASH_ABC_BLOCK_H #ifndef GNASH_ABC_BLOCK_H
#define GNASH_ABC_BLOCK_H #define GNASH_ABC_BLOCK_H
   
#include "string_table.h" #include "string_table.h"
#include "MultiName.h" #include "MultiName.h"
#include "Namespace.h" #include "Namespace.h"
#include "as_value.h" #include "as_value.h"
   
#include <vector> #include <vector>
#include <string> #include <string>
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <stdexcept> #include <stdexcept>
   
namespace gnash { namespace gnash {
   namespace abc {    namespace abc {
       class AbcBlock;        class AbcBlock;
       class Machine;        class Machine;
       class Class;        class Class;
       class Method;        class Method;
   }    }
   class SWFStream; // for read signature    class SWFStream; // for read signature
   class ClasstHierarchy;    class ClasstHierarchy;
} }
   
namespace gnash { namespace gnash {
   
/// ABC-only resources for parsing and execution. /// ABC-only resources for parsing and execution.
namespace abc { namespace abc {
   
/// Class describing a static property /// Class describing a static property
// //
/// Traits are non-dynamic properties. That is, they are not deletable or /// Traits are non-dynamic properties. That is, they are not deletable or
/// modifiable in certain ways through ActionScript. They exist for reasons /// modifiable in certain ways through ActionScript. They exist for reasons
/// of performance. A property lookup on an object always checks the Traits /// of performance. A property lookup on an object always checks the Traits
/// before dynamic properties. /// before dynamic properties.
// //
/// Traits can belong to Methods, Classes, and Scripts. Classes have both /// Traits can belong to Methods, Classes, and Scripts. Classes have both
/// instance and Class traits. /// instance and Class traits.
// //
/// TODO: Traits currently need finalization. This performs two tasks. At least /// TODO: Traits currently need finalization. This performs two tasks. At least
/// one, and possibly both, are wrong: /// one, and possibly both, are wrong:
/// 1. Trait definitions contain references to AbcBlock definitions. Currently /// 1. Trait definitions contain references to AbcBlock definitions. Currently
///    these references are resolved during finalization. It may be possible ///    these references are resolved during finalization. It may be possible
///    to do this during parsing. ///    to do this during parsing.
/// 2. Traits should be made available to ActionScript. Currently this is done /// 2. Traits should be made available to ActionScript. Currently this is done
///    by attaching them to an object. This is plain wrong and doesn't even ///    by attaching them to an object. This is plain wrong and doesn't even
///    work in many cases. ///    work in many cases.
// //
/// TODO: As Traits are stored in the correct Class, Method etc, they do not /// TODO: As Traits are stored in the correct Class, Method etc, they do not
///       need to store a target. ///       need to store a target.
class Trait class Trait
{ {
public: public:
   
   enum Kind    enum Kind
   {    {
       KIND_SLOT = 0,        KIND_SLOT = 0,
       KIND_CONST = 6,        KIND_CONST = 6,
       KIND_METHOD = 1,        KIND_METHOD = 1,
       KIND_GETTER = 2,        KIND_GETTER = 2,
       KIND_SETTER = 3,        KIND_SETTER = 3,
       KIND_CLASS = 4,        KIND_CLASS = 4,
       KIND_FUNCTION = 5        KIND_FUNCTION = 5
   };    };
   
   Trait()    Trait()
       :        :
       _hasValue(false),        _hasValue(false),
       _kind(KIND_SLOT),        _kind(KIND_SLOT),
       _slotID(0),        _slotID(0),
       _typeIndex(0),        _typeIndex(0),
       _classInfoIndex(0),        _classInfoIndex(0),
       _value(),        _value(),
       _name(0),        _name(0),
       _globalName(),        _globalName(),
       _namespace(0),        _namespace(0),
       _method(0),        _method(0),
       _valueSet(false),        _valueSet(false),
       _classTarget(0),        _classTarget(0),
       _methodTarget(0),        _methodTarget(0),
       _static(false)        _static(false)
   {}    {}
   
   bool read(SWFStream* in, AbcBlock *block);    bool read(SWFStream* in, AbcBlock *block);
   
   bool finalize(AbcBlock* block, abc::Class* cl, bool do_static);    bool finalize(AbcBlock* block, abc::Class* cl, bool do_static);
   
   bool finalize_mbody(AbcBlock* block, Method* m);    bool finalize_mbody(AbcBlock* block, Method* m);
   
   void set_target(abc::Class* cl, bool do_static) {    void set_target(abc::Class* cl, bool do_static) {
       _classTarget = cl;        _classTarget = cl;
       _static = do_static;        _static = do_static;
   }    }
   
   void set_target(Method *m) {    void set_target(Method *m) {
       _classTarget = 0;        _classTarget = 0;
       _methodTarget = m;        _methodTarget = m;
   }    }
   
   bool finalize(AbcBlock* block)    bool finalize(AbcBlock* block)
   {    {
       if (_classTarget) {        if (_classTarget) {
           return finalize(block, _classTarget, _static);            return finalize(block, _classTarget, _static);
       }        }
       return finalize_mbody(block, _methodTarget);        return finalize_mbody(block, _methodTarget);
   }    }
   
private: private:
   
   friend class AbcBlock;    friend class AbcBlock;
   
   bool _hasValue;    bool _hasValue;
   Kind _kind;    Kind _kind;
   boost::uint32_t _slotID;    boost::uint32_t _slotID;
   boost::uint32_t _typeIndex;    boost::uint32_t _typeIndex;
   boost::uint32_t _classInfoIndex;    boost::uint32_t _classInfoIndex;
   as_value _value;    as_value _value;
   
   URI _name;    URI _name;
   string_table::key _globalName;    string_table::key _globalName;
   
   Namespace* _namespace;    Namespace* _namespace;
   Method* _method;    Method* _method;
   bool _valueSet;    bool _valueSet;
   
   abc::Class* _classTarget;    abc::Class* _classTarget;
   Method* _methodTarget;    Method* _methodTarget;
   bool _static;    bool _static;
   
}; };
   
/// Output stream operator for abc::Trait::Kind /// Output stream operator for abc::Trait::Kind
std::ostream& operator<<(std::ostream& o, const Trait::Kind k); std::ostream& operator<<(std::ostream& o, const Trait::Kind k);
   
namespace { namespace {
   
template<typename T> template<typename T>
inline void checkBounds(size_t i, const T& container) inline void checkBounds(size_t i, const T& container)
{ {
   if (i >= container.size()) {    if (i < 0 || i >= container.size()) {
       throw std::range_error("Attempt to access pool out of range");        throw std::range_error("Attempt to access pool out of range");
   }    }
} }
   
} }
   
   
/// The ActionScript bytecode of a single ABC tag in a SWF. /// The ActionScript bytecode of a single ABC tag in a SWF.
// //
/// ABC blocks have their own "names" for all resources. In Gnash, these are /// ABC blocks have their own "names" for all resources. In Gnash, these are
/// a string table index. They are different from global names. These are used /// a string table index. They are different from global names. These are used
/// to locate resources inside the ABC block. /// to locate resources inside the ABC block.
// //
/// ABC blocks have a set of "namespace" resources. Some namespaces are /// ABC blocks have a set of "namespace" resources. Some namespaces are
/// private. We make these into anonymous namespaces. /// private. We make these into anonymous namespaces.
// //
/// We assume all non-private namespaces are public. Some are "package" /// We assume all non-private namespaces are public. Some are "package"
/// namespaces; these seem to coincide with the built-in packages or 0, /// namespaces; these seem to coincide with the built-in packages or 0,
/// the global namespace. /// the global namespace.
/// ///
/// We always search for these public namespaces by global URI in our /// We always search for these public namespaces by global URI in our
/// ClassHierarchy. If we use ABC names, "flash.text" will not find the built-in /// ClassHierarchy. If we use ABC names, "flash.text" will not find the built-in
/// flash.text namespace. Using the global name means that we 'import' the /// flash.text namespace. Using the global name means that we 'import' the
/// built-in namespace into our own resources. /// built-in namespace into our own resources.
// //
/// Instances / Scriptes /// Instances / Scriptes
// //
/// Likewise, classes are always given a global name, not an ABC name. This is /// Likewise, classes are always given a global name, not an ABC name. This is
/// because they become globally available, including (we assume) to other ABC /// because they become globally available, including (we assume) to other ABC
/// blocks, so using an ABC name means they cannot be located externally. /// blocks, so using an ABC name means they cannot be located externally.
/// Even if ABC block resources should not be available to other blocks (which /// Even if ABC block resources should not be available to other blocks (which
/// seems unlikely), using an ABC name for classes risks name conflicts with /// seems unlikely), using an ABC name for classes risks name conflicts with
/// the built-in classes already in a namespace: ABC names and global names /// the built-in classes already in a namespace: ABC names and global names
/// can have the same index even when the names are different. /// can have the same index even when the names are different.
// //
/// Class lookup /// Class lookup
// //
/// This is particularly important for locateClass (called by instantiateScript /// This is particularly important for locateClass (called by instantiateScript
/// from SymbolScript tag execution). The SymbolScript tag identifies a class /// from SymbolScript tag execution). The SymbolScript tag identifies a class
/// using a global name, which may be qualified with a namespace. If it is /// using a global name, which may be qualified with a namespace. If it is
/// not qualified, we look in the global namespace 0. /// not qualified, we look in the global namespace 0.
// //
/// When we call locateClass, we use global names, not ABC names, because /// When we call locateClass, we use global names, not ABC names, because
/// classes are identified by global names (see above). However, we /// classes are identified by global names (see above). However, we
/// still look only in the ABC block's namespaces. The block's first namespace /// still look only in the ABC block's namespaces. The block's first namespace
/// is always the global namespace; other package namespaces are imported /// is always the global namespace; other package namespaces are imported
/// according to the block's namespace constants. /// according to the block's namespace constants.
class AbcBlock class AbcBlock
{ {
public: public:
         
   enum NamespaceConstant    enum NamespaceConstant
   {    {
       PRIVATE_NS = 0x05,        PRIVATE_NS = 0x05,
       CONSTANT_NS = 0x08,        CONSTANT_NS = 0x08,
       PACKAGE_NS = 0x16,        PACKAGE_NS = 0x16,
       PACKAGE_INTERNAL_NS = 0x17,        PACKAGE_INTERNAL_NS = 0x17,
       PROTECTED_NS = 0x18,        PROTECTED_NS = 0x18,
       EXPLICIT_NS = 0x19,        EXPLICIT_NS = 0x19,
       STATIC_PROTECTED_NS = 0x1A        STATIC_PROTECTED_NS = 0x1A
   };    };
   
   enum MethodConstant    enum MethodConstant
   {    {
       METHOD_ARGS = 0x01,        METHOD_ARGS = 0x01,
       METHOD_ACTIVATION = 0x02,        METHOD_ACTIVATION = 0x02,
       METHOD_MORE = 0x04,        METHOD_MORE = 0x04,
       METHOD_OPTIONAL_ARGS = 0x08,        METHOD_OPTIONAL_ARGS = 0x08,
       METHOD_IGNORE = 0x10,        METHOD_IGNORE = 0x10,
       METHOD_NATIVE = 0x20,        METHOD_NATIVE = 0x20,
       METHOD_DEFAULT_NS = 0x40,        METHOD_DEFAULT_NS = 0x40,
       METHOD_ARG_NAMES = 0x80        METHOD_ARG_NAMES = 0x80
   };    };
   
   enum InstanceConstant    enum InstanceConstant
   {    {
       INSTANCE_SEALED = 0x01,        INSTANCE_SEALED = 0x01,
       INSTANCE_FINAL = 0x02,        INSTANCE_FINAL = 0x02,
       INSTANCE_INTERFACE = 0x04,        INSTANCE_INTERFACE = 0x04,
       INSTANCE_DYNAMIC = 0x00,        INSTANCE_DYNAMIC = 0x00,
       INSTANCE_PROTECTED_NS = 0x08        INSTANCE_PROTECTED_NS = 0x08
   };    };
   
   enum PoolConstant    enum PoolConstant
   {    {
       POOL_STRING = 0x01,        POOL_STRING = 0x01,
       POOL_INTEGER = 0x03,        POOL_INTEGER = 0x03,
       POOL_UINTEGER = 0x04,        POOL_UINTEGER = 0x04,
       POOL_DOUBLE = 0x06,        POOL_DOUBLE = 0x06,
       POOL_NAMESPACE = 0x08,        POOL_NAMESPACE = 0x08,
       POOL_FALSE = 0x0A,        POOL_FALSE = 0x0A,
       POOL_TRUE = 0x0B,        POOL_TRUE = 0x0B,
       POOL_NULL = 0x0C        POOL_NULL = 0x0C
   };    };
         
   typedef std::vector<Namespace*> NamespaceSet;    typedef std::vector<Namespace*> NamespaceSet;
   
   AbcBlock();    AbcBlock();
   
   abc::Class* locateClass(MultiName &m);    abc::Class* locateClass(MultiName &m);
   
   abc::Class* locateClass(const std::string& className);    abc::Class* locateClass(const std::string& className);
   
   bool read(SWFStream& in);    bool read(SWFStream& in);
   
   void update_global_name(unsigned int multiname_index);    void update_global_name(unsigned int multiname_index);
   
   /// Scripts can contain several classes.    /// Scripts can contain several classes.
   //    //
   /// TODO: why on earth are Scripts implemented using Classes?    /// TODO: why on earth are Scripts implemented using Classes?
   const std::vector<abc::Class*>& scripts() const {    const std::vector<abc::Class*>& scripts() const {
       return _scripts;        return _scripts;
   }    }
   
   boost::uint32_t uIntegerPoolAt(size_t i) const {    boost::uint32_t uIntegerPoolAt(size_t i) const {
       checkBounds(i, _uIntegerPool);        checkBounds(i, _uIntegerPool);
       return _uIntegerPool[i];        return _uIntegerPool[i];
   }    }
   
   const std::string& stringPoolAt(size_t i) const {    const std::string& stringPoolAt(size_t i) const {
       checkBounds(i, _stringPool);        checkBounds(i, _stringPool);
       return _stringPool[i];        return _stringPool[i];
   }    }
   
   boost::int32_t integerPoolAt(size_t i) const {    boost::int32_t integerPoolAt(size_t i) const {
       checkBounds(i, _integerPool);        checkBounds(i, _integerPool);
       return _integerPool[i];        return _integerPool[i];
   }    }
   
   double doublePoolAt(size_t i) const {    double doublePoolAt(size_t i) const {
       checkBounds(i, _doublePool);        checkBounds(i, _doublePool);
       return _doublePool[i];        return _doublePool[i];
   }    }
   
   Method* methodPoolAt(size_t i) const {    Method* methodPoolAt(size_t i) const {
       checkBounds(i, _methods);        checkBounds(i, _methods);
       return _methods[i];        return _methods[i];
   }    }
   
   MultiName multinamePoolAt(size_t i) const {    MultiName multinamePoolAt(size_t i) const {
       checkBounds(i, _multinamePool);        checkBounds(i, _multinamePool);
       return _multinamePool[i];        return _multinamePool[i];
   }    }
   
   abc::Class* classPoolAt(size_t i) const {    abc::Class* classPoolAt(size_t i) const {
       checkBounds(i, _classes);        checkBounds(i, _classes);
       return _classes[i];        return _classes[i];
   }    }
   
   Namespace* namespacePoolAt(size_t i) const {    Namespace* namespacePoolAt(size_t i) const {
       checkBounds(i, _namespacePool);        checkBounds(i, _namespacePool);
       return _namespacePool[i];        return _namespacePool[i];
   }    }
   
   void prepare(Machine* mach);    void prepare(Machine* mach);
   
private: private:
         
   friend class abc::Trait;    friend class abc::Trait;
   
   bool pool_value(boost::uint32_t index, PoolConstant type, as_value &v);    bool pool_value(boost::uint32_t index, PoolConstant type, as_value &v);
   
   bool read_version();    bool read_version();
   bool read_integer_constants();    bool read_integer_constants();
   bool read_unsigned_integer_constants();    bool read_unsigned_integer_constants();
   bool read_double_constants();    bool read_double_constants();
   bool read_string_constants();    bool read_string_constants();
   bool read_namespaces();    bool read_namespaces();
   bool read_namespace_sets();    bool read_namespace_sets();
   bool read_multinames();    bool read_multinames();
   bool read_method_infos();    bool read_method_infos();
   bool skip_metadata();    bool skip_metadata();
   bool read_instances();    bool read_instances();
   bool read_classes();    bool read_classes();
   bool read_scripts();    bool read_scripts();
   bool read_method_bodies();    bool read_method_bodies();
   
   void check_multiname_name(boost::uint32_t name);    void check_multiname_name(boost::uint32_t name);
   
   void check_multiname_namespace(boost::uint32_t ns);    void check_multiname_namespace(boost::uint32_t ns);
   
   void check_multiname_namespaceset(boost::uint32_t nsset);    void check_multiname_namespaceset(boost::uint32_t nsset);
   
   void setMultinameNames(MultiName *n, abc::URI ABCName);    void setMultinameNames(MultiName *n, abc::URI ABCName);
   
   void setNamespaceURI(Namespace *ns, abc::URI ABCName);    void setNamespaceURI(Namespace *ns, abc::URI ABCName);
   
   std::vector<boost::int32_t> _integerPool;    std::vector<boost::int32_t> _integerPool;
   std::vector<boost::uint32_t> _uIntegerPool;    std::vector<boost::uint32_t> _uIntegerPool;
   std::vector<double> _doublePool;    std::vector<double> _doublePool;
   std::vector<std::string> _stringPool;    std::vector<std::string> _stringPool;
   std::vector<Namespace*> _namespacePool;    std::vector<Namespace*> _namespacePool;
   std::vector<NamespaceSet> _namespaceSetPool;    std::vector<NamespaceSet> _namespaceSetPool;
   std::vector<Method*> _methods;    std::vector<Method*> _methods;
   std::vector<MultiName> _multinamePool;    std::vector<MultiName> _multinamePool;
   std::vector<Class*> _classes;      std::vector<Class*> _classes;  
   std::vector<Class*> _scripts;    std::vector<Class*> _scripts;
   
   string_table* _stringTable;    string_table* _stringTable;
   SWFStream* _stream; // Not stored beyond one read.    SWFStream* _stream; // Not stored beyond one read.
   
   abc::Class *mTheObject;    abc::Class *mTheObject;
   ClassHierarchy *mCH;    ClassHierarchy *mCH;
   
   boost::uint32_t mVersion;    boost::uint32_t mVersion;
   
   
}; };
   
std::ostream& operator<<(std::ostream& o, AbcBlock::NamespaceConstant c); std::ostream& operator<<(std::ostream& o, AbcBlock::NamespaceConstant c);
std::ostream& operator<<(std::ostream& o, AbcBlock::MethodConstant c); std::ostream& operator<<(std::ostream& o, AbcBlock::MethodConstant c);
std::ostream& operator<<(std::ostream& o, AbcBlock::InstanceConstant c); std::ostream& operator<<(std::ostream& o, AbcBlock::InstanceConstant c);
std::ostream& operator<<(std::ostream& o, AbcBlock::PoolConstant c); std::ostream& operator<<(std::ostream& o, AbcBlock::PoolConstant c);
   
} // namespace abc } // namespace abc
} // namespace gnash } // namespace gnash
   
   
#endif #endif