00001 // Copyright (C) 2001--2002 Petter Urkedal (petter.urkedal@matfys.lth.se) 00002 // 00003 // This file is free software; you can redistribute it and/or modify 00004 // it under the terms of the GNU General Public License as published by 00005 // the Free Software Foundation; either version 2 of the License, or 00006 // (at your option) any later version. 00007 // 00008 // This file is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 // GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License 00014 // along with this program; if not, write to the Free Software 00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software library without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to 00021 // produce an executable, this file does not by itself cause the 00022 // resulting executable to be covered by the GNU General Public 00023 // License. This exception does not however invalidate any other 00024 // reasons why the executable file might be covered by the GNU General 00025 // Public License. 00026 // 00027 // $Id: package.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $ 00028 00029 /** \file more/lang/package.h 00030 ** 00031 ** Definitions of \c package an \c cx_package_variable. */ 00032 00033 00034 #ifndef MORE_LANG_PACKAGE_H 00035 #define MORE_LANG_PACKAGE_H 00036 00037 #include <more/gen/memory.h> 00038 #include <more/lang/fwd.h> 00039 #include <more/lang/cx_expr.h> 00040 #include <more/lang/ct_proto.h> 00041 #include <more/lang/ct_struct.h> 00042 #include <more/lang/location.h> 00043 #include <more/lang/stdint.h> 00044 #include <ltdl.h> 00045 #include <set> 00046 #include <map> 00047 00048 00049 namespace more { 00050 namespace lang { 00051 00052 /** \class cx_package_variable package.h more/lang/package.h 00053 ** 00054 ** The representation of a global C variable with a definition. */ 00055 struct cx_package_variable : cx_identifier, resolver 00056 { 00057 /** Construct a package variable bound to \a val. */ 00058 explicit cx_package_variable(cx_expr* val); 00059 00060 protected: 00061 /** Construct a package variable with no binding. The subclass 00062 must override the \c make_definiens member function. */ 00063 explicit cx_package_variable(ct_type const* t); 00064 00065 ~cx_package_variable(); 00066 00067 public: 00068 virtual ct_type const* resolve_type_of() const; 00069 00070 /** Return the definiens of the variable's definition. */ 00071 cx_expr* definiens() 00072 { 00073 if (!m_val) { 00074 m_includes.clear(); 00075 m_val = make_definiens(); 00076 } 00077 return m_val; 00078 } 00079 00080 /** Set the version of the symbol. This is used to avoid 00081 recompilation of code that is unchanged, and works only if 00082 the \c package is constructed with \c split_p=true. */ 00083 void set_version(unsigned long version) 00084 { 00085 m_has_version = 1; 00086 m_version = version; 00087 } 00088 00089 /** Print the definition of the variable. */ 00090 void print_definition(std::ostream& os); 00091 00092 /** Appends ctors of the variable and its definition. */ 00093 virtual void append_ctors_to(cx_block* blk); 00094 00095 /** Appends dtors of the variable and its definition. */ 00096 virtual void append_dtors_to(cx_block* blk); 00097 00098 protected: 00099 /** Add an #include directive to the implementation file. */ 00100 void include(std::string const& name) { m_includes.insert(name); } 00101 00102 /** Try to resolve the location by writing out the source, 00103 compile and dynamically link it in. */ 00104 virtual void* resolve(); 00105 00106 /** Create the definition of \a idr. The constructors and 00107 destructors of the defined variable, if any, will be put 00108 into separate functions, which will be run when the library 00109 is <tt>lt_dlopen</tt>ed or <tt>lt_dlclose</tt>d. */ 00110 virtual cx_expr* make_definiens(); 00111 00112 /** Return the equality of \c this and \c rhs as pointers. */ 00113 virtual bool equal_to(resolver* rhs); 00114 00115 private: 00116 cx_expr* m_val; 00117 package* m_pkg; 00118 00119 // Used to store the old m_ptr that must be copied when 00120 // relinking this value. 00121 void* m_old_ptr; 00122 00123 location* m_client; 00124 00125 unsigned long m_version; 00126 unsigned int m_has_version : 1; 00127 00128 // Non-zero if m_ptr points to a dlsym. 00129 unsigned int m_is_dlsym : 1; 00130 00131 // Non-zero if a public definition. 00132 unsigned int m_export_p : 1; 00133 00134 std::set<std::string> m_includes; 00135 00136 friend class package; 00137 }; 00138 00139 00140 /** \class package package.h more/lang/package.h 00141 ** 00142 ** A package of C function and type definitions. An internal 00143 ** package has access to a writable directory determined by the 00144 ** package name, where it can place source code and do 00145 ** compilations. An external package acts as a wrapper for an \c 00146 ** lt_dlhandle (see libltdl in the GNU Libtool). */ 00147 struct package 00148 : gc_cleanup 00149 { 00150 /// Type used for flags. 00151 typedef uint_least16_t flag_type; 00152 00153 /// Allow compilations to be done for this package. 00154 static flag_type const flag_compile = 1 << 0; 00155 00156 /// Split source files into one per symbol and compile separately. 00157 static flag_type const flag_split = 1 << 2; 00158 00159 /// Create a header file. 00160 static flag_type const flag_create_header = 1 << 3; 00161 00162 /// Include header files in source file. 00163 static flag_type const flag_use_headers = 1 << 4; 00164 00165 /// Mask of backend language specification 00166 static flag_type const flag_lang_mask = 3 << 8; 00167 00168 /// Generate C code. 00169 static flag_type const flag_lang_c = 1 << 8; 00170 00171 /// Generate C++ code (unfinished). 00172 static flag_type const flag_lang_cxx = 2 << 8; 00173 00174 /** If generating C++ code, don't use extern "C" linkage for 00175 ** exported names. Note that C++ mangeling is not handled, so 00176 ** with this flag set, the generated symbols can not be linked 00177 ** into the application. */ 00178 static flag_type const flag_cxx_symbols = 1 << 10; 00179 00180 /// FYI, the default flags for internal packages. 00181 static flag_type const flags_intern_default 00182 = flag_compile | flag_create_header | flag_use_headers | flag_lang_c; 00183 00184 /// FYI, the default flags for external packages. 00185 static flag_type const flags_extern_default = 0; 00186 00187 private: 00188 struct ct_struct_ptr_less 00189 { 00190 bool operator()(ct_struct* x, ct_struct* y) const 00191 { 00192 return x->c_name() < y->c_name(); 00193 } 00194 }; 00195 typedef std::set<package*> requires_container; 00196 typedef requires_container::iterator requires_iterator; 00197 typedef std::set< gen::hidden_ptr<package> > required_by_container; 00198 typedef required_by_container::iterator required_by_iterator; 00199 typedef std::set<ct_struct*, ct_struct_ptr_less> struct_container; 00200 typedef std::map<identifier, cx_package_variable*> definition_container; 00201 typedef definition_container::iterator definition_iterator; 00202 00203 public: 00204 /** Construct a package rooted at \a cxt named \a idr. If \a 00205 split_p, use one source file per symbol. \a cxt may be 0. 00206 The flags are set to <tt>flags_intern_default & ~flags_clear 00207 | flags_set</tt>. */ 00208 package(package* cxt, identifier idr, 00209 flag_type flags_set = 0, flag_type flags_clear = 0); 00210 00211 /** Construct an external package \a idr rooted at \a cxt with 00212 symbols from \a h. The destructor will call \c 00213 lt_dlclose(h). \a cxt may be 0. The flags are set to 00214 <tt>flags_extern_default & ~flags_clear | 00215 flags_set</tt>. */ 00216 package(package* cxt, identifier idr, lt_dlhandle h, 00217 flag_type flags_set = 0, flag_type flags_clear = 0); 00218 00219 /** Construct an external package \a idr rooted at \a cxt with 00220 symbols from \c lt_dlopenext(file). \a cxt may be 0. The 00221 flags are set to <tt>flags_extern_default & ~flags_clear | 00222 flags_set</tt>. */ 00223 package(package* cxt, identifier idr, char const* file, 00224 flag_type flags_set = 0, flag_type flags_clear = 0); 00225 00226 /** Destruct the package, this should be called by the collector. */ 00227 ~package(); 00228 00229 /** Return the flags. */ 00230 flag_type flags() const { return m_flags; } 00231 00232 /** True if this is an external package. */ 00233 bool is_extern() const { return m_extern_p; } 00234 00235 /** Define the variable \a pv in \a this package under the name 00236 \a idr. The package name and names of parent packages will 00237 be prepended to the name. If \a export_p is true, the name 00238 will have external linkage. */ 00239 void define(identifier idr, cx_package_variable* pv, bool export_p); 00240 00241 /** Define the variable of \a locn in \a this package under the 00242 name \a idr. See the other overload for details. \pre \c 00243 locn->get_resolver() is a \c cx_package_variable. */ 00244 void define(identifier idr, location& locn, bool export_p); 00245 00246 /** Undefine the variable with the name \a idr. */ 00247 void undefine(identifier idr); 00248 00249 /** Bind \a idr to \a tp is this package. The definition of the 00250 type is written out if needed. */ 00251 void define_type(identifier idr, ct_struct* tp, bool export_p); 00252 00253 /** Return the \c cx_package_variable of \a idfr or 0 if none. */ 00254 cx_package_variable* 00255 lookup(identifier idr) 00256 { 00257 definition_iterator it = m_defs.find(idr); 00258 if (it == m_defs.end()) 00259 return 0; 00260 else 00261 return it->second; 00262 } 00263 00264 /** Resolve the fully named symbol \a sym. */ 00265 void* 00266 resolve_no_prefix(char const* sym) 00267 { 00268 if (m_dlhandle) { 00269 if (void* ptr = lt_dlsym(m_dlhandle, sym)) 00270 return ptr; 00271 } 00272 return link(sym); 00273 } 00274 00275 /** Resolve \a sym adding the package prefix if applicable. */ 00276 void* 00277 resolve(char const* sym) 00278 { 00279 return resolve_no_prefix(mk_c_name(sym).c_str()); 00280 } 00281 00282 /** Create sources now. This is normally done 00283 automatically. */ 00284 void create_sources(); 00285 00286 /** Create sources and (re-)compile all symbols now. This is 00287 normally done automatically when an identifier is 00288 requested. */ 00289 void compile(); 00290 00291 /** Return a path for the package with components separated by 00292 ** \a sep. */ 00293 gen::gc_string mk_path(char const* sep) const; 00294 00295 private: 00296 void* link(char const* sym); 00297 void unlink(); 00298 bool use_cxx_symbols() const { return m_flags & flag_cxx_symbols; } 00299 00300 gen::gc_string mk_c_name(gen::gc_string) const; 00301 gen::gc_string include_name() const; 00302 char const* top_builddir() const { return "bld"; } //XXX 00303 00304 // The package which contains the definition of this package. 00305 package* m_context; 00306 00307 // The name of the C++ namespace or a string to mangle into 00308 // public C identifiers. 00309 identifier m_c_name; 00310 00311 // The definitions in this package. 00312 definition_container m_defs; 00313 00314 // Type definitions. 00315 struct_container m_structs; 00316 00317 // Packages that this package depends on. 00318 requires_container m_requires; 00319 00320 // Packages depending on this package. This container contains 00321 // "hidden_ptr"s that are erased by the package when it is 00322 // freed. 00323 required_by_container m_required_by; 00324 00325 // The compilation state. Always non-zero for an internal package. 00326 compilation* m_comp; 00327 00328 // Used if split_p to create the initializer and finalizer code. 00329 std::set<identifier> m_inits; 00330 std::set<identifier> m_finalizers; 00331 00332 // This is defined to the shared library handle afer 00333 // compilation with open_p = true. 00334 lt_dlhandle m_dlhandle; 00335 00336 // Function to call before closing the library. 00337 gen::gc_string m_name_init; 00338 gen::gc_string m_name_fin; 00339 void (*m_finalizer)(); 00340 00341 // Set if the package is external, i.e. constructed with an 00342 // lt_dlhandle. 00343 unsigned int m_extern_p : 1; 00344 00345 // Debugging flag set if a package which this depends on was 00346 // deleted. This should only happend when this packages is also 00347 // scheduled for cleanup. 00348 unsigned int m_dropped_dep : 1; 00349 00350 // Failed to lt_dlclose previous revision of the libtool library. 00351 unsigned int m_dl_not_closed : 1; 00352 00353 flag_type m_flags; 00354 00355 friend class cx_package_variable; 00356 }; 00357 00358 /// \internal 00359 package* bits_package(); 00360 00361 /** An anonymous package containing the symbols of the running 00362 ** program. 00363 ** 00364 ** \pre The program must be compiled with \c -export-dynamic or \c 00365 ** -dlopen self (see the Libtool documentation). 00366 ** 00367 ** \exception std::runtime_error if dlopen-ing itself is not 00368 ** possible. */ 00369 package* self_package(); 00370 }} 00371 00372 #endif