Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

metaclass.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 /*
00016   Copyright (c) 1995, 1996 Xerox Corporation.
00017   All Rights Reserved.
00018 
00019   Use and copying of this software and preparation of derivative works
00020   based upon this software are permitted. Any copy of this software or
00021   of any derivative work must include the above copyright notice of
00022   Xerox Corporation, this paragraph and the one after it.  Any
00023   distribution of this software or derivative works must comply with all
00024   applicable United States export control laws.
00025 
00026   This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
00027   ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029   PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
00030   LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
00031   EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
00032   NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
00033   OF THE POSSIBILITY OF SUCH DAMAGES.
00034 */
00035 
00036 #include "metaclass.h"
00037 #include "ptree-core.h"
00038 
00039 #if USE_DLOADER
00040 #include <stdio.h>
00041 #include <fstream.h>
00042 #include <string.h>
00043 #include <stdlib.h>     /* for exit() */
00044 
00045 // in driver2.cc
00046 extern void RunSoCompiler(const char* src_file);
00047 extern void* LoadSoLib(char* file_name);
00048 extern void* LookupSymbol(void* handle, char* symbol);
00049 
00050 #if !USE_SO
00051 extern void BaseClassUsed(char *, int);         // in driver2.cc
00052 #endif /* USE_SO */
00053 
00054 #endif /* USE_DLOADER */
00055 
00056 extern bool verboseMode;        // defined in driver.cc
00057 extern bool makeSharedLibrary;
00058 
00059 
00060 // class QuoteClass
00061 //
00062 // Part of the implementation of QuoteClass is included here to let
00063 // quote-class.cc linked to others if the compiler is produced by
00064 // "g++ -o occ opencxx.a".
00065 
00066 #include "quote-class.h"
00067 
00068 // The followings should be automatically generated but we write it
00069 // down here for bootstrapping.  Also see Metaclass::IsBuiltinMetaclass()
00070 
00071 static Class* CreateQuoteClass(Ptree* def, Ptree* marg)
00072 {
00073     Class* metaobject = new QuoteClass;
00074     metaobject->InitializeInstance(def, marg);
00075     return metaobject;
00076 }
00077 
00078 static opcxx_ListOfMetaclass QuoteClassCreator("QuoteClass",
00079                                                CreateQuoteClass,
00080                                                QuoteClass::Initialize,
00081                                                nil);
00082 
00083 opcxx_ListOfMetaclass* opcxx_init_QuoteClass()
00084 {
00085     return new opcxx_ListOfMetaclass("QuoteClass", CreateQuoteClass,
00086                                      QuoteClass::Initialize, nil);
00087 }
00088 
00089 bool QuoteClass::Initialize()
00090 {
00091     return TRUE;
00092 }
00093 
00094 char* QuoteClass::MetaclassName()
00095 {
00096     return "QuoteClass";
00097 }
00098 
00099 
00100 // class Metaclass
00101 
00102 static Class* CreateMetaclass(Ptree* def, Ptree* marg)
00103 {
00104     Class* metaobject = new Metaclass;
00105     metaobject->InitializeInstance(def, marg);
00106     return metaobject;
00107 }
00108 
00109 static opcxx_ListOfMetaclass metaclassCreator("Metaclass", CreateMetaclass,
00110                                               Metaclass::Initialize, nil);
00111 
00112 opcxx_ListOfMetaclass* opcxx_init_Metaclass()
00113 {
00114     return new opcxx_ListOfMetaclass("Metaclass", CreateMetaclass,
00115                                      Metaclass::Initialize, nil);
00116 }
00117 
00118 Metaclass::Metaclass()
00119 {
00120     new_function_name = nil;
00121     first_not_inlined_vf = -1;
00122 }
00123 
00124 bool Metaclass::Initialize()
00125 {
00126     return TRUE;
00127 }
00128 
00129 char* Metaclass::MetaclassName()
00130 {
00131     return "Metaclass";
00132 }
00133 
00134 void Metaclass::TranslateClass(Environment* env)
00135 {
00136     Ptree* name = Name();
00137 
00138     if(!IsBuiltinMetaclass(name)){
00139         CheckObsoleteness();
00140         InsertInitialize();
00141 #if defined(_MSC_VER) || defined(_PARSE_VCC)
00142         AddClassSpecifier(Ptree::Make("__declspec(dllexport)"));
00143 #endif
00144         AppendMember(Ptree::Make("public: char* MetaclassName() {\n"
00145                                  "    return \"%p\"; }\n",
00146                                  Name()));
00147 
00148         Ptree* tmpname = Ptree::GenSym();
00149         Ptree* tmpname2 = Ptree::GenSym();
00150         Ptree* finalizer = GetFinalizer();
00151         AppendAfterToplevel(env, Ptree::Make(
00152                 "static Class* %p(Ptree* def, Ptree* marg){\n"
00153                 "    Class* c = new %p;\n"
00154                 "    c->InitializeInstance(def, marg);\n"
00155                 "    return c; }\n"
00156                 "static opcxx_ListOfMetaclass %p(\"%p\", %p,\n"
00157                 "    %p::Initialize, %p);\n",
00158                 tmpname, name, tmpname2, name, tmpname, name, finalizer));
00159 
00160         if(makeSharedLibrary){
00161             ProduceInitFile(name);
00162             first_not_inlined_vf = FindFirstNotInlinedVirtualFunction();
00163             new_function_name = tmpname;
00164             if(first_not_inlined_vf < 0)
00165                 AppendHousekeepingCode(env, Name(), tmpname, finalizer);
00166         }
00167     }
00168 
00169     Class::TranslateClass(env);
00170 }
00171 
00172 Ptree* Metaclass::GetFinalizer()
00173 {
00174     Member m;
00175     if(LookupMember("FinalizeClass", m) && m.Supplier() == this){
00176         if(!m.IsStatic())
00177             ErrorMessage("FinalizeClass() must be static in ", Name(),
00178                          Definition());
00179 
00180         return Ptree::Make("%p::FinalizeClass", Name());
00181     }
00182     else
00183         return Ptree::Make("0");
00184 }
00185 
00186 void Metaclass::CheckObsoleteness()
00187 {
00188     Member m;
00189 
00190     if(LookupMember("Finalize", m) && m.Supplier() == this)
00191         WarningMessage("Finalize() is obsolete.  Use FinalizeInstance() in ",
00192                        Name(),
00193                        Definition());
00194 }
00195 
00196 void Metaclass::ProduceInitFile(Ptree* class_name)
00197 {
00198 #if USE_DLOADER
00199 #if USE_SO
00200     const char* fname = Ptree::Make("%p-init.cc", class_name)->ToString();
00201     if(verboseMode)
00202         cerr << "Produce " << fname << " ..\n";
00203 
00204     ofstream src_file(fname);
00205     if(!src_file){
00206         perror(fname);
00207         exit(1);
00208     }
00209 
00210     src_file << "extern void LoadMetaclass(char*);\n";
00211     src_file << "char* opcxx_Init_" << class_name << "(){\n";
00212 
00213     Ptree* base_name;
00214     for(int i = 0; (base_name = NthBaseClassName(i)) != nil; ++i)
00215         if(!base_name->Eq("Class"))
00216             src_file << "  LoadMetaclass(\"" << base_name << "\");\n";
00217 
00218     src_file << "    return 0;\n}\n";
00219 
00220     src_file.close();
00221 
00222     RunSoCompiler(fname);
00223 #else
00224     // Push base class names forward to RunCompiler
00225     Ptree* base_name;
00226     for (int i = 0; (base_name = NthBaseClassName(i)) != nil; ++i)
00227         if (!base_name->Eq("Class") && !base_name->Eq("TemplateClass"))
00228             BaseClassUsed(base_name->GetPosition(), base_name->GetLength());
00229 #endif /* USE_SO */
00230 #endif /* USE_DLOADER */
00231 }
00232 
00233 bool Metaclass::IsBuiltinMetaclass(Ptree* name)
00234 {
00235     return bool(name->Eq("Class") || name->Eq("Metaclass")
00236                 || name->Eq("TemplateClass")
00237                 || name->Eq("QuoteClass"));
00238 }
00239 
00240 void Metaclass::InsertInitialize()
00241 {
00242     Member m;
00243     if(!LookupMember("Initialize", m) || m.Supplier() != this){
00244 #if !defined(_MSC_VER) || (_MSC_VER >= 1100)
00245         AppendMember(Ptree::Make(
00246                 "public: static bool Initialize() { return 1; }\n"));
00247 #else
00248         AppendMember(Ptree::Make(
00249                 "public: static int Initialize() { return 1; }\n"));
00250 #endif
00251     }
00252     else if(!m.IsStatic())
00253         ErrorMessage("Initialize() must be static in ", Name(),
00254                      Definition());
00255 }
00256 
00257 int Metaclass::FindFirstNotInlinedVirtualFunction()
00258 {
00259     Member m;
00260     for(int i = 0; NthMember(i, m); ++i)
00261         if(m.IsFunction() && m.IsVirtual() && !m.IsInline()
00262            && m.Supplier() == this)
00263             return i;
00264 
00265     WarningMessage("a metaclass should include at least one"
00266                    " not-inlined virtual function: ", Name(), Name());
00267     return -1;
00268 }
00269 
00270 void Metaclass::TranslateMemberFunction(Environment* env, Member& m)
00271 {
00272     if(m.Nth() != first_not_inlined_vf)
00273         return;
00274 
00275     if(m.IsInline()){
00276         ErrorMessage("This member function should not be inlined: ",
00277                      m.Name(), m.ArgumentList());
00278         return;
00279     }
00280 
00281     AppendHousekeepingCode(env, Name(), new_function_name,
00282                            GetFinalizer());
00283 }
00284 
00285 void Metaclass::AppendHousekeepingCode(Environment* env, Ptree* class_name,
00286                                        Ptree* creator_name,
00287                                        Ptree* finalizer)
00288 {
00289 #if !defined(_MSC_VER)
00290     AppendAfterToplevel(env, Ptree::Make(
00291                 "opcxx_ListOfMetaclass* opcxx_init_%p(){\n"
00292                 "    return new opcxx_ListOfMetaclass(\"%p\", %p,\n"
00293                 "                   %p::Initialize, %p); }\n",
00294                 class_name, class_name, creator_name, class_name,
00295                 finalizer));
00296 #endif
00297 }
00298 
00299 void LoadMetaclass(char* metaclass_name)
00300 {
00301 #if USE_DLOADER
00302     if(metaclass_name != nil && *metaclass_name != '\0')
00303         if(!opcxx_ListOfMetaclass::AlreadyRecorded(metaclass_name))
00304             Metaclass::Load(metaclass_name, strlen(metaclass_name));
00305 #endif
00306 }
00307 
00308 void Metaclass::Load(Ptree* metaclass_name)
00309 {
00310 #if USE_DLOADER
00311     if(opcxx_ListOfMetaclass::AlreadyRecorded(metaclass_name))
00312         return;
00313 
00314     Load(metaclass_name->GetPosition(), metaclass_name->GetLength());
00315 #endif
00316 }
00317 
00318 void Metaclass::Load(char* metaclass_name, int len)
00319 {
00320 #if USE_DLOADER
00321 #if USE_SO
00322 #if DLSYM_NEED_UNDERSCORE
00323     static char header[] = "_opcxx_Init_";
00324 #else
00325     static char header[] = "opcxx_Init_";
00326 #endif
00327 #if defined(IRIX_CC)
00328     static char tail[] = "__Gv";
00329 #else
00330     static char tail[] = "__Fv";
00331 #endif
00332 
00333     char* func_name = new char[len + sizeof(header) + sizeof(tail)];
00334     strcpy(func_name, header);
00335     memmove(func_name + sizeof(header) - 1, metaclass_name, len);
00336     strcpy(func_name + sizeof(header) + len - 1, tail);
00337 
00338     // here, func_name is "_opcxx_Init_<metaclass>__Fv" or ".._Gv".
00339 
00340     char* file_name = new char[len + 9];
00341     memmove(file_name, metaclass_name, len);
00342 
00343     strcpy(file_name + len, "-init.so");
00344     void* handle_init = LoadSoLib(file_name);   // load <metaclass>-init.so
00345 
00346     // call opcxx_Init_<metaclass>() in <metaclass>-init.so
00347 
00348     void (*loader)();
00349     loader = (void (*)())LookupSymbol(handle_init, func_name);
00350     (*loader)();
00351 
00352     strcpy(file_name + len, ".so");
00353     void* handle = LoadSoLib(file_name);        // load <metaclass>.so
00354 
00355     if(verboseMode)
00356         cerr << "Initialize.. ";
00357 
00358     // call opcxx_init_<metaclass>() in <metaclass>.so
00359 
00360     func_name[sizeof(header) - 6] = 'i';
00361     void (*func)();
00362     func = (void (*)())LookupSymbol(handle, func_name);
00363     (*func)();
00364 
00365     delete [] file_name;
00366     delete [] func_name;
00367 
00368     if(verboseMode)
00369         cerr << "Done.\n";
00370 
00371 #else /* USE_SO */
00372 
00373     // Win32 uses auto-initialization of DLL's static variables
00374     static char ext[] = ".dll";
00375     char* file_name = new char[len + sizeof(ext)];
00376     memmove(file_name, metaclass_name, len);
00377     strcpy(file_name + len, ext);
00378     void* handle = LoadSoLib(file_name);        // load <metaclass>.dll
00379 
00380     delete [] file_name;
00381 
00382     if(verboseMode)
00383         cerr << "Done.\n";
00384 #endif /* USE_SO */
00385 #endif /* USE_DLOADER */
00386 }
00387 
00388 void* Metaclass::LoadSoLib(char* file_name)
00389 {
00390     void* handle = nil;
00391 #if USE_DLOADER
00392     if(verboseMode)
00393         cerr << "Load " << file_name << ".. ";
00394 
00395     handle = ::LoadSoLib(file_name);
00396 #endif /* USE_DLOADER */
00397 
00398     return handle;
00399 }
00400 
00401 void* Metaclass::LookupSymbol(void* handle, char* symbol)
00402 {
00403     void* func = 0;
00404 #if USE_DLOADER
00405     func = ::LookupSymbol(handle, symbol);
00406 #endif
00407     return func;
00408 }

Generated on Mon Feb 10 17:32:51 2003 for VFiasco Semantics Compiler by doxygen1.2.15