Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/lang/package.h

Go to the documentation of this file.
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

Generated on Sat Sep 7 19:11:17 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.