17 July 1996 IT Solutions GNU AWK DLL Page 1 User's Manual for the IT Solutions GNU AWK DLL (GAWKDLL) Version 2.0 by James Gray Walker "IT Solutions" GmbH 0. Table of Contents 0. Table of Contents . . . . . . . . . . . . . . . . . . . . . 1 1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2. Components . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.1. GAWK.DLL and AWKLIB.DLL . . . . . . . . . . . . . . . . 2 2.2. AWK Script Files . . . . . . . . . . . . . . . . . . . 2 2.3. Input and Output Data Files . . . . . . . . . . . . . . 3 2.4. INI and DBF Data Files . . . . . . . . . . . . . . . . 3 3. GAWKDLL Invocation . . . . . . . . . . . . . . . . . . . . . 3 3.1. Overview . . . . . . . . . . . . . . . . . . . . . . . 3 3.2. Creating the Argument List . . . . . . . . . . . . . . 4 3.3. Loading GAWK.DLL and Locating an Entry Point . . . . . 4 3.4. Calling the Entry Point . . . . . . . . . . . . . . . . 5 4. GAWK Features Disabled in GAWKDLL . . . . . . . . . . . . . 5 4.1. Standard Input, Output, Error . . . . . . . . . . . . . 5 4.2. system() Calls and Pipes . . . . . . . . . . . . . . . 5 4.3. Command Line Options . . . . . . . . . . . . . . . . . 6 5. Features Added to GAWK in GAWKDLL . . . . . . . . . . . . . 6 5.1. Error Handling . . . . . . . . . . . . . . . . . . . . 6 5.1.1. Error Message Boxes . . . . . . . . . . . . . 6 5.1.2. abort() Function . . . . . . . . . . . . . . 6 5.2. User Message Functions . . . . . . . . . . . . . . . . 6 5.2.1. decision() Function . . . . . . . . . . . . . 6 5.2.2. message() Function . . . . . . . . . . . . . 7 5.3. INI-File Interface Functions . . . . . . . . . . . . . 7 5.3.1. iniget() Function . . . . . . . . . . . . . . 7 5.3.2. iniput() Function . . . . . . . . . . . . . . 7 5.4. DBF-File Interface Functions . . . . . . . . . . . . . 7 5.4.1. dbfproject() Function . . . . . . . . . . . . 7 5.4.2. dbfselect() Function . . . . . . . . . . . . 7 Copyright (C) 1996, ITS Information Technology Solutions GmbH. 17 July 1996 IT Solutions GNU AWK DLL Page 2 5.5. Slash-Backslash Conversion . . . . . . . . . . . . . . 8 6. Installation . . . . . . . . . . . . . . . . . . . . . . . . 8 6.1. GAWKDLL-Only Distribution . . . . . . . . . . . . . . . 8 6.1.1. Overview . . . . . . . . . . . . . . . . . . 8 6.1.2. Unzipping the Distribution . . . . . . . . . 8 6.1.3. Installing the GAWKDLL Modules . . . . . . . 9 6.2. Whole ITSEDIPP Distribution . . . . . . . . . . . . . . 9 6.2.1. Overview . . . . . . . . . . . . . . . . . . 9 6.2.2. Unzipping the Distribution . . . . . . . . . 9 6.2.3. Copying the GAWKDLL Elements . . . . . . . . 9 6.2.4. Installing the GAWKDLL Modules . . . . . . . 9 6.3. Examining the Sources . . . . . . . . . . . . . . . . . 9 7. Technical Issues and Potential Trouble Spots . . . . . . . . 10 7.1. Runtime Stack . . . . . . . . . . . . . . . . . . . . . 10 7.2. Memory Management . . . . . . . . . . . . . . . . . . . 11 7.3. Multiple Invocations . . . . . . . . . . . . . . . . . 11 7.4. Input Field Values . . . . . . . . . . . . . . . . . . 12 8. Software and Hardware Requirements . . . . . . . . . . . . . 12 9. Licensing . . . . . . . . . . . . . . . . . . . . . . . . . 12 10. Support . . . . . . . . . . . . . . . . . . . . . . . . . . 12 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 13 1. Overview The IT Solutions GNU AWK DLL (GAWKDLL) is a DLL implementation of the GNU version of the AWK utility. It works almost exactly as the AWK program does, but is invoked as a function call by and within a Windows application instead of as a standalone program from Windows or the DOS command line. AWK has a simple, but very flexible, script language. It can be used for pattern matching, data selection, data validation and data transformation. It can also read in small databases from secondary files to be used in the data manipulation. The complexity of AWK scripts can range from one-liners to programs of hundreds of lines. AWK has been around for a long time; it was first developed as an UNIX utility in 1977, so many programmers have had exposure to it at one time or another. GAWKDLL is distributed in two forms, either alone or as part of the IT Solutions EDI Pseudo Printer (ITSEDIPP) package. When bundled with ITSEDIPP, the relevant files can be manually separated from the rest of package. 2. Components 2.1. GAWK.DLL and AWKLIB.DLL The GAWK.DLL module is the main fixed component of the product. The AWKLIB.DLL module is a subsidiary fixed component containing a set of routines which GAWKDLL uses for memory management and access to DBF (standard DataBase Format) files. Both must reside in the Windows System directory. 2.2. AWK Script Files AWK script files steer the actions of an invocation of GAWKDLL. The locations of an invocation's AWK script files are specified in the argument list of the call to a GAWK entry point. The script 17 July 1996 IT Solutions GNU AWK DLL Page 3 language used for GAWKDLL is a slightly modified version of the standard GAWK script language, which is itself an enhanced version of the original AWK script language. Almost all of the features of the AWK and GAWK script languages have been retained, so anyone familiar with AWK will have no problem creating and modifying these files. AWK scripts are plain ASCII program files which determine what an execution of GAWKDLL does. Every GAWKDLL run must have at least one script. It is recommended to give AWK script files the .AWK suffix. Officially, the script language accepted by GAWKDLL is defined in The GAWK Manual, Edition 0.15, published by the Free Software Foundation, 1993, with some minor omissions and additions, as described below. It conforms to the language definition in the POSIX 1003.2 Command Language And Utilities Standard, plus some GNU- specific extensions. POSIX AWK is in turn based on the description in The AWK Programming Language, Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger, Addison-Wesley, 1988. ISBN 0-201-07981-X, with the additional features defined in the System V Release 4 version of UNIX AWK. 2.3. Input and Output Data Files Each GAWKDLL invocation usually has both input and output data files. An input file is usually a white-space delimited ASCII text file, but can have any format that the AWK scripts are programmed to accept. An output file is usually an ASCII text file, but again, can have any format which the AWK scripts produce. The locations of the input files can be specified either directly or as variables in the argument list of the call to the GAWK entry point, hardwired in the AWK script files or derived at runtime. The locations of output files can be specified as variables in the argument list of the call to the GAWK entry point, hardwired in the AWK script files or determined at runtime. 2.4. INI and DBF Data Files Depending on the requirements and implementation of the specific application, other data files in the INI and DBF formats can be accessed from within AWK script files at runtime. Files with the INI format can be updated as well as read. They are suitable for small ASCII databases and can be created by any text editor. Files with the DBF format can only be read. They are suitable for larger data-validation databases and are created by common database programs. The locations of these files can be specified as variables in the argument list of the call to the GAWK entry point, hardwired in the AWK script files or determined at runtime. 3. GAWKDLL Invocation 3.1. Overview Because GAWKDLL is called from within a running Windows application, some preparatory programming will be necessary. The basic steps are: a) creating and filling an argument list, b) 17 July 1996 IT Solutions GNU AWK DLL Page 4 loading the GAWK.DLL module, c) getting the address of the desired GAWKDLL entry point function and d) calling the entry point function with the argument list. A "C" example of how to program all of this, GAWKINT.C, can be found in the source code of the ITSCTRL module of ITSEDIPP. If you have the GAWKDLL-only distribution, there will also be a BASIC example, GAWKINT.BAS; both examples will be found in the INVOKE source directory. If you have the whole ITSEDIPP distribution, then when ITSEDIPP has been installed, or at least unzipped, you can navigate to the ITSCTRL source directory, unzip the ITSCTRL sources and find GAWKINT.C there. 3.2. Creating the Argument List What would normally be the command line parameters in a standalone program version of GAWK are presented similarly to GAWKDLL, but from within a compiled, executing program instead of from a command shell. The entry point function of GAWKDLL receives the "command line" argument list as if it had been assembled by a command shell from user input at the prompt, that is, in the form "main(int argc, char *argv[])" in the "C" language. The calling program must allocate and assemble the "command line" argument list for an invocation of GAWKDLL. This consists of the name of the called module, "GAWKDLL", a set of variable assignments, specification of the AWK script files and optional specification of input files. Each variable assignment actually consists of two arguments: the first "-v", to signal that a variable assignment is coming and the second is the actual assignment, of the form "Name=Value". The set of these assignments must include a variable containing the output filename if the AWK scripts will generate any output. The specification of the script files comes next and is again two arguments per script file: the first "-f", for script file and the second the actual script filename. Finally, the names of any input files can be appended to the argument list. Note that the input filename need not and the output filename does not appear in the "command line" as they would when using GAWK as a standalone program. Instead, the input filename can be assigned to a variable (INFILE is recommended) and the output filename must be assigned to a variable (OUTFILE is recommended) as variable assignments in the argument list. The AWK script then must check for the variables INFILE and OUTFILE as its first task in the BEGIN block and specify that the input be taken from INFILE by assigning it to the variable ARGV[ARGC++] immediately. Furthermore, all AWK script output must be explicitly directed to OUTFILE using the "> OUTFILE" output redirection operator. 3.3. Loading GAWK.DLL and Locating an Entry Point Once the argument list has been completed, the calling program loads GAWK.DLL. This is done using the Windows LoadLibrary() kernel function. Then the caller must get the location of a GAWKDLL entry point function using the Windows GetProcAddress() kernel function. There are three defined entry points, each of which has the same calling sequence, that is, "main(argc, argv)", and each of which has 17 July 1996 IT Solutions GNU AWK DLL Page 5 the same functionality, running GAWKDLL. The only difference among the three is how they handle the runtime stack while in GAWKDLL. See the Runtime Stack discussion in the Technical Issues to determine which entry point to use. 3.4. Calling the Entry Point Having the argument list and the entry point address, all that is left to do is to actually call GAWKDLL. GAWKDLL will run and return an exit value. An exit value of zero indicates success. A non-zero exit value indicates some kind of failure, be it insufficient memory or file space, a problem with a program script, an invalid file name or data value or execution of the decision() function where the user cancels, the abort() function or the exit statement with a non-zero return code. In any case, the GAWK.DLL module should be unloaded with the Windows FreeLibrary() kernel function after GAWKDLL returns. 4. GAWK Features Disabled in GAWKDLL 4.1. Standard Input, Output, Error The runtime environment of a Windows DLL differs in some important aspects from that of a standalone program. The main difference for GAWKDLL is that it is not started with its own standard input, standard output and standard error data streams, in fact, the calling program may not even have them. Therefore, GAWKDLL can not expect to be able to read or write from them; if it tries to, an error message box to the screen will result. What this means to the AWK script programmer is that there must always be an explicit input filename, either in the argument list or added to the end of the ARGV[] array, from which input filenames are read, within the AWK script. The standard way to do this is to assign the input filename to the variable INFILE via an argument list "-v" assignment and add this value to the end of the ARGV[] array as the first statement of the BEGIN block. Additionally, all output, that is, all print and printf calls must be directed explicitly to an output filename using ">". The standard way to do this is to assign the output filename to the variable OUTFILE via an argument list "-v" assignment and direct the output of every print and printf statement with "> OUTFILE". Any undirected prints or printfs will generate an error message box to the screen. Furthermore, the special I/O-related filename extensions, "/dev/stdin", "/dev/stdout", "/dev/stderr" and "/dev/fd/n", have been disabled; their use in GAWKDLL will instead refer to real files having those names, if they exist or can be created. 4.2. system() Calls and Pipes For much the same reasons given above, the system() call and the use of pipes to or from other processes have also been disabled in GAWKDLL. While starting other Windows processes from GAWKDLL would not be impossible, it would involve considerable additional 17 July 1996 IT Solutions GNU AWK DLL Page 6 programming effort and introduce a lot of complexity. Using these constructs in an AWK script will generate an error message box on the screen. 4.3. Command Line Options Several command line options to GAWK generate only informational messages to standard output or standard error. Because those streams do not exist in GAWKDLL these options have been disabled. They are "--help", "--usage", "--copyleft", "--copyright", "--version" and their corresponding "-W" forms. 5. Features Added to GAWK in GAWKDLL 5.1. Error Handling 5.1.1. Error Message Boxes Normally, when a GAWK process encounters a runtime error, it issues an error message or warning to the standard error stream. This stream does not exist in GAWKDLL, so all such errors and warnings are written instead to error message boxes on the screen. This message box output has been enhanced to provide much information about the error's environment, such as which version of the program is running, which script line is being executed, which input file is being read, which input line is being processed and what specific error was encountered. The information in these message boxes goes a long way to helping the user help himself when an error turns up. 5.1.2. abort() Function The abort() function in an AWK script does just what you would think; when executed, it outputs an error message box and aborts the GAWKDLL run immediately, without executing the END block. The abort() function can take one or two arguments. The first argument is a non-zero numeric exit value which will be returned to the caller of GAWKDLL. The optional second argument is a string message which will be output in the error message box on the screen just before GAWKDLL exits. This function allows the programmer to abort the run when certain conditions arise, while telling the user what went wrong. 5.2. User Message Functions 5.2.1. decision() Function The decision() function presents an informational message to the user in a message box and provides him the opportunity to cancel the GAWKDLL run, given the content of the message. The function takes one or two arguments. The first argument is the message to be displayed. The optional second argument is a non-zero numeric exit value (default is 3) to be returned to the calling program if the user cancels the run. When the function is called, it outputs a decision message box with an "OK" button and a "Cancel" button. If the user chooses "OK", the job continues. If the user chooses "Cancel", the function aborts the run immediately, without executing 17 July 1996 IT Solutions GNU AWK DLL Page 7 the END block. This function allows user decision points to be programmed into the AWK scripts so that the user can cancel the job when certain user-recognizable conditions arise. 5.2.2. message() Function The message() function displays an informational message to the user in a message box. The function takes one argument, the message to be displayed. When the function is called, the message appears in a message box with an "OK" button, which the user must select before the run continues. 5.3. INI-File Interface Functions 5.3.1. iniget() Function The iniget() function returns the value of a specific entry in a specific section of a specific INI file. The function takes three arguments: the first is the filename of the INI-format file to read from, the second is the section name to read from, the third is the entry name whose value to get. The default directory for the INI file is the Windows directory. If the entry is not found, then the function returns the null string. 5.3.2. iniput() Function The iniput() function is the opposite of the iniget() function; it puts a value to an entry in a section in an INI file. The function takes four arguments: the first three as in iniget() and the fourth is the value to assign to the entry. The function's return value is always the null string. The iniget() and iniput() functions give GAWKDLL runs a method by which to save values or pass values to subsequent GAWKDLL invocations or other programs. 5.4. DBF-File Interface Functions 5.4.1. dbfproject() Function The dbfproject() function is used to get (project) column values from a specific record of a DBF-format database file. It takes three arguments: first a DBF file name, second a record number (beginning with 1) and third a column name. It returns the value of the given column in the given row of the given file. "Deleted" records can be queried by using their record numbers, too. If an error occurs, a warning message box appears and a null string is returned. If the DBF file has not been accessed yet, it is read whole into memory so that subsequent accesses will be significantly faster. 5.4.2. dbfselect() Function The dbfselect() function is used to find (select) records of a DBF-format database file matching an optional single criterion. It takes either two or four arguments. In the case of two, they are: first a DBF file name and second a starting record number. Here, 17 July 1996 IT Solutions GNU AWK DLL Page 8 the record number of the next non-deleted record after the given record number is returned. So, to get the first record number, dbfselect() is called with record number 0. If four arguments are given, the first two are the same as above, third is a column name and fourth is a sought column value. In this case, the function returns the record number of the next non-deleted record after the given record number where the value of the given column in the record matches the given column value. If the given sought column value in the AWK script is numeric, then the comparison is forced numeric. Otherwise, the type of the given column determines the comparison type. If no record is found, 0 is returned. If an error occurs, a warning message box appears and -1 is returned. If the DBF file has not been accessed yet, it is read whole into memory so that subsequent accesses will be significantly faster. 5.5. Slash-Backslash Conversion An incompatibility in file-naming conventions exists between the UNIX and DOS/Windows worlds. UNIX programs expect directory and file names to be separated by slash ('/') characters while DOS/Windows programs expect the separators to be backslash ('\') characters. As an originally UNIX-based utility, GAWK works internally with slashes, as does GAWKDLL. To bridge the gap, at certain places where strings come into or leave GAWKDLL from or to Windows, a conversion is done. All argument list filename arguments, argument list variable assignments, environment variables and values from iniget() have all backslashes converted to slashes just before being assigned, as they are entering GAWKDLL. In order to get a backslash into GAWKDLL from these sources, it must be escaped with a preceding backslash ('\\'). All values used as filenames or put using iniput() have all slashes converted to backslashes just before being used, as they are leaving GAWKDLL. In order to get a slash out of GAWKDLL to these destinations, it must be escaped with a preceding backslash ('\/'). 6. Installation 6.1. GAWKDLL-Only Distribution 6.1.1. Overview The GAWKDLL-only distribution contains an installation script, INSTALL.BAT, which installs the package in a fixed position, C:\GAWKDLL, and copies the object modules, GAWK.DLL and AWKLIB.DLL, to the assumed Windows system directory, C:\WINDOWS\SYSTEM. 6.1.2. Unzipping the Distribution GWKD20A.EXE is the self-extracting .ZIP distribution file for GAWKDLL. To install GAWKDLL by hand, copy the file GWKD20A.EXE to the directory where you wish the GAWKDLL directory to be installed. Then call it with the command "GWKD20A -e -d" and it will unzip itself. 17 July 1996 IT Solutions GNU AWK DLL Page 9 6.1.3. Installing the GAWKDLL Modules You can install the GAWKDLL object modules by hand by copying GAWK.DLL and AWKLIB.DLL from the GAWKDLL\BIN directory to the Windows system directory. 6.2. Whole ITSEDIPP Distribution 6.2.1. Overview Although GAWKDLL is distributed as part of ITSEDIPP, it can be used independently. To install GAWKDLL without ITSEDIPP requires that the distribution file on the ITSEDIPP installation diskette be unzipped, the GAWKDLL elements copied from the ITSEDIPP directory and the GAWK.DLL and AWKLIB.DLL object modules copied to the Windows System directory. At this point, the ITSEDIPP directory can be discarded, however, it is recommended that it be retained for a while, at least at first, for the AWK script examples in the demo directories and the "C" code example in the ITSCTRL component of how to set up and call GAWKDLL. 6.2.2. Unzipping the Distribution ITSP20A.EXE is the self-extracting .ZIP distribution file for ITSEDIPP. To get only GAWKDLL, you should install the ITSEDIPP directory by hand. Copy the file ITSP20A.EXE to the directory where you wish the ITSEDIPP directory to be installed. Then call it with the command "ITSP20A -e -d" and it will unzip itself. 6.2.3. Copying the GAWKDLL Elements GAWKDLL's two object files, GAWK.DLL and AWKLIB.DLL, are unpacked to the ITSEDIPP\BIN directory by ITSP20A.EXE. Create a new directory for GAWKDLL files and copy the two object files there. GAWKDLL's sources will be found in the directories ITSEDIPP\SRC\AWKLIB and ITSEDIPP\SRC\GAWKDLL. Copy these two directories to your new GAWKDLL directory. The documentation for GAWKDLL are the files GAWKDLL.* in the directory ITSEDIPP\DOC. Copy them too to the new directory. At this point, you have all of the parts of GAWKDLL in your new directory, so you can delete the ITSEDIPP directory if you wish. 6.2.4. Installing the GAWKDLL Modules Once you have the GAWKDLL files segregated from ITSEDIPP, you can install them by copying GAWK.DLL and AWKLIB.DLL to the Windows system directory, commonly \WINDOWS\SYSTEM. 6.3. Examining the Sources The source code is included in order to fulfil the provision of the GNU General Public License that you have free access to the source code to change as you wish. The source files are packed in .ZIP files, for which you will need an unzip program, for example PKUNZIP, to unpack. If you believe you can make anything of the sources, then you will know where to get an unzip program on your own and probably already have one. 17 July 1996 IT Solutions GNU AWK DLL Page 10 7. Technical Issues and Potential Trouble Spots 7.1. Runtime Stack GAWKDLL has recursive components and can therefore descend quite far into the stack at runtime, especially given large, complex or recursive AWK scripts. While GAWKDLL may look like a separate program, it is, in fact, a called function and, as such, executes using the stack of the calling program. In some cases, this can create serious problems; in particular, under Windows 3.xx when the calling program calls GAWKDLL with less remaining stack space than GAWKDLL needs, given the AWK scripts specified and input data provided. Under Windows 95 and Windows NT, this is not a problem because the operating system manages the stack and can expand it automatically, if necessary. To deal with the potential problem under Windows 3.xx, three measures have been taken. First, the GAWKDLL source code has been examined and modified so that all functions' stack frames are reasonably small, or at least as small as possible. Large arrays which were previously automatically allocated from the stack are now dynamically allocated and freed at runtime. Second, the entire GAWKDLL package (as well as all of ITSEDIPP) has been compiled with stack checking turned on, so any stack overflow is detected and reported before it can cause any damage. Third, an additional entry point to GAWKDLL has been provided which switches to and uses a very large GAWKDLL-local stack, instead of the caller's stack, while running in GAWKDLL. Thus, there are two real entry points to GAWKDLL and one aliased entry point to choose from. The two real entry points are named "GAWKmain_CallerStack" and "GAWKmain_LocalStack". The aliased entry point is named "GAWKmain" and points to the real local stack entry point. The caller stack entry point uses the caller's stack at runtime, that is, it makes no stack change and runs as a normal DLL. The local stack entry point checks the Windows version, and if it is Windows 3.1, Windows 3.11 or Windows for Workgroups 3.11, switches the stack to a large GAWKDLL-local stack located in the GAWKDLL data segment while execution is in GAWKDLL. When the execution flow leaves GAWKDLL, either returning to the caller or issuing a message box, the original stack is restored. If the Windows version is not one of those named above, the local stack entry point calls instead the caller stack entry point and no stack switch is performed. Deciding which entry point to use in the GetProcAddress() function is not difficult. Unless you are using Windows 3.1x, there is no decision to be made, just use "GAWKmain". If you are using Windows 3.1x, start by trying "GAWKmain", which will give you the local stack entry point. If this causes problems with you application, in particular, it hangs on a GAWKDLL message box, then try "GAWKmain_CallerStack". If you then get a stack overflow, then you need to try to reduce the complexity of your AWK scripts, eliminating recursion if possible. If you still get stack overflows, then try switching back to "GAWKmain" and not generating 17 July 1996 IT Solutions GNU AWK DLL Page 11 any message boxes (using the message() or decision() functions). If you must have message boxes, but get stack overflows, then try splitting your GAWKDLL tasks apart into multiple sequential GAWKDLL calls, where the complex work is done via the "GAWKmain" entry point and the message boxes are issued via the "GAWKmain_CallerStack" entry point. This will be very rarely necessary, though. 7.2. Memory Management Given that GAWKDLL is a dynamic, interpretive program, it can also be very memory-hungry, depending on the AWK scripts used and the data volume. While a DLL normally uses the stack of the calling program, it has its own data segment, containing its static data and a local heap. Under Windows, this data segment can be a maximum of 64 kilobytes large, which is easily fully consumed by GAWKDLL when given complex AWK scripts and lots of data. GAWKDLL needs to be able somehow to allocate more memory than its local data segment can hold. Using global allocations is one alternative, but has the disadvantage that the calling program, not GAWKDLL would then own these allocated memory blocks. GAWKDLL cannot be depended upon to free all of its allocated memory before exiting; as a standalone program, GAWK never needed to. The solution is to have a set of customized memory management routines, which is in the AWKLIB.DLL module, which GAWKDLL loads and binds to when first started. These routines allocate large segments, install a heap in each, and dole out small memory allocations from these heaps. Each task which wishes to use these routines must register beforehand, so that a task's heap segments can be kept track of; each heap segment is used only by a single registered task. Furthermore, when a task is ready to quit, it must unregister, so that all of its heap segments can be freed. This solution allows GAWKDLL to allocate as much runtime memory as it needs, while ensuring that when a GAWKDLL run terminates, it can and will be fully cleaned up after. 7.3. Multiple Invocations As a DLL, all invocations of GAWKDLL share a single data segment, containing all the static data and the switched-to stack. To ensure that from one GAWKDLL run to the next the program restarts in its initial state, rather than inheriting the state from a previous terminated run, the sources were modified to reinitialize all the static data upon startup. However, this does not prevent multiple simultaneous GAWKDLL runs from corrupting each other's state (or stack). In fact, there is absolutely no precaution taken by GAWKDLL to prevent simultaneous runs from crashing each other. [ There is a method of duplicating a DLL's data segment upon entry, but it has not been implemented in GAWKDLL. ] Therefore, there can be at most one active GAWKDLL run on the machine at a time. The user or programmer using GAWKDLL must take steps to prevent multiple simultaneous GAWKDLL runs. This means not starting multiple instances of an application which uses GAWKDLL, or at least, not allowing more than one instance to be in GAWKDLL at a 17 July 1996 IT Solutions GNU AWK DLL Page 12 time. Also, single instances of multiple applications, each of which use GAWKDLL, must be prevented from entering GAWKDLL simultaneously. The use of GAWKDLL on a machine must be strictly serialized. 7.4. Input Field Values It has been observed in using the GAWK program that the handling of input field values sometimes goes wrong. For instance, in complex scripts with several execution blocks, only the first block gets the right values when it refers to fields from the input line; subsequent blocks erroneously get null strings for these field values. A workaround for this is to make a first block which simply assigns each input field to a named array or variable and refer to these variables in the rest of the blocks. Here is how such a block would be coded: "{ LINE = $0 ; for ( X = 1; X <= NF; ++X ) FIELD[X] = $X }". 8. Software and Hardware Requirements The software requirements are Windows 3.xx, Windows 95 or Windows NT and a Windows application programmed or configured to call GAWKDLL. The hardware requirement is a machine which can run the chosen software configuration. 9. Licensing Following is the standard licensing statement for all GNU- "Free" software: GAWKDLL is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GAWKDLL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAWKDLL; see the file COPYING. If not, write to the Free Software Foundation, Inc, 675 Mass Ave, Cambridge, MA 02139, USA. 17 July 1996 IT Solutions GNU AWK DLL Page 13 10. Support The author of GAWKDLL, IT Solutions, will provide support at a fair price to users who need it. The contact information is: "IT Solutions" ITS Information Technology Solutions GmbH Untere Grasstr. 10 D - 81541 Munich Germany Phone: +49 (89) 69708525 E-Mail: walkerj@compuserve.com 11. References The GAWK Manual, Edition 0.15, Diane Barlow Close, Arnold D. Robbins, Paul H. Rubin, Richard Stallman, Free Software Foundation, 1993. The AWK Programming Language, Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger, Addison-Wesley, 1988, ISBN 0-201-07981-X. sed & awk, UNIX Power Tools, Dale Dougherty, O'Reilly & Associates, 1990, ISBN 0-937175-59-5.