home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rexxtk12.zip / rxpack.c < prev    next >
Text File  |  2002-08-07  |  31KB  |  1,057 lines

  1. /*
  2.  * Copyright (C) 1998-1999  Mark Hessling <M.Hessling@qut.edu.au>
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Library General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  * Library General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Library General Public
  15.  * License along with this library; if not, write to the Free
  16.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. static char RCSid[] = "$Id: rxpack.c,v 1.2 2001/07/22 09:37:20 mark Exp $";
  20.  
  21. #include "rxpack.h"
  22.  
  23. RxPackageGlobalDataDef *RxPackageGlobalData=NULL;
  24.  
  25. #if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  26. RexxExitHandler RxExitHandlerForSayTraceRedirection;
  27. #endif
  28.  
  29. extern RexxFunction RxPackageFunctions[];
  30.  
  31. #if !defined(HAVE_STRERROR)
  32. /*
  33.  * This function and the following description borrowed from Regina 0.08a
  34.  *
  35.  * Sigh! This must probably be done this way, although it's incredibly 
  36.  * backwards. Some versions of gcc comes with a complete set of ANSI C
  37.  * include files, which contains the definition of strerror(). However,
  38.  * that function does not exist in the default libraries of SunOS. 
  39.  * To circumvent that problem, strerror() is #define'd to get_sys_errlist() 
  40.  * in config.h, and here follows the definition of that function. 
  41.  * Originally, strerror() was #defined to sys_errlist[x], but that does
  42.  * not work if string.h contains a declaration of the (non-existing) 
  43.  * function strerror(). 
  44.  *
  45.  * So, this is a mismatch between the include files and the library, and
  46.  * it should not create problems for Regina. However, the _user_ will not
  47.  * encounter any problems until he compiles Regina, so we'll have to 
  48.  * clean up after a buggy installation of the C compiler!
  49.  */
  50. char *rxpackage_get_sys_errlist( int num )
  51. {
  52.    extern char *sys_errlist[] ;
  53.    return sys_errlist[num] ;
  54. }
  55. #endif
  56.  
  57.  
  58. /*-----------------------------------------------------------------------------
  59.  * Compares buffers for equality ignoring case
  60.  *----------------------------------------------------------------------------*/
  61. int memcmpi
  62.  
  63. #ifdef HAVE_PROTO
  64.    (char *buf1, char *buf2, int len)
  65. #else
  66.    (buf1,buf2,len)
  67.    char    *buf1;
  68.    char    *buf2;
  69.    int     len;
  70. #endif
  71. {
  72.    register short i=0;
  73.    char c1=0,c2=0;
  74.    for(i=0;i<len;i++)
  75.    {
  76.       if (isupper(*buf1))
  77.          c1 = tolower(*buf1);
  78.       else
  79.          c1 = *buf1;
  80.       if (isupper(*buf2))
  81.          c2 = tolower(*buf2);
  82.       else
  83.          c2 = *buf2;
  84.       if (c1 != c2)
  85.          return(c1-c2);
  86.       ++buf1;
  87.       ++buf2;
  88.    }
  89.  return(0);
  90. }
  91. /*-----------------------------------------------------------------------------
  92.  * Uppercases the supplied string.
  93.  *----------------------------------------------------------------------------*/
  94. char *make_upper
  95.  
  96. #ifdef HAVE_PROTO
  97.    (char *str)
  98. #else
  99.    (str)
  100.    char    *str;
  101. #endif
  102.  
  103. {
  104.    char *save_str=str;
  105.    while(*str)
  106.    {
  107.       if (islower(*str))
  108.          *str = toupper(*str);
  109.       ++str;
  110.    }
  111.    return(save_str);
  112. }
  113.  
  114. /*-----------------------------------------------------------------------------
  115.  * Allocate memory for a char * based on an RXSTRING
  116.  *----------------------------------------------------------------------------*/
  117. char *AllocString
  118.  
  119. #ifdef HAVE_PROTO
  120.    (char *buf, int bufsize)
  121. #else
  122.    (buf, bufsize)
  123.    char    *buf;
  124.    int   bufsize;
  125. #endif
  126. {
  127.    char *tempstr=NULL;
  128.  
  129.    tempstr = (char *)malloc(sizeof(char)*(bufsize+1));
  130.    return tempstr;
  131. }
  132.  
  133.  
  134. /*-----------------------------------------------------------------------------
  135.  * Copy a non terminated character array to the nominated buffer (truncate
  136.  * if necessary) and null terminate.
  137.  *----------------------------------------------------------------------------*/
  138. char *MkAsciz
  139.  
  140. #ifdef HAVE_PROTO
  141.    (char *buf, int bufsize, char *str, int len)
  142. #else
  143.    (buf, bufsize, str, len)
  144.    char    *buf;
  145.    int  bufsize;
  146.    char    *str;
  147.    int  len;
  148. #endif
  149.  
  150. {
  151.    bufsize--;     /* Make room for terminating byte */
  152.    if (len > bufsize)
  153.       len = bufsize;
  154.    (void)memcpy(buf, str, len);
  155.    buf[len] = '\0';
  156.    return buf;
  157. }
  158.  
  159. /*-----------------------------------------------------------------------------
  160.  * Check number of parameters
  161.  *----------------------------------------------------------------------------*/
  162. int my_checkparam(const char *name, int argc, int mini, int maxi)
  163. {
  164.    if ( argc < mini )
  165.    {
  166.       RxDisplayError(name, 
  167.                      "*ERROR* Not enough parameters in call to \"%s\". Minimum %d\n",
  168.                      name, mini);
  169.       return 1;
  170.    }
  171.    if ( argc > maxi
  172.    &&   maxi != 0 )
  173.    {
  174.       RxDisplayError(name, 
  175.                      "*ERROR* Too many parameters in call to \"%s\". Maximum %d\n",
  176.                      name, maxi);
  177.       return 1;
  178.    }
  179.    return 0;
  180. }
  181.  
  182. /*-----------------------------------------------------------------------------
  183.  * Create a REXX variable of the specified name and bind the value to it.
  184.  *----------------------------------------------------------------------------*/
  185. int SetRexxVariable
  186.  
  187. #ifdef HAVE_PROTO
  188.    (char *name, int namelen, char *value, int valuelen)
  189. #else
  190.    (name, namelen, value, valuelen)
  191.    char    *name;
  192.    int     namelen;
  193.    char    *value;
  194.    int     valuelen;
  195. #endif
  196.  
  197. {
  198.    ULONG  rc=0L;
  199.    SHVBLOCK       shv;
  200.  
  201.    InternalTrace( "SetRexxVariable", "%s,%d,%s,%d", name, namelen, value, valuelen );
  202.  
  203.    if ( RxPackageGlobalData->RxRunFlags & MODE_DEBUG)
  204.    {
  205.       char buf1[50], buf2[50];
  206.  
  207.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer,
  208.          "*DEBUG* Setting variable \"%s\" to \"%s\".\n",
  209.          MkAsciz( buf1, sizeof( buf1 ), name, namelen ),
  210.          MkAsciz( buf2, sizeof( buf2 ), value, valuelen ) );
  211.    }
  212.    shv.shvnext = ( SHVBLOCK* )NULL;
  213. #if defined(USE_REGINA)
  214.    shv.shvcode = RXSHV_SYSET;
  215. #else
  216.    shv.shvcode = RXSHV_SET;
  217. #endif
  218.    MAKERXSTRING( shv.shvname, name, ( ULONG )namelen );
  219.    MAKERXSTRING( shv.shvvalue, value, ( ULONG )valuelen );
  220.    shv.shvnamelen = shv.shvname.strlength;
  221.    shv.shvvaluelen = shv.shvvalue.strlength;
  222.    assert( shv.shvname.strptr );
  223.    assert( shv.shvvalue.strptr );
  224.    rc = RexxVariablePool( &shv );
  225.    if ( rc == RXSHV_OK
  226.    ||   rc == RXSHV_NEWV )
  227.       return( 0 );
  228.    else
  229.       return( 1 );
  230. }
  231.  
  232. /*-----------------------------------------------------------------------------
  233.  * This function gets a REXX variable and returns it in an RXSTRING
  234.  *----------------------------------------------------------------------------*/
  235. RXSTRING *GetRexxVariable
  236.  
  237. #ifdef HAVE_PROTO
  238.    ( char *name, RXSTRING *value, int suffix )
  239. #else
  240.    ( name, value, suffix )
  241.    char *name;
  242.    RXSTRING *value;
  243.    int suffix;
  244. #endif
  245. {
  246.    static SHVBLOCK shv;
  247.    char variable_name[50];
  248.    ULONG rc = 0L;
  249.  
  250.    InternalTrace( "GetRexxVariable", "%s,%x,%d", name, value, suffix );
  251.  
  252.    shv.shvnext=NULL;                                /* only one block */
  253.    shv.shvcode = RXSHV_FETCH;
  254. /*
  255.  * This calls the RexxVariablePool() function for each value. This is
  256.  * not the most efficient way of doing this.
  257.  */
  258.    if ( suffix == -1)
  259.       strcpy( variable_name, name );
  260.    else
  261.       sprintf( variable_name, "%s%-d", name, suffix );
  262.    ( void )make_upper( variable_name );
  263. /*
  264.  * Now (attempt to) get the REXX variable
  265.  * Set shv.shvvalue to NULL to force interpreter to allocate memory.
  266.  */
  267.    assert( variable_name );
  268.    MAKERXSTRING( shv.shvname, variable_name, strlen( variable_name ) );
  269.    assert( shv.shvname.strptr );
  270.    shv.shvvalue.strptr = NULL;
  271.    shv.shvvalue.strlength = 0;
  272. /*
  273.  * One or both of these is needed, too <sigh>
  274.  */
  275.    shv.shvnamelen = strlen( variable_name );
  276.    shv.shvvaluelen = 0;
  277.    rc = RexxVariablePool( &shv );              /* Set the REXX variable */
  278.    if ( rc == RXSHV_OK )
  279.    {
  280.       assert( value );
  281.       value->strptr = ( RXSTRING_STRPTR_TYPE )malloc( ( sizeof( char )*shv.shvvalue.strlength ) + 1 );
  282.       if ( value->strptr != NULL )
  283.       {
  284.          value->strlength = shv.shvvalue.strlength;
  285.          memcpy( value->strptr, shv.shvvalue.strptr, value->strlength );
  286.          *( value->strptr + value->strlength ) = '\0';
  287.       }
  288. #if defined(REXXFREEMEMORY)
  289.       RexxFreeMemory( shv.shvvalue.strptr );
  290. #elif defined(WIN32) && (defined(USE_OREXX) || defined(USE_WINREXX) || defined(USE_QUERCUS))
  291.       GlobalFree( shv.shvvalue.strptr );
  292. #elif defined(USE_OS2REXX)
  293.       DosFreeMem( shv.shvvalue.strptr );
  294. #else
  295.       free( shv.shvvalue.strptr );
  296. #endif
  297.    }
  298.    else
  299.       value = NULL;
  300.    return( value );
  301. }
  302.  
  303. /*-----------------------------------------------------------------------------
  304.  * Converts a RXSTRING to integer. Return 0 if OK and -1 if error.
  305.  * Assumes a string of decimal digits and does not check for overflow!
  306.  *----------------------------------------------------------------------------*/
  307. int StrToInt
  308.  
  309. #ifdef HAVE_PROTO
  310.    (RXSTRING *ptr, ULONG *result) 
  311. #else
  312.    (ptr, result) 
  313.    RXSTRING *ptr;
  314.    ULONG    *result; 
  315. #endif
  316.  
  317. {
  318.    int    i=0;
  319.    char   *p=NULL;
  320.    ULONG  sum=0L;
  321.  
  322.    p = (char *)ptr->strptr;
  323.    for (i = ptr->strlength; i; i--)
  324.    {
  325.       if (isdigit(*p))
  326.          sum = sum * 10 + (*p++ - '0');
  327.       else
  328.          return -1;
  329.    }
  330.    *result = sum;
  331.    return 0;
  332. }
  333.  
  334.  
  335. /*-----------------------------------------------------------------------------
  336.  * Converts a RXSTRING to a boolean. Input can be ON, Yes, 1 or OFF No, 0
  337.  *----------------------------------------------------------------------------*/
  338. int StrToBool
  339.  
  340. #ifdef HAVE_PROTO
  341.    (RXSTRING *ptr, ULONG *result) 
  342. #else
  343.    (ptr, result) 
  344.    RXSTRING *ptr;
  345.    ULONG    *result; 
  346. #endif
  347.  
  348. {
  349.    char   *p=(char *)ptr->strptr;
  350.    int    len=ptr->strlength;
  351.  
  352.    if (memcmp(p,"YES",len) == 0
  353.    ||  memcmp(p,"yes",len) == 0
  354.    ||  memcmp(p,"Y",len) == 0
  355.    ||  memcmp(p,"y",len) == 0
  356.    ||  memcmp(p,"ON",len) == 0
  357.    ||  memcmp(p,"on",len) == 0
  358.    ||  memcmp(p,"1",len) == 0)
  359.    {
  360.       *result = 1;
  361.       return(0);
  362.    }
  363.    if (memcmp(p,"NO",len) == 0
  364.    ||  memcmp(p,"no",len) == 0
  365.    ||  memcmp(p,"N",len) == 0
  366.    ||  memcmp(p,"n",len) == 0
  367.    ||  memcmp(p,"OFF",len) == 0
  368.    ||  memcmp(p,"off",len) == 0
  369.    ||  memcmp(p,"0",len) == 0)
  370.    {
  371.       *result = 0;
  372.       return(0);
  373.    }
  374.    return (-1);
  375. }
  376.  
  377.  
  378. /*-----------------------------------------------------------------------------
  379.  * This is called when in VERBOSE mode. It prints function name & arg values.
  380.  *----------------------------------------------------------------------------*/
  381. void FunctionPrologue
  382.  
  383. #ifdef HAVE_PROTO
  384.    ( char *name, ULONG argc, RXSTRING *argv )
  385. #else
  386.    ( name, argc, argv )
  387.    char *name;
  388.    ULONG argc;
  389.    RXSTRING *argv;
  390. #endif
  391.  
  392. {
  393.    ULONG i = 0L;
  394.    char buf[61];
  395.  
  396.    if ( RxPackageGlobalData == NULL
  397.    ||   RxPackageGlobalData->RxPackageInitialised != RXPACKAGE_MAGIC_NUMBER )
  398.    {
  399.       (void)InitRxPackage( NULL );
  400.    }
  401.  
  402.    if ( RxPackageGlobalData->RxRunFlags & MODE_VERBOSE )
  403.    {
  404.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer, "++\n" );
  405.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer, "++ Call %s%s\n", name, argc ? "" : "()" );
  406.       for (i = 0; i < argc; i++) 
  407.       {
  408.          (void)fprintf( RxPackageGlobalData->RxTraceFilePointer, "++ %3ld: \"%s\"\n",
  409.             i+1,
  410.             MkAsciz( buf, sizeof(buf), (char *)RXSTRPTR( argv[i] ), (int)RXSTRLEN( argv[i] ) ) );
  411.       }
  412.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  413.    }
  414.    /*
  415.     * This should be replaced with an integer to make things
  416.     * run faster!!
  417.     */
  418.    if ( strcmp( name, RxPackageGlobalData->FName ) != 0 )
  419.       strcpy( RxPackageGlobalData->FName, name );
  420. }
  421.  
  422. /*-----------------------------------------------------------------------------
  423.  * This is called when in VERBOSE mode. It prints function name & return value.
  424.  *----------------------------------------------------------------------------*/
  425. long FunctionEpilogue
  426.  
  427. #ifdef HAVE_PROTO
  428.    ( char *name, long rc )
  429. #else
  430.    ( name, rc )
  431.    char *name;
  432.    long rc;
  433. #endif
  434.  
  435. {
  436.    if ( RxPackageGlobalData == NULL
  437.    ||   RxPackageGlobalData->RxPackageInitialised != RXPACKAGE_MAGIC_NUMBER )
  438.    {
  439.       return rc;
  440.    }
  441.  
  442.    if ( RxPackageGlobalData->RxRunFlags & MODE_VERBOSE )
  443.    {
  444.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer, "++\n" );
  445.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer, "++ Exiting %s() with %ld\n", name, rc );
  446.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  447.    }
  448.    return rc;
  449. }
  450.  
  451. /*-----------------------------------------------------------------------------
  452.  * This is called when run_flags & MODE_INTERNAL is true
  453.  *----------------------------------------------------------------------------*/
  454. void InternalTrace
  455.  
  456. #ifdef HAVE_PROTO
  457.     (char *name, ...)
  458. #else
  459.     (name)
  460.     char *name;
  461. #endif
  462.  
  463. {
  464.    va_list argptr;
  465.    char *fmt=NULL;
  466.  
  467.    if ( RxPackageGlobalData != NULL
  468.    &&   RxPackageGlobalData->RxPackageInitialised == RXPACKAGE_MAGIC_NUMBER 
  469.    &&   RxPackageGlobalData->RxRunFlags & MODE_INTERNAL )
  470.    {
  471.       (void) fprintf( RxPackageGlobalData->RxTraceFilePointer, ">>>> Call %s(", name );
  472.       va_start( argptr, name );
  473.       fmt = va_arg( argptr, char *);
  474.       if (fmt != NULL)
  475.       {
  476.          (void)vfprintf( RxPackageGlobalData->RxTraceFilePointer, fmt, argptr );
  477.       }
  478.       (void) fprintf( RxPackageGlobalData->RxTraceFilePointer, ")\n");
  479.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  480.       va_end( argptr );
  481.    }
  482.    return;
  483. }
  484. void RxDisplayError
  485.  
  486. #ifdef HAVE_PROTO
  487.     (RFH_ARG0_TYPE name, ...)
  488. #else
  489.     (name)
  490.     char *name;
  491. #endif
  492.  
  493. {
  494.    va_list argptr;
  495.    char *fmt=NULL;
  496.  
  497.    if ( RxPackageGlobalData != NULL
  498.    &&   RxPackageGlobalData->RxPackageInitialised == RXPACKAGE_MAGIC_NUMBER )
  499.    {
  500.       (void) fprintf( RxPackageGlobalData->RxTraceFilePointer, ">>>> Calling %s(", name );
  501.       va_start( argptr, name );
  502.       fmt = va_arg( argptr, char *);
  503.       if (fmt != NULL)
  504.       {
  505.          (void)vfprintf( RxPackageGlobalData->RxTraceFilePointer, fmt, argptr );
  506.       }
  507.       (void) fprintf( RxPackageGlobalData->RxTraceFilePointer, ")\n");
  508.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  509.       va_end( argptr );
  510.    }
  511.    return;
  512. }
  513.  
  514.  
  515. /*-----------------------------------------------------------------------------
  516.  * This function registers the external functions...
  517.  *----------------------------------------------------------------------------*/
  518. int RegisterRxFunctions
  519.  
  520. #ifdef HAVE_PROTO
  521.    ( void )
  522. #else
  523.    ( )
  524. #endif
  525.  
  526. {
  527.    RexxFunction *func=NULL;
  528.    ULONG rc=0L;
  529.  
  530.    InternalTrace( "RegisterRxFunctions", NULL );
  531.  
  532.    for ( func = RxPackageFunctions; func->InternalName; func++ )
  533.    {
  534. #if defined(DYNAMIC_LIBRARY)
  535. # if !defined(USE_REXX6000)
  536.       if (func->DllLoad)
  537.       {
  538.          rc = RexxRegisterFunctionDll( func->ExternalName,
  539.               RxPackageName,
  540.               func->InternalName );
  541.          InternalTrace("RegisterRxFunctions","%s-%d: Registered (DLL) %s with rc = %ld\n",__FILE__,__LINE__,func->ExternalName,rc);
  542.       }
  543. # endif
  544. #else
  545. # if defined(WIN32) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  546.       (void)RexxDeregisterFunction( func->ExternalName );
  547. # endif
  548. # if defined(USE_REXX6000)
  549.       rc = RexxRegisterFunction( func->ExternalName, func->EntryPoint, NULL );
  550.       InternalTrace("RegisterRxFunctions","%s-%d: Registered (EXE) %s with rc = %d\n",__FILE__,__LINE__,func->ExternalName,rc);
  551. # else
  552.       rc = RexxRegisterFunctionExe( func->ExternalName, func->EntryPoint );
  553.       InternalTrace("RegisterRxFunctions","%s-%d: Registered (EXE) %s with rc = %d\n",__FILE__,__LINE__,func->ExternalName,rc);
  554. # endif
  555. #endif
  556.       if (rc != RXFUNC_OK
  557. #ifdef RXFUNC_DUP
  558.       &&  rc != RXFUNC_DUP /* bug in Object Rexx for Linux */
  559. #else
  560.       &&  rc != RXFUNC_DEFINED
  561. #endif
  562.       &&  rc != RXFUNC_NOTREG)
  563.          return 1;
  564.    }
  565. #if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  566.    if ( RexxRegisterExitExe( ( RREE_ARG0_TYPE )RxPackageName,
  567.                              ( RREE_ARG1_TYPE )RxExitHandlerForSayTraceRedirection,
  568.                              ( RREE_ARG2_TYPE )NULL) != RXEXIT_OK )
  569.       return 1;
  570. #endif
  571.    return 0 ;
  572. }
  573.  
  574. /*-----------------------------------------------------------------------------
  575.  * This function queries if the supplied external function has been registered
  576.  *----------------------------------------------------------------------------*/
  577. int QueryRxFunction
  578.  
  579. #ifdef HAVE_PROTO
  580.    ( char *funcname )
  581. #else
  582.    ( funcname )
  583.    char *funcname;
  584. #endif
  585.  
  586. {
  587.    InternalTrace( "QueryRxFunction", "%s", funcname );
  588.  
  589. #if defined(USE_REXX6000)
  590.    if ( RexxQueryFunction( funcname, NULL ) == RXFUNC_OK )
  591. #else
  592.    if ( RexxQueryFunction( funcname ) == RXFUNC_OK )
  593. #endif
  594.    {
  595.       DEBUGDUMP(fprintf(stderr,"%s-%d: Query function %s - found\n",__FILE__,__LINE__,funcname);)
  596.       return 1;
  597.    }
  598.    DEBUGDUMP(fprintf(stderr,"%s-%d: Query function %s - not found\n",__FILE__,__LINE__,funcname);)
  599.    return 0;
  600. }
  601.  
  602. /*-----------------------------------------------------------------------------
  603.  * This function deregisters the external functions...
  604.  *----------------------------------------------------------------------------*/
  605. int DeregisterRxFunctions
  606.  
  607. #ifdef HAVE_PROTO
  608.    ( int verbose )
  609. #else
  610.    ( verbose )
  611.    int verbose;
  612. #endif
  613.  
  614. {
  615.    RexxFunction *func=NULL;
  616.    int rc=0;
  617.  
  618.    InternalTrace( "DeregisterRxFunctions", NULL );
  619.  
  620.    for ( func = RxPackageFunctions; func->InternalName; func++ )
  621.    {
  622.       assert( func->ExternalName );
  623.       rc = RexxDeregisterFunction( func->ExternalName );
  624.       if ( verbose )
  625.          fprintf(stderr,"Deregistering...%s - %d\n",func->ExternalName,rc);
  626.       DEBUGDUMP(fprintf(stderr,"%s-%d: Deregistered %s with rc %d\n",__FILE__,__LINE__,func->ExternalName,rc);)
  627.    }
  628. #if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  629.    RexxDeregisterExit( RxPackageName, NULL );
  630. #endif
  631.    return 0 ;
  632. }
  633.  
  634. /*-----------------------------------------------------------------------------
  635.  * This function is called to initialise the package
  636.  *----------------------------------------------------------------------------*/
  637. int InitRxPackage
  638.  
  639. #ifdef HAVE_PROTO
  640.    ( RxPackageGlobalDataDef *MyGlob )
  641. #else
  642.    ( MyGlob )
  643.    RxPackageGlobalDataDef *MyGlob;
  644. #endif
  645.  
  646. {
  647.    ULONG rc=0L;
  648.    char *env;
  649.  
  650.    DEBUGDUMP(fprintf(stderr,"%s-%d: Start of InitRxPackage\n",__FILE__,__LINE__);)
  651.    RxPackageGlobalData = NULL;
  652.    if ( ( RxPackageGlobalData = ( RxPackageGlobalDataDef *)malloc( sizeof( RxPackageGlobalDataDef ) ) ) == NULL )
  653.    {
  654.       fprintf( stderr, "Unable to allocate memory for Global Data\n" );
  655.       return 1;
  656.    }
  657.    if ( MyGlob == NULL )
  658.    {
  659.       memset( RxPackageGlobalData, 0, sizeof( RxPackageGlobalDataDef ) );
  660.       (void)RxSetTraceFile( "stderr" );
  661.    }
  662.    else
  663.    {
  664.       memcpy( RxPackageGlobalData, MyGlob, sizeof( RxPackageGlobalDataDef ) );
  665.       (void)RxSetTraceFile( MyGlob->RxTraceFileName );
  666.    }
  667.    RxPackageGlobalData->RxPackageInitialised = RXPACKAGE_MAGIC_NUMBER;
  668.    if ((env = getenv(RXPACKAGE_DEBUG_VAR)))
  669.       RxPackageGlobalData->RxRunFlags |= atoi(env);
  670.  
  671.    /* 
  672.     * Call any package-specific startup code here
  673.     */
  674.    rc = InitialisePackage( );
  675.    DEBUGDUMP(fprintf(stderr,"%s-%d: End of InitRxPackage with rc = %ld\n",__FILE__,__LINE__,rc);)
  676.    return rc;
  677. }
  678.  
  679.  
  680. /*-----------------------------------------------------------------------------
  681.  * This function is called to terminate all activity with the package.
  682.  *----------------------------------------------------------------------------*/
  683. int TermRxPackage
  684.  
  685. #ifdef HAVE_PROTO
  686.    ( char *progname, int deregfunc )
  687. #else
  688.    ( progname, deregfunc )
  689.    char *progname;
  690.    int deregfunc;
  691. #endif
  692.  
  693. {
  694.    int rc=0;
  695.  
  696.    FunctionPrologue( "TermRxPackage", 0L, NULL );
  697.  
  698.    DEBUGDUMP(fprintf(stderr,"%s-%d: Start of TermRxPackage\n",__FILE__,__LINE__);)
  699.    /* 
  700.     * De-register all REXX/SQL functions only 
  701.     * if DEBUG value = 99
  702.     * DO NOT DO THIS FOR DYNAMIC LIBRARY
  703.     * AS IT WILL DEREGISTER FOR ALL PROCESSES
  704.     * NOT JUST THE CURRENT ONE.               
  705.     */
  706.    if (deregfunc)
  707.    {
  708.       if ( ( rc = DeregisterRxFunctions( 0 ) ) )
  709.          return (int)FunctionEpilogue( "TermRxPackage", (long)rc );
  710.    }
  711.    /* 
  712.     * Call any package-specific termination code here
  713.     */
  714.    if ( ( rc = TerminatePackage( ) ) )
  715.       return (int)FunctionEpilogue( "TermRxPackage", (long)rc );
  716. #if !defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  717.    RexxDeregisterExit( ( RDE_ARG0_TYPE )RxPackageName,
  718.                        ( RDE_ARG1_TYPE )NULL );
  719. #endif
  720.    if ( RxPackageGlobalData->RxTraceFilePointer != stdin
  721.    &&   RxPackageGlobalData->RxTraceFilePointer != stderr )
  722.       fclose( RxPackageGlobalData->RxTraceFilePointer );
  723.  
  724.    free( RxPackageGlobalData );
  725.    RxPackageGlobalData = NULL;
  726.    DEBUGDUMP(fprintf(stderr,"%s-%d: End of TermRxPackage with rc = 0\n",__FILE__,__LINE__);)
  727.    return (int)FunctionEpilogue( "TermRxPackage", (long)0 );
  728. }
  729.  
  730.  
  731. /*-----------------------------------------------------------------------------
  732.  * This function 
  733.  *----------------------------------------------------------------------------*/
  734. int RxSetTraceFile
  735.  
  736. #ifdef HAVE_PROTO
  737.    ( char *name )
  738. #else
  739.    ( name )
  740.    char *name;
  741. #endif
  742.  
  743. {
  744.    FILE *fp = NULL;
  745.  
  746.    InternalTrace( "RxSetTraceFile", "%s", name );
  747.  
  748.    if ( strcmp( "stdin", name ) == 0 )
  749.    {
  750.       RxPackageGlobalData->RxTraceFilePointer = stdin;
  751.       strcpy( RxPackageGlobalData->RxTraceFileName, "stdin" );
  752.    }
  753.    else
  754.    {
  755.       if ( strcmp( "stderr", name ) == 0 )
  756.       {
  757.          RxPackageGlobalData->RxTraceFilePointer = stderr;
  758.          strcpy( RxPackageGlobalData->RxTraceFileName, "stderr" );
  759.       }
  760.       else
  761.       {
  762.          if ( RxPackageGlobalData->RxTraceFilePointer != NULL )
  763.             fclose( RxPackageGlobalData->RxTraceFilePointer );
  764.          fp = fopen( name, "w" );
  765.          if ( fp == NULL )
  766.          {
  767.             (void)fprintf( stderr, "ERROR: Could not open trace file: %s for writing\n", name );
  768.             return( 1 );
  769.          }
  770.          RxPackageGlobalData->RxTraceFilePointer = fp;
  771.          strcpy( RxPackageGlobalData->RxTraceFileName, name );
  772.       }
  773.    }
  774.    return( 0 );
  775. }
  776.  
  777. /*-----------------------------------------------------------------------------
  778.  * This function 
  779.  *----------------------------------------------------------------------------*/
  780. char *RxGetTraceFile
  781.  
  782. #ifdef HAVE_PROTO
  783.    ( void )
  784. #else
  785.    ( )
  786. #endif
  787.  
  788. {
  789.    InternalTrace( "RxGetTraceFile", NULL );
  790.    return ( RxPackageGlobalData->RxTraceFileName );
  791. }
  792.  
  793. /*-----------------------------------------------------------------------------
  794.  * This function 
  795.  *----------------------------------------------------------------------------*/
  796. void RxSetRunFlags
  797.  
  798. #ifdef HAVE_PROTO
  799.    ( int flags )
  800. #else
  801.    ( flags )
  802.    int flags;
  803. #endif
  804.  
  805. {
  806.    InternalTrace( "RxSetRunFlags", "%d", flags );
  807.    RxPackageGlobalData->RxRunFlags = flags;
  808. }
  809.  
  810. /*-----------------------------------------------------------------------------
  811.  * This function 
  812.  *----------------------------------------------------------------------------*/
  813. int RxGetRunFlags
  814.  
  815. #ifdef HAVE_PROTO
  816.    ( void )
  817. #else
  818.    ( )
  819. #endif
  820.  
  821. {  
  822.    InternalTrace( "RxGetRunFlags", NULL );
  823.    return ( RxPackageGlobalData->RxRunFlags );
  824. }
  825.  
  826. /*-----------------------------------------------------------------------------
  827.  * This function 
  828.  *----------------------------------------------------------------------------*/
  829. int RxReturn
  830.  
  831. #ifdef HAVE_PROTO
  832.    ( RXSTRING *retstr )
  833. #else
  834.    ( retstr )
  835.    RXSTRING *retstr;
  836. #endif
  837. {
  838.    InternalTrace( "RxReturn" );
  839.  
  840.    if ( RxPackageGlobalData
  841.    &&   RxPackageGlobalData->RxRunFlags & MODE_VERBOSE )
  842.    {
  843.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer,
  844.           "++ Exit %s with value \"%s\"\n",
  845.           RxPackageGlobalData->FName,
  846.           retstr->strptr );
  847.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  848.    }
  849.    return( 0 );
  850. }
  851.  
  852. /*-----------------------------------------------------------------------------
  853.  * This function 
  854.  *----------------------------------------------------------------------------*/
  855. int RxReturnNumber
  856.  
  857. #ifdef HAVE_PROTO
  858.    ( RXSTRING *retstr, long num )
  859. #else
  860.    ( retstr, num )
  861.    RXSTRING *retstr;
  862.    long num;
  863. #endif
  864. {
  865.    InternalTrace( "RxReturnNumber", "%x,%d", retstr, num );
  866.  
  867.    sprintf( (char *)retstr->strptr, "%ld", num );
  868.    retstr->strlength = strlen( (char *)retstr->strptr );
  869.    if ( RxPackageGlobalData
  870.    &&   RxPackageGlobalData->RxRunFlags & MODE_VERBOSE )
  871.    {
  872.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer,
  873.          "++ Exit %s with value \"%ld\"\n",
  874.          RxPackageGlobalData->FName,
  875.          num );
  876.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  877.    }
  878.    return( 0 );
  879. }
  880.  
  881. /*-----------------------------------------------------------------------------
  882.  * This function 
  883.  *----------------------------------------------------------------------------*/
  884. int RxReturnString
  885.  
  886. #ifdef HAVE_PROTO
  887.    ( RXSTRING *retstr, char *str )
  888. #else
  889.    ( retstr, str )
  890.    RXSTRING *retstr;
  891.    char *str;
  892. #endif
  893. {
  894.    return( RxReturnStringAndFree( retstr, str, 0 ) );
  895. }
  896.  
  897. /*-----------------------------------------------------------------------------
  898.  * This function 
  899.  *----------------------------------------------------------------------------*/
  900. int RxReturnStringAndFree
  901.  
  902. #ifdef HAVE_PROTO
  903.    ( RXSTRING *retstr, char *str, int freeit )
  904. #else
  905.    ( retstr, str, freeit )
  906.    RXSTRING *retstr;
  907.    char *str;
  908.    int freeit;
  909. #endif
  910. {
  911.    int len = strlen( str );
  912.    char *ret = NULL;
  913.  
  914.    InternalTrace( "RxReturnStringAndFree", "%x,%s Free: %d", retstr, str, freeit );
  915.  
  916.    if ( len > RXAUTOBUFLEN )
  917.    {
  918. #if defined(REXXFREEMEMORY)
  919.       ret = (char *)RexxAllocateMemory( len + 1 );
  920. #elif defined(WIN32) && ( defined(USE_WINREXX) || defined(USE_QUERCUS) || defined(USE_OREXX) )
  921.       ret = ( char * )GlobalLock( GlobalAlloc ( GMEM_FIXED, len + 1 ) );
  922. #elif defined(USE_OS2REXX)
  923.       if ( ( BOOL )DosAllocMem( (void **)&ret, len + 1, fPERM|PAG_COMMIT ) )
  924.          ret = ( char * )NULL;
  925. #else
  926.       ret = ( char * )malloc( len );
  927. #endif
  928.       if ( ret == ( char * )NULL )
  929.       {
  930.          fprintf( stderr, "Unable to allocate %d bytes for return string \"%s\"\n", len, str );
  931.          return( 1 );
  932.       }
  933.       retstr->strptr = (RXSTRING_STRPTR_TYPE)ret;
  934.    }
  935.    memcpy( retstr->strptr, str, len );
  936.    retstr->strlength = len;
  937.    if ( RxPackageGlobalData
  938.    &&   RxPackageGlobalData->RxRunFlags & MODE_VERBOSE )
  939.    {
  940.       (void)fprintf( RxPackageGlobalData->RxTraceFilePointer,
  941.          "++ Exit %s with value \"%s\"\n",
  942.          RxPackageGlobalData->FName,
  943.          str );
  944.       fflush( RxPackageGlobalData->RxTraceFilePointer );
  945.    }
  946.    if ( freeit ) free( str );
  947.    return( 0 );
  948. }
  949.  
  950. /*-----------------------------------------------------------------------------
  951.  * This function
  952.  *----------------------------------------------------------------------------*/
  953. REH_RETURN_TYPE RxExitHandlerForSayTraceRedirection
  954.  
  955. #if defined(HAVE_PROTO)
  956.    ( REH_ARG0_TYPE ExitNumber, REH_ARG1_TYPE Subfunction, REH_ARG2_TYPE ParmBlock )
  957. #else
  958.    ( ExitNumber, Subfunction, ParmBlock )
  959.    REH_ARG0_TYPE ExitNumber;    /* code defining the exit function    */
  960.    REH_ARG1_TYPE Subfunction;   /* code defining the exit subfunction */
  961.    REH_ARG2_TYPE ParmBlock;     /* function dependent control block   */
  962. #endif
  963. {
  964.    long i = 0;
  965.    int rc = 0;
  966.  
  967.    switch( Subfunction )
  968.    {
  969.       case RXSIOSAY:
  970.       {
  971.          RXSIOSAY_PARM *say_parm = (RXSIOSAY_PARM *)ParmBlock;
  972.          if ( say_parm->rxsio_string.strptr != NULL )
  973.          {
  974.             for( i = 0; i < (long)say_parm->rxsio_string.strlength; i++ )
  975.                fputc( ( char )say_parm->rxsio_string.strptr[i], 
  976.                   RxPackageGlobalData->RxTraceFilePointer );
  977.          }
  978.          fputc( '\n', RxPackageGlobalData->RxTraceFilePointer );
  979.          rc = RXEXIT_HANDLED;
  980.          break;
  981.       }
  982.       case RXSIOTRC:
  983.       {
  984.          RXSIOTRC_PARM *trc_parm = (RXSIOTRC_PARM *)ParmBlock;
  985.          if ( trc_parm->rxsio_string.strptr != NULL )
  986.          {
  987.             for( i = 0; i < (long)trc_parm->rxsio_string.strlength; i++ )
  988.                fputc( ( char )trc_parm->rxsio_string.strptr[i], 
  989.                   RxPackageGlobalData->RxTraceFilePointer );
  990.          }
  991.          fputc( '\n', RxPackageGlobalData->RxTraceFilePointer );
  992.          rc = RXEXIT_HANDLED;
  993.          break;
  994.       }
  995.       case RXSIOTRD:
  996.       {
  997.          RXSIOTRD_PARM *trd_parm = (RXSIOTRD_PARM *)ParmBlock;
  998.          int i = 0, ch = 0;
  999.          do
  1000.          {
  1001.             if ( i < 256 )
  1002.                trd_parm->rxsiotrd_retc.strptr[i++] = ch = getc( stdin ) ;
  1003.          } while( ch != '\012' && (ch != EOF ) ) ;
  1004.          trd_parm->rxsiotrd_retc.strlength = i - 1;
  1005.          rc = RXEXIT_HANDLED;
  1006.          break;
  1007.       }
  1008.       case RXSIODTR:
  1009.       {
  1010.          RXSIODTR_PARM *dtr_parm = (RXSIODTR_PARM *)ParmBlock;
  1011.          int i = 0, ch = 0;
  1012.          do
  1013.          {
  1014.             if ( i < 256 )
  1015.                dtr_parm->rxsiodtr_retc.strptr[i++] = ch = getc( stdin ) ;
  1016.          } while( ch != '\012' && (ch != EOF ) ) ;
  1017.          dtr_parm->rxsiodtr_retc.strlength = i - 1;
  1018.          rc = RXEXIT_HANDLED;
  1019.          break;
  1020.       }
  1021.       default:
  1022.          rc = RXEXIT_NOT_HANDLED;
  1023.          break;
  1024.    }
  1025.    return rc;
  1026. }
  1027.  
  1028. /*
  1029.  * Both WinRexx and Personal Rexx load and unload this DLL before and
  1030.  * after each call to an external function. If this DLL is not resident
  1031.  * a new copy of the DLL is loaded together with its data.  What happens
  1032.  * then is any data set by one call to an external function is lost
  1033.  * and there is no persistence of data.  This code ensures that when the
  1034.  * DLL starts, it stays resident, and when the DLL finishes it is
  1035.  * unloaded.
  1036.  */
  1037. #if defined(DYNAMIC_LIBRARY) && (defined(USE_WINREXX) || defined(USE_QUERCUS))
  1038. BOOL WINAPI DllMain( HINSTANCE hDLL, DWORD dwReason, LPVOID pReserved)
  1039. {
  1040.    switch( dwReason)
  1041.    {
  1042.       case DLL_PROCESS_ATTACH:
  1043.          LoadLibrary( RxPackageName );
  1044.          break;
  1045.       case DLL_PROCESS_DETACH:
  1046.          FreeLibrary( GetModuleHandle( RxPackageName ) );
  1047.          break;
  1048.       case DLL_THREAD_ATTACH:
  1049.          break;
  1050.       case DLL_THREAD_DETACH:
  1051.          break;
  1052.    }
  1053.    return(TRUE);
  1054. }
  1055. #endif
  1056.  
  1057.