1 //===-- PluginManager.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/PluginManager.h"
11 
12 #include <string>
13 #include <vector>
14 
15 using namespace lldb_private;
16 
17 typedef enum PluginAction
18 {
19     ePluginRegisterInstance,
20     ePluginUnregisterInstance,
21     ePluginGetInstanceAtIndex
22 };
23 
24 
25 #pragma mark ABI
26 
27 
28 typedef struct ABIInstance
29 {
30     ABIInstance() :
31         name(),
32         description(),
33         create_callback(NULL)
34     {
35     }
36 
37     std::string name;
38     std::string description;
39     ABICreateInstance create_callback;
40 };
41 
42 typedef std::vector<ABIInstance> ABIInstances;
43 
44 static bool
45 AccessABIInstances (PluginAction action, ABIInstance &instance, uint32_t index)
46 {
47     static ABIInstances g_plugin_instances;
48 
49     switch (action)
50     {
51         case ePluginRegisterInstance:
52             if (instance.create_callback)
53             {
54                 g_plugin_instances.push_back (instance);
55                 return true;
56             }
57             break;
58 
59         case ePluginUnregisterInstance:
60             if (instance.create_callback)
61             {
62                 ABIInstances::iterator pos, end = g_plugin_instances.end();
63                 for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
64                 {
65                     if (pos->create_callback == instance.create_callback)
66                     {
67                         g_plugin_instances.erase(pos);
68                         return true;
69                     }
70                 }
71             }
72             break;
73 
74         case ePluginGetInstanceAtIndex:
75             if (index < g_plugin_instances.size())
76             {
77                 instance = g_plugin_instances[index];
78                 return true;
79             }
80             break;
81 
82         default:
83             break;
84     }
85     return false;
86 }
87 
88 
89 bool
90 PluginManager::RegisterPlugin
91     (
92         const char *name,
93         const char *description,
94         ABICreateInstance create_callback
95      )
96 {
97     if (create_callback)
98     {
99         ABIInstance instance;
100         assert (name && name[0]);
101         instance.name = name;
102         if (description && description[0])
103             instance.description = description;
104         instance.create_callback = create_callback;
105         return AccessABIInstances (ePluginRegisterInstance, instance, 0);
106     }
107     return false;
108 }
109 
110 bool
111 PluginManager::UnregisterPlugin (ABICreateInstance create_callback)
112 {
113     if (create_callback)
114     {
115         ABIInstance instance;
116         instance.create_callback = create_callback;
117         return AccessABIInstances (ePluginUnregisterInstance, instance, 0);
118     }
119     return false;
120 }
121 
122 ABICreateInstance
123 PluginManager::GetABICreateCallbackAtIndex (uint32_t idx)
124 {
125     ABIInstance instance;
126     if (AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx))
127         return instance.create_callback;
128     return false;
129 }
130 
131 ABICreateInstance
132 PluginManager::GetABICreateCallbackForPluginName (const char *name)
133 {
134     if (name && name[0])
135     {
136         ABIInstance instance;
137         std::string ss_name(name);
138         for (uint32_t idx = 0; AccessABIInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
139         {
140             if (instance.name == ss_name)
141                 return instance.create_callback;
142         }
143     }
144     return NULL;
145 }
146 
147 
148 #pragma mark Disassembler
149 
150 
151 typedef struct DisassemblerInstance
152 {
153     DisassemblerInstance() :
154         name(),
155         description(),
156         create_callback(NULL)
157     {
158     }
159 
160     std::string name;
161     std::string description;
162     DisassemblerCreateInstance create_callback;
163 };
164 
165 typedef std::vector<DisassemblerInstance> DisassemblerInstances;
166 
167 static bool
168 AccessDisassemblerInstances (PluginAction action, DisassemblerInstance &instance, uint32_t index)
169 {
170     static DisassemblerInstances g_plugin_instances;
171 
172     switch (action)
173     {
174     case ePluginRegisterInstance:
175         if (instance.create_callback)
176         {
177             g_plugin_instances.push_back (instance);
178             return true;
179         }
180         break;
181 
182     case ePluginUnregisterInstance:
183         if (instance.create_callback)
184         {
185             DisassemblerInstances::iterator pos, end = g_plugin_instances.end();
186             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
187             {
188                 if (pos->create_callback == instance.create_callback)
189                 {
190                     g_plugin_instances.erase(pos);
191                     return true;
192                 }
193             }
194         }
195         break;
196 
197     case ePluginGetInstanceAtIndex:
198         if (index < g_plugin_instances.size())
199         {
200             instance = g_plugin_instances[index];
201             return true;
202         }
203         break;
204 
205     default:
206         break;
207     }
208     return false;
209 }
210 
211 
212 bool
213 PluginManager::RegisterPlugin
214 (
215     const char *name,
216     const char *description,
217     DisassemblerCreateInstance create_callback
218 )
219 {
220     if (create_callback)
221     {
222         DisassemblerInstance instance;
223         assert (name && name[0]);
224         instance.name = name;
225         if (description && description[0])
226             instance.description = description;
227         instance.create_callback = create_callback;
228         return AccessDisassemblerInstances (ePluginRegisterInstance, instance, 0);
229     }
230     return false;
231 }
232 
233 bool
234 PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback)
235 {
236     if (create_callback)
237     {
238         DisassemblerInstance instance;
239         instance.create_callback = create_callback;
240         return AccessDisassemblerInstances (ePluginUnregisterInstance, instance, 0);
241     }
242     return false;
243 }
244 
245 DisassemblerCreateInstance
246 PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx)
247 {
248     DisassemblerInstance instance;
249     if (AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx))
250         return instance.create_callback;
251     return false;
252 }
253 
254 DisassemblerCreateInstance
255 PluginManager::GetDisassemblerCreateCallbackForPluginName (const char *name)
256 {
257     if (name && name[0])
258     {
259         DisassemblerInstance instance;
260         std::string ss_name(name);
261         for (uint32_t idx = 0; AccessDisassemblerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
262         {
263             if (instance.name == ss_name)
264                 return instance.create_callback;
265         }
266     }
267     return NULL;
268 }
269 
270 
271 
272 #pragma mark DynamicLoader
273 
274 
275 typedef struct DynamicLoaderInstance
276 {
277     DynamicLoaderInstance() :
278         name(),
279         description(),
280         create_callback(NULL)
281     {
282     }
283 
284     std::string name;
285     std::string description;
286     DynamicLoaderCreateInstance create_callback;
287 };
288 
289 typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
290 
291 static bool
292 AccessDynamicLoaderInstances (PluginAction action, DynamicLoaderInstance &instance, uint32_t index)
293 {
294     static DynamicLoaderInstances g_plugin_instances;
295 
296     switch (action)
297     {
298     case ePluginRegisterInstance:
299         if (instance.create_callback)
300         {
301             g_plugin_instances.push_back (instance);
302             return true;
303         }
304         break;
305 
306     case ePluginUnregisterInstance:
307         if (instance.create_callback)
308         {
309             DynamicLoaderInstances::iterator pos, end = g_plugin_instances.end();
310             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
311             {
312                 if (pos->create_callback == instance.create_callback)
313                 {
314                     g_plugin_instances.erase(pos);
315                     return true;
316                 }
317             }
318         }
319         break;
320 
321     case ePluginGetInstanceAtIndex:
322         if (index < g_plugin_instances.size())
323         {
324             instance = g_plugin_instances[index];
325             return true;
326         }
327         break;
328 
329     default:
330         break;
331     }
332     return false;
333 }
334 
335 
336 bool
337 PluginManager::RegisterPlugin
338 (
339     const char *name,
340     const char *description,
341     DynamicLoaderCreateInstance create_callback
342 )
343 {
344     if (create_callback)
345     {
346         DynamicLoaderInstance instance;
347         assert (name && name[0]);
348         instance.name = name;
349         if (description && description[0])
350             instance.description = description;
351         instance.create_callback = create_callback;
352         return AccessDynamicLoaderInstances (ePluginRegisterInstance, instance, 0);
353     }
354     return false;
355 }
356 
357 bool
358 PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback)
359 {
360     if (create_callback)
361     {
362         DynamicLoaderInstance instance;
363         instance.create_callback = create_callback;
364         return AccessDynamicLoaderInstances (ePluginUnregisterInstance, instance, 0);
365     }
366     return false;
367 }
368 
369 DynamicLoaderCreateInstance
370 PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx)
371 {
372     DynamicLoaderInstance instance;
373     if (AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx))
374         return instance.create_callback;
375     return false;
376 }
377 
378 DynamicLoaderCreateInstance
379 PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const char *name)
380 {
381     if (name && name[0])
382     {
383         DynamicLoaderInstance instance;
384         std::string ss_name(name);
385         for (uint32_t idx = 0; AccessDynamicLoaderInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
386         {
387             if (instance.name == ss_name)
388                 return instance.create_callback;
389         }
390     }
391     return NULL;
392 }
393 
394 
395 
396 
397 #pragma mark ObjectFile
398 
399 typedef struct ObjectFileInstance
400 {
401     ObjectFileInstance() :
402         name(),
403         description(),
404         create_callback(NULL)
405     {
406     }
407 
408     std::string name;
409     std::string description;
410     ObjectFileCreateInstance create_callback;
411 };
412 
413 typedef std::vector<ObjectFileInstance> ObjectFileInstances;
414 
415 static bool
416 AccessObjectFileInstances (PluginAction action, ObjectFileInstance &instance, uint32_t index)
417 {
418     static ObjectFileInstances g_plugin_instances;
419 
420     switch (action)
421     {
422     case ePluginRegisterInstance:
423         if (instance.create_callback)
424         {
425             g_plugin_instances.push_back (instance);
426             return true;
427         }
428         break;
429 
430     case ePluginUnregisterInstance:
431         if (instance.create_callback)
432         {
433             ObjectFileInstances::iterator pos, end = g_plugin_instances.end();
434             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
435             {
436                 if (pos->create_callback == instance.create_callback)
437                 {
438                     g_plugin_instances.erase(pos);
439                     return true;
440                 }
441             }
442         }
443         break;
444 
445     case ePluginGetInstanceAtIndex:
446         if (index < g_plugin_instances.size())
447         {
448             instance = g_plugin_instances[index];
449             return true;
450         }
451         break;
452 
453     default:
454         break;
455     }
456     return false;
457 }
458 
459 
460 bool
461 PluginManager::RegisterPlugin
462 (
463     const char *name,
464     const char *description,
465     ObjectFileCreateInstance create_callback
466 )
467 {
468     if (create_callback)
469     {
470         ObjectFileInstance instance;
471         assert (name && name[0]);
472         instance.name = name;
473         if (description && description[0])
474             instance.description = description;
475         instance.create_callback = create_callback;
476         return AccessObjectFileInstances (ePluginRegisterInstance, instance, 0);
477     }
478     return false;
479 }
480 
481 bool
482 PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback)
483 {
484     if (create_callback)
485     {
486         ObjectFileInstance instance;
487         instance.create_callback = create_callback;
488         return AccessObjectFileInstances (ePluginUnregisterInstance, instance, 0);
489     }
490     return false;
491 }
492 
493 ObjectFileCreateInstance
494 PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
495 {
496     ObjectFileInstance instance;
497     if (AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx))
498         return instance.create_callback;
499     return false;
500 }
501 ObjectFileCreateInstance
502 PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
503 {
504     if (name && name[0])
505     {
506         ObjectFileInstance instance;
507         std::string ss_name(name);
508         for (uint32_t idx = 0; AccessObjectFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
509         {
510             if (instance.name == ss_name)
511                 return instance.create_callback;
512         }
513     }
514     return NULL;
515 }
516 
517 
518 
519 #pragma mark ObjectContainer
520 
521 typedef struct ObjectContainerInstance
522 {
523     ObjectContainerInstance() :
524         name(),
525         description(),
526         create_callback(NULL)
527     {
528     }
529 
530     std::string name;
531     std::string description;
532     ObjectContainerCreateInstance create_callback;
533 };
534 
535 typedef std::vector<ObjectContainerInstance> ObjectContainerInstances;
536 
537 static bool
538 AccessObjectContainerInstances (PluginAction action, ObjectContainerInstance &instance, uint32_t index)
539 {
540     static ObjectContainerInstances g_plugin_instances;
541 
542     switch (action)
543     {
544     case ePluginRegisterInstance:
545         if (instance.create_callback)
546         {
547             g_plugin_instances.push_back (instance);
548             return true;
549         }
550         break;
551 
552     case ePluginUnregisterInstance:
553         if (instance.create_callback)
554         {
555             ObjectContainerInstances::iterator pos, end = g_plugin_instances.end();
556             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
557             {
558                 if (pos->create_callback == instance.create_callback)
559                 {
560                     g_plugin_instances.erase(pos);
561                     return true;
562                 }
563             }
564         }
565         break;
566 
567     case ePluginGetInstanceAtIndex:
568         if (index < g_plugin_instances.size())
569         {
570             instance = g_plugin_instances[index];
571             return true;
572         }
573         break;
574 
575     default:
576         break;
577     }
578     return false;
579 }
580 
581 
582 bool
583 PluginManager::RegisterPlugin
584 (
585     const char *name,
586     const char *description,
587     ObjectContainerCreateInstance create_callback
588 )
589 {
590     if (create_callback)
591     {
592         ObjectContainerInstance instance;
593         assert (name && name[0]);
594         instance.name = name;
595         if (description && description[0])
596             instance.description = description;
597         instance.create_callback = create_callback;
598         return AccessObjectContainerInstances (ePluginRegisterInstance, instance, 0);
599     }
600     return false;
601 }
602 
603 bool
604 PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback)
605 {
606     if (create_callback)
607     {
608         ObjectContainerInstance instance;
609         instance.create_callback = create_callback;
610         return AccessObjectContainerInstances (ePluginUnregisterInstance, instance, 0);
611     }
612     return false;
613 }
614 
615 ObjectContainerCreateInstance
616 PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx)
617 {
618     ObjectContainerInstance instance;
619     if (AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx))
620         return instance.create_callback;
621     return false;
622 }
623 ObjectContainerCreateInstance
624 PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name)
625 {
626     if (name && name[0])
627     {
628         ObjectContainerInstance instance;
629         std::string ss_name(name);
630         for (uint32_t idx = 0; AccessObjectContainerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
631         {
632             if (instance.name == ss_name)
633                 return instance.create_callback;
634         }
635     }
636     return NULL;
637 }
638 
639 #pragma mark LogChannel
640 
641 typedef struct LogChannelInstance
642 {
643     LogChannelInstance() :
644         name(),
645         description(),
646         create_callback(NULL)
647     {
648     }
649 
650     std::string name;
651     std::string description;
652     LogChannelCreateInstance create_callback;
653 };
654 
655 typedef std::vector<LogChannelInstance> LogChannelInstances;
656 
657 static bool
658 AccessLogChannelInstances (PluginAction action, LogChannelInstance &instance, uint32_t index)
659 {
660     static LogChannelInstances g_plugin_instances;
661 
662     switch (action)
663     {
664     case ePluginRegisterInstance:
665         if (instance.create_callback)
666         {
667             g_plugin_instances.push_back (instance);
668             return true;
669         }
670         break;
671 
672     case ePluginUnregisterInstance:
673         if (instance.create_callback)
674         {
675             LogChannelInstances::iterator pos, end = g_plugin_instances.end();
676             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
677             {
678                 if (pos->create_callback == instance.create_callback)
679                 {
680                     g_plugin_instances.erase(pos);
681                     return true;
682                 }
683             }
684         }
685         break;
686 
687     case ePluginGetInstanceAtIndex:
688         if (index < g_plugin_instances.size())
689         {
690             instance = g_plugin_instances[index];
691             return true;
692         }
693         break;
694 
695     default:
696         break;
697     }
698     return false;
699 }
700 
701 
702 bool
703 PluginManager::RegisterPlugin
704 (
705     const char *name,
706     const char *description,
707     LogChannelCreateInstance create_callback
708 )
709 {
710     if (create_callback)
711     {
712         LogChannelInstance instance;
713         assert (name && name[0]);
714         instance.name = name;
715         if (description && description[0])
716             instance.description = description;
717         instance.create_callback = create_callback;
718         return AccessLogChannelInstances (ePluginRegisterInstance, instance, 0);
719     }
720     return false;
721 }
722 
723 bool
724 PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback)
725 {
726     if (create_callback)
727     {
728         LogChannelInstance instance;
729         instance.create_callback = create_callback;
730         return AccessLogChannelInstances (ePluginUnregisterInstance, instance, 0);
731     }
732     return false;
733 }
734 
735 const char *
736 PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx)
737 {
738     LogChannelInstance instance;
739     if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
740         return instance.name.c_str();
741     return NULL;
742 }
743 
744 
745 LogChannelCreateInstance
746 PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx)
747 {
748     LogChannelInstance instance;
749     if (AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx))
750         return instance.create_callback;
751     return false;
752 }
753 
754 LogChannelCreateInstance
755 PluginManager::GetLogChannelCreateCallbackForPluginName (const char *name)
756 {
757     if (name && name[0])
758     {
759         LogChannelInstance instance;
760         std::string ss_name(name);
761         for (uint32_t idx = 0; AccessLogChannelInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
762         {
763             if (instance.name == ss_name)
764                 return instance.create_callback;
765         }
766     }
767     return NULL;
768 }
769 
770 #pragma mark Process
771 
772 typedef struct ProcessInstance
773 {
774     ProcessInstance() :
775         name(),
776         description(),
777         create_callback(NULL)
778     {
779     }
780 
781     std::string name;
782     std::string description;
783     ProcessCreateInstance create_callback;
784 };
785 
786 typedef std::vector<ProcessInstance> ProcessInstances;
787 
788 static bool
789 AccessProcessInstances (PluginAction action, ProcessInstance &instance, uint32_t index)
790 {
791     static ProcessInstances g_plugin_instances;
792 
793     switch (action)
794     {
795     case ePluginRegisterInstance:
796         if (instance.create_callback)
797         {
798             g_plugin_instances.push_back (instance);
799             return true;
800         }
801         break;
802 
803     case ePluginUnregisterInstance:
804         if (instance.create_callback)
805         {
806             ProcessInstances::iterator pos, end = g_plugin_instances.end();
807             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
808             {
809                 if (pos->create_callback == instance.create_callback)
810                 {
811                     g_plugin_instances.erase(pos);
812                     return true;
813                 }
814             }
815         }
816         break;
817 
818     case ePluginGetInstanceAtIndex:
819         if (index < g_plugin_instances.size())
820         {
821             instance = g_plugin_instances[index];
822             return true;
823         }
824         break;
825 
826     default:
827         break;
828     }
829     return false;
830 }
831 
832 
833 bool
834 PluginManager::RegisterPlugin
835 (
836     const char *name,
837     const char *description,
838     ProcessCreateInstance create_callback
839 )
840 {
841     if (create_callback)
842     {
843         ProcessInstance instance;
844         assert (name && name[0]);
845         instance.name = name;
846         if (description && description[0])
847             instance.description = description;
848         instance.create_callback = create_callback;
849         return AccessProcessInstances (ePluginRegisterInstance, instance, 0);
850     }
851     return false;
852 }
853 
854 bool
855 PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
856 {
857     if (create_callback)
858     {
859         ProcessInstance instance;
860         instance.create_callback = create_callback;
861         return AccessProcessInstances (ePluginUnregisterInstance, instance, 0);
862     }
863     return false;
864 }
865 
866 ProcessCreateInstance
867 PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx)
868 {
869     ProcessInstance instance;
870     if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx))
871         return instance.create_callback;
872     return false;
873 }
874 
875 ProcessCreateInstance
876 PluginManager::GetProcessCreateCallbackForPluginName (const char *name)
877 {
878     if (name && name[0])
879     {
880         ProcessInstance instance;
881         std::string ss_name(name);
882         for (uint32_t idx = 0; AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
883         {
884             if (instance.name == ss_name)
885                 return instance.create_callback;
886         }
887     }
888     return NULL;
889 }
890 
891 #pragma mark SymbolFile
892 
893 typedef struct SymbolFileInstance
894 {
895     SymbolFileInstance() :
896         name(),
897         description(),
898         create_callback(NULL)
899     {
900     }
901 
902     std::string name;
903     std::string description;
904     SymbolFileCreateInstance create_callback;
905 };
906 
907 typedef std::vector<SymbolFileInstance> SymbolFileInstances;
908 
909 static bool
910 AccessSymbolFileInstances (PluginAction action, SymbolFileInstance &instance, uint32_t index)
911 {
912     static SymbolFileInstances g_plugin_instances;
913 
914     switch (action)
915     {
916     case ePluginRegisterInstance:
917         if (instance.create_callback)
918         {
919             g_plugin_instances.push_back (instance);
920             return true;
921         }
922         break;
923 
924     case ePluginUnregisterInstance:
925         if (instance.create_callback)
926         {
927             SymbolFileInstances::iterator pos, end = g_plugin_instances.end();
928             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
929             {
930                 if (pos->create_callback == instance.create_callback)
931                 {
932                     g_plugin_instances.erase(pos);
933                     return true;
934                 }
935             }
936         }
937         break;
938 
939     case ePluginGetInstanceAtIndex:
940         if (index < g_plugin_instances.size())
941         {
942             instance = g_plugin_instances[index];
943             return true;
944         }
945         break;
946 
947     default:
948         break;
949     }
950     return false;
951 }
952 
953 
954 bool
955 PluginManager::RegisterPlugin
956 (
957     const char *name,
958     const char *description,
959     SymbolFileCreateInstance create_callback
960 )
961 {
962     if (create_callback)
963     {
964         SymbolFileInstance instance;
965         assert (name && name[0]);
966         instance.name = name;
967         if (description && description[0])
968             instance.description = description;
969         instance.create_callback = create_callback;
970         return AccessSymbolFileInstances (ePluginRegisterInstance, instance, 0);
971     }
972     return false;
973 }
974 
975 bool
976 PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback)
977 {
978     if (create_callback)
979     {
980         SymbolFileInstance instance;
981         instance.create_callback = create_callback;
982         return AccessSymbolFileInstances (ePluginUnregisterInstance, instance, 0);
983     }
984     return false;
985 }
986 
987 SymbolFileCreateInstance
988 PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx)
989 {
990     SymbolFileInstance instance;
991     if (AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx))
992         return instance.create_callback;
993     return false;
994 }
995 SymbolFileCreateInstance
996 PluginManager::GetSymbolFileCreateCallbackForPluginName (const char *name)
997 {
998     if (name && name[0])
999     {
1000         SymbolFileInstance instance;
1001         std::string ss_name(name);
1002         for (uint32_t idx = 0; AccessSymbolFileInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1003         {
1004             if (instance.name == ss_name)
1005                 return instance.create_callback;
1006         }
1007     }
1008     return NULL;
1009 }
1010 
1011 
1012 
1013 #pragma mark SymbolVendor
1014 
1015 typedef struct SymbolVendorInstance
1016 {
1017     SymbolVendorInstance() :
1018         name(),
1019         description(),
1020         create_callback(NULL)
1021     {
1022     }
1023 
1024     std::string name;
1025     std::string description;
1026     SymbolVendorCreateInstance create_callback;
1027 };
1028 
1029 typedef std::vector<SymbolVendorInstance> SymbolVendorInstances;
1030 
1031 static bool
1032 AccessSymbolVendorInstances (PluginAction action, SymbolVendorInstance &instance, uint32_t index)
1033 {
1034     static SymbolVendorInstances g_plugin_instances;
1035 
1036     switch (action)
1037     {
1038     case ePluginRegisterInstance:
1039         if (instance.create_callback)
1040         {
1041             g_plugin_instances.push_back (instance);
1042             return true;
1043         }
1044         break;
1045 
1046     case ePluginUnregisterInstance:
1047         if (instance.create_callback)
1048         {
1049             SymbolVendorInstances::iterator pos, end = g_plugin_instances.end();
1050             for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
1051             {
1052                 if (pos->create_callback == instance.create_callback)
1053                 {
1054                     g_plugin_instances.erase(pos);
1055                     return true;
1056                 }
1057             }
1058         }
1059         break;
1060 
1061     case ePluginGetInstanceAtIndex:
1062         if (index < g_plugin_instances.size())
1063         {
1064             instance = g_plugin_instances[index];
1065             return true;
1066         }
1067         break;
1068 
1069     default:
1070         break;
1071     }
1072     return false;
1073 }
1074 
1075 bool
1076 PluginManager::RegisterPlugin
1077 (
1078     const char *name,
1079     const char *description,
1080     SymbolVendorCreateInstance create_callback
1081 )
1082 {
1083     if (create_callback)
1084     {
1085         SymbolVendorInstance instance;
1086         assert (name && name[0]);
1087         instance.name = name;
1088         if (description && description[0])
1089             instance.description = description;
1090         instance.create_callback = create_callback;
1091         return AccessSymbolVendorInstances (ePluginRegisterInstance, instance, 0);
1092     }
1093     return false;
1094 }
1095 
1096 bool
1097 PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback)
1098 {
1099     if (create_callback)
1100     {
1101         SymbolVendorInstance instance;
1102         instance.create_callback = create_callback;
1103         return AccessSymbolVendorInstances (ePluginUnregisterInstance, instance, 0);
1104     }
1105     return false;
1106 }
1107 
1108 SymbolVendorCreateInstance
1109 PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx)
1110 {
1111     SymbolVendorInstance instance;
1112     if (AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx))
1113         return instance.create_callback;
1114     return false;
1115 }
1116 
1117 SymbolVendorCreateInstance
1118 PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
1119 {
1120     if (name && name[0])
1121     {
1122         SymbolVendorInstance instance;
1123         std::string ss_name(name);
1124         for (uint32_t idx = 0; AccessSymbolVendorInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
1125         {
1126             if (instance.name == ss_name)
1127                 return instance.create_callback;
1128         }
1129     }
1130     return NULL;
1131 }
1132 
1133 
1134