home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Control Common / StartupSharedLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-11  |  6.4 KB  |  196 lines  |  [TEXT/CWIE]

  1.  
  2. /*
  3.  *    StartupSharedLib.c    -    init/startup/termination routines for Metrowerks C++ (PowerPC)
  4.  *
  5.  *    Copyright © 1995 metrowerks inc. All Rights Reserved.
  6.  *
  7.  *
  8.  *    THEORY OF OPERATION
  9.  *
  10.  *    This version of the PPC startup code is intended to be used for shared library
  11.  *    components of multi-fragment applications. It is designed to properly support
  12.  *    exceptions thrown across fragment boundaries, and proper initialization and
  13.  *    termination--including construction and destruction of static objects--for
  14.  *    a shared library that is one component of a complex, multi-fragment program.
  15.  *
  16.  *    The startup file defines 2 entry-points:
  17.  *
  18.  *        __initialize    This must be the Initialization Entry-Point for the Application.
  19.  *                        __initialize() registers the exception-handling info for
  20.  *                        the application, and calls all static initializers.
  21.  *
  22.  *        __terminate        This must be the Termination Entry-Point for the Application
  23.  *                        __terminate() unregisters the exception-handling info for the
  24.  *                        shared application before the fragment is unloaded.
  25.  *
  26.  *    The new zero-runtime-overhead exception-handling mechanism requires that we
  27.  *    keep track of all loaded fragments and their code/data section ranges--we
  28.  *    cannot use the OS data structures to do this--so we must call routines which
  29.  *    register and unregister the exception-handling info as a fragment is loaded/unloaded.
  30.  *
  31.  *    When the shared library is loaded, __sinit() will call constructors for static
  32.  *    objects, linking them into the (per-application) global destructor chain. These
  33.  *    objects will be destroyed when the application component of the program calls
  34.  *    __destroy_global_chain() as part of its exit() handling. This will ensure the
  35.  *    proper ordering of destruction wrt calling _atexit() handlers, cleaning up the
  36.  *    I/O and console packages, etc.
  37.  *
  38.  *    This startup file must -not- be used for shared libraries with shared data sections,
  39.  *    since these may be linked into multiple applications simultaneously, and cannot
  40.  *    have its static objects linked into the application's global destructor chain.
  41.  *
  42.  */
  43.  
  44. #include <Types.h>
  45. #include <exception.h>
  46. #include "ExceptionPPC.h"
  47. #include <NMWException.h>
  48.  
  49.  
  50.     /*    external data    */
  51.  
  52. extern char __code_start__[];                /*    (defined by linker)    */
  53. extern char    __code_end__[];                    /*    (defined by linker)    */
  54. extern char __data_start__[];                /*    (defined by linker)    */
  55. extern char __data_end__[];                    /*    (defined by linker)    */
  56. extern char __exception_table_start__[];    /*    (defined by linker)    */
  57. extern char __exception_table_end__[];        /*    (defined by linker)    */
  58.  
  59.  
  60.     /*    private data    */
  61.  
  62. static int fragmentID;                        /*    ID given to fragment by exception-handling    */
  63.  
  64. typedef struct FragmentInfo {
  65.     ExceptionTableIndex*    exception_start;    //    start of exception table index for fragment
  66.     ExceptionTableIndex*    exception_end;        //    end of exception table index for fragment
  67.     char*                    code_start;            //    start of code section for fragment
  68.     char*                    code_end;            //    end of code section for fragment
  69.     char*                    data_start;            //    start of data section for fragment
  70.     char*                    data_end;            //    end of data section for fragment
  71.     char*                    TOC;                //    TOC pointer for fragment
  72. } FragmentInfo;
  73.  
  74. #define    MAXFRAGMENTS    32                    //    maximum # of code fragments we can register
  75. static FragmentInfo fragmentinfo[MAXFRAGMENTS];
  76.  
  77.     /*    prototypes    */
  78.  
  79. #ifdef __cplusplus
  80. extern "C" {
  81. #endif
  82.  
  83. void __sinit(void);    /*    (generated by linker)    */
  84. OSErr __initialize(void);
  85. void __terminate(void);
  86.  
  87. #ifdef __cplusplus
  88. }
  89. #endif
  90.  
  91.  
  92. /*
  93.  *    __RTOC    -    return the TOC pointer for our code fragment
  94.  *
  95.  */
  96.  
  97. static asm char *__RTOC(void)
  98. {
  99.         mr        r3,RTOC
  100.         blr
  101. }
  102.  
  103.  
  104. /*
  105.  *    __initialize    -    Default initialization routine for Metrowerks C++ (PowerPC)
  106.  *
  107.  *    This routine should be specified as the PEF initialization routine in the container
  108.  *    for any multi-fragment application.
  109.  *
  110.  */
  111.  
  112. short __initialize(void)
  113. {
  114.     //    register this code fragment with the Exception Handling mechanism
  115.     fragmentID = __register_fragment(__code_start__, __code_end__,
  116.                                     __data_start__, __data_end__,
  117.                                     __exception_table_start__, __exception_table_end__,
  118.                                     __RTOC());
  119.     
  120.     //    call all static initializers
  121.     __sinit();
  122.     
  123.     //    return success to Code Fragment Manager
  124.     return(noErr);
  125. }
  126.  
  127.  
  128. /*
  129.  *    __terminate    -    Default termination routine for Metrowerks C++ (PowerPC)
  130.  *
  131.  *    This routine should be specified as the PEF termination routine in the container
  132.  *    for any multi-fragment application.
  133.  *
  134.  */
  135.  
  136. void __terminate(void)
  137. {
  138.     //    unregister this code fragment with the Exception Handling mechanism
  139.     __unregister_fragment(fragmentID);
  140. }
  141.  
  142. /************************************************************************/
  143. /* Purpose..: Register a code fragment and its exception tables            */
  144. /* Input....: pointer to start of fragments code section                */
  145. /* Input....: pointer to end   of fragments code section                */
  146. /* Input....: pointer to start of fragments data section                */
  147. /* Input....: pointer to end   of fragments data section                */
  148. /* Input....: pointer to start of fragments exception table index        */
  149. /* Input....: pointer to end   of fragments exception table index        */
  150. /* Input....: RTOC for fragment                                            */
  151. /* Return...: unique ID for __ex_unregister_fragment                    */
  152. /************************************************************************/
  153. int __register_fragment(char *code_start, char *code_end,
  154.                         char *data_start, char *data_end,
  155.                         char *exception_start, char *exception_end,
  156.                         char *TOC)
  157. {
  158.     FragmentInfo *f;
  159.     int i;
  160.     
  161.     //    find a free entry in the fragment table
  162.     for(i=0,f=fragmentinfo;i<MAXFRAGMENTS;++i,++f) if(f->code_start==0)
  163.     {
  164.         f->code_start=code_start;
  165.         f->code_end=code_end;
  166.         f->data_start=data_start;
  167.         f->data_end=data_end;
  168.         f->exception_start=(ExceptionTableIndex *)exception_start;
  169.         f->exception_end=(ExceptionTableIndex *)exception_end;
  170.         f->TOC=TOC;
  171.         return(i);
  172.     }
  173.     //    couldn't register the fragment
  174.     return(-1);
  175. }
  176.  
  177. /************************************************************************/
  178. /* Purpose..: Un-register a code fragment and its exception tables        */
  179. /* Input....: unique ID assigned in __ex_register_fragment                */
  180. /* Return...: ---                                                        */
  181. /************************************************************************/
  182. void __unregister_fragment(int fragmentID)
  183. {
  184.     FragmentInfo *f;
  185.     
  186.     if(fragmentID>=0 && fragmentID<MAXFRAGMENTS)
  187.     {
  188.         f = &fragmentinfo[fragmentID];
  189.         f->code_start=0; f->code_end=0;
  190.         f->data_start=0; f->data_end=0;
  191.         f->exception_start=0; f->exception_end=0;
  192.         f->TOC=0;
  193.     }
  194. }
  195.  
  196.