A Multi-Purpose String Editing Function (Similar to DCL's F$EDIT) which can be Added to 3GLs or DATATRIEVE. Bart Z. Lederman System Resources Corporation Burlington, MA I have often wanted to process a line of text in a program or DATATRIEVE procedure. In DCL, there is a useful lexical function F$EDIT which can convert a string to upper case, remove trailing blanks, convert multiple blank spaces and tabs to a single blank space, and other functions: and it can do all of those functions simultaneously. It was frustrating that there wasn't an equivalent LIB$ or STR$ function. Since I don't normally use VAX BASIC, it was only by accident (while looking through someone else's program) that I discovered that such a function is provided in VAX BASIC. What is even better is that it is in the BASIC Run-Time Library BASRTL.EXE, which is supplied with the VAX/VMS operating system. This means that everyone has it: you don't have to buy VAX BASIC to use the function. Since I don't use VAX BASIC, I wanted to make the function available in VAX C. The file BAS$EDIT.H provides the necessary definitions. Any or all of the qualifiers in the header file can be "ORed" together. To demonstrate what this function can do, I wrote a simple demonstration program, BAS$EDIT.C When you run this program, you should see this (if the 8-bit characters came through o.k.): This string has stuff ïn it THIS STRING HAS STUFF ÏN IT Thisstringhasstuffonit I also wrote TEST_BAS_EDIT.C which runs through all of the possible permutations of editing functions. All this is very well and good for 3GL programmers, but what about DATATRIEVE? Anyone who has seen my articles in the past knows that it's very easy to add RTL functions to DATATRIEVE. I added the following to my DTRFNDnnn.MAR file: ; FN$BAS_EDIT - process a character string with BAS$EDIT ; B. Z. Lederman ; output is a one character string ; input is an unsigned byte ASCII code ; .LINK "SYS$SHARE:BASRTL.EXE"/SHAREABLE $DTR$FUN_DEF FN$BAS_EDIT, BAS$EDIT, 3 $DTR$FUN_NOOPTIMIZE $DTR$FUN_HEADER HDR = <"Edited"> $DTR$FUN_EDIT_STRING ^\T(80)\ $DTR$FUN_OUT_ARG TYPE = FUN$K_STATUS $DTR$FUN_IN_ARG TYPE = FUN$K_TEXT, OUT_PUT = TRUE, ALL_LEN = 255 $DTR$FUN_IN_ARG TYPE = FUN$K_DESC, DTYPE = DSC$K_DTYPE_T, ORDER = 1, ALL_LEN = 255 $DTR$FUN_IN_ARG TYPE = FUN$K_VALUE, DTYPE = DSC$K_DTYPE_L, ORDER = 2 $DTR$FUN_END_DEF To use this you have to do what BASIC programmers do, and put in the numeric value of the editing function. This is because you can't add new keywords to DATATRIEVE to give symbolic values for the editing functions. You can, however, DECLARE a local variable and give it the value of the editing function you want. An example of how this function works is: PROCEDURE TEST_BAS_EDIT ! DECLARE EDIT_VALUE USAGE LONG. ! EDIT_VALUE = 0 ! ! embedded Line Feed V V eight-bit character PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 0) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 1) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 2) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 4) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 8) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 16) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 32) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 64) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 128) | "<" PRINT FN$BAS_EDIT (" This string [has] stuff ïn it ", 256) | "<" ! PRINT SKIP ! WHILE EDIT_VALUE LE 512 BEGIN PRINT EDIT_VALUE, SPACE 1, FN$BAS_EDIT (" This string [has] stuff ïn it ", EDIT_VALUE) | "<" EDIT_VALUE = EDIT_VALUE + 1 END ! END_PROCEDURE Part of what this looks like when you run it follows (I'm not going to print all 512 possible variations here): :test_bas_edit This string [has] stuff ïn < This string [has] stuff on < Thisstring[has] stuffïnit< This string [has] stuff ïn i< This string [has] stuff ïn i< This string [has] stuff ïn i< THIS STRING [HAS] STUFF ÏN < This string (has) stuff ïn < This string [has] stuff ïn < This string [has] stuff ïn < EDIT VALUE 0 This string [has] stuff ïn < 1 This string [has] stuff on < 2 Thisstring[has] stuffïnit< 3 Thisstring[has] stuffonit< 4 This string [has] stuff ïn i< 5 This string [has] stuff on i< 6 Thisstring[has]stuffïnit< 7 Thisstring[has]stuffonit< and so on. I belive this function will be most useful in two areas. The first is when data is read in from a text or "free-format" file and has to be processed to be stored into a domain. The other is when the user is prompted for input: the function can be used to "normalize" input (uniform case, no extra spaces or tabs, etc.) to make it easier to look for words or commands within the input string.