update copyright date
[gnash.git] / libcore / abc / AbcBlock.cpp
blobcc4de866c33121ce599dee97428791672b4e2e60
1 //
2 // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 // The AS3 abc block format reader.
21 #include "gnashconfig.h"
22 #include "AbcBlock.h"
23 #include "SWFStream.h" // for use
24 #include "VM.h"
25 #include "log.h"
26 #include "ClassHierarchy.h"
27 #include "Class.h"
28 #include "namedStrings.h"
29 #include "CodeStream.h"
30 #include "action_buffer.h"
31 #include "Machine.h"
32 #include "Global_as.h"
34 #include <boost/bind.hpp>
36 namespace gnash {
38 namespace abc {
40 bool
41 Trait::finalize(AbcBlock *block, abc::Class* script, bool do_static)
43 log_abc("Finalize class %s (%s), trait kind: %s",
44 block->_stringTable->value(script->getName()), script, _kind);
46 switch (_kind)
48 case KIND_SLOT:
49 case KIND_CONST:
51 // Validate the type.
52 abc::Class* type;
53 if (_typeIndex) {
54 log_abc("Trait type: %s",
55 block->_stringPool[
56 block->_multinamePool[_typeIndex].getABCName()]);
57 type = block->locateClass(block->_multinamePool[_typeIndex]);
59 else {
60 type = block->mTheObject;
63 if (!type) {
64 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
65 return false;
68 // The name has been validated in read.
69 // TODO: Find a better way to initialize trait values.
70 if (!_hasValue) {
71 as_object* null = 0;
72 _value = null;
75 log_abc("Adding property=%s with value=%s slot=%u",
76 block->_stringPool[_name], _value, _slotID);
78 script->addValue(_globalName, _namespace, _slotID, type,
79 _value, _kind == KIND_CONST, do_static);
80 break;
83 case KIND_METHOD:
84 script->addMethod(_globalName, _namespace, _method, false);
85 break;
87 case KIND_GETTER:
88 script->addGetter(_name, _namespace, _method, do_static);
89 break;
91 case KIND_SETTER:
92 script->addSetter(_name, _namespace, _method, do_static);
93 break;
95 case KIND_CLASS:
96 log_abc("Adding class %s, value %s, slot=%u",
97 block->_stringPool[_name], _value, _slotID);
98 script->addMemberScript(_globalName, _namespace, _slotID,
99 block->_classes[_classInfoIndex], do_static);
100 break;
102 case KIND_FUNCTION:
103 script->addSlotFunction(_name, _namespace, _slotID, _method,
104 do_static);
105 break;
107 default:
108 return false;
110 return true;
113 bool
114 Trait::finalize_mbody(AbcBlock *block, Method *pMethod)
116 log_abc("Finalizing method trait: kind %s", _kind);
117 switch (_kind)
119 case KIND_SLOT:
120 case KIND_CONST:
122 // Validate the type.
123 abc::Class *type;
124 if (_typeIndex) {
125 type = block->locateClass(block->_multinamePool[_typeIndex]);
127 else {
128 type = block->mTheObject;
131 if (!type) {
132 log_error(_("ABC: Finalizing trait yielded bad type for slot."));
133 return false;
136 // The name has been validated in read.
137 // TODO: Find a better way to initialize trait values.
138 if (!_hasValue) {
139 _value = as_value((as_object*)0); // NULL value, right ?
141 log_abc("Adding property=%s with value=%s slot=%u",
142 block->_stringPool[_name], _value.toDebugString(), _slotID);
143 pMethod->addValue(_globalName, _namespace, _slotID, type,
144 _value, _kind == KIND_CONST);
145 break;
147 case KIND_METHOD:
149 pMethod->addMethod(_name, _namespace, _method);
150 break;
152 case KIND_GETTER:
154 pMethod->addGetter(_name, _namespace, _method);
155 break;
157 case KIND_SETTER:
159 pMethod->addSetter(_name, _namespace, _method);
160 break;
162 case KIND_CLASS:
164 pMethod->addMemberScript(_name, _namespace, _slotID,
165 block->_classes[_classInfoIndex]);
166 break;
168 case KIND_FUNCTION:
170 pMethod->addSlotFunction(_name, _namespace, _slotID, _method);
171 break;
173 default:
174 // Not here -- validated already in read.
175 return false;
177 return true;
180 /// Read an AS3 'trait'
181 bool
182 Trait::read(SWFStream* in, AbcBlock *block)
184 boost::uint32_t name = in->read_V32();
185 if (name >= block->_multinamePool.size())
187 log_error(_("ABC: Bad name for trait."));
188 return false;
190 if (!block->_multinamePool[name].isQName())
192 log_error(_("ABC: Trait name must be fully qualified."));
193 return false;
195 MultiName multiname = block->_multinamePool[name];
196 _name = block->_multinamePool[name].getABCName();
197 _globalName = block->_multinamePool[name].getGlobalName();
198 _namespace = block->_multinamePool[name].getNamespace();
200 boost::uint8_t kind = in->read_u8();
201 _kind = static_cast<Kind>(kind & 0x0F);
203 log_abc("Trait name: %s, Trait kind: %s",
204 block->_stringPool[multiname.getABCName()], _kind);
206 switch (_kind)
208 case KIND_SLOT:
209 case KIND_CONST:
211 _slotID = in->read_V32();
212 _typeIndex = in->read_V32();
213 boost::uint32_t vindex = in->read_V32();
214 log_abc("Slot ID=%u Type=%s Pool index=%u", _slotID,
215 block->_stringPool[
216 block->_multinamePool[_typeIndex].getABCName()], vindex);
218 if (vindex) {
219 const AbcBlock::PoolConstant c =
220 static_cast<AbcBlock::PoolConstant>(in->read_u8());
222 if (!block->pool_value(vindex, c, _value))
223 return false; // Message done by pool_value
224 _hasValue = true;
226 else _hasValue = false;
227 break;
229 case KIND_METHOD:
230 case KIND_GETTER:
231 case KIND_SETTER:
233 // Ignore the 'disp_id'
234 in->skip_V32();
236 boost::uint32_t offset = in->read_V32();
237 log_abc("Method index=%u", offset);
238 if (offset >= block->_methods.size()) {
239 log_error(_("Bad method id in trait."));
240 return false;
242 _method = block->_methods[offset];
243 break;
245 case KIND_CLASS:
247 _slotID = in->read_V32();
248 _classInfoIndex = in->read_V32();
249 log_abc("Slot id: %u Class index: %u Class Name: %s", _slotID,
250 _classInfoIndex,
251 block->_stringTable->value(
252 block->_classes[_classInfoIndex]->getName()));
254 if (_classInfoIndex >= block->_classes.size()) {
255 log_error(_("Bad Class id in trait."));
256 return false;
258 break;
260 case KIND_FUNCTION:
262 _slotID = in->read_V32();
263 boost::uint32_t offset = in->read_V32();
264 if (offset >= block->_methods.size()) {
265 log_error(_("Bad method id in trait."));
266 return false;
268 _method = block->_methods[offset];
269 break;
271 default:
273 log_error(_("ABC: Unknown type of trait."));
277 // Ignore the metadata, but it must be read to know how to ignore it.
278 if ((kind >> 4) & 0x04) {
279 boost::uint32_t mcount = in->read_V32();
280 for (size_t i = 0; i < mcount; ++i) {
281 in->skip_V32();
284 return true;
287 std::ostream&
288 operator<<(std::ostream& o, const Trait::Kind k)
290 switch (k) {
291 case abc::Trait::KIND_SLOT:
292 return o << "slot";
293 case abc::Trait::KIND_CONST:
294 return o << "const";
295 case abc::Trait::KIND_METHOD:
296 return o << "method";
297 case abc::Trait::KIND_GETTER:
298 return o << "getter";
299 case abc::Trait::KIND_SETTER:
300 return o << "setter";
301 case abc::Trait::KIND_CLASS:
302 return o << "class";
303 case abc::Trait::KIND_FUNCTION:
304 return o << "function";
305 default:
306 return o << "Unknown kind " << static_cast<int>(k);
310 AbcBlock::AbcBlock()
312 _stringTable(&VM::get().getStringTable())
314 mCH = &VM::get().getMachine()->global()->classHierarchy();
315 // TODO: Make this the real 'Object' prototype.
316 mCH->getGlobalNs()->stubPrototype(*mCH, NSV::CLASS_OBJECT);
317 mTheObject = mCH->getGlobalNs()->getScript(NSV::CLASS_OBJECT);
320 void
321 AbcBlock::prepare(Machine* mach)
324 std::for_each(_classes.begin(), _classes.end(),
325 std::mem_fun(&abc::Class::initPrototype));
326 // The last (entry) script has Global as its prototype.
327 // This can be deduced because the global classes are initialized with a
328 // slot on script 0 (entry script). OpNewClass then attempts to set the
329 // corresponding slot once the class has been constructed. At this point,
330 // global should verifiably be on the stack, so the slots are expected
331 // to be set on the global object.
332 // It seems likely, though testing it is not straightforward, that all
333 // scripts have Global as a target object (prototype), so for now we
334 // will do that.
335 std::for_each(_scripts.begin(), _scripts.end(),
336 boost::bind(&abc::Class::setPrototype, _1, mach->global()));
338 std::for_each(_methods.begin(), _methods.end(),
339 boost::bind(&Method::initPrototype, _1, mach));
341 // TODO: Remove this, initialize traits only when needed; possibly
342 // consruct them on parsing without the need for a finalize method.
343 std::for_each(_methods.begin(), _methods.end(),
344 boost::bind(&abc::Method::initTraits, _1, *this));
345 std::for_each(_classes.begin(), _classes.end(),
346 boost::bind(&abc::Class::initTraits, _1, *this));
347 std::for_each(_scripts.begin(), _scripts.end(),
348 boost::bind(&abc::Class::initTraits, _1, *this));
352 void
353 AbcBlock::check_multiname_name(boost::uint32_t name)
356 if (name >= _stringPool.size()) {
357 throw ParserException("ABC: Out of bounds string for Multiname.");
361 void
362 AbcBlock::check_multiname_namespace(boost::uint32_t ns)
364 if (ns >= _namespacePool.size()) {
365 throw ParserException("ABC: Out of bounds namespace for Multiname.");
369 void
370 AbcBlock::check_multiname_namespaceset(boost::uint32_t nsset)
372 if (!nsset)
374 throw ParserException("ABC: 0 selection for namespace set is invalid.");
376 if (nsset >= _namespaceSetPool.size())
378 throw ParserException("ABC: Out of bounds namespace set for Multiname.");
382 void
383 AbcBlock::setMultinameNames(MultiName *n, abc::URI ABCName)
386 n->setABCName(ABCName);
387 std::string name = _stringPool[ABCName];
388 string_table::key global_key = _stringTable->find(name, true);
389 log_abc("Global key %u", global_key);
390 n->setGlobalName(global_key);
391 log_abc("Multiname: %s ABCName set to %u, global name set to %u",
392 name, n->getABCName(), n->getGlobalName());
395 void
396 AbcBlock::setNamespaceURI(Namespace *ns, abc::URI ABCName)
398 std::string name = _stringPool[ABCName];
399 string_table::key global_key = _stringTable->find(name);
400 ns->setURI(global_key);
401 log_abc("Namespace: %s AbcURI=%u URI=%u.", name, ABCName, global_key);
404 abc::Class*
405 AbcBlock::locateClass(const std::string& className)
408 const std::string::size_type pos = className.rfind(".");
410 MultiName a;
412 const std::string& nsstr = (pos != std::string::npos) ?
413 className.substr(0, pos) : "";
415 const std::string& clstr = (pos != std::string::npos) ?
416 className.substr(pos + 1) : className;
418 a.setGlobalName(_stringTable->find(clstr));
420 for (std::vector<Namespace*>::iterator i = _namespacePool.begin();
421 i != _namespacePool.end(); ++i) {
423 const size_t key = (*i)->getURI();
425 if (key == _stringTable->find(nsstr)) {
426 a.setNamespace(*i);
427 break;
431 return locateClass(a);
435 abc::Class*
436 AbcBlock::locateClass(MultiName& m)
438 abc::Class* found = 0;
440 if (m.getNamespace())
442 found = m.getNamespace()->getScript(m.getGlobalName());
443 if (found) return found;
445 if (m.namespaceSet() && !m.namespaceSet()->empty())
447 std::vector<Namespace*>::const_iterator i;
448 for (i = m.namespaceSet()->begin(); i != m.namespaceSet()->end(); ++i) {
450 found = (*i)->getScript(m.getGlobalName());
451 if (found) return found;
455 log_abc("Could not locate class in ABC block resources!");
457 return 0;
461 /// Read the ActionBlock version number.
462 bool
463 AbcBlock::read_version()
465 // Minor version, major version.
466 mVersion = (_stream->read_u16()) | (_stream->read_u16() << 16);
467 log_debug(_("Abc Version: %d.%d"), (mVersion & 0xFFFF0000) >> 16,
468 (mVersion & 0x0000FFFF));
469 return true;
472 /// Read the pool of integer constants.
473 bool
474 AbcBlock::read_integer_constants()
476 // count overestimates by 1.
477 boost::uint32_t count = _stream->read_V32();
478 _integerPool.resize(count);
479 if (count)
480 _integerPool[0] = 0;
481 for (unsigned int i = 1; i < count; ++i)
483 _integerPool[i] = static_cast<boost::int32_t> (_stream->read_V32());
485 return true;
488 /// Read the pool of unsigned integer constants.
489 bool
490 AbcBlock::read_unsigned_integer_constants()
492 // count overestimates by 1.
493 boost::uint32_t count = _stream->read_V32();
494 _uIntegerPool.resize(count);
495 if (count)
496 _uIntegerPool[0] = 0;
497 for (unsigned int i = 1; i < count; ++i)
499 _uIntegerPool[i] = _stream->read_V32();
501 return true;
504 /// Read the pool of 64-bit double constants.
505 bool
506 AbcBlock::read_double_constants()
508 boost::uint32_t count = _stream->read_V32();
509 _doublePool.resize(count);
510 if (count) _doublePool[0] = 0.0;
512 for (size_t i = 1; i < count; ++i)
514 _doublePool[i] = _stream->read_d64();
515 log_abc("Double %u=%lf", i, _doublePool[i]);
517 return true;
520 /// Read the pool of string constants.
521 bool
522 AbcBlock::read_string_constants()
524 log_abc("Begin reading string constants.");
525 boost::uint32_t count = _stream->read_V32();
526 log_abc("There are %u string constants.", count);
527 _stringPool.resize(count);
529 if (count) {
530 _stringPool[0] = "";
533 for (size_t i = 1; i < count; ++i) {
534 boost::uint32_t length = _stream->read_V32();
535 _stream->read_string_with_length(length, _stringPool[i]);
536 log_abc("Adding string constant to string pool: index=%u %s",
537 i, _stringPool[i]);
539 return true;
542 /// Read the pool of namespaces
543 /// Any two namespaces with the same uri here are the same namespace,
544 /// excepting private namespaces.
545 bool
546 AbcBlock::read_namespaces()
548 log_abc("Begin reading namespaces.");
549 boost::uint32_t count = _stream->read_V32();
550 log_abc("There are %u namespaces.", count);
551 _namespacePool.resize(count);
552 if (count) {
553 _namespacePool[0] = mCH->getGlobalNs();
556 for (size_t i = 1; i < count; ++i)
558 NamespaceConstant kind =
559 static_cast<NamespaceConstant>(_stream->read_u8());
561 boost::uint32_t nameIndex = _stream->read_V32();
562 log_abc("Namespace %u: %s, index %u, name %s", i, kind,
563 nameIndex, _stringPool[nameIndex]);
565 if (nameIndex >= _stringPool.size()) {
566 log_error(_("ABC: Bad string given for namespace."));
567 return false;
570 if (kind == PRIVATE_NS)
572 _namespacePool[i] = mCH->anonNamespace(nameIndex);
573 _namespacePool[i]->setPrivate();
575 else
577 string_table::key gn = _stringTable->find(_stringPool[nameIndex]);
578 Namespace *n = mCH->findNamespace(gn);
579 if (!n) n = mCH->addNamespace(gn);
580 _namespacePool[i] = n;
582 if (kind == PROTECTED_NS) _namespacePool[i]->setProtected();
583 if (kind == PACKAGE_NS) _namespacePool[i]->setPackage();
584 setNamespaceURI(_namespacePool[i], nameIndex);
586 return true;
589 /// Read the set of sets of namespaces.
590 bool
591 AbcBlock::read_namespace_sets()
593 boost::uint32_t count = _stream->read_V32();
594 _namespaceSetPool.resize(count);
595 if (count)
597 _namespaceSetPool[0].resize(0);
599 for (unsigned int i = 1; i < count; ++i)
601 boost::uint32_t icount = _stream->read_V32();
602 _namespaceSetPool[i].resize(icount);
603 for (unsigned int j = 0; j < icount; ++j)
605 boost::uint32_t selection = _stream->read_V32();
606 if (!selection || selection >= _namespacePool.size())
608 log_error(_("ABC: Bad namespace for namespace set."));
609 return false;
611 _namespaceSetPool[i][j] = _namespacePool[selection];
614 return true;
617 /// Read the multinames.
618 bool
619 AbcBlock::read_multinames()
621 boost::uint32_t count = _stream->read_V32();
622 log_abc("There are %u multinames.", count);
623 _multinamePool.resize(count);
624 if (count)
626 // _multinamePool[0].setABCName(0);
627 setMultinameNames(&_multinamePool[0], 0);
628 _multinamePool[0].setNamespace(mCH->getGlobalNs());
630 for (unsigned int i = 1; i < count; ++i)
632 MultiName::Kind kind = static_cast<MultiName::Kind>(_stream->read_u8());
633 boost::uint32_t ns = 0;
634 boost::uint32_t name = 0;
635 boost::uint32_t nsset = 0;
637 log_abc("Multiname %u has kind %s", i, static_cast<int>(kind));
639 // Read, but don't upper validate until after the switch.
640 switch (kind)
642 case MultiName::KIND_Qname:
643 case MultiName::KIND_QnameA:
644 ns = _stream->read_V32();
645 check_multiname_namespace(ns);
646 name = _stream->read_V32();
647 check_multiname_name(name);
648 log_abc("\tnamespace_index=%u name_index=%u name=%s",
649 ns, name, _stringPool[name]);
650 break;
652 case MultiName::KIND_RTQname:
653 case MultiName::KIND_RTQnameA:
654 name = _stream->read_V32();
655 check_multiname_name(name);
656 break;
658 case MultiName::KIND_RTQnameL:
659 case MultiName::KIND_RTQnameLA:
660 break;
662 case MultiName::KIND_Multiname:
663 case MultiName::KIND_MultinameA:
664 name = _stream->read_V32();
665 check_multiname_name(name);
666 nsset = _stream->read_V32();
667 check_multiname_namespaceset(nsset);
668 break;
670 case MultiName::KIND_MultinameL:
671 case MultiName::KIND_MultinameLA:
672 nsset = _stream->read_V32();
673 check_multiname_namespaceset(nsset);
674 break;
676 default:
677 // Unknown type.
678 log_error(_("Action Block: Unknown multiname type (%d)."),
679 kind);
680 return false;
683 _multinamePool[i].setFlags(kind);
684 setMultinameNames(&_multinamePool[i], name);
685 log_abc("Done setting multinames: abc=%u global=%u",
686 _multinamePool[i].getABCName(),
687 _multinamePool[i].getGlobalName());
689 _multinamePool[i].setNamespace(_namespacePool[ns]);
691 if (nsset) {
692 _multinamePool[i].namespaceSet(&_namespaceSetPool[nsset]);
694 } // End of main loop.
695 return true;
698 bool
699 AbcBlock::pool_value(boost::uint32_t index, PoolConstant type, as_value &v)
701 if (!index)
702 return true;
704 log_abc("Pool value: index is %u type is 0x%X", index, type | 0x0);
705 switch (type)
707 case POOL_STRING:
709 if (index >= _stringPool.size())
711 log_error(_("Action Block: Bad index in optional argument."));
712 return false;
714 v.set_string(_stringPool[index]);
715 break;
717 case POOL_INTEGER:
719 if (index >= _integerPool.size())
721 log_error(_("Action Block: Bad index in optional argument."));
722 return false;
724 v.set_double(_integerPool[index]);
725 break;
727 case POOL_UINTEGER:
729 if (index >= _uIntegerPool.size())
731 log_error(_("Action Block: Bad index in optional argument."));
732 return false;
734 v.set_double(_uIntegerPool[index]);
735 break;
737 case POOL_DOUBLE:
739 if (index >= _doublePool.size())
741 log_error(_("Action Block: Bad index in optional argument."));
742 return false;
744 v.set_double(static_cast<double>(_doublePool[index]));
745 break;
747 case POOL_NAMESPACE: // Namespace
749 if (index >= _namespacePool.size())
751 log_error(_("ABC: Bad index in optional argument, namespaces."));
752 return false;
754 break;
756 case POOL_FALSE: // False value
758 v.set_bool(false);
759 break;
761 case POOL_TRUE: // True value
763 v.set_bool(true);
764 break;
766 case POOL_NULL: // NULL value
768 v.set_null();
769 break;
771 default: // All others are bogus.
773 log_error(_("ABC: Bad default value type (%X), but continuing."), type);
774 return true;
775 break;
777 } // end of switch
778 return true;
781 /// Read the method infos.
782 bool
783 AbcBlock::read_method_infos()
785 log_abc("Begin read_method_infos.");
787 boost::uint32_t count = _stream->read_V32();
788 log_abc("Method count: %u", count);
790 _methods.resize(count);
791 for (unsigned int i = 0; i < count; ++i)
793 log_abc(" Reading method %u", i);
794 Method *pMethod = mCH->newMethod();
795 pMethod->setMethodID(i);
796 _methods[i] = pMethod;
797 boost::uint32_t param_count = _stream->read_V32();
798 boost::uint32_t return_type = _stream->read_V32();
800 const std::string& rt = return_type ?
801 _stringPool[_multinamePool[return_type].getABCName()] :
802 "*";
804 log_abc(" Param count: %u, return type: %s", param_count,
805 rt, return_type);
807 pMethod->setMinArgumentCount(param_count);
808 pMethod->setMaxArgumentCount(param_count);
810 if (return_type >= _multinamePool.size()) {
811 log_error(_("ABC: Bad return type for method info."));
812 return false;
815 if (!return_type) {
816 pMethod->setReturnType(0);
818 else {
819 // TODO: this can be 'void', which clearly isn't a class, so this
820 // seems bogus. As setReturnType is a no-op, we should log it
821 // and ignore it.
822 abc::Class* rtScript = locateClass(_multinamePool[return_type]);
823 if (!rtScript) {
824 log_abc(_("ABC: Unknown return type."));
827 pMethod->setReturnType(rtScript);
829 for (size_t j = 0; j < param_count; ++j) {
830 log_abc(" Reading parameter %u", j);
831 // The parameter type.
832 boost::uint32_t ptype = _stream->read_V32();
834 const std::string& pt = return_type ?
835 _stringPool[_multinamePool[ptype].getABCName()] :
836 "*";
838 log_abc(" Parameter type(index): %s(%u)", pt, ptype);
840 if (ptype >= _multinamePool.size()) {
841 log_error(_("ABC: Bad parameter type in method."));
842 return false;
845 // A value of 0 is legitimate, meaning 'any (*)'.
846 if (ptype) {
847 abc::Class* param_type = locateClass(_multinamePool[ptype]);
849 if (!param_type) {
850 log_abc((_("ABC: Unknown parameter type.")));
853 // This currently also pushes 0, meaning 'any'; perhaps it
854 // should throw a VerifyError if the class is not known.
855 pMethod->pushArgument(param_type);
857 else {
858 pMethod->pushArgument(0);
862 boost::uint32_t method_name = _stream->read_V32();
863 log_abc( "Method name=%s %d", _stringPool[method_name], method_name);
864 boost::uint8_t flags = _stream->read_u8();
865 log_abc(" Flags: %X", flags | 0x0);
866 // log_abc("Check if flags and optional args.");
867 // If there are default parameters, read them now.
868 // Runtime will do validation of whether or not these can actually
869 // be assigned to the corresponding parameters.
870 if (flags & METHOD_OPTIONAL_ARGS) {
872 boost::uint32_t ocount = _stream->read_V32();
873 log_abc(" Optional args: %u", ocount);
874 pMethod->setMinArgumentCount(pMethod->maxArgumentCount() - ocount);
876 for (unsigned int j = 0; j < ocount; ++j) {
877 log_abc(" Reading optional arg: %u", j);
878 boost::uint32_t index = _stream->read_V32();
880 PoolConstant kindof =
881 static_cast<PoolConstant>(_stream->read_u8());
883 log_abc(" Index: %u Kindof: %u", index, kindof);
884 as_value v;
885 if (!pool_value(index, kindof, v)) {
886 return false;
888 pMethod->pushOptional(v);
890 log_abc("Done handling optional args.");
893 if (flags & METHOD_ACTIVATION) {
894 log_abc("Method needs activation");
895 pMethod->setNeedsActivation();
898 // If there are names present for the parameters, skip them.
899 if (flags & METHOD_ARG_NAMES) {
900 for (size_t j = 0; j < param_count; ++j) {
901 _stream->skip_V32();
904 } // End of method loop.
905 return true;
908 /// Skip the metadata, which is useless to us.
909 bool
910 AbcBlock::skip_metadata()
912 boost::uint32_t count = _stream->read_V32();
913 for (unsigned int i = 0; i < count; ++i)
915 _stream->skip_V32(); // A name index.
916 boost::uint32_t icount = _stream->read_V32();
917 for (unsigned int j = 0; j < icount; ++j)
919 // key/values may not be stored together, but this still works.
920 _stream->skip_V32();
921 _stream->skip_V32();
924 return true;
927 /// Load the instances from the block.
928 bool
929 AbcBlock::read_instances()
931 boost::uint32_t count = _stream->read_V32();
932 log_abc("There are %u instances.", count);
933 _classes.resize(count);
934 for (size_t i = 0; i < count; ++i) {
935 //Read multiname index.
936 boost::uint32_t index = _stream->read_V32();
937 // 0 is allowed as a name, typically for the last entry.
938 if (index >= _multinamePool.size()) {
939 log_error(_("ABC: Out of bounds instance name."));
940 return false;
943 MultiName& multiname = _multinamePool[index];
945 // This must be a QName.
946 if (!multiname.isQName()) {
947 log_error(_("ABC: QName required for instance."));
948 return false;
951 if (!multiname.getNamespace()) {
952 log_error(_("ABC: No namespace to use for storing class."));
953 return false;
956 abc::Class* cl = locateClass(multiname);
958 if (!cl) {
960 const string_table::key className = multiname.getGlobalName();
962 cl = mCH->newClass();
963 cl->setName(className);
965 if (!multiname.getNamespace()->addScript(className, cl)) {
967 log_error(_("Duplicate class registration."));
968 return false;
970 log_debug("Adding class %s (%s) to namespace %s",
971 _stringTable->value(multiname.getGlobalName()),
972 _stringPool[multiname.getABCName()],
973 _stringTable->value(multiname.getNamespace()->getURI()));
974 log_debug("Namespace now:");
975 multiname.getNamespace()->dump(*_stringTable);
978 cl->setDeclared();
979 _classes[i] = cl;
980 boost::uint32_t super_index = _stream->read_V32();
982 if (super_index && super_index >= _multinamePool.size()) {
983 log_error(_("ABC: Bad super type."));
984 return false;
987 if (!super_index) {
988 cl->setSuper(mTheObject);
990 else {
991 abc::Class *pSuper = locateClass(_multinamePool[super_index]);
992 if (!pSuper)
994 log_error(_("ABC: Super type not found (%s)"),
995 _stringPool[_multinamePool[super_index].getABCName()]);
996 return false;
999 if (pSuper->isFinal())
1001 log_error(_("ABC: Can't extend a class which is final."));
1002 return false;
1005 if (pSuper->isInterface())
1007 log_error(_("ABC: Can't extend an interface type."));
1008 return false;
1011 if (pSuper == cl)
1013 log_error(_("ABC: Class cannot be its own supertype."));
1014 return false;
1016 cl->setSuper(pSuper);
1017 pSuper->setInherited();
1020 boost::uint8_t flags = _stream->read_u8();
1021 log_abc("Instance %u(%s) multiname index=%u name=%s super index=%u "
1022 "flags=%X", i, cl, index,
1023 _stringPool[_multinamePool[index].getABCName()],
1024 super_index, flags | 0x0);
1026 if (flags & INSTANCE_SEALED) cl->setSealed();
1027 if (flags & INSTANCE_FINAL) cl->setFinal();
1028 if (flags & INSTANCE_INTERFACE) cl->setInterface();
1029 if ((flags & 7) == INSTANCE_DYNAMIC) cl->setDynamic();
1031 if (flags & INSTANCE_PROTECTED_NS) {
1032 boost::uint32_t ns_index = _stream->read_V32();
1033 if (ns_index >= _namespacePool.size()) {
1034 log_error(_("ABC: Bad namespace for protected."));
1035 return false;
1037 // Set the protected namespace's parent, if it exists.
1038 if (cl->getSuper()->hasProtectedNs())
1039 _namespacePool[ns_index]->setParent(
1040 cl->getSuper()->getProtectedNs());
1041 cl->setProtectedNs(_namespacePool[ns_index]);
1044 // This is the list of interfaces which the instances has agreed to
1045 // implement. They must be interfaces, and they must exist.
1046 boost::uint32_t intcount = _stream->read_V32();
1047 log_abc("This instance has %u interfaces.", intcount);
1048 for (size_t j = 0; j < intcount; ++j) {
1049 boost::uint32_t i_index = _stream->read_V32();
1050 log_abc("Interface %u has multiname index=%u", i, i_index);
1051 // 0 is allowed as an interface, typically for the last one.
1052 if (i_index >= _multinamePool.size()) {
1053 log_error(_("ABC: Bad name for interface."));
1054 return false;
1056 abc::Class *pInterface = locateClass(_multinamePool[i_index]);
1057 // These may be undefined still, so don't check interface just yet.
1058 if (0) //!pInterface || !pInterface->isInterface())
1060 log_error(_("ABC: Can't implement a non-interface type."));
1061 return false;
1063 cl->pushInterface(pInterface);
1066 // The next thing should be the constructor.
1067 // TODO: What does this mean exactly? How does it differ from the one in
1068 // the class info block?
1069 boost::uint32_t offset = _stream->read_V32();
1070 log_abc("Moffset: %u", offset);
1071 if (offset >= _methods.size()) {
1072 log_error(_("ABC: Out of bounds method for initializer."));
1073 return false;
1075 // Don't validate for previous owner.
1076 cl->setConstructor(_methods[offset]);
1078 // Next come the 'traits' of the instance. (The members.)
1079 boost::uint32_t tcount = _stream->read_V32();
1080 log_abc("Trait count: %u", tcount);
1081 for (unsigned int j = 0; j < tcount; ++j)
1083 Trait t;
1084 t.set_target(cl, false);
1085 if (!t.read(_stream, this)) return false;
1086 cl->addInstanceTrait(t);
1089 return true;
1092 /// Read the class data
1093 bool
1094 AbcBlock::read_classes()
1096 // Count was found in read_instances().
1097 log_abc("Begin reading classes.");
1098 boost::uint32_t count = _classes.size();
1099 log_abc("There are %u classes.", count);
1101 for (size_t i = 0; i < count; ++i) {
1102 abc::Class* cl = _classes[i];
1103 boost::uint32_t offset = _stream->read_V32();
1104 log_abc("Class %u(%s) static constructor index=%u", i, cl, offset);
1106 if (offset >= _methods.size()) {
1107 log_error(_("ABC: Out of bound static constructor for class."));
1108 return false;
1111 // Don't validate for previous owner.
1112 cl->setStaticConstructor(_methods[offset]);
1114 boost::uint32_t tcount = _stream->read_V32();
1115 log_abc("This class has %u traits.", tcount);
1116 for (size_t j = 0; j < tcount; ++j) {
1117 Trait t;
1118 t.set_target(cl, true);
1119 if (!(t.read(_stream, this))) return false;
1120 cl->addStaticTrait(t);
1123 return true;
1126 /// Read the scripts (global functions)
1127 /// The final script is the entry point for the block.
1128 bool
1129 AbcBlock::read_scripts()
1131 log_abc("Begin reading scripts.");
1133 const boost::uint32_t scriptcount = _stream->read_V32();
1134 log_abc("There are %u scripts.", scriptcount);
1136 _scripts.resize(scriptcount);
1137 for (size_t i = 0; i < scriptcount; ++i) {
1139 abc::Class* script = mCH->newClass();
1140 _scripts[i] = script;
1142 boost::uint32_t offset = _stream->read_V32();
1143 log_abc("Reading script %u(%s) initializer method index=%u", i,
1144 script, offset);
1145 if (offset >= _methods.size()) {
1146 log_error(_("ABC: Out of bounds method for script."));
1147 return false;
1150 script->setConstructor(_methods[offset]);
1152 const boost::uint32_t tcount = _stream->read_V32();
1153 for (size_t j = 0; j < tcount; ++j) {
1155 Trait t;
1156 t.set_target(script, false);
1157 if (!(t.read(_stream, this))) {
1158 return false;
1160 log_abc("Trait: %u name: %s(%u) kind: %s value: %s ", j,
1161 _stringPool[t._name], t._name, t._kind, t._value);
1163 // TODO: this should not use Class!
1164 script->addStaticTrait(t);
1167 return true;
1170 /// Read the method bodies and attach them to the methods.
1171 bool
1172 AbcBlock::read_method_bodies()
1174 boost::uint32_t count = _stream->read_V32();
1175 log_abc("There are %u method bodies.", count);
1176 for (unsigned int i = 0; i < count; ++i)
1178 boost::uint32_t offset = _stream->read_V32();
1179 log_abc("Method body %u method offset=%u", i, offset);
1181 if (offset >= _methods.size()) {
1182 log_error(_("ABC: Out of bounds for method body."));
1183 return false;
1186 Method& method = *_methods[offset];
1188 if (method.getBody()) {
1189 log_error(_("ABC: Only one body per method."));
1190 return false;
1193 // Maximum stack size.
1194 method.setMaxStack(_stream->read_V32());
1196 // Maximum register size.
1197 method.setMaxRegisters(_stream->read_V32());
1199 // Scope depth.
1200 method.setScopeDepth(_stream->read_V32());
1202 // Max scope depth.
1203 method.setMaxScope(_stream->read_V32());
1205 // Code length
1206 boost::uint32_t clength = _stream->read_V32();
1207 method.setBodyLength(clength);
1209 // The code.
1210 //TODO: Clean this up.
1211 std::string body;
1212 _stream->read_string_with_length(clength, body);
1214 method.setBody(new CodeStream(body));
1216 // Exception count and exceptions
1218 // Note: catch type and variable name are documented to be
1219 // indices in the string pool, but they are in fact indices
1220 // in the multiname pool.
1221 const boost::uint32_t ecount = _stream->read_V32();
1222 for (unsigned int j = 0; j < ecount; ++j) {
1223 asException *ex = mCH->newException();
1225 // Where the try block begins and ends.
1226 ex->setStart(_stream->read_V32());
1227 ex->setEnd(_stream->read_V32());
1229 // Where to go when the exception is activated.
1230 ex->setCatch(_stream->read_V32());
1232 // What types should be caught.
1233 boost::uint32_t catch_type = _stream->read_V32();
1234 if (catch_type >= _multinamePool.size()) {
1235 log_error(_("ABC: Out of bound type for exception."));
1236 return false;
1238 if (!catch_type) {
1239 ex->catchAny();
1241 else {
1242 abc::Class *type = locateClass(_multinamePool[catch_type]);
1243 if (!type) {
1245 log_error(_("ABC: Unknown type of object to catch. (%s)"),
1246 _stringTable->value(
1247 _multinamePool[catch_type].getABCName()));
1249 // return false;
1250 // Fake it, for now:
1251 ex->catchAny();
1253 else {
1254 ex->setCatchType(type);
1258 // A variable name for the catch type.
1259 // In version 46.15, no names.
1260 if (mVersion != ((46 << 16) | 15)) {
1261 boost::uint32_t cvn = _stream->read_V32();
1262 if (cvn >= _multinamePool.size()) {
1263 log_error(_("ABC: Out of bound name for caught "
1264 "exception."));
1265 return false;
1267 ex->setName(_multinamePool[cvn].getABCName());
1268 ex->setNamespace(_multinamePool[cvn].getNamespace());
1272 // Traits
1273 boost::uint32_t tcount = _stream->read_V32();
1274 for (unsigned int j = 0; j < tcount; ++j)
1276 Trait t;
1277 t.set_target(_methods[offset]);
1279 if (!t.read(_stream, this)) {
1280 return false;
1283 log_abc("Activation trait: %u name: %s, kind: %s, value: %s ", j,
1284 _stringPool[t._name], t._kind, t._value);
1285 _methods[offset]->addTrait(t);
1288 return true;
1291 // Load up all of the data.
1292 bool
1293 AbcBlock::read(SWFStream& in)
1295 // This isn't very nice:
1296 _stream = &in;
1298 if (!read_version()) return false;
1299 if (!read_integer_constants()) return false;
1300 if (!read_unsigned_integer_constants()) return false;
1301 log_abc("Done reading unsigned integer constants.");
1303 if (!read_double_constants()) return false;
1304 log_abc("Done reading double constants.");
1306 if (!read_string_constants()) return false;
1307 log_abc("Done reading string constants.");
1309 if (!read_namespaces()) return false;
1310 log_abc("Done reading namespaces.");
1312 if (!read_namespace_sets()) return false;
1313 log_abc("Done reading namespace sets.");
1315 if (!read_multinames()) return false;
1316 log_abc("Done reading multinames.");
1318 if (!read_method_infos()) return false;
1319 log_abc("Done reading method infos.");
1321 if (!skip_metadata()) return false;
1322 log_abc("Done reading metadata.");
1324 if (!read_instances()) return false;
1325 log_abc("Done reading instances.");
1327 if (!read_classes()) return false;
1328 log_abc("Done reading classes.");
1330 if (!read_scripts()) return false;
1331 log_abc("Done reading scripts.");
1333 if (!read_method_bodies()) return false;
1334 log_abc("Done reading stuff.");
1336 for (size_t i=0; i < _methods.size(); ++i) {
1337 log_abc("Method %d body:", i);
1338 IF_VERBOSE_PARSE(_methods[i]->print_body());
1340 return true;
1344 void
1345 AbcBlock::update_global_name(unsigned int multiname_index)
1348 MultiName* multiname = &_multinamePool[multiname_index];
1349 string_table::key new_key =
1350 _stringTable->find(_stringPool[multiname->getABCName()], false);
1351 multiname->setGlobalName(new_key);
1354 std::ostream&
1355 operator<<(std::ostream& o, AbcBlock::NamespaceConstant c)
1357 switch (c)
1359 case AbcBlock::PRIVATE_NS:
1360 return o << "private namespace";
1361 case AbcBlock::CONSTANT_NS:
1362 return o << "constant namespace";
1363 case AbcBlock::PACKAGE_NS:
1364 return o << "package namespace";
1365 case AbcBlock::PACKAGE_INTERNAL_NS:
1366 return o << "package internal namespace";
1367 case AbcBlock::PROTECTED_NS:
1368 return o << "protected namespace";
1369 case AbcBlock::EXPLICIT_NS:
1370 return o << "explicit namespace";
1371 case AbcBlock::STATIC_PROTECTED_NS:
1372 return o << "static protected namespace";
1373 default:
1374 return o << "invalid namespace constant";
1378 std::ostream&
1379 operator<<(std::ostream& o, AbcBlock::MethodConstant c)
1381 switch (c)
1383 case AbcBlock::METHOD_ARGS:
1384 return o << "method arg";
1385 case AbcBlock::METHOD_ACTIVATION:
1386 return o << "method activation";
1387 case AbcBlock::METHOD_MORE:
1388 return o << "method more";
1389 case AbcBlock::METHOD_OPTIONAL_ARGS:
1390 return o << "method optional args";
1391 case AbcBlock::METHOD_IGNORE:
1392 return o << "method ignore";
1393 case AbcBlock::METHOD_NATIVE:
1394 return o << "method native";
1395 case AbcBlock::METHOD_DEFAULT_NS:
1396 return o << "default namespace";
1397 case AbcBlock::METHOD_ARG_NAMES:
1398 return o << "method arg names";
1399 default:
1400 return o << "invalid method constant";
1404 std::ostream&
1405 operator<<(std::ostream& o, AbcBlock::InstanceConstant c)
1407 switch (c)
1409 case AbcBlock::INSTANCE_SEALED:
1410 return o << "instance sealed";
1411 case AbcBlock::INSTANCE_FINAL:
1412 return o << "instance final";
1413 case AbcBlock::INSTANCE_INTERFACE:
1414 return o << "instance interface";
1415 case AbcBlock::INSTANCE_DYNAMIC:
1416 return o << "instance dynamic";
1417 case AbcBlock::INSTANCE_PROTECTED_NS:
1418 return o << "instance protected namespace";
1419 default:
1420 return o << "invalid instance constant";
1424 std::ostream&
1425 operator<<(std::ostream& o, AbcBlock::PoolConstant c)
1427 switch (c)
1429 case AbcBlock::POOL_STRING:
1430 return o << "pool string";
1431 case AbcBlock::POOL_INTEGER:
1432 return o << "pool integer";
1433 case AbcBlock::POOL_UINTEGER:
1434 return o << "pool uinteger";
1435 case AbcBlock::POOL_DOUBLE:
1436 return o << "pool double";
1437 case AbcBlock::POOL_NAMESPACE:
1438 return o << "pool namespace";
1439 case AbcBlock::POOL_FALSE:
1440 return o << "pool false";
1441 case AbcBlock::POOL_TRUE:
1442 return o << "pool true";
1443 case AbcBlock::POOL_NULL:
1444 return o << "pool null";
1445 default:
1446 return o << "invalid pool constant";
1451 } // namespace abc
1452 } // namespace gnash