Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Parser/C++/occ/metaclass.cc
1| /*
2| Copyright (C) 1997-2000 Shigeru Chiba, University of Tsukuba.
3|
4| Permission to use, copy, distribute and modify this software and
5| its documentation for any purpose is hereby granted without fee,
6| provided that the above copyright notice appear in all copies and that
7| both that copyright notice and this permission notice appear in
8| supporting documentation.
9|
10| Shigeru Chiba makes no representations about the suitability of this
11| software for any purpose. It is provided "as is" without express or
12| implied warranty.
13| */
14| /*
15| Copyright (c) 1995, 1996 Xerox Corporation.
16| All Rights Reserved.
17|
18| Use and copying of this software and preparation of derivative works
19| based upon this software are permitted. Any copy of this software or
20| of any derivative work must include the above copyright notice of
21| Xerox Corporation, this paragraph and the one after it. Any
22| distribution of this software or derivative works must comply with all
23| applicable United States export control laws.
24|
25| This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
26| ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
27| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28| PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
29| LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
30| EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
31| NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
32| OF THE POSSIBILITY OF SUCH DAMAGES.
33| */
34|
35| #include "metaclass.h"
36| #include "ptree-core.h"
37|
38| #if USE_DLOADER
39| #include <iostream>
40| #include <cstdio>
41| #include <fstream>
42| #include <cstring>
43| #include <cstdlib> /* for exi
44|
45|
46| extern void RunSoCompiler(const char* src_file);
47| extern void* LoadSoLib(char* file_name);
48| extern void* LookupSymbol(void* handle, char* symbol);
49|
50| #if !USE_SO
51| extern void BaseClassUsed(char *, int); // in dr
52| #endif /* USE_SO */
53|
54| #endif /* USE_DLOADER */
55|
56| extern bool verboseMode;
57| extern bool makeSharedLibrary;
58|
59|
60| // class QuoteClass
61| //
62| // Part of the implementation of QuoteClass is included here to let
63| // quote-class.cc linked to others if the compiler is produced by
64| // "g++ -o occ opencxx.a".
65|
66| #include "quote-class.h"
67|
68|
69|
70|
71| static opcxx_ListOfMetaclass* QuoteClassCreator;
72| static opcxx_ListOfMetaclass* metaclassCreator;
73|
74| static Class* CreateQuoteClass(Ptree* def, Ptree* marg)
75| {
76| Class* metaobject = new QuoteClass;
77| metaobject->InitializeInstance(def, marg);
78| return metaobject;
79| }
80|
81| opcxx_ListOfMetaclass* opcxx_init_QuoteClass()
82| {
83| return new opcxx_ListOfMetaclass("QuoteClass", CreateQuoteClass,
84| QuoteClass::Initialize, nil);
85| }
86|
87| static Class* CreateMetaclass(Ptree* def, Ptree* marg)
88| {
89| Class* metaobject = new Metaclass;
90| metaobject->InitializeInstance(def, marg);
91| return metaobject;
92| }
93|
94| opcxx_ListOfMetaclass* opcxx_init_Metaclass()
95| {
96| return new opcxx_ListOfMetaclass("Metaclass", CreateMetaclass,
97| Metaclass::Initialize, nil);
98| }
99|
100|
101| bool QuoteClass::Initialize()
102| {
103| return TRUE;
104| }
105|
106| char* QuoteClass::MetaclassName()
107| {
108| return "QuoteClass";
109| }
110|
111|
112| // class Metaclass
113|
114| void Metaclass::do_init_static()
115| {
116| QuoteClassCreator = new opcxx_ListOfMetaclass(
117| "QuoteClass", CreateQuoteClass, QuoteClass::Initialize, nil);
118| metaclassCreator = new opcxx_ListOfMetaclass(
119| "Metaclass", CreateMetaclass, Metaclass::Initialize, nil);
120| }
121|
122| Metaclass::Metaclass()
123| {
124| new_function_name = nil;
125| first_not_inlined_vf = -1;
126| }
127|
128| bool Metaclass::Initialize()
129| {
130| return TRUE;
131| }
132|
133| char* Metaclass::MetaclassName()
134| {
135| return "Metaclass";
136| }
137|
138| void Metaclass::TranslateClass(Environment* env)
139| {
140| Ptree* name = Name();
141|
142| if(!IsBuiltinMetaclass(name)){
143| CheckObsoleteness();
144| InsertInitialize();
145| #if defined(_MSC_VER) || defined(_PARSE_VCC)
146| AddClassSpecifier(Ptree::Make("__declspec(dllexport)"));
147| #endif
148| AppendMember(Ptree::Make("public: char* MetaclassName() {\n"
149| " return \"%p\"; }\n",
150| Name()));
151|
152| Ptree* tmpname = Ptree::GenSym();
153| Ptree* tmpname2 = Ptree::GenSym();
154| Ptree* finalizer = GetFinalizer();
155| AppendAfterToplevel(env, Ptree::Make(
156| "static Class* %p(Ptree* def, Ptree* marg){\n"
157| " Class* c = new %p;\n"
158| " c->InitializeInstance(def, marg);\n"
159| " return c; }\n"
160| "static opcxx_ListOfMetaclass %p(\"%p\", %p,\n"
161| " %p::Initialize, %p);\n",
162| tmpname, name, tmpname2, name, tmpname, name, finalizer));
163|
164| if(makeSharedLibrary){
165| ProduceInitFile(name);
166| first_not_inlined_vf = FindFirstNotInlinedVirtualFunction();
167| new_function_name = tmpname;
168| if(first_not_inlined_vf < 0)
169| AppendHousekeepingCode(env, Name(), tmpname, finalizer);
170| }
171| }
172|
173| Class::TranslateClass(env);
174| }
175|
176| Ptree* Metaclass::GetFinalizer()
177| {
178| Member m;
179| if(LookupMember("FinalizeClass", m) && m.Supplier() == this){
180| if(!m.IsStatic())
181| ErrorMessage("FinalizeClass() must be static in ", Name(),
182| Definition());
183|
184| return Ptree::Make("%p::FinalizeClass", Name());
185| }
186| else
187| return Ptree::Make("0");
188| }
189|
190| void Metaclass::CheckObsoleteness()
191| {
192| Member m;
193|
194| if(LookupMember("Finalize", m) && m.Supplier() == this)
195| WarningMessage("Finalize() is obsolete. Use FinalizeInstance() in ",
196| Name(),
197| Definition());
198| }
199|
200| void Metaclass::ProduceInitFile(Ptree* class_name)
201| {
202| #if USE_DLOADER
203| #if USE_SO
204| const char* fname = Ptree::Make("%p-init.cc", class_name)->ToString();
205| if(verboseMode)
206| std::cerr << "Produce " << fname << " ..\n";
207|
208| std::ofstream src_file(fname);
209| if(!src_file){
210| perror(fname);
211| exit(1);
212| }
213|
214| src_file << "extern void LoadMetaclass(char*);\n";
215| src_file << "char* opcxx_Init_" << class_name << "(){\n";
216|
217| Ptree* base_name;
218| for(int i = 0; (base_name = NthBaseClassName(i)) != nil; ++i)
219| if(!base_name->Eq("Class"))
220| src_file << " LoadMetaclass(\"" << base_name << "\");\n";
221|
222| src_file << " return 0;\n}\n";
223|
224| src_file.close();
225|
226| RunSoCompiler(fname);
227| #else
228| // Push base class names forward to RunCompiler
229| Ptree* base_name;
230| for (int i = 0; (base_name = NthBaseClassName(i)) != nil; ++i)
231| if (!base_name->Eq("Class") && !base_name->Eq("TemplateClass"))
232| BaseClassUsed(base_name->GetPosition(), base_name->GetLength());
233| #endif /* USE_SO */
234| #endif /* USE_DLOADER */
235| }
236|
237| bool Metaclass::IsBuiltinMetaclass(Ptree* name)
238| {
239| return bool(name->Eq("Class") || name->Eq("Metaclass")
240| || name->Eq("TemplateClass")
241| || name->Eq("QuoteClass"));
242| }
243|
244| void Metaclass::InsertInitialize()
245| {
246| Member m;
247| if(!LookupMember("Initialize", m) || m.Supplier() != this){
248| #if !defined(_MSC_VER) || (_MSC_VER >= 1100)
249| AppendMember(Ptree::Make(
250| "public: static bool Initialize() { return 1; }\n"));
251| #else
252| AppendMember(Ptree::Make(
253| "public: static int Initialize() { return 1; }\n"));
254| #endif
255| }
256| else if(!m.IsStatic())
257| ErrorMessage("Initialize() must be static in ", Name(),
258| Definition());
259| }
260|
261| int Metaclass::FindFirstNotInlinedVirtualFunction()
262| {
263| Member m;
264| for(int i = 0; NthMember(i, m); ++i)
265| if(m.IsFunction() && m.IsVirtual() && !m.IsInline()
266| && m.Supplier() == this)
267| return i;
268|
269| WarningMessage("a metaclass should include at least one"
270| " not-inlined virtual function: ", Name(), Name());
271| return -1;
272| }
273|
274| void Metaclass::TranslateMemberFunction(Environment* env, Member& m)
275| {
276| if(m.Nth() != first_not_inlined_vf)
277| return;
278|
279| if(m.IsInline()){
280| ErrorMessage("This member function should not be inlined: ",
281| m.Name(), m.ArgumentList());
282| return;
283| }
284|
285| AppendHousekeepingCode(env, Name(), new_function_name,
286| GetFinalizer());
287| }
288|
289| void Metaclass::AppendHousekeepingCode(Environment* env, Ptree* class_name,
290| Ptree* creator_name,
291| Ptree* finalizer)
292| {
293| #if !defined(_MSC_VER)
294| AppendAfterToplevel(env, Ptree::Make(
295| "opcxx_ListOfMetaclass* opcxx_init_%p(){\n"
296| " return new opcxx_ListOfMetaclass(\"%p\", %p,\n"
297| " %p::Initialize, %p); }\n",
298| class_name, class_name, creator_name, class_name,
299| finalizer));
300| #endif
301| }
302|
303| void LoadMetaclass(char* metaclass_name)
304| {
305| #if USE_DLOADER
306| if(metaclass_name != nil && *metaclass_name != '\0')
307| if(!opcxx_ListOfMetaclass::AlreadyRecorded(metaclass_name))
308| Metaclass::Load(metaclass_name, strlen(metaclass_name));
309| #endif
310| }
311|
312| void Metaclass::Load(Ptree* metaclass_name)
313| {
314| #if USE_DLOADER
315| if(opcxx_ListOfMetaclass::AlreadyRecorded(metaclass_name))
316| return;
317|
318| Load(metaclass_name->GetPosition(), metaclass_name->GetLength());
319| #endif
320| }
321|
322| void Metaclass::Load(char* metaclass_name, int len)
323| {
324| #if USE_DLOADER
325| #if USE_SO
326| #if DLSYM_NEED_UNDERSCORE
327| static char header[] = "_opcxx_Init_";
328| #else
329| static char header[] = "opcxx_Init_";
330| #endif
331| #if defined(IRIX_CC)
332| static char tail[] = "__Gv";
333| #else
334| static char tail[] = "__Fv";
335| #endif
336|
337| char* func_name = new char[len + sizeof(header) + sizeof(tail)];
338| strcpy(func_name, header);
339| memmove(func_name + sizeof(header) - 1, metaclass_name, len);
340| strcpy(func_name + sizeof(header) + len - 1, tail);
341|
342| // here, func_name is "_opcxx_Init_<metaclass>__Fv" or ".._Gv".
343|
344| char* file_name = new char[len + 9];
345| memmove(file_name, metaclass_name, len);
346|
347| strcpy(file_name + len, "-init.so");
348| void* handle_init = LoadSoLib(file_name); // load <metaclass>-init
349|
350| // call opcxx_Init_<metaclass>() in <metaclass>-init.so
351|
352| void (*loader)();
353| loader = (void (*)())LookupSymbol(handle_init, func_name);
354| (*loader)();
355|
356| strcpy(file_name + len, ".so");
357| void* handle = LoadSoLib(file_name); // load <metac
358|
359| if(verboseMode)
360| std::cerr << "Initialize.. ";
361|
362| // call opcxx_init_<metaclass>() in <metaclass>.so
363|
364| func_name[sizeof(header) - 6] = 'i';
365| void (*func)();
366| func = (void (*)())LookupSymbol(handle, func_name);
367| (*func)();
368|
369| delete [] file_name;
370| delete [] func_name;
371|
372| if(verboseMode)
373| std::cerr << "Done.\n";
374|
375| #else /* USE_SO */
376|
377| // Win32 uses auto-initialization of DLL's static variables
378| static char ext[] = ".dll";
379| char* file_name = new char[len + sizeof(ext)];
380| memmove(file_name, metaclass_name, len);
381| strcpy(file_name + len, ext);
382| void* handle = LoadSoLib(file_name); // load <metacl
383|
384| delete [] file_name;
385|
386| if(verboseMode)
387| std::cerr << "Done.\n";
388| #endif /* USE_SO */
389| #endif /* USE_DLOADER */
390| }
391|
392| void* Metaclass::LoadSoLib(char* file_name)
393| {
394| void* handle = nil;
395| #if USE_DLOADER
396| if(verboseMode)
397| std::cerr << "Load " << file_name << ".. ";
398|
399| handle = ::LoadSoLib(file_name);
400| #endif /* USE_DLOADER */
401|
402| return handle;
403| }
404|
405| void* Metaclass::LookupSymbol(void* handle, char* symbol)
406| {
407| void* func = 0;
408| #if USE_DLOADER
409| func = ::LookupSymbol(handle, symbol);
410| #endif
411| return func;
412| }