xref: /haiku/src/kits/support/Archivable.cpp (revision 7037b5d9bc71a4f2eeab7d73cb00d124da6fe3b5)
1 /*
2  * Copyright 2001-2012 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Rene Gollent (rene@gollent.com)
7  *		Erik Jaesler (erik@cgsoftware.com)
8  *		Alex Wilson (yourpalal2@gmail.com)
9  */
10 
11 /*!	BArchivable mix-in class defines the archiving protocol.
12 	Also some global archiving functions.
13 */
14 
15 
16 #include <ctype.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string>
21 #include <syslog.h>
22 #include <typeinfo>
23 #include <vector>
24 
25 #include <AppFileInfo.h>
26 #include <Archivable.h>
27 #include <Entry.h>
28 #include <List.h>
29 #include <OS.h>
30 #include <Path.h>
31 #include <Roster.h>
32 #include <String.h>
33 
34 #include <binary_compatibility/Support.h>
35 
36 #include "ArchivingManagers.h"
37 
38 
39 using std::string;
40 using std::vector;
41 
42 using namespace BPrivate::Archiving;
43 
44 const char* B_CLASS_FIELD = "class";
45 const char* B_ADD_ON_FIELD = "add_on";
46 const int32 FUNC_NAME_LEN = 1024;
47 
48 // TODO: consider moving these to a separate module, and making them more
49 //	full-featured (e.g., taking NS::ClassName::Function(Param p) instead
50 //	of just NS::ClassName)
51 
52 
53 static status_t
demangle_class_name(const char * name,BString & out)54 demangle_class_name(const char* name, BString& out)
55 {
56 // TODO: add support for template classes
57 //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
58 
59 	out = "";
60 
61 #if __GNUC__ >= 4
62 	if (name[0] == 'N')
63 		name++;
64 	int nameLen;
65 	bool first = true;
66 	while ((nameLen = strtoul(name, (char**)&name, 10))) {
67 		if (!first)
68 			out += "::";
69 		else
70 			first = false;
71 		out.Append(name, nameLen);
72 		name += nameLen;
73 	}
74 	if (first)
75 		return B_BAD_VALUE;
76 
77 #else
78 	if (name[0] == 'Q') {
79 		// The name is in a namespace
80 		int namespaceCount = 0;
81 		name++;
82 		if (name[0] == '_') {
83 			// more than 10 namespaces deep
84 			if (!isdigit(*++name))
85 				return B_BAD_VALUE;
86 
87 			namespaceCount = strtoul(name, (char**)&name, 10);
88 			if (name[0] != '_')
89 				return B_BAD_VALUE;
90 		} else
91 			namespaceCount = name[0] - '0';
92 
93 		name++;
94 
95 		for (int i = 0; i < namespaceCount - 1; i++) {
96 			if (!isdigit(name[0]))
97 				return B_BAD_VALUE;
98 
99 			int nameLength = strtoul(name, (char**)&name, 10);
100 			out.Append(name, nameLength);
101 			out += "::";
102 			name += nameLength;
103 		}
104 	}
105 
106 	int nameLength = strtoul(name, (char**)&name, 10);
107 	out.Append(name, nameLength);
108 #endif
109 
110 	return B_OK;
111 }
112 
113 
114 static void
mangle_class_name(const char * name,BString & out)115 mangle_class_name(const char* name, BString& out)
116 {
117 // TODO: add support for template classes
118 //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
119 
120 	//	Chop this:
121 	//		testthree::testfour::Testthree::Testfour
122 	//	up into little bite-sized pieces
123 	int count = 0;
124 	string origName(name);
125 	vector<string> spacenames;
126 
127 	string::size_type pos = 0;
128 	string::size_type oldpos = 0;
129 	while (pos != string::npos) {
130 		pos = origName.find_first_of("::", oldpos);
131 		spacenames.push_back(string(origName, oldpos, pos - oldpos));
132 		pos = origName.find_first_not_of("::", pos);
133 		oldpos = pos;
134 		++count;
135 	}
136 
137 	//	Now mangle it into this:
138 	//		9testthree8testfour9Testthree8Testfour
139 	//			(for __GNUC__ > 2)
140 	//			this isn't always the proper mangled class name, it should
141 	//			actually have an 'N' prefix and 'E' suffix if the name is
142 	//			in > 0 namespaces, but these would have to be removed in
143 	//			build_function_name() (the only place this function is called)
144 	//			so we don't add them.
145 	//	or this:
146 	//		Q49testthree8testfour9Testthree8Testfour
147 	//			(for __GNUC__ == 2)
148 
149 	out = "";
150 #if __GNUC__ == 2
151 	if (count > 1) {
152 		out += 'Q';
153 		if (count > 10)
154 			out += '_';
155 		out << count;
156 		if (count > 10)
157 			out += '_';
158 	}
159 #endif
160 
161 	for (unsigned int i = 0; i < spacenames.size(); ++i) {
162 		out << (int)spacenames[i].length();
163 		out += spacenames[i].c_str();
164 	}
165 }
166 
167 
168 static void
build_function_name(const BString & className,BString & funcName)169 build_function_name(const BString& className, BString& funcName)
170 {
171 	funcName = "";
172 
173 	//	This is what we're after:
174 	//		Instantiate__Q28OpenBeOS11BArchivableP8BMessage
175 	mangle_class_name(className.String(), funcName);
176 #if __GNUC__ >= 4
177 	funcName.Prepend("_ZN");
178 	funcName.Append("11InstantiateE");
179 #else
180 	funcName.Prepend("Instantiate__");
181 #endif
182 	funcName.Append("P8BMessage");
183 }
184 
185 
186 static bool
add_private_namespace(BString & name)187 add_private_namespace(BString& name)
188 {
189 	if (name.Compare("_", 1) != 0)
190 		return false;
191 
192 	name.Prepend("BPrivate::");
193 	return true;
194 }
195 
196 
197 static instantiation_func
find_function_in_image(BString & funcName,image_id id,status_t & err)198 find_function_in_image(BString& funcName, image_id id, status_t& err)
199 {
200 	instantiation_func instantiationFunc = NULL;
201 	err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT,
202 		(void**)&instantiationFunc);
203 	if (err != B_OK)
204 		return NULL;
205 
206 	return instantiationFunc;
207 }
208 
209 
210 static status_t
check_signature(const char * signature,image_info & info)211 check_signature(const char* signature, image_info& info)
212 {
213 	if (signature == NULL) {
214 		// If it wasn't specified, anything "matches"
215 		return B_OK;
216 	}
217 
218 	// Get image signature
219 	BFile file(info.name, B_READ_ONLY);
220 	status_t err = file.InitCheck();
221 	if (err != B_OK)
222 		return err;
223 
224 	char imageSignature[B_MIME_TYPE_LENGTH];
225 	BAppFileInfo appFileInfo(&file);
226 	err = appFileInfo.GetSignature(imageSignature);
227 	if (err != B_OK) {
228 		syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s",
229 			info.name);
230 		return err;
231 	}
232 
233 	if (strcmp(signature, imageSignature) != 0)
234 		return B_MISMATCHED_VALUES;
235 
236 	return B_OK;
237 }
238 
239 
240 namespace BPrivate {
241 
242 instantiation_func
find_instantiation_func(const char * className,const char * signature,image_id * id)243 find_instantiation_func(const char* className, const char* signature,
244 	image_id* id)
245 {
246 	if (className == NULL) {
247 		errno = B_BAD_VALUE;
248 		return NULL;
249 	}
250 
251 	thread_info threadInfo;
252 	status_t err = get_thread_info(find_thread(NULL), &threadInfo);
253 	if (err != B_OK) {
254 		errno = err;
255 		return NULL;
256 	}
257 
258 	instantiation_func instantiationFunc = NULL;
259 	image_info imageInfo;
260 
261 	BString name = className;
262 	for (int32 pass = 0; pass < 2; pass++) {
263 		BString funcName;
264 		build_function_name(name, funcName);
265 
266 		// for each image_id in team_id
267 		int32 cookie = 0;
268 		while (instantiationFunc == NULL
269 			&& get_next_image_info(threadInfo.team, &cookie, &imageInfo)
270 				== B_OK) {
271 			instantiationFunc = find_function_in_image(funcName, imageInfo.id,
272 				err);
273 		}
274 		if (instantiationFunc != NULL) {
275 			// if requested, save the image id in
276 			// which the function was found
277 			if (id != NULL)
278 				*id = imageInfo.id;
279 			break;
280 		}
281 
282 		// Check if we have a private class, and add the BPrivate namespace
283 		// (for backwards compatibility)
284 		if (!add_private_namespace(name))
285 			break;
286 	}
287 
288 	if (instantiationFunc != NULL
289 		&& check_signature(signature, imageInfo) != B_OK)
290 		return NULL;
291 
292 	return instantiationFunc;
293 }
294 
295 }	// namespace BPrivate
296 
297 
298 //	#pragma mark - BArchivable
299 
300 
BArchivable()301 BArchivable::BArchivable()
302 	:
303 	fArchivingToken(NULL_TOKEN)
304 {
305 }
306 
307 
BArchivable(BMessage * from)308 BArchivable::BArchivable(BMessage* from)
309 	:
310 	fArchivingToken(NULL_TOKEN)
311 {
312 	if (BUnarchiver::IsArchiveManaged(from)) {
313 		BUnarchiver::PrepareArchive(from);
314 		BUnarchiver(from).RegisterArchivable(this);
315 	}
316 }
317 
318 
~BArchivable()319 BArchivable::~BArchivable()
320 {
321 }
322 
323 
324 status_t
Archive(BMessage * into,bool deep) const325 BArchivable::Archive(BMessage* into, bool deep) const
326 {
327 	if (!into) {
328 		// TODO: logging/other error reporting?
329 		return B_BAD_VALUE;
330 	}
331 
332 	if (BManagerBase::ArchiveManager(into))
333 		BArchiver(into).RegisterArchivable(this);
334 
335 	BString name;
336 	status_t status = demangle_class_name(typeid(*this).name(), name);
337 	if (status != B_OK)
338 		return status;
339 
340 	return into->AddString(B_CLASS_FIELD, name);
341 }
342 
343 
344 BArchivable*
Instantiate(BMessage * from)345 BArchivable::Instantiate(BMessage* from)
346 {
347 	debugger("Can't create a plain BArchivable object");
348 	return NULL;
349 }
350 
351 
352 status_t
Perform(perform_code d,void * arg)353 BArchivable::Perform(perform_code d, void* arg)
354 {
355 	switch (d) {
356 		case PERFORM_CODE_ALL_UNARCHIVED:
357 		{
358 			perform_data_all_unarchived* data =
359 				(perform_data_all_unarchived*)arg;
360 
361 			data->return_value = BArchivable::AllUnarchived(data->archive);
362 			return B_OK;
363 		}
364 
365 		case PERFORM_CODE_ALL_ARCHIVED:
366 		{
367 			perform_data_all_archived* data =
368 				(perform_data_all_archived*)arg;
369 
370 			data->return_value = BArchivable::AllArchived(data->archive);
371 			return B_OK;
372 		}
373 	}
374 
375 	return B_NAME_NOT_FOUND;
376 }
377 
378 
379 status_t
AllUnarchived(const BMessage * archive)380 BArchivable::AllUnarchived(const BMessage* archive)
381 {
382 	return B_OK;
383 }
384 
385 
386 status_t
AllArchived(BMessage * archive) const387 BArchivable::AllArchived(BMessage* archive) const
388 {
389 	return B_OK;
390 }
391 
392 
393 // #pragma mark - BArchiver
394 
395 
BArchiver(BMessage * archive)396 BArchiver::BArchiver(BMessage* archive)
397 	:
398 	fManager(BManagerBase::ArchiveManager(archive)),
399 	fArchive(archive),
400 	fFinished(false)
401 {
402 	if (fManager == NULL)
403 		fManager = new BArchiveManager(this);
404 }
405 
406 
~BArchiver()407 BArchiver::~BArchiver()
408 {
409 	if (!fFinished)
410 		fManager->ArchiverLeaving(this, B_OK);
411 }
412 
413 
414 status_t
AddArchivable(const char * name,BArchivable * archivable,bool deep)415 BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep)
416 {
417 	int32 token;
418 	status_t err = GetTokenForArchivable(archivable, deep, token);
419 
420 	if (err != B_OK)
421 		return err;
422 
423 	return fArchive->AddInt32(name, token);
424 }
425 
426 
427 status_t
GetTokenForArchivable(BArchivable * archivable,bool deep,int32 & _token)428 BArchiver::GetTokenForArchivable(BArchivable* archivable,
429 	bool deep, int32& _token)
430 {
431 	return fManager->ArchiveObject(archivable, deep, _token);
432 }
433 
434 
435 bool
IsArchived(BArchivable * archivable)436 BArchiver::IsArchived(BArchivable* archivable)
437 {
438 	return fManager->IsArchived(archivable);
439 }
440 
441 
442 status_t
Finish(status_t err)443 BArchiver::Finish(status_t err)
444 {
445 	if (fFinished)
446 		debugger("Finish() called multiple times on same BArchiver.");
447 
448 	fFinished = true;
449 
450 	return fManager->ArchiverLeaving(this, err);
451 }
452 
453 
454 BMessage*
ArchiveMessage() const455 BArchiver::ArchiveMessage() const
456 {
457 	return fArchive;
458 }
459 
460 
461 void
RegisterArchivable(const BArchivable * archivable)462 BArchiver::RegisterArchivable(const BArchivable* archivable)
463 {
464 	fManager->RegisterArchivable(archivable);
465 }
466 
467 
468 // #pragma mark - BUnarchiver
469 
470 
BUnarchiver(const BMessage * archive)471 BUnarchiver::BUnarchiver(const BMessage* archive)
472 	:
473 	fManager(BManagerBase::UnarchiveManager(archive)),
474 	fArchive(archive),
475 	fFinished(false)
476 {
477 }
478 
479 
~BUnarchiver()480 BUnarchiver::~BUnarchiver()
481 {
482 	if (!fFinished && fManager)
483 		fManager->UnarchiverLeaving(this, B_OK);
484 }
485 
486 
487 template<>
488 status_t
GetObject(int32 token,ownership_policy owning,BArchivable * & object)489 BUnarchiver::GetObject<BArchivable>(int32 token,
490 	ownership_policy owning, BArchivable*& object)
491 {
492 	_CallDebuggerIfManagerNull();
493 	return fManager->GetArchivableForToken(token, owning, object);
494 }
495 
496 
497 template<>
498 status_t
FindObject(const char * name,int32 index,ownership_policy owning,BArchivable * & archivable)499 BUnarchiver::FindObject<BArchivable>(const char* name,
500 	int32 index, ownership_policy owning, BArchivable*& archivable)
501 {
502 	archivable = NULL;
503 	int32 token;
504 	status_t err = fArchive->FindInt32(name, index, &token);
505 	if (err != B_OK)
506 		return err;
507 
508 	return GetObject(token, owning, archivable);
509 }
510 
511 
512 bool
IsInstantiated(int32 token)513 BUnarchiver::IsInstantiated(int32 token)
514 {
515 	_CallDebuggerIfManagerNull();
516 	return fManager->IsInstantiated(token);
517 }
518 
519 
520 bool
IsInstantiated(const char * field,int32 index)521 BUnarchiver::IsInstantiated(const char* field, int32 index)
522 {
523 	int32 token;
524 	if (fArchive->FindInt32(field, index, &token) == B_OK)
525 		return IsInstantiated(token);
526 
527 	return false;
528 }
529 
530 
531 status_t
Finish(status_t err)532 BUnarchiver::Finish(status_t err)
533 {
534 	if (fFinished)
535 		debugger("Finish() called multiple times on same BArchiver.");
536 
537 	fFinished = true;
538 	if (fManager)
539 		return fManager->UnarchiverLeaving(this, err);
540 	else
541 		return B_OK;
542 }
543 
544 
545 const BMessage*
ArchiveMessage() const546 BUnarchiver::ArchiveMessage() const
547 {
548 	return fArchive;
549 }
550 
551 
552 void
AssumeOwnership(BArchivable * archivable)553 BUnarchiver::AssumeOwnership(BArchivable* archivable)
554 {
555 	_CallDebuggerIfManagerNull();
556 	fManager->AssumeOwnership(archivable);
557 }
558 
559 
560 void
RelinquishOwnership(BArchivable * archivable)561 BUnarchiver::RelinquishOwnership(BArchivable* archivable)
562 {
563 	_CallDebuggerIfManagerNull();
564 	fManager->RelinquishOwnership(archivable);
565 }
566 
567 
568 bool
IsArchiveManaged(const BMessage * archive)569 BUnarchiver::IsArchiveManaged(const BMessage* archive)
570 {
571 	// managed child archives will return here
572 	if (BManagerBase::ManagerPointer(archive))
573 		return true;
574 
575 	if (archive == NULL)
576 		return false;
577 
578 	// managed top level archives return here
579 	bool dummy;
580 	if (archive->FindBool(kManagedField, &dummy) == B_OK)
581 		return true;
582 
583 	return false;
584 }
585 
586 
587 template<>
588 status_t
InstantiateObject(BMessage * from,BArchivable * & object)589 BUnarchiver::InstantiateObject<BArchivable>(BMessage* from,
590 	BArchivable* &object)
591 {
592 	BUnarchiver unarchiver(BUnarchiver::PrepareArchive(from));
593 	object = instantiate_object(from);
594 	return unarchiver.Finish();
595 }
596 
597 
598 BMessage*
PrepareArchive(BMessage * & archive)599 BUnarchiver::PrepareArchive(BMessage* &archive)
600 {
601 	// this check allows PrepareArchive to be
602 	// called on new or old-style archives
603 	if (BUnarchiver::IsArchiveManaged(archive)) {
604 		BUnarchiveManager* manager = BManagerBase::UnarchiveManager(archive);
605 		if (!manager)
606 			manager = new BUnarchiveManager(archive);
607 
608 		manager->Acquire();
609 	}
610 
611 	return archive;
612 }
613 
614 
615 void
RegisterArchivable(BArchivable * archivable)616 BUnarchiver::RegisterArchivable(BArchivable* archivable)
617 {
618 	_CallDebuggerIfManagerNull();
619 	fManager->RegisterArchivable(archivable);
620 }
621 
622 
623 void
_CallDebuggerIfManagerNull()624 BUnarchiver::_CallDebuggerIfManagerNull()
625 {
626 	if (!fManager)
627 		debugger("BUnarchiver used with legacy or unprepared archive.");
628 }
629 
630 
631 // #pragma mark -
632 
633 
634 BArchivable*
instantiate_object(BMessage * archive,image_id * _id)635 instantiate_object(BMessage* archive, image_id* _id)
636 {
637 	status_t statusBuffer;
638 	status_t* status = &statusBuffer;
639 	if (_id != NULL)
640 		status = _id;
641 
642 	// Check our params
643 	if (archive == NULL) {
644 		syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument");
645 		*status = B_BAD_VALUE;
646 		return NULL;
647 	}
648 
649 	// Get class name from archive
650 	const char* className = NULL;
651 	status_t err = archive->FindString(B_CLASS_FIELD, &className);
652 	if (err) {
653 		syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry "
654 			"defining the class name (%s).", strerror(err));
655 		*status = B_BAD_VALUE;
656 		return NULL;
657 	}
658 
659 	// Get sig from archive
660 	const char* signature = NULL;
661 	bool hasSignature = archive->FindString(B_ADD_ON_FIELD, &signature) == B_OK;
662 
663 	instantiation_func instantiationFunc = BPrivate::find_instantiation_func(
664 		className, signature, _id);
665 
666 	// if find_instantiation_func() can't locate Class::Instantiate()
667 	// and a signature was specified
668 	if (!instantiationFunc && hasSignature) {
669 		// use BRoster::FindApp() to locate an app or add-on with the symbol
670 		BRoster Roster;
671 		entry_ref ref;
672 		err = Roster.FindApp(signature, &ref);
673 
674 		// if an entry_ref is obtained
675 		BEntry entry;
676 		if (err == B_OK)
677 			err = entry.SetTo(&ref);
678 
679 		BPath path;
680 		if (err == B_OK)
681 			err = entry.GetPath(&path);
682 
683 		if (err != B_OK) {
684 			syslog(LOG_ERR, "instantiate_object failed: Error finding app "
685 				"with signature \"%s\" (%s)", signature, strerror(err));
686 			*status = err;
687 			return NULL;
688 		}
689 
690 		// load the app/add-on
691 		image_id addOn = load_add_on(path.Path());
692 		if (addOn < B_OK) {
693 			syslog(LOG_ERR, "instantiate_object failed: Could not load "
694 				"add-on %s: %s.", path.Path(), strerror(addOn));
695 			*status = addOn;
696 			return NULL;
697 		}
698 
699 		// Save the image_id
700 		if (_id != NULL)
701 			*_id = addOn;
702 
703 		BString name = className;
704 		for (int32 pass = 0; pass < 2; pass++) {
705 			BString funcName;
706 			build_function_name(name, funcName);
707 
708 			instantiationFunc = find_function_in_image(funcName, addOn, err);
709 			if (instantiationFunc != NULL)
710 				break;
711 
712 			// Check if we have a private class, and add the BPrivate namespace
713 			// (for backwards compatibility)
714 			if (!add_private_namespace(name))
715 				break;
716 		}
717 
718 		if (instantiationFunc == NULL) {
719 			syslog(LOG_ERR, "instantiate_object failed: Failed to find exported "
720 				"Instantiate static function for class %s.", className);
721 			*status = B_NAME_NOT_FOUND;
722 			return NULL;
723 		}
724 	} else if (instantiationFunc == NULL) {
725 		syslog(LOG_ERR, "instantiate_object failed: No signature specified "
726 			"in archive, looking for class \"%s\".", className);
727 		*status = B_NAME_NOT_FOUND;
728 		return NULL;
729 	}
730 
731 	// if Class::Instantiate(BMessage*) was found
732 	if (instantiationFunc != NULL) {
733 		// use to create and return an object instance
734 		return instantiationFunc(archive);
735 	}
736 
737 	return NULL;
738 }
739 
740 
741 BArchivable*
instantiate_object(BMessage * from)742 instantiate_object(BMessage* from)
743 {
744 	return instantiate_object(from, NULL);
745 }
746 
747 
748 //	#pragma mark - support_globals
749 
750 
751 bool
validate_instantiation(BMessage * from,const char * className)752 validate_instantiation(BMessage* from, const char* className)
753 {
754 	// Make sure our params are kosher -- original skimped here =P
755 	if (!from) {
756 		errno = B_BAD_VALUE;
757 		return false;
758 	}
759 
760 	BString name = className;
761 	for (int32 pass = 0; pass < 2; pass++) {
762 		const char* archiveClassName;
763 		for (int32 index = 0; from->FindString(B_CLASS_FIELD, index,
764 				&archiveClassName) == B_OK; ++index) {
765 			if (name == archiveClassName) {
766 				errno = B_OK;
767 				return true;
768 			}
769 		}
770 
771 		if (!add_private_namespace(name))
772 			break;
773 	}
774 
775 	errno = B_MISMATCHED_VALUES;
776 	syslog(LOG_ERR, "validate_instantiation failed on class %s.", className);
777 
778 	return false;
779 }
780 
781 
782 instantiation_func
find_instantiation_func(const char * className,const char * signature)783 find_instantiation_func(const char* className, const char* signature)
784 {
785 	return BPrivate::find_instantiation_func(className, signature, NULL);
786 }
787 
788 
789 instantiation_func
find_instantiation_func(const char * className)790 find_instantiation_func(const char* className)
791 {
792 	return find_instantiation_func(className, NULL);
793 }
794 
795 
796 instantiation_func
find_instantiation_func(BMessage * archive)797 find_instantiation_func(BMessage* archive)
798 {
799 	if (archive == NULL) {
800 		errno = B_BAD_VALUE;
801 		return NULL;
802 	}
803 
804 	const char* name = NULL;
805 	const char* signature = NULL;
806 	if (archive->FindString(B_CLASS_FIELD, &name) != B_OK
807 		|| archive->FindString(B_ADD_ON_FIELD, &signature)) {
808 		errno = B_BAD_VALUE;
809 		return NULL;
810 	}
811 
812 	return find_instantiation_func(name, signature);
813 }
814 
815 
816 //	#pragma mark - BArchivable binary compatibility
817 
818 
819 #if __GNUC__ == 2
820 
821 extern "C" status_t
_ReservedArchivable1__11BArchivable(BArchivable * archivable,const BMessage * archive)822 _ReservedArchivable1__11BArchivable(BArchivable* archivable,
823 	const BMessage* archive)
824 {
825 	// AllUnarchived
826 	perform_data_all_unarchived performData;
827 	performData.archive = archive;
828 
829 	archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData);
830 	return performData.return_value;
831 }
832 
833 
834 extern "C" status_t
_ReservedArchivable2__11BArchivable(BArchivable * archivable,BMessage * archive)835 _ReservedArchivable2__11BArchivable(BArchivable* archivable,
836 	BMessage* archive)
837 {
838 	// AllArchived
839 	perform_data_all_archived performData;
840 	performData.archive = archive;
841 
842 	archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData);
843 	return performData.return_value;
844 }
845 
846 
847 #elif __GNUC__ > 2
848 
849 extern "C" status_t
_ZN11BArchivable20_ReservedArchivable1Ev(BArchivable * archivable,const BMessage * archive)850 _ZN11BArchivable20_ReservedArchivable1Ev(BArchivable* archivable,
851 	const BMessage* archive)
852 {
853 	// AllUnarchived
854 	perform_data_all_unarchived performData;
855 	performData.archive = archive;
856 
857 	archivable->Perform(PERFORM_CODE_ALL_UNARCHIVED, &performData);
858 	return performData.return_value;
859 }
860 
861 
862 extern "C" status_t
_ZN11BArchivable20_ReservedArchivable2Ev(BArchivable * archivable,BMessage * archive)863 _ZN11BArchivable20_ReservedArchivable2Ev(BArchivable* archivable,
864 	BMessage* archive)
865 {
866 	// AllArchived
867 	perform_data_all_archived performData;
868 	performData.archive = archive;
869 
870 	archivable->Perform(PERFORM_CODE_ALL_ARCHIVED, &performData);
871 	return performData.return_value;
872 }
873 
874 #endif // _GNUC__ > 2
875 
876 
_ReservedArchivable3()877 void BArchivable::_ReservedArchivable3() {}
878