====================== RexxHost.Library v34.12 ======================= ====================================================================== An Amiga shared library for creating/managing ARexx host environments. ====================================================================== ========================== IMPORTANT NOTICE ========================== ====================================================================== This is the official new release of rexxhost.library. Due to register rearrangements programs compiled using the old 1.6 release have to be recompiled or serious system crashes will result! Note that the supplied library code can only be recompiled under Aztec 'C' 5.0. ============================= Background ============================= ====================================================================== A friend of mine was busy developing a stock management program when he suddenly realized that an ARexx interface would be the only feature that wasn't already part of his project. So he started to analyze, to program, to try - just to find out that it would be too much work to add it. Some months later a programmer who works for the same company I am working for decided to rewrite his home-brewn assembler/linker program to interface to CygnusEd Professional. The problem is: his program is written in assembly language, the standard host management routines are written in 'C'... To simplify the host creation/management procedure I decided to put the required routines as well as some extra code into a shared library, easy to use by ANY language (can you imagine AmigaBASIC controlling AmigaTeX?). As soon as the Aztec 'C' 5.0 update came in, the library has been updated to take advantage of the new compiler features. I suppose the source code can be seen as a real 'treasure' for programmers who also wish to build shared libraries with the new Manx compiler but find the original Manx support code too confusing. ========================= Supplied material ========================== ====================================================================== The RexxHostLib package contains the following files: ----------------------------------------------------- FancyDemo.............. Demonstration program FancyDemo.c............ Source code for demonstration program LibStartup.asm......... Library support code LibMain.c.............. Library support code PreInclude.c........... Source for precompiled header file RexxHostLib.c.......... Library support code rexxhostbase.h......... Library header file StringAsm.asm.......... Assembly language string routines rexxhostlat.lib........ Lattice 'C' linker library rexxhostnew.lib........ Aztec 'C' 5.0 linker library rexxhostold.lib........ Aztec 'C' 3.6 linker library rexxhost.library....... Amiga shared library MakeFile............... Library building-instructions RexxHost.fd............ Library function definitions TestDemo.rexx.......... ARexx demonstration script RexxHost.doc........... This file Glue................... Subdirectory containing library glue routine source codes ============================= How to use ============================= ====================================================================== The rexxhost.library needs ARexx (any version will do, v1.10 is best) to work properly. It needs to be opened EXPLICITELY, i.e. it is not forced into memory by the ARexx server and CANNOT be loaded with the ADDLIB() call in rexx-scriptfiles. An unlimited number of callers may open the library, it is 100% reentrant. Just like the rexxsyslib.library the rexxhost.library stays in memory until explicitely expunged (e.g. via "flushlibs" call from Workbench). The OpenLibrary() call returns a pointer to a RexxHostBase structure (as defined in the rexxhostbase.h include file). It has the following format: struct RexxHostBase { struct Library LibNode; struct RxsLib *RexxSysBase; }; The pointer to the RxsLib structure represents a pointer to the base of rexxsyslib.library. It can be copied by the calling process, rexxsyslib.library does not need to be opened explicitely. All library functions are "bullet proof", i.e. if the supplied arguments are illegal the functions return immediately. Note that this library only contains basic support functions, you will still have to do command analysis, parsing and command processing on your own (which isn't difficult, look at the DClockHandler.c sourcecode for an example). ============================= Compiling ============================== ====================================================================== A Makefile for Aztec 'C' 5.0 is supplied. This version CANNOT be recompiled under compiler versions previous to 5.0. Note that line 67 in the ARexx 'C' include file 'rxslib.h' has to be changed from: WORD rl_NumMsg; /* pending count */ to: WORD rl_PgmMsg; /* pending count */ or you will get a 'multiple entry' message from the compiler (Bill obviously overlooked the misspelled entry). ===================== RexxHost.Library Functions ===================== ====================================================================== CreateRexxHost - Create a RexxHost with supplied name Usage: RexxHost = CreateRexxHost(HostName) D0 A0 This function tries to allocate a public messageport with a unique name. If a port with the supplied name does already exist NULL is returned. The name of the HostPort to be created is copied so there is no need to keep it statically initialized in you application. Note: NEVER use this function if you only want to allocate a general purpose MsgPort. Some additional type checking is done in this routine. A RexxHost is an extended MsgPort structure with some additional data which allows all library functions to test if a host address is valid. You should rather see a RexxHost as a MsgPort. Do not rely on the existence of the flags following the MsgPort structure. DeleteRexxHost - Remove RexxHost Usage: NULL = DeleteRexxHost(RexxHost) D0 A0 A supplied RexxHost is removed from the system, freeing allocated signals and nodes. A NULL-pointer is always returned so user can do 'Host = DeleteRexxHost(Host);'. Never use this function to remove a general purpose MsgPort from the system list, in which case DeleteRexxHost() is guaranteed to return immediately without doing anything. SendRexxCommand() - Send a command to the rexx server Usage: Success = SendRexxCommand(RexxHost,CommandString,FileExtension,HostName) D0 A0 A1 A2 A3 This function causes the rexx server to execute a script file. HostPort must point to the host RexxHost, CommandString points to a string containing the name of the command to be executed. FileExtension and HostName are optional and may be NULL. FileExtension defines the script file name extension for this host (for standard rexx scripts this is ".rexx", for CygnusEd Professional it is ".ced"). HostName is supplied to allow the host to address different sub-hosts, such as different windows a text editor may have open. This function returns FALSE (= 0) if the command cannot be sent (rexx may not be running) and TRUE (= 1) if the message has been posted. FreeRexxCommand() - Free the contents of a RexxMsg Usage: FreeRexxCommand(RexxMessage) A0 Having successfully called SendRexxCommand() the rexx server will return the RexxMsg with result flags set. This kind of message cannot be replied (since it already has been replied by the rexx server) but has to be deallocated. Be sure to examine the result code flags before you remove the RexxMsg. ReplyRexxCommand() - Returns a RexxMsg to the rexx server Usage: ReplyRexxCommand(RexxMessage,Primary,Secondary,Result) A0 D0 D1 A1 Having received a command from the rexx server the host has to process it. After that the RexxMsg has to be replied so the rexx server knows about the result. Primary and Secondary are the values to be passed in the result flags of the RexxMsg structure, Result is optional and may be NULL. It usually points to a string containing the result (numeric or string) of the command having been executed. GetRexxCommand() - Get the first argument from a RexxMsg Usage: String = GetRexxCommand(RexxMessage) D0 A0 This function is supported to save the calling program from dealing with pointer offsets (which may be difficult with some language implementations). It returns a pointer to the first argument entry in the supplied RexxMsg structure. This is usually a command to be executed by the host. If NULL is returned then the RexxMsg is a reply to a former SendRexxCommand() command. GetRexxArg() - Get the first argument from a RexxMsg Usage: String = GetRexxArg(RexxMessage) D0 A0 This function is supported to save the calling program from dealing with pointer offsets (which may be difficult with some language implementations). It returns a pointer to the first argument entry in the supplied RexxMsg structure. This function is almost identical to GetRexxCommand(), the string pointer is always returned, no RexxMsg type consideration is done. GetRexxResult1() - Get the first RexxMsg result code Usage: Result = GetRexxResult1(RexxMessage) D0 A0 This function is supported to save the calling program from dealing with pointer offsets (which may be difficult with some language implementations). It returns the value of the first result code entry in the supplied RexxMsg structure. GetRexxResult2() - Get the second RexxMsg result code Usage: Result = GetRexxResult2(RexxMessage) D0 A0 This function is supported to save the calling program from dealing with pointer offsets (which may be difficult with some language implementations). It returns the value of the second result code entry in the supplied RexxMsg structure. GetToken() - Get the next argument from a string Usage: Argument = GetToken(String,StartChar,AuxBuff,MaxLength) D0 A0 A1 A2 D0 GetToken() implements easy argument parsing. ARexx posts commands as NULL-terminated strings with arguments separated by spaces. GetToken() takes a pointer to the command string (String), a pointer to a counter variable (StartChar, must be a long), a pointer to a buffer the next argument will be copied to (AuxBuff) and the length of the buffer the next argument will be copied to (MaxLength). The result will be a pointer to AuxBuff if an argument was found, NULL if the end of the command string was reached. You are to make sure that the string pointed to by AuxBuff is long enough to hold the arguments. GetStringValue() - Return the numeric value of a string Usage: Value = GetStringValue(String) D0 A0 Just like the 'C' language atoi() function GetStringValue() evaluates the contents of a string. Its value is returned as a long word. This function helps to analyze the contents of a RexxMsg result code or command argument. BuildValueString() - Turns a numeric value into a string Usage: String = BuildValueString(Value,String) D0 D0 A0 This function helps to build a string from a numeric value, just like the 'C' language itoa() function. The supplied string must be long enough to hold the digits built from Value. A pointer to the built string is returned. RexxStrCmp() - Compare two strings ignoring case Usage: Match = RexxStrCmp(String1,String2) D0 A0 A1 This function is intended to be a replacement for the 'C' function strcmp(). Other than the builtin strcmp, RexxStrCmp ignores the case of both strings and even handles international characters correctly (i.e. RexxStrCmp("äöüß","ÄÖÜß") == 0). The value returned as Match is 0 if both strings are considered equal, any other value indicates that both strings are different. ============================== Nuisance ============================== ====================================================================== The library could be shorter if the Aztec 'C' linker 'LN' generated proper hunks: 1) DATA and BSS hunks are intermixed; as a result the BSS hunk turns out to have length zero which will still force DOS to allocate four extra bytes which are never used. 2) Additionally the DATA/BSS hunk has to be zeroed 'manually' which requires some extra code in crt0.a68. 3) Even if you don't request a BSS hunk the linker still generates one. The - empty - hunk (including superfluous relocation information) occupies disk space it doesn't need. Is there any chance this 'kludging' will ever be fixed? ============================== Credits =============================== ====================================================================== rexxhost.library was built from example source code written by Gary Samad & Bill Hawes (fancydemo.c), extensions & additional functions were created by Olaf 'Olsen' Barthel. The entire contents of this library package may be used for any purpose, no regard whether commercial or non-commercial. No credit must be given to the creator, nor must a registration fee be paid (though I wouldn't mind if anybody did). THIS IS TRULY PUBLIC DOMAIN! =============================== Author =============================== ====================================================================== Olaf 'Olsen' Barthel, MXM Brabeckstrasse 35 D-3000 Hannover 71 Federal Republic of Germany Phone: (05 11) 52 23 38 ============ Revision history (most recent change first) ============= ====================================================================== 34.12 The library can be recompiled using 16 bit integers now. I don't know if anybody profits from this feature but it's included anyway. By the way: code size went up to 2912 bytes. 34.11 The library went through the third major rewrite, along with some more cleanups (nobody told me that the NULL-function has to be supported) assembly language string-routines were introduced to reduce the amount of support-library code. Code size dropped to 2840 bytes. 34.10 Some more cleanups in RexxStrCmp and other routines were really necessary. As a result, code size went up to 2900 bytes. 34.9 Added more sanity checks in the Rexx Host creation/management procedure. An extended MsgPort structure with additional type data holds the interface now. Library code and data are now much more compact than in the previous releases (I spent two additional days debugging the code). Library size should be 2792 bytes now. 34.8 ANSIfication, more cleanups, added RexxStrCmp, rewrote CreateRexxHost/DeleteRexxHost to become shorter, made library use #pragma calls rather than to rely on the rexxglue.asm output file. Code size went down to about 2764 bytes (original size: 3512 bytes). 34.7 Ported to Aztec 'C' 5.0, the strange library creation procedure consumed lots of time (in which the author consumed lots of cups of coffee). 1.6 Initial creation using MkLib & elib.