home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tcltk805.zip / tcl805s.zip / tcl8.0.5 / os2 / tclOS2Dll.c < prev    next >
C/C++ Source or Header  |  2001-08-19  |  9KB  |  356 lines

  1. /* 
  2.  * tclOS2Dll.c --
  3.  *
  4.  *    This file contains the DLL entry point.
  5.  *
  6.  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
  7.  * Copyright (c) 1996-2001 Illya Vaes
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  */
  12.  
  13.  
  14. #include "tclOS2Int.h"
  15.  
  16. int _CRT_init(void);
  17. void _CRT_term(void);
  18.  
  19. static int           tclProcessesAttached = 0;
  20.  
  21. /*
  22.  * The following data structure is used to keep track of all of the DLL's
  23.  * opened by Tcl so that they can be freed when the Tcl.dll is unloaded.
  24.  */
  25.  
  26. typedef struct LibraryList {
  27.     HMODULE handle;
  28.     struct LibraryList *nextPtr;
  29. } LibraryList;
  30. /* List of currently loaded DLL's.  */
  31. static LibraryList *libraryList = NULL;
  32.  
  33. /*
  34.  * The following data structure is used to keep track of all of the memory
  35.  * alloced for environ by Tcl so that it can be freed when the dll is unloaded.
  36.  */
  37.  
  38. typedef struct AllocedMemList {
  39.     unsigned long handle;
  40.     char **environ;
  41.     int nrEntries;
  42.     struct AllocedMemList *nextPtr;
  43. } AllocedMemList;
  44. /* List of currently loaded DLL's.  */
  45. static AllocedMemList *allocedMemoryList = NULL;
  46.  
  47. static HMODULE tclInstance;   /* Global library instance handle. */
  48.  
  49. /*
  50.  * Declarations for functions that are only used in this file.
  51.  */
  52.  
  53. static void             UnloadLibraries _ANSI_ARGS_((void));
  54.  
  55. #ifndef STATIC_BUILD
  56.  
  57.  
  58. /*
  59.  *----------------------------------------------------------------------
  60.  *
  61.  * _DLL_InitTerm --
  62.  *
  63.  *    DLL entry point.
  64.  *
  65.  * Results:
  66.  *    TRUE on sucess, FALSE on failure.
  67.  *
  68.  * Side effects:
  69.  *    None.
  70.  *
  71.  *----------------------------------------------------------------------
  72.  */
  73. unsigned long
  74. _DLL_InitTerm(
  75.     unsigned long hInst,    /* Library instance handle. */
  76.     unsigned long reason    /* Reason this function is being called. */
  77. )
  78. {
  79.     switch (reason) {
  80.     case 0: {    /* INIT */
  81.         PPIB pibPtr;
  82.         PTIB tibPtr;
  83.         AllocedMemList *ptr;
  84.  
  85.         /* Add to the list for alloced memory */
  86.         ptr = (AllocedMemList*) ckalloc(sizeof(AllocedMemList));
  87. #ifdef VERBOSE
  88.         printf("Inserting item, allocedMemoryList was %p\n", allocedMemoryList);
  89. #endif
  90.         if (ptr == NULL) return FALSE;
  91.         ptr->handle = hInst;
  92.         ptr->nrEntries = 0;
  93.         ptr->environ = NULL;
  94.         ptr->nextPtr = allocedMemoryList;
  95.         allocedMemoryList = ptr;
  96.  
  97.         /* Let Tcl know our handle */
  98.     tclInstance = (HMODULE)hInst;
  99.  
  100.         /* Fill environ */
  101.         rc = DosGetInfoBlocks(&tibPtr, &pibPtr);
  102.         if (environ == NULL) {
  103.             /* Determine length of environment */
  104.             BOOL lastString = FALSE;
  105.             PCHAR nextString = pibPtr->pib_pchenv;
  106.             int length = 0;
  107. #ifdef VERBOSE
  108.             int envSize = 0;
  109.             printf("Copying environ...\n");
  110. #endif
  111.             if (nextString == NULL || *nextString == 0) {
  112.                 lastString = TRUE;
  113.             }
  114.             while (!lastString) {
  115.                 length = strlen(nextString);
  116. #ifdef VERBOSE
  117.                 envSize += length+1;
  118. #endif
  119.                 nextString += length+1;
  120.                 ptr->nrEntries++;
  121.                 if (*nextString == 0) lastString = TRUE;
  122.             }
  123. #ifdef VERBOSE
  124.             printf("envSize %d\n", envSize);
  125. #endif
  126.             if (ptr->nrEntries > 0) {
  127.                 PCHAR copyString;
  128.                 int count = 0;
  129.                 environ = (char **) ckalloc(ptr->nrEntries * sizeof(char *));
  130.                 if (environ == NULL) return FALSE;
  131. #ifdef VERBOSE
  132.                 printf("ckalloced environ %d\n", ptr->nrEntries*sizeof(char *));
  133. #endif
  134.                 ptr->environ = environ;
  135.                 lastString = FALSE;
  136.                 nextString = pibPtr->pib_pchenv;
  137.                 while (!lastString) {
  138.                     length = strlen(nextString);
  139.                     copyString = ckalloc(length * sizeof(char) + 1);
  140. #ifdef VERBOSE
  141.                     printf("ckalloced copyString %d\n", length* sizeof(char)+1);
  142. #endif
  143.                     if (copyString == NULL) return FALSE;
  144.                     strncpy(copyString, nextString, length);
  145.                     environ[count] = copyString;
  146.                     count++;
  147.                     nextString += length+1;
  148.                     if (*nextString == 0) lastString = TRUE;
  149.                 }
  150.             }
  151. #ifdef VERBOSE
  152.         } else {
  153.             printf("Not copying environ\n");
  154. #endif
  155.         }
  156.  
  157.         tclProcessesAttached++;
  158.  
  159.         return TRUE; 
  160.     }
  161.  
  162.     case 1: {    /* TERM */
  163.         AllocedMemList *ptr, *prevPtr;
  164.  
  165.         /* Find in list of allocated memory */
  166.         ptr = allocedMemoryList;
  167.         prevPtr = ptr;
  168.         while (ptr != NULL && ptr->handle != hInst) {
  169. #ifdef VERBOSE
  170.             printf("while search\n");
  171. #endif
  172.             prevPtr = ptr;
  173.             ptr = ptr->nextPtr;
  174.         }
  175.         if (ptr != NULL) {
  176.             /* Remove from list */
  177.             if (allocedMemoryList == ptr) {
  178. #ifdef VERBOSE
  179.                 printf("remove first from list\n");
  180. #endif
  181.                 allocedMemoryList = ptr->nextPtr;
  182.             } else {
  183.                 prevPtr->nextPtr = ptr->nextPtr;
  184. #ifdef VERBOSE
  185.                 printf("remove non-first from list\n");
  186. #endif
  187.             }
  188.             /* Free memory */
  189.             while (ptr->nrEntries > 0) {
  190. #ifdef VERBOSE
  191.                 printf("ckfree entry %d [%s]\n", ptr->nrEntries - 1,
  192.                        ptr->environ[ptr->nrEntries - 1]);
  193. #endif
  194.                 ckfree(ptr->environ[ptr->nrEntries - 1]);
  195.                 ptr->nrEntries--;
  196.             }
  197.             ckfree((char *)ptr->environ);
  198. #ifdef VERBOSE
  199.             printf("ckfree-ed environ\n");
  200. #endif
  201.         }
  202.  
  203.         tclProcessesAttached--;
  204.         if (tclProcessesAttached == 0) {
  205.  
  206.             /*
  207.              * Finalize our use of Tcl.
  208.              */
  209.  
  210.             Tcl_Finalize();
  211.         }
  212.         return TRUE; 
  213.     }
  214.  
  215.     }
  216.  
  217.     return FALSE; 
  218. }
  219.  
  220. #endif /* !STATIC_BUILD */
  221.  
  222. /*
  223.  *----------------------------------------------------------------------
  224.  *
  225.  * TclpFinalize --
  226.  *
  227.  *      Clean up the OS/2 specific library state.
  228.  *
  229.  * Results:
  230.  *      None.
  231.  *
  232.  * Side effects:
  233.  *      Unloads any DLLs, if necessary.
  234.  *
  235.  *----------------------------------------------------------------------
  236.  */
  237.  
  238. void
  239. TclpFinalize()
  240. {
  241.     /*
  242.      * Cleanup any dynamically loaded libraries.
  243.      */
  244.  
  245.     UnloadLibraries();
  246. }
  247.  
  248. /*
  249.  *----------------------------------------------------------------------
  250.  *
  251.  * TclOS2LoadLibrary --
  252.  *
  253.  *      This function is a wrapper for the system DosLoadModule.  It is
  254.  *      responsible for adding library handles to the library list so
  255.  *      the libraries can be freed when tcl.dll is unloaded.
  256.  *
  257.  * Results:
  258.  *      Returns the handle of the newly loaded library, or NULL on
  259.  *      failure.
  260.  *
  261.  * Side effects:
  262.  *      Loads the specified library into the process.
  263.  *
  264.  *----------------------------------------------------------------------
  265.  */
  266.  
  267. HMODULE
  268. TclOS2LoadLibrary(name)
  269.     char *name;                 /* Library file to load. */
  270. {
  271.     HMODULE handle;
  272.     LibraryList *ptr;
  273.     UCHAR LoadError[256];       /* Area for name of DLL that we failed on */
  274.  
  275. #ifdef VERBOSE
  276.     LoadError[255] = '\0';
  277.     printf("TclOS2LoadLibrary [%s]\n", name);
  278.     fflush(stdout);
  279. #endif
  280.     rc = DosLoadModule((PSZ)LoadError, sizeof(LoadError), (PSZ)name, &handle);
  281.     if (rc == NO_ERROR) {
  282. #ifdef VERBOSE
  283.         printf("DosLoadModule [%s] OK (LoadError [%s])\n", name, LoadError);
  284.         fflush(stdout);
  285. #endif
  286.         ptr = (LibraryList*) ckalloc(sizeof(LibraryList));
  287.         ptr->handle = handle;
  288.         ptr->nextPtr = libraryList;
  289.         libraryList = ptr;
  290.         return handle;
  291.     } else {
  292. #ifdef VERBOSE
  293.         printf("DosLoadModule %s ERROR %d on %s\n", name, rc, LoadError);
  294.         fflush(stdout);
  295. #endif
  296.         TclOS2ConvertError(rc);
  297.         return NULLHANDLE;
  298.     }
  299. }
  300.  
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * UnloadLibraries --
  305.  *
  306.  *      Frees any dynamically allocated libraries loaded by Tcl.
  307.  *
  308.  * Results:
  309.  *      None.
  310.  *
  311.  * Side effects:
  312.  *      Frees the libraries on the library list as well as the list.
  313.  *
  314.  *----------------------------------------------------------------------
  315.  */
  316.  
  317. static void
  318. UnloadLibraries()
  319. {
  320.     LibraryList *ptr;
  321.  
  322.     while (libraryList != NULL) {
  323.         DosFreeModule(libraryList->handle);
  324.         ptr = libraryList->nextPtr;
  325.         ckfree((char *)libraryList);
  326.         libraryList = ptr;
  327.     }
  328.     /* Don't forget to cleanly exit PM if applicable */
  329.     if (usePm) {
  330.         TclOS2PMShutdown();
  331.     }
  332.  
  333. }
  334.  
  335. /*
  336.  *----------------------------------------------------------------------
  337.  *
  338.  * TclOS2GetTclInstance --
  339.  *
  340.  *      Retrieves the global library instance handle.
  341.  *
  342.  * Results:
  343.  *      Returns the global library instance handle.
  344.  *
  345.  * Side effects:
  346.  *      None.
  347.  *
  348.  *----------------------------------------------------------------------
  349.  */
  350.  
  351. HMODULE
  352. TclOS2GetTclInstance()
  353. {
  354.     return tclInstance;
  355. }
  356.