"Fossies" - the Fresh Open Source Software Archive

Member "gnash-0.8.10/libcore/abc/AbcBlock.cpp" (19 Jan 2012, 41350 Bytes) of package /linux/www/old/gnash-0.8.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // 
    2 //   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
    3 //   Free Software Foundation, Inc.
    4 // 
    5 // This program is free software; you can redistribute it and/or modify
    6 // it under the terms of the GNU General Public License as published by
    7 // the Free Software Foundation; either version 3 of the License, or
    8 // (at your option) any later version.
    9 // 
   10 // This program is distributed in the hope that it will be useful, 
   11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 // GNU General Public License for more details.
   14 // 
   15 // You should have received a copy of the GNU General Public License
   16 // along with this program; if not, write to the Free Software
   17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   18 
   19 // The AS3 abc block format reader.
   20 //
   21 
   22 #include "gnashconfig.h"
   23 #include "AbcBlock.h"
   24 #include "SWFStream.h" // for use
   25 #include "VM.h"
   26 #include "log.h"
   27 #include "ClassHierarchy.h"
   28 #include "Class.h"
   29 #include "namedStrings.h"
   30 #include "CodeStream.h"
   31 #include "action_buffer.h"
   32 #include "Machine.h"
   33 #include "Global_as.h"
   34 
   35 #include <boost/bind.hpp>
   36 
   37 namespace gnash {
   38 
   39 namespace abc {
   40 
   41 bool
   42 Trait::finalize(AbcBlock *block, abc::Class* script, bool do_static)
   43 {
   44     log_abc("Finalize class %s (%s), trait kind: %s", 
   45             block->_stringTable->value(script->getName()), script, _kind);
   46 
   47     switch (_kind)
   48     {
   49         case KIND_SLOT:
   50         case KIND_CONST:
   51         {
   52             // Validate the type.
   53             abc::Class* type;
   54             if (_typeIndex) {
   55                 log_abc("Trait type: %s", 
   56                     block->_stringPool[
   57                         block->_multinamePool[_typeIndex].getABCName()]);
   58                 type = block->locateClass(block->_multinamePool[_typeIndex]);
   59             }
   60             else {
   61                 type = block->mTheObject;
   62             }
   63 
   64             if (!type) {
   65                 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
   66                 return false;
   67             }
   68 
   69             // The name has been validated in read.
   70             // TODO: Find a better way to initialize trait values.
   71             if (!_hasValue) {
   72                 as_object* null = 0;
   73                 _value = null; 
   74             }
   75 
   76             log_abc("Adding property=%s with value=%s slot=%u",
   77                     block->_stringPool[_name], _value, _slotID);
   78 
   79             script->addValue(_globalName, _namespace, _slotID, type, 
   80                 _value, _kind == KIND_CONST, do_static);
   81             break;
   82         }
   83 
   84         case KIND_METHOD:
   85             script->addMethod(_globalName, _namespace, _method, false);
   86             break;
   87         
   88         case KIND_GETTER:
   89             script->addGetter(_name, _namespace, _method, do_static);
   90             break;
   91 
   92         case KIND_SETTER:
   93             script->addSetter(_name, _namespace, _method, do_static);
   94             break;
   95         
   96         case KIND_CLASS:
   97             log_abc("Adding class %s, value %s, slot=%u",
   98                     block->_stringPool[_name], _value, _slotID);
   99             script->addMemberScript(_globalName, _namespace, _slotID, 
  100                 block->_classes[_classInfoIndex], do_static);
  101             break;
  102 
  103         case KIND_FUNCTION:
  104             script->addSlotFunction(_name, _namespace, _slotID, _method,
  105                     do_static);
  106             break;
  107 
  108         default:
  109             return false;
  110     } 
  111     return true;
  112 }
  113 
  114 bool
  115 Trait::finalize_mbody(AbcBlock *block, Method *pMethod)
  116 {
  117     log_abc("Finalizing method trait: kind %s", _kind);
  118     switch (_kind)
  119     {
  120         case KIND_SLOT:
  121         case KIND_CONST:
  122         {
  123             // Validate the type.
  124             abc::Class *type;
  125             if (_typeIndex) {
  126                 type = block->locateClass(block->_multinamePool[_typeIndex]);
  127             }
  128             else {
  129                 type = block->mTheObject;
  130             }
  131 
  132             if (!type) {
  133                 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
  134                 return false;
  135             }
  136 
  137             // The name has been validated in read.
  138             // TODO: Find a better way to initialize trait values.
  139             if (!_hasValue) {
  140                 _value = as_value((as_object*)0); // NULL value, right ?
  141             }
  142             log_abc("Adding property=%s with value=%s slot=%u",
  143                     block->_stringPool[_name], _value.toDebugString(), _slotID);
  144             pMethod->addValue(_globalName, _namespace, _slotID, type, 
  145                 _value, _kind == KIND_CONST);
  146             break;
  147         }
  148         case KIND_METHOD:
  149         {
  150             pMethod->addMethod(_name, _namespace, _method);
  151             break;
  152         }
  153         case KIND_GETTER:
  154         {
  155             pMethod->addGetter(_name, _namespace, _method);
  156             break;
  157         }
  158         case KIND_SETTER:
  159         {
  160             pMethod->addSetter(_name, _namespace, _method);
  161             break;
  162         }
  163         case KIND_CLASS:
  164         {
  165             pMethod->addMemberScript(_name, _namespace, _slotID, 
  166                 block->_classes[_classInfoIndex]);
  167             break;
  168         }
  169         case KIND_FUNCTION:
  170         {
  171             pMethod->addSlotFunction(_name, _namespace, _slotID, _method);
  172             break;
  173         }
  174         default:
  175             // Not here -- validated already in read.
  176             return false;
  177     } 
  178     return true;
  179 }
  180 
  181 /// Read an AS3 'trait'
  182 bool
  183 Trait::read(SWFStream* in, AbcBlock *block)
  184 {
  185     boost::uint32_t name = in->read_V32();
  186     if (name >= block->_multinamePool.size())
  187     {
  188         log_error(_("ABC: Bad name for trait."));
  189         return false;
  190     }
  191     if (!block->_multinamePool[name].isQName())
  192     {
  193         log_error(_("ABC: Trait name must be fully qualified."));
  194         return false;
  195     }
  196     MultiName multiname = block->_multinamePool[name];
  197     _name = block->_multinamePool[name].getABCName();
  198     _globalName = block->_multinamePool[name].getGlobalName();
  199     _namespace = block->_multinamePool[name].getNamespace();
  200 
  201     boost::uint8_t kind = in->read_u8();
  202     _kind = static_cast<Kind>(kind & 0x0F);
  203 
  204     log_abc("Trait name: %s, Trait kind: %s",
  205             block->_stringPool[multiname.getABCName()], _kind);
  206 
  207     switch (_kind)
  208     {
  209         case KIND_SLOT:
  210         case KIND_CONST:
  211         {
  212             _slotID = in->read_V32();
  213             _typeIndex = in->read_V32();
  214             boost::uint32_t vindex = in->read_V32();
  215             log_abc("Slot ID=%u Type=%s Pool index=%u", _slotID,
  216                     block->_stringPool[
  217                     block->_multinamePool[_typeIndex].getABCName()], vindex);
  218             
  219             if (vindex) {
  220                 const AbcBlock::PoolConstant c =
  221                     static_cast<AbcBlock::PoolConstant>(in->read_u8());
  222 
  223                 if (!block->pool_value(vindex, c, _value))
  224                     return false; // Message done by pool_value
  225                 _hasValue = true;
  226             }
  227             else _hasValue = false;
  228             break;
  229         }
  230         case KIND_METHOD:
  231         case KIND_GETTER:
  232         case KIND_SETTER:
  233         {
  234             // Ignore the 'disp_id'
  235             in->skip_V32();
  236 
  237             boost::uint32_t offset = in->read_V32();
  238             log_abc("Method index=%u", offset);
  239             if (offset >= block->_methods.size()) {
  240                 log_error(_("Bad method id in trait."));
  241                 return false;
  242             }
  243             _method = block->_methods[offset];
  244             break;
  245         }
  246         case KIND_CLASS:
  247         {
  248             _slotID = in->read_V32();
  249             _classInfoIndex = in->read_V32();
  250             log_abc("Slot id: %u Class index: %u Class Name: %s", _slotID, 
  251                 _classInfoIndex, 
  252                 block->_stringTable->value(
  253                     block->_classes[_classInfoIndex]->getName()));
  254 
  255             if (_classInfoIndex >= block->_classes.size()) {
  256                 log_error(_("Bad Class id in trait."));
  257                 return false;
  258             }
  259             break;
  260         }
  261         case KIND_FUNCTION:
  262         {
  263             _slotID = in->read_V32();
  264             boost::uint32_t offset = in->read_V32();
  265             if (offset >= block->_methods.size()) {
  266                 log_error(_("Bad method id in trait."));
  267                 return false;
  268             }
  269             _method = block->_methods[offset];
  270             break;
  271         }
  272         default:
  273         {
  274             log_error(_("ABC: Unknown type of trait."));
  275         }
  276     }
  277 
  278     // Ignore the metadata, but it must be read to know how to ignore it.
  279     if ((kind >> 4) & 0x04) {
  280         boost::uint32_t mcount = in->read_V32();
  281         for (size_t i = 0; i < mcount; ++i) {
  282             in->skip_V32();
  283         }
  284     }
  285     return true;
  286 }
  287 
  288 std::ostream&
  289 operator<<(std::ostream& o, const Trait::Kind k)
  290 {
  291     switch (k) {
  292         case abc::Trait::KIND_SLOT:
  293             return o << "slot";
  294         case abc::Trait::KIND_CONST:
  295             return o << "const";
  296         case abc::Trait::KIND_METHOD:
  297             return o << "method";
  298         case abc::Trait::KIND_GETTER:
  299             return o << "getter";
  300         case abc::Trait::KIND_SETTER:
  301             return o << "setter";
  302         case abc::Trait::KIND_CLASS:
  303             return o << "class";
  304         case abc::Trait::KIND_FUNCTION:
  305             return o << "function";
  306         default:
  307             return o << "Unknown kind " << static_cast<int>(k);
  308     }
  309 }
  310 
  311 AbcBlock::AbcBlock()
  312     :
  313     _stringTable(&VM::get().getStringTable())
  314 {
  315     mCH = &VM::get().getMachine()->global()->classHierarchy();
  316     // TODO: Make this the real 'Object' prototype.
  317     mCH->getGlobalNs()->stubPrototype(*mCH, NSV::CLASS_OBJECT);
  318     mTheObject = mCH->getGlobalNs()->getScript(NSV::CLASS_OBJECT);
  319 }
  320 
  321 void
  322 AbcBlock::prepare(Machine* mach)
  323 {
  324 
  325     std::for_each(_classes.begin(), _classes.end(),
  326             std::mem_fun(&abc::Class::initPrototype));
  327     // The last (entry) script has Global as its prototype.
  328     // This can be deduced because the global classes are initialized with a
  329     // slot on script 0 (entry script). OpNewClass then attempts to set the
  330     // corresponding slot once the class has been constructed. At this point,
  331     // global should verifiably be on the stack, so the slots are expected
  332     // to be set on the global object.
  333     // It seems likely, though testing it is not straightforward, that all
  334     // scripts have Global as a target object (prototype), so for now we
  335     // will do that.
  336     std::for_each(_scripts.begin(), _scripts.end(),
  337             boost::bind(&abc::Class::setPrototype, _1, mach->global()));
  338  
  339     std::for_each(_methods.begin(), _methods.end(),
  340             boost::bind(&Method::initPrototype, _1, mach));
  341     
  342     // TODO: Remove this, initialize traits only when needed; possibly 
  343     // consruct them on parsing without the need for a finalize method.
  344     std::for_each(_methods.begin(), _methods.end(),
  345             boost::bind(&abc::Method::initTraits, _1, *this));
  346     std::for_each(_classes.begin(), _classes.end(),
  347             boost::bind(&abc::Class::initTraits, _1, *this));
  348     std::for_each(_scripts.begin(), _scripts.end(),
  349             boost::bind(&abc::Class::initTraits, _1, *this));
  350 
  351 }
  352 
  353 void
  354 AbcBlock::check_multiname_name(boost::uint32_t name)
  355 {
  356 
  357     if (name >= _stringPool.size()) {
  358         throw ParserException("ABC: Out of bounds string for Multiname.");
  359     }
  360 }
  361 
  362 void
  363 AbcBlock::check_multiname_namespace(boost::uint32_t ns)
  364 {
  365     if (ns >= _namespacePool.size()) {
  366         throw ParserException("ABC: Out of bounds namespace for Multiname.");
  367     }
  368 }
  369 
  370 void
  371 AbcBlock::check_multiname_namespaceset(boost::uint32_t nsset)
  372 {
  373     if (!nsset)
  374     {
  375         throw ParserException("ABC: 0 selection for namespace set is invalid.");
  376     }
  377     if (nsset >= _namespaceSetPool.size())
  378     {
  379         throw ParserException("ABC: Out of bounds namespace set for Multiname.");
  380     }
  381 }
  382 
  383 void
  384 AbcBlock::setMultinameNames(MultiName *n, abc::URI ABCName)
  385 {
  386     
  387     n->setABCName(ABCName);
  388     std::string name = _stringPool[ABCName];
  389     string_table::key global_key = _stringTable->find(name, true);
  390     log_abc("Global key %u", global_key);
  391     n->setGlobalName(global_key);
  392     log_abc("Multiname: %s ABCName set to %u, global name set to %u",
  393             name, n->getABCName(), n->getGlobalName());
  394 }
  395 
  396 void
  397 AbcBlock::setNamespaceURI(Namespace *ns, abc::URI ABCName)
  398 {
  399     std::string name = _stringPool[ABCName];
  400     string_table::key global_key = _stringTable->find(name);
  401     ns->setURI(global_key);
  402     log_abc("Namespace: %s AbcURI=%u URI=%u.", name, ABCName, global_key);
  403 }
  404 
  405 abc::Class*
  406 AbcBlock::locateClass(const std::string& className)
  407 {
  408 
  409     const std::string::size_type pos = className.rfind(".");
  410     
  411     MultiName a;
  412 
  413     const std::string& nsstr = (pos != std::string::npos) ? 
  414         className.substr(0, pos) : "";
  415 
  416     const std::string& clstr = (pos != std::string::npos) ? 
  417         className.substr(pos + 1) : className;
  418     
  419     a.setGlobalName(_stringTable->find(clstr));
  420 
  421     for (std::vector<Namespace*>::iterator i = _namespacePool.begin();
  422             i != _namespacePool.end(); ++i) {
  423         
  424         const size_t key = (*i)->getURI();
  425 
  426         if (key == _stringTable->find(nsstr)) {
  427             a.setNamespace(*i);
  428             break;
  429         }
  430     }
  431     
  432     return locateClass(a);
  433 
  434 }
  435 
  436 abc::Class*
  437 AbcBlock::locateClass(MultiName& m)
  438 {
  439     abc::Class* found = 0;
  440 
  441     if (m.getNamespace())
  442     {
  443         found = m.getNamespace()->getScript(m.getGlobalName());
  444         if (found) return found;
  445     }
  446     if (m.namespaceSet() && !m.namespaceSet()->empty())
  447     {
  448         std::vector<Namespace*>::const_iterator i;
  449         for (i = m.namespaceSet()->begin(); i != m.namespaceSet()->end(); ++i) {
  450 
  451             found = (*i)->getScript(m.getGlobalName());
  452             if (found) return found;
  453         }
  454     }
  455 
  456     log_abc("Could not locate class in ABC block resources!");
  457 
  458     return 0;
  459 
  460 }
  461 
  462 /// Read the ActionBlock version number.
  463 bool
  464 AbcBlock::read_version()
  465 {
  466     // Minor version, major version.
  467     mVersion = (_stream->read_u16()) | (_stream->read_u16() << 16);
  468     log_debug(_("Abc Version: %d.%d"), (mVersion & 0xFFFF0000) >> 16, 
  469         (mVersion & 0x0000FFFF));
  470     return true;
  471 }
  472 
  473 /// Read the pool of integer constants.
  474 bool
  475 AbcBlock::read_integer_constants()
  476 {
  477     // count overestimates by 1.
  478     boost::uint32_t count = _stream->read_V32();
  479     _integerPool.resize(count);
  480     if (count)
  481         _integerPool[0] = 0;
  482     for (unsigned int i = 1; i < count; ++i)
  483     {
  484         _integerPool[i] = static_cast<boost::int32_t> (_stream->read_V32());
  485     }
  486     return true;
  487 }
  488 
  489 /// Read the pool of unsigned integer constants.
  490 bool
  491 AbcBlock::read_unsigned_integer_constants()
  492 {
  493     // count overestimates by 1.
  494     boost::uint32_t count = _stream->read_V32();
  495     _uIntegerPool.resize(count);
  496     if (count)
  497         _uIntegerPool[0] = 0;
  498     for (unsigned int i = 1; i < count; ++i)
  499     {
  500         _uIntegerPool[i] = _stream->read_V32();
  501     }
  502     return true;
  503 }
  504 
  505 /// Read the pool of 64-bit double constants.
  506 bool
  507 AbcBlock::read_double_constants()
  508 {
  509     boost::uint32_t count = _stream->read_V32();
  510     _doublePool.resize(count);
  511     if (count) _doublePool[0] = 0.0;
  512 
  513     for (size_t i = 1; i < count; ++i)
  514     {
  515         _doublePool[i] = _stream->read_d64();
  516         log_abc("Double %u=%lf", i, _doublePool[i]);
  517     }
  518     return true;
  519 }
  520 
  521 /// Read the pool of string constants.
  522 bool
  523 AbcBlock::read_string_constants()
  524 {
  525     log_abc("Begin reading string constants.");
  526     boost::uint32_t count = _stream->read_V32();
  527     log_abc("There are %u string constants.", count);
  528     _stringPool.resize(count);
  529 
  530     if (count) {
  531         _stringPool[0] = "";
  532     }
  533 
  534     for (size_t i = 1; i < count; ++i) {
  535         boost::uint32_t length = _stream->read_V32();
  536         _stream->read_string_with_length(length, _stringPool[i]);
  537         log_abc("Adding string constant to string pool: index=%u %s",
  538                 i, _stringPool[i]);
  539     }
  540     return true;
  541 }
  542 
  543 /// Read the pool of namespaces
  544 /// Any two namespaces with the same uri here are the same namespace, 
  545 /// excepting private namespaces.
  546 bool
  547 AbcBlock::read_namespaces()
  548 {   
  549     log_abc("Begin reading namespaces.");
  550     boost::uint32_t count = _stream->read_V32();
  551     log_abc("There are %u namespaces.", count);
  552     _namespacePool.resize(count);
  553     if (count) {
  554         _namespacePool[0] = mCH->getGlobalNs();
  555     }
  556 
  557     for (size_t i = 1; i < count; ++i)
  558     {
  559         NamespaceConstant kind =
  560             static_cast<NamespaceConstant>(_stream->read_u8());
  561 
  562         boost::uint32_t nameIndex = _stream->read_V32();
  563         log_abc("Namespace %u: %s, index %u, name %s", i, kind,
  564                 nameIndex, _stringPool[nameIndex]);
  565 
  566         if (nameIndex >= _stringPool.size()) {
  567             log_error(_("ABC: Bad string given for namespace."));
  568             return false;
  569         }
  570         
  571         if (kind == PRIVATE_NS)
  572         {
  573             _namespacePool[i] = mCH->anonNamespace(nameIndex);
  574             _namespacePool[i]->setPrivate();
  575         }
  576         else
  577         {
  578             string_table::key gn = _stringTable->find(_stringPool[nameIndex]);
  579             Namespace *n = mCH->findNamespace(gn);
  580             if (!n) n = mCH->addNamespace(gn);
  581             _namespacePool[i] = n;
  582         }
  583         if (kind == PROTECTED_NS) _namespacePool[i]->setProtected();
  584         if (kind == PACKAGE_NS) _namespacePool[i]->setPackage();
  585         setNamespaceURI(_namespacePool[i], nameIndex);
  586     }
  587     return true;
  588 }
  589 
  590 /// Read the set of sets of namespaces.
  591 bool
  592 AbcBlock::read_namespace_sets()
  593 {
  594     boost::uint32_t count = _stream->read_V32();
  595     _namespaceSetPool.resize(count);
  596     if (count)
  597     {
  598         _namespaceSetPool[0].resize(0);
  599     }
  600     for (unsigned int i = 1; i < count; ++i)
  601     {
  602         boost::uint32_t icount = _stream->read_V32();
  603         _namespaceSetPool[i].resize(icount);
  604         for (unsigned int j = 0; j < icount; ++j)
  605         {
  606             boost::uint32_t selection = _stream->read_V32();
  607             if (!selection || selection >= _namespacePool.size())
  608             {
  609                 log_error(_("ABC: Bad namespace for namespace set."));
  610                 return false;
  611             }
  612             _namespaceSetPool[i][j] = _namespacePool[selection];
  613         }
  614     }
  615     return true;
  616 }
  617 
  618 /// Read the multinames.
  619 bool
  620 AbcBlock::read_multinames()
  621 {
  622     boost::uint32_t count = _stream->read_V32();
  623     log_abc("There are %u multinames.", count);
  624     _multinamePool.resize(count);
  625     if (count)
  626     {
  627 //      _multinamePool[0].setABCName(0);
  628         setMultinameNames(&_multinamePool[0], 0);
  629         _multinamePool[0].setNamespace(mCH->getGlobalNs());
  630     }
  631     for (unsigned int i = 1; i < count; ++i)
  632     {
  633         MultiName::Kind kind = static_cast<MultiName::Kind>(_stream->read_u8());
  634         boost::uint32_t ns = 0;
  635         boost::uint32_t name = 0;
  636         boost::uint32_t nsset = 0;
  637 
  638         log_abc("Multiname %u has kind %s", i, static_cast<int>(kind));
  639 
  640         // Read, but don't upper validate until after the switch.
  641         switch (kind)
  642         {
  643             case MultiName::KIND_Qname:
  644             case MultiName::KIND_QnameA:
  645                 ns = _stream->read_V32();
  646                 check_multiname_namespace(ns);
  647                 name = _stream->read_V32();
  648                 check_multiname_name(name);
  649                 log_abc("\tnamespace_index=%u name_index=%u name=%s",
  650                         ns, name, _stringPool[name]);
  651                 break;
  652             
  653             case MultiName::KIND_RTQname:
  654             case MultiName::KIND_RTQnameA:
  655                 name = _stream->read_V32();
  656                 check_multiname_name(name);
  657                 break;
  658             
  659             case MultiName::KIND_RTQnameL:
  660             case MultiName::KIND_RTQnameLA:
  661                 break;
  662             
  663             case MultiName::KIND_Multiname:
  664             case MultiName::KIND_MultinameA:
  665                 name = _stream->read_V32();
  666                 check_multiname_name(name);
  667                 nsset = _stream->read_V32();
  668                 check_multiname_namespaceset(nsset);
  669                 break;
  670             
  671             case MultiName::KIND_MultinameL:
  672             case MultiName::KIND_MultinameLA:
  673                 nsset = _stream->read_V32();
  674                 check_multiname_namespaceset(nsset);
  675                 break;
  676             
  677             default:
  678                 // Unknown type.
  679                 log_error(_("Action Block: Unknown multiname type (%d)."),
  680                         kind);
  681                 return false;
  682         } 
  683 
  684         _multinamePool[i].setFlags(kind);
  685         setMultinameNames(&_multinamePool[i], name);
  686         log_abc("Done setting multinames: abc=%u global=%u",
  687                _multinamePool[i].getABCName(),
  688                _multinamePool[i].getGlobalName());
  689 
  690         _multinamePool[i].setNamespace(_namespacePool[ns]);
  691 
  692         if (nsset) {
  693             _multinamePool[i].namespaceSet(&_namespaceSetPool[nsset]);
  694         }
  695     } // End of main loop.
  696     return true;
  697 }
  698 
  699 bool
  700 AbcBlock::pool_value(boost::uint32_t index, PoolConstant type, as_value &v)
  701 {
  702     if (!index)
  703         return true;
  704 
  705     log_abc("Pool value: index is %u type is 0x%X", index, type | 0x0);
  706     switch (type)
  707     {
  708     case POOL_STRING: 
  709     {
  710         if (index >= _stringPool.size())
  711         {
  712             log_error(_("Action Block: Bad index in optional argument."));
  713             return false;
  714         }
  715         v.set_string(_stringPool[index]);
  716         break;
  717     }
  718     case POOL_INTEGER: 
  719     {
  720         if (index >= _integerPool.size())
  721         {
  722             log_error(_("Action Block: Bad index in optional argument."));
  723             return false;
  724         }
  725         v.set_double(_integerPool[index]);
  726         break;
  727     }
  728     case POOL_UINTEGER:
  729     {
  730         if (index >= _uIntegerPool.size())
  731         {
  732             log_error(_("Action Block: Bad index in optional argument."));
  733             return false;
  734         }
  735         v.set_double(_uIntegerPool[index]);
  736         break;
  737     }
  738     case POOL_DOUBLE: 
  739     {
  740         if (index >= _doublePool.size())
  741         {
  742             log_error(_("Action Block: Bad index in optional argument."));
  743             return false;
  744         }
  745         v.set_double(static_cast<double>(_doublePool[index]));
  746         break;
  747     }
  748     case POOL_NAMESPACE: // Namespace
  749     {
  750         if (index >= _namespacePool.size())
  751         {
  752             log_error(_("ABC: Bad index in optional argument, namespaces."));
  753             return false;
  754         }
  755         break;
  756     }
  757     case POOL_FALSE: // False value
  758     {
  759         v.set_bool(false);
  760         break;
  761     }
  762     case POOL_TRUE: // True value
  763     {
  764         v.set_bool(true);
  765         break;
  766     }
  767     case POOL_NULL: // NULL value
  768     {
  769         v.set_null();
  770         break;
  771     }
  772     default: // All others are bogus.
  773     {
  774         log_error(_("ABC: Bad default value type (%X), but continuing."), type);
  775         return true;
  776         break;
  777     }
  778     } // end of switch
  779     return true;
  780 }
  781 
  782 /// Read the method infos.
  783 bool
  784 AbcBlock::read_method_infos()
  785 {
  786     log_abc("Begin read_method_infos.");
  787 
  788     boost::uint32_t count = _stream->read_V32();
  789     log_abc("Method count: %u", count);
  790 
  791     _methods.resize(count);
  792     for (unsigned int i = 0; i < count; ++i)
  793     {
  794         log_abc(" Reading method %u", i);
  795         Method *pMethod = mCH->newMethod();
  796         pMethod->setMethodID(i);
  797         _methods[i] = pMethod;
  798         boost::uint32_t param_count = _stream->read_V32();
  799         boost::uint32_t return_type = _stream->read_V32();
  800 
  801         const std::string& rt = return_type ? 
  802             _stringPool[_multinamePool[return_type].getABCName()] :
  803             "*";
  804 
  805         log_abc("  Param count: %u, return type: %s", param_count, 
  806                 rt, return_type);
  807 
  808         pMethod->setMinArgumentCount(param_count);
  809         pMethod->setMaxArgumentCount(param_count);
  810 
  811         if (return_type >= _multinamePool.size()) {
  812             log_error(_("ABC: Bad return type for method info."));
  813             return false;
  814         }
  815 
  816         if (!return_type) {
  817             pMethod->setReturnType(0);
  818         }
  819         else {
  820             // TODO: this can be 'void', which clearly isn't a class, so this
  821             // seems bogus. As setReturnType is a no-op, we should log it
  822             // and ignore it.
  823             abc::Class* rtScript = locateClass(_multinamePool[return_type]);
  824             if (!rtScript) {
  825                 log_abc(_("ABC: Unknown return type."));
  826             }
  827 
  828             pMethod->setReturnType(rtScript);
  829         }
  830         for (size_t j = 0; j < param_count; ++j) {
  831             log_abc("  Reading parameter %u", j);
  832             // The parameter type.
  833             boost::uint32_t ptype = _stream->read_V32();
  834             
  835             const std::string& pt = return_type ? 
  836                 _stringPool[_multinamePool[ptype].getABCName()] :
  837                 "*";
  838             
  839             log_abc("   Parameter type(index): %s(%u)", pt, ptype);
  840 
  841             if (ptype >= _multinamePool.size()) {
  842                 log_error(_("ABC: Bad parameter type in method."));
  843                 return false;
  844             }
  845             
  846             // A value of 0 is legitimate, meaning 'any (*)'. 
  847             if (ptype) {
  848                 abc::Class* param_type = locateClass(_multinamePool[ptype]);
  849 
  850                 if (!param_type) {
  851                     log_abc((_("ABC: Unknown parameter type.")));
  852                 }
  853                 
  854                 // This currently also pushes 0, meaning 'any'; perhaps it
  855                 // should throw a VerifyError if the class is not known.
  856                 pMethod->pushArgument(param_type);
  857             }
  858             else {
  859                 pMethod->pushArgument(0);
  860             }
  861         }
  862 
  863         boost::uint32_t method_name = _stream->read_V32();
  864         log_abc(  "Method name=%s %d", _stringPool[method_name], method_name);
  865         boost::uint8_t flags = _stream->read_u8();
  866         log_abc("  Flags: %X", flags | 0x0);
  867 //      log_abc("Check if flags and optional args.");
  868         // If there are default parameters, read them now.
  869         // Runtime will do validation of whether or not these can actually
  870         // be assigned to the corresponding parameters.
  871         if (flags & METHOD_OPTIONAL_ARGS) {
  872             
  873             boost::uint32_t ocount = _stream->read_V32();
  874             log_abc("  Optional args: %u", ocount);
  875             pMethod->setMinArgumentCount(pMethod->maxArgumentCount() - ocount);
  876             
  877             for (unsigned int j = 0; j < ocount; ++j) {
  878                 log_abc("  Reading optional arg: %u", j);
  879                 boost::uint32_t index = _stream->read_V32();
  880                 
  881                 PoolConstant kindof =
  882                     static_cast<PoolConstant>(_stream->read_u8());
  883 
  884                 log_abc("   Index: %u Kindof: %u", index, kindof);
  885                 as_value v;
  886                 if (!pool_value(index, kindof, v)) {
  887                     return false; 
  888                 }
  889                 pMethod->pushOptional(v);
  890             }
  891             log_abc("Done handling optional args.");
  892         }
  893 
  894         if (flags & METHOD_ACTIVATION) {
  895             log_abc("Method needs activation");
  896             pMethod->setNeedsActivation();
  897         }
  898 
  899         // If there are names present for the parameters, skip them.
  900         if (flags & METHOD_ARG_NAMES) {
  901             for (size_t j = 0; j < param_count; ++j) {
  902                 _stream->skip_V32();
  903             }
  904         }
  905     } // End of method loop.
  906     return true;
  907 }
  908 
  909 /// Skip the metadata, which is useless to us.
  910 bool
  911 AbcBlock::skip_metadata()
  912 {
  913     boost::uint32_t count = _stream->read_V32();
  914     for (unsigned int i = 0; i < count; ++i)
  915     {
  916         _stream->skip_V32(); // A name index.
  917         boost::uint32_t icount = _stream->read_V32();
  918         for (unsigned int j = 0; j < icount; ++j)
  919         {
  920             // key/values may not be stored together, but this still works.
  921             _stream->skip_V32();
  922             _stream->skip_V32();
  923         }
  924     }
  925     return true;
  926 }
  927 
  928 /// Load the instances from the block.
  929 bool
  930 AbcBlock::read_instances()
  931 {
  932     boost::uint32_t count = _stream->read_V32();
  933     log_abc("There are %u instances.", count);
  934     _classes.resize(count);
  935     for (size_t i = 0; i < count; ++i) {
  936         //Read multiname index.
  937         boost::uint32_t index = _stream->read_V32();
  938         // 0 is allowed as a name, typically for the last entry.
  939         if (index >= _multinamePool.size()) {
  940             log_error(_("ABC: Out of bounds instance name."));
  941             return false;
  942         }
  943         
  944         MultiName& multiname = _multinamePool[index];
  945         
  946         // This must be a QName.
  947         if (!multiname.isQName()) {
  948             log_error(_("ABC: QName required for instance."));
  949             return false;
  950         }
  951         
  952         if (!multiname.getNamespace()) {
  953             log_error(_("ABC: No namespace to use for storing class."));
  954             return false;
  955         }
  956 
  957         abc::Class* cl = locateClass(multiname);
  958         
  959         if (!cl) {
  960 
  961             const string_table::key className = multiname.getGlobalName();
  962 
  963             cl = mCH->newClass();
  964             cl->setName(className);
  965 
  966             if (!multiname.getNamespace()->addScript(className, cl)) {
  967 
  968                 log_error(_("Duplicate class registration."));
  969                 return false;
  970             }
  971             log_debug("Adding class %s (%s) to namespace %s",
  972                     _stringTable->value(multiname.getGlobalName()),
  973                     _stringPool[multiname.getABCName()],
  974                     _stringTable->value(multiname.getNamespace()->getURI()));
  975             log_debug("Namespace now:");
  976             multiname.getNamespace()->dump(*_stringTable);
  977 
  978         }
  979         cl->setDeclared();
  980         _classes[i] = cl;
  981         boost::uint32_t super_index = _stream->read_V32();
  982 
  983         if (super_index && super_index >= _multinamePool.size()) {
  984             log_error(_("ABC: Bad super type."));
  985             return false;
  986         }
  987 
  988         if (!super_index) {
  989             cl->setSuper(mTheObject);
  990         }
  991         else {
  992             abc::Class *pSuper = locateClass(_multinamePool[super_index]);
  993             if (!pSuper)
  994             {
  995                 log_error(_("ABC: Super type not found (%s)"), 
  996                     _stringPool[_multinamePool[super_index].getABCName()]);
  997                 return false;
  998             }
  999 
 1000             if (pSuper->isFinal())
 1001             {
 1002                 log_error(_("ABC: Can't extend a class which is final."));
 1003                 return false;
 1004             }
 1005 
 1006             if (pSuper->isInterface())
 1007             {
 1008                 log_error(_("ABC: Can't extend an interface type."));
 1009                 return false;
 1010             }
 1011 
 1012             if (pSuper == cl)
 1013             {
 1014                 log_error(_("ABC: Class cannot be its own supertype."));
 1015                 return false;
 1016             }
 1017             cl->setSuper(pSuper);
 1018             pSuper->setInherited();
 1019         }
 1020 
 1021         boost::uint8_t flags = _stream->read_u8();
 1022         log_abc("Instance %u(%s) multiname index=%u name=%s super index=%u "
 1023                 "flags=%X", i, cl, index, 
 1024                 _stringPool[_multinamePool[index].getABCName()],
 1025                 super_index, flags | 0x0);
 1026 
 1027         if (flags & INSTANCE_SEALED) cl->setSealed();
 1028         if (flags & INSTANCE_FINAL) cl->setFinal();
 1029         if (flags & INSTANCE_INTERFACE) cl->setInterface();
 1030         if ((flags & 7) == INSTANCE_DYNAMIC) cl->setDynamic();
 1031 
 1032         if (flags & INSTANCE_PROTECTED_NS) {
 1033             boost::uint32_t ns_index = _stream->read_V32();
 1034             if (ns_index >= _namespacePool.size()) {
 1035                 log_error(_("ABC: Bad namespace for protected."));
 1036                 return false;
 1037             }
 1038             // Set the protected namespace's parent, if it exists.
 1039             if (cl->getSuper()->hasProtectedNs())
 1040                 _namespacePool[ns_index]->setParent(
 1041                         cl->getSuper()->getProtectedNs());
 1042             cl->setProtectedNs(_namespacePool[ns_index]);
 1043         }
 1044 
 1045         // This is the list of interfaces which the instances has agreed to
 1046         // implement. They must be interfaces, and they must exist.
 1047         boost::uint32_t intcount = _stream->read_V32();
 1048         log_abc("This instance has %u interfaces.", intcount);
 1049         for (size_t j = 0; j < intcount; ++j) {
 1050             boost::uint32_t i_index = _stream->read_V32();
 1051             log_abc("Interface %u has multiname index=%u", i, i_index);
 1052             // 0 is allowed as an interface, typically for the last one.
 1053             if (i_index >= _multinamePool.size()) {
 1054                 log_error(_("ABC: Bad name for interface."));
 1055                 return false;
 1056             }
 1057             abc::Class *pInterface = locateClass(_multinamePool[i_index]);
 1058             // These may be undefined still, so don't check interface just yet.
 1059             if (0) //!pInterface || !pInterface->isInterface())
 1060             {
 1061                 log_error(_("ABC: Can't implement a non-interface type."));
 1062                 return false;
 1063             }
 1064             cl->pushInterface(pInterface);
 1065         }
 1066 
 1067         // The next thing should be the constructor.
 1068         // TODO: What does this mean exactly? How does it differ from the one in
 1069         // the class info block?
 1070         boost::uint32_t offset = _stream->read_V32();
 1071         log_abc("Moffset: %u", offset);
 1072         if (offset >= _methods.size()) {
 1073             log_error(_("ABC: Out of bounds method for initializer."));
 1074             return false;
 1075         }
 1076         // Don't validate for previous owner.
 1077         cl->setConstructor(_methods[offset]);
 1078 
 1079         // Next come the 'traits' of the instance. (The members.)
 1080         boost::uint32_t tcount = _stream->read_V32();
 1081         log_abc("Trait count: %u", tcount);
 1082         for (unsigned int j = 0; j < tcount; ++j)
 1083         {
 1084             Trait t;
 1085             t.set_target(cl, false);
 1086             if (!t.read(_stream, this)) return false;
 1087             cl->addInstanceTrait(t);
 1088         }
 1089     } 
 1090     return true;
 1091 }
 1092 
 1093 /// Read the class data
 1094 bool
 1095 AbcBlock::read_classes()
 1096 {
 1097     // Count was found in read_instances().
 1098     log_abc("Begin reading classes.");
 1099     boost::uint32_t count = _classes.size();
 1100     log_abc("There are %u classes.", count);
 1101     
 1102     for (size_t i = 0; i < count; ++i) {
 1103         abc::Class* cl = _classes[i];
 1104         boost::uint32_t offset = _stream->read_V32();
 1105         log_abc("Class %u(%s) static constructor index=%u", i, cl, offset);
 1106 
 1107         if (offset >= _methods.size()) {
 1108             log_error(_("ABC: Out of bound static constructor for class."));
 1109             return false;
 1110         }
 1111 
 1112         // Don't validate for previous owner.
 1113         cl->setStaticConstructor(_methods[offset]);
 1114 
 1115         boost::uint32_t tcount = _stream->read_V32();
 1116         log_abc("This class has %u traits.", tcount);
 1117         for (size_t j = 0; j < tcount; ++j) {
 1118             Trait t;
 1119             t.set_target(cl, true);
 1120             if (!(t.read(_stream, this))) return false;
 1121             cl->addStaticTrait(t);
 1122         }
 1123     } 
 1124     return true;
 1125 }
 1126 
 1127 /// Read the scripts (global functions)
 1128 /// The final script is the entry point for the block.
 1129 bool
 1130 AbcBlock::read_scripts()
 1131 {
 1132     log_abc("Begin reading scripts.");
 1133 
 1134     const boost::uint32_t scriptcount = _stream->read_V32();
 1135     log_abc("There are %u scripts.", scriptcount);
 1136 
 1137     _scripts.resize(scriptcount);
 1138     for (size_t i = 0; i < scriptcount; ++i) {
 1139 
 1140         abc::Class* script = mCH->newClass();
 1141         _scripts[i] = script;
 1142 
 1143         boost::uint32_t offset = _stream->read_V32();
 1144         log_abc("Reading script %u(%s) initializer method index=%u", i,
 1145                 script, offset);
 1146         if (offset >= _methods.size()) {
 1147             log_error(_("ABC: Out of bounds method for script."));
 1148             return false;
 1149         }
 1150 
 1151         script->setConstructor(_methods[offset]);
 1152 
 1153         const boost::uint32_t tcount = _stream->read_V32();
 1154         for (size_t j = 0; j < tcount; ++j) {
 1155             
 1156             Trait t;
 1157             t.set_target(script, false);
 1158             if (!(t.read(_stream, this))) {
 1159                 return false;
 1160             }
 1161             log_abc("Trait: %u name: %s(%u) kind: %s value: %s ", j, 
 1162                     _stringPool[t._name], t._name, t._kind, t._value);
 1163 
 1164             // TODO: this should not use Class!
 1165             script->addStaticTrait(t);
 1166         }
 1167     } 
 1168     return true;
 1169 }
 1170 
 1171 /// Read the method bodies and attach them to the methods.
 1172 bool
 1173 AbcBlock::read_method_bodies()
 1174 {
 1175     boost::uint32_t count = _stream->read_V32();
 1176     log_abc("There are %u method bodies.", count);
 1177     for (unsigned int i = 0; i < count; ++i)
 1178     {
 1179         boost::uint32_t offset = _stream->read_V32();
 1180         log_abc("Method body %u method offset=%u", i, offset);
 1181 
 1182         if (offset >= _methods.size()) {
 1183             log_error(_("ABC: Out of bounds for method body."));
 1184             return false;
 1185         }
 1186 
 1187         Method& method = *_methods[offset];
 1188 
 1189         if (method.getBody()) {
 1190             log_error(_("ABC: Only one body per method."));
 1191             return false;
 1192         }
 1193 
 1194         // Maximum stack size.
 1195         method.setMaxStack(_stream->read_V32());
 1196         
 1197         // Maximum register size.
 1198         method.setMaxRegisters(_stream->read_V32());
 1199         
 1200         // Scope depth.
 1201         method.setScopeDepth(_stream->read_V32());
 1202         
 1203         // Max scope depth.
 1204         method.setMaxScope(_stream->read_V32());
 1205         
 1206         // Code length
 1207         boost::uint32_t clength = _stream->read_V32();
 1208         method.setBodyLength(clength);
 1209 
 1210         // The code.
 1211         //TODO: Clean this up.
 1212         std::string body;
 1213         _stream->read_string_with_length(clength, body);
 1214 
 1215         method.setBody(new CodeStream(body));
 1216         
 1217         // Exception count and exceptions
 1218         
 1219         // Note: catch type and variable name are documented to be
 1220         // indices in the string pool, but they are in fact indices
 1221         // in the multiname pool.
 1222         const boost::uint32_t ecount = _stream->read_V32();
 1223         for (unsigned int j = 0; j < ecount; ++j) {
 1224             asException *ex = mCH->newException();
 1225 
 1226             // Where the try block begins and ends.
 1227             ex->setStart(_stream->read_V32());
 1228             ex->setEnd(_stream->read_V32());
 1229 
 1230             // Where to go when the exception is activated.
 1231             ex->setCatch(_stream->read_V32());
 1232 
 1233             // What types should be caught.
 1234             boost::uint32_t catch_type = _stream->read_V32();
 1235             if (catch_type >= _multinamePool.size()) {
 1236                 log_error(_("ABC: Out of bound type for exception."));
 1237                 return false;
 1238             }
 1239             if (!catch_type) {
 1240                 ex->catchAny();
 1241             }
 1242             else {
 1243                 abc::Class *type = locateClass(_multinamePool[catch_type]);
 1244                 if (!type) {
 1245 
 1246                     log_error(_("ABC: Unknown type of object to catch. (%s)"), 
 1247                         _stringTable->value(
 1248                             _multinamePool[catch_type].getABCName()));
 1249 
 1250                     // return false;
 1251                     // Fake it, for now:
 1252                     ex->catchAny();
 1253                 }
 1254                 else {
 1255                     ex->setCatchType(type);
 1256                 }
 1257             }
 1258 
 1259             // A variable name for the catch type.
 1260             // In version 46.15, no names.
 1261             if (mVersion != ((46 << 16) | 15)) {
 1262                 boost::uint32_t cvn = _stream->read_V32();
 1263                 if (cvn >= _multinamePool.size()) {
 1264                     log_error(_("ABC: Out of bound name for caught "
 1265                                 "exception."));
 1266                     return false;
 1267                 }
 1268                 ex->setName(_multinamePool[cvn].getABCName());
 1269                 ex->setNamespace(_multinamePool[cvn].getNamespace());
 1270             }
 1271         } 
 1272 
 1273         // Traits
 1274         boost::uint32_t tcount = _stream->read_V32();
 1275         for (unsigned int j = 0; j < tcount; ++j)
 1276         {
 1277             Trait t;
 1278             t.set_target(_methods[offset]);
 1279             
 1280             if (!t.read(_stream, this)) {
 1281                 return false;
 1282             }
 1283 
 1284             log_abc("Activation trait: %u name: %s, kind: %s, value: %s ", j, 
 1285                     _stringPool[t._name], t._kind, t._value);
 1286             _methods[offset]->addTrait(t);
 1287         }
 1288     } 
 1289     return true;
 1290 }
 1291 
 1292 // Load up all of the data.
 1293 bool
 1294 AbcBlock::read(SWFStream& in)
 1295 {
 1296     // This isn't very nice:
 1297     _stream = &in;
 1298 
 1299     if (!read_version()) return false;
 1300     if (!read_integer_constants()) return false;
 1301     if (!read_unsigned_integer_constants()) return false;
 1302     log_abc("Done reading unsigned integer constants.");
 1303     
 1304     if (!read_double_constants()) return false;
 1305     log_abc("Done reading double constants.");
 1306     
 1307     if (!read_string_constants()) return false;
 1308     log_abc("Done reading string constants.");
 1309     
 1310     if (!read_namespaces()) return false;
 1311     log_abc("Done reading namespaces.");
 1312     
 1313     if (!read_namespace_sets()) return false;
 1314     log_abc("Done reading namespace sets.");
 1315     
 1316     if (!read_multinames()) return false;
 1317     log_abc("Done reading multinames.");
 1318     
 1319     if (!read_method_infos()) return false;
 1320     log_abc("Done reading method infos.");
 1321     
 1322     if (!skip_metadata()) return false;
 1323     log_abc("Done reading metadata.");
 1324     
 1325     if (!read_instances()) return false;
 1326     log_abc("Done reading instances.");
 1327     
 1328     if (!read_classes()) return false;
 1329     log_abc("Done reading classes.");
 1330     
 1331     if (!read_scripts()) return false;
 1332     log_abc("Done reading scripts.");
 1333     
 1334     if (!read_method_bodies()) return false;
 1335     log_abc("Done reading stuff.");
 1336 
 1337     for (size_t i=0; i < _methods.size(); ++i) {
 1338         log_abc("Method %d body:", i);
 1339         IF_VERBOSE_PARSE(_methods[i]->print_body());
 1340     }
 1341     return true;
 1342 }
 1343 
 1344 
 1345 void
 1346 AbcBlock::update_global_name(unsigned int multiname_index)
 1347 {
 1348     
 1349     MultiName* multiname = &_multinamePool[multiname_index];
 1350     string_table::key new_key = 
 1351         _stringTable->find(_stringPool[multiname->getABCName()], false);
 1352     multiname->setGlobalName(new_key);  
 1353 }
 1354 
 1355 std::ostream&
 1356 operator<<(std::ostream& o, AbcBlock::NamespaceConstant c)
 1357 {
 1358     switch (c)
 1359     {
 1360         case AbcBlock::PRIVATE_NS:
 1361             return o << "private namespace";
 1362         case AbcBlock::CONSTANT_NS:
 1363             return o << "constant namespace";
 1364         case AbcBlock::PACKAGE_NS:
 1365             return o << "package namespace";
 1366         case AbcBlock::PACKAGE_INTERNAL_NS:
 1367             return o << "package internal namespace";
 1368         case AbcBlock::PROTECTED_NS:
 1369             return o << "protected namespace";
 1370         case AbcBlock::EXPLICIT_NS:
 1371             return o << "explicit namespace";
 1372         case AbcBlock::STATIC_PROTECTED_NS:
 1373             return o << "static protected namespace";
 1374         default:
 1375             return o << "invalid namespace constant";
 1376     }
 1377 }
 1378 
 1379 std::ostream&
 1380 operator<<(std::ostream& o, AbcBlock::MethodConstant c)
 1381 {
 1382     switch (c)
 1383     {
 1384         case AbcBlock::METHOD_ARGS:
 1385             return o << "method arg";
 1386         case AbcBlock::METHOD_ACTIVATION:
 1387             return o << "method activation";
 1388         case AbcBlock::METHOD_MORE:
 1389             return o << "method more";
 1390         case AbcBlock::METHOD_OPTIONAL_ARGS:
 1391             return o << "method optional args";
 1392         case AbcBlock::METHOD_IGNORE:
 1393             return o << "method ignore";
 1394         case AbcBlock::METHOD_NATIVE:
 1395             return o << "method native";
 1396         case AbcBlock::METHOD_DEFAULT_NS:
 1397             return o << "default namespace";
 1398         case AbcBlock::METHOD_ARG_NAMES:
 1399             return o << "method arg names";
 1400         default:
 1401             return o << "invalid method constant";
 1402     }
 1403 }
 1404 
 1405 std::ostream&
 1406 operator<<(std::ostream& o, AbcBlock::InstanceConstant c)
 1407 {
 1408     switch (c)
 1409     {
 1410         case AbcBlock::INSTANCE_SEALED:
 1411             return o << "instance sealed";
 1412         case AbcBlock::INSTANCE_FINAL:
 1413             return o << "instance final";
 1414         case AbcBlock::INSTANCE_INTERFACE:
 1415             return o << "instance interface";
 1416         case AbcBlock::INSTANCE_DYNAMIC:
 1417             return o << "instance dynamic";
 1418         case AbcBlock::INSTANCE_PROTECTED_NS:
 1419             return o << "instance protected namespace";
 1420         default:
 1421             return o << "invalid instance constant";
 1422     }
 1423 }
 1424 
 1425 std::ostream&
 1426 operator<<(std::ostream& o, AbcBlock::PoolConstant c)
 1427 {
 1428     switch (c)
 1429     {
 1430         case AbcBlock::POOL_STRING:
 1431             return o << "pool string";
 1432         case AbcBlock::POOL_INTEGER:
 1433             return o << "pool integer";
 1434         case AbcBlock::POOL_UINTEGER:
 1435             return o << "pool uinteger";
 1436         case AbcBlock::POOL_DOUBLE:
 1437             return o << "pool double";
 1438         case AbcBlock::POOL_NAMESPACE:
 1439             return o << "pool namespace";
 1440         case AbcBlock::POOL_FALSE:
 1441             return o << "pool false";
 1442         case AbcBlock::POOL_TRUE:
 1443             return o << "pool true";
 1444         case AbcBlock::POOL_NULL:
 1445             return o << "pool null";
 1446         default:
 1447             return o << "invalid pool constant";
 1448 
 1449     }
 1450 }
 1451 
 1452 } // namespace abc
 1453 } // namespace gnash
 1454