The following is from the September 1990 Issue of the DECUS U. S. Chapter SIGs Newsletter, Volume 6, Number 1, page DTR-2 to DTR-4. ----------------------------------------------------------------- Dear Wombat Wizard ----------------------------------------------------------------- Dear Wombat Wizard: When the user written FORTRAN version of the DATATRIEVE function BABY_ED appeared on the SIG tape, I thought I had found the solution to a problem I had been trying to solve for years. We have a database of projects; each project has a project number, a funding level, a project description (1500 characters), and other variables such a lists of employee numbers who work on the project. The function FN$BABY_ED with its fairly extensive emulation of the EDIT editor in FORTRAN using SMG$ calls looked like an ideal way to enter the project description into the database. However, when I set up a definition for FN$BABY_ED in my DTRFND.MAR function linkage file as ; FN$BABY_ED - "Baby" editor $DTR$FUN_DEF FN$BABY_ED, BABY_ED, 6 $DTR$FUN_OUT_ARG TYPE = FUN$K_STATUS $DTR$FUN_IN_ARG TYPE = FUN$K_DESC, DTYPE = DSC$K_DTYPE_T, ORDER = 1 $DTR$FUN_IN_ARG TYPE = FUN$K_TEXT, OUT_PUT = TRUE , ALL_LEN = 1500 $DTR$FUN_IN_ARG TYPE = FUN$K_REF, DTYPE = DSC$K_DTYPE_L, ORDER = 2 $DTR$FUN_IN_ARG TYPE = FUN$K_REF, DTYPE = DSC$K_DTYPE_L, ORDER = 3 $DTR$FUN_IN_ARG TYPE = FUN$K_REF, DTYPE = DSC$K_DTYPE_L, ORDER = 4 $DTR$FUN_IN_ARG TYPE = FUN$K_REF, DTYPE = DSC$K_DTYPE_L, ORDER = 5 $DTR$FUN_NOOPTIMIZE $DTR$FUN_HEADER HDR = <-> $DTR$FUN_EDIT_STRING ^\X(1500)\ $DTR$FUN_END_DEF with the returned string allocation length to be 1500 characters, I got the following error $MACRO DTRFND %MACRO-E-GENERR, Generated ERROR: 3 Parameter value out of range There were 1 error, 0 warnings and 0 information messages, on line: nnn(1) What is a MACRO Generated ERROR and how can I get DATATRIEVE to accept the return of a big character string from the FORTRAN version of BABY_ED? Signed, Stymied by assembly of DTRFND Dear Stymied: You have hit on an esoteric if not obscure point in the "language" used to add functions to DATATRIEVE. The rules for creating the linkage to user written and system library functions are given in the chapter on "Adding Functions to DATATRIEVE" in the "VAX DATATRIEVE Guide to Programming and Customizing" manual. To understand the work-around to your problem, we need some background information. The VMS architecture supports three kinds of strings: fixed-length, varying-length, and dynamic length. DATATRIEVE and BASIC (normally) store strings using the dynamic length format; FORTRAN uses only the fixed-length form. When the return variable is a FUN$K_TEXT type variable, DATATRIEVE has got to know whether the variable being returned is fixed-length or dynamic length and whether to allocated space at call-time or return-time. If the BABY_ED routine were written in BASIC you would not need the ALL_LEN parameter in the $DTR$FUN_IN_ARG, and your problem would not exist. (Note that even for dynamic length strings there is still a size limit; the limit is 65,525 bytes, however!) But because FORTRAN uses only fixed-length strings, the ALL_LEN parameter must be specified. Now the rules for creating function linkages are really a set of MACROs which are converted to MACRO-32 code by the VAX MACRO assembler using the MACRO definitions in the file DTR$LIBRARY:DTRFNLB.MLB. Note that there is a reference to this macro library in DTRFND.MAR and IDTRFND.MAR immediately after the .PSECT statement near the beginning of each file. You can see what macro modules are in this file by $LIBRARY/LIST/MACRO DTR$LIBRARY:DTRFNLB or you can extract all the macro definitions and list them by $LIBRARY/EXTRACT=*/OUTPUT=DTRFNLB/MACRO DTR$LIBRARY:DTRFNLB $TYPE DTRFNLB.MAR Now when the DATATRIEVE developers put together this little "language" and the macros, they decided that it would probably be a good idea to check to make sure that the size of the fixed-length string that the user wanted to return was a reasonable size. The problem is your idea of reasonable and their idea of reasonable are different. So in the MACRO $DTR$FUN_IN_ARG they decided that if the TYPE was FUN$K_TEXT, the ALL_LEN should be between 0 and 1000. The MACRO generated error is a failure of your ALL_LEN to fall between 0 and 1000. If your interested in more details, list out the MACRO $VALIDATE_PARM to see how this is really done. On two different occasions (more that two years ago and just this week) I discussed this size limitation with DATATRIEVE developers. They (and I) do not see any reason why it should not be possible to increase this (apparently artificial) size limit to 2,000 or even 10,000 characters. However, as with any unsupported or unofficial modification to a Digital product, there are no guarantees that this will not break something. So don't go crying to Colorado Support Services if this causes DATATRIEVE to take some rude exits. I never like to make a modification to one of the files on the distribution kit, so I rename and append the version number. To get started, login to a privileged account, set the default to DTR$LIBRARY, and make a backup copy, by ! Login to an account with SYSPRV and CMKRNL. $set default dtr$library: $rename dtrfnlb.mlb dtrfnlb_v0N0M.mlb ! depending on version #, 0N0M is 0400, 0401, 0402 or 0500 Then restore the macro library, extract the module, edit it changing 1000 to 2000, and re-insert it in the macro library with $copy dtrfnlb_v0N0M.mlb dtrfnlb.mlb $library/extract=$dtr$fun_in_arg - /output=$dtr$fun_in_arg/macro dtrfnlb $edit/nocommand $dtr$fun_in_arg.mar '1000' s /1000/2000/ exit $! The "2000" 2 lines above could be replaced with $! something larger if need be. $library/replace/macro dtrfnlb $dtr$fun_in_arg Then assemble DTRFND, compile BABY_ED, and insert these two modules in the DTRFUN.OLB object library by $macro dtrfnd $fortran/ext baby_ed $library/replace dtrfun dtrfnd,baby_ed Then re-link and install the various modules of DATATRIEVE with $@dtrbld I hope this little fix to DATATRIEVE macro function definition library will un-stymie your use of the full capabilities of FORTRAN version of BABY_ED. Signed, The Wombat Wizard (JHG) Dear Wombat Wizard: I have added the following macro definition to my DTRFND.MAR file. ; ; FN$JUSTIFY_special ; ; input is a 10 character field (left justified number or text) ; output is a 10 character field (right justified leading zeros added or text) ; $DTR$FUN_DEF FN$JUSTIFY_special, JUSTIFY_special, 2 $DTR$FUN_OUT_ARG TYPE = FUN$K_STATUS $DTR$FUN_IN_ARG TYPE = FUN$K_DESC, DTYPE = DSC$K_DTYPE_T, ORDER = 1 $DTR$FUN_IN_ARG TYPE = FUN$K_TEXT, OUT_PUT = TRUE , ALL_LEN = 10 $DTR$FUN_NOOPTIMIZE $DTR$FUN_END_DEF I have used the usual compile, library replace, and re-link with DTRBLD.COM. There are are NO error or warning messages. Yet when I attempt to use the function in DATATRIEVE DTR> print fn$justify_special("1-A-123 ") I get FN$JUSTIFY_SPECIAL is undefined or used out of context. Why can't DATATRIEVE find this function which is linked to it? Signed, DTR has lost my function Dear Lost: Ordinarily MACRO 32 statements are not case sensitive. But, in the case of a function definition, the definitions are converted into MACRO from the macro definitions in the file DTR$LIBRARY:DTRFNLB.MLB. The MACRO $DTR$FUN_DEF takes arguments of the internal name, the external name, and the number of input arguments. The internal name is used in a .ASCIC statement to create a string which is the name of the function. DATATRIEVE converts all of its key words to upper case before trying to resolve its statement syntax. As you might have now guessed, in this case, the arguments in the function definitions are case sensitive and should appear in all upper case. So if you replace $DTR$FUN_DEF FN$JUSTIFY_special, JUSTIFY_special, 2 with $DTR$FUN_DEF FN$JUSTIFY_SPECIAL, JUSTIFY_SPECIAL, 2 your problem goes away. This restriction is not specified anywhere in the DATATRIEVE documentation. Actually, the MACRO definitions should be enhanced to force the names to all upper case. Signed, The Wombat Wizard (JHG,AJS,BZL) Dear Readers: The two previous Wombat Wizard responses emphasize the importance of functions in VAX-DATATRIEVE. In Version 4.1, a large number of new functions were added to DATATREIVE to manage the interaction with the keyboard and keypad. In Version 4.2, the function linkages were seperated into two files, IDTRFND.MAR for the Digital supported functions and DTRFND.MAR for the user supported functions, and the function FN$GET_SYMBOL was added. However, there have been two undocumented functions which have been part of DATATRIEVE since at least Version 4.0. The two functions are FN$VERSION and FN$TODAY. Neither function takes an argument. The function FN$VERSION returns the version number of DATATRIEVE. The function FN$TODAY returns the current system date and time in the usual DD-MMM-YYYY HH:MM:SS.CC format. Note, however, that the characters of the month are upper case so that the output of FN$TODAY is suitable for the input to FN$DATE. But you ask, why would we need this function since we already have the ability to set a date variable to "NOW". Well, suppose you want to set a date field to 24-hours from NOW (or any time relative to NOW): DTR> declare day usage is date. DTR> day = "NOW" DTR> day = "NOW" + (1) Variable "DAY" may contain an incorrect value due to error during assignment. Non-digit in string "now", ignoring character(s). DTR> day = fn$date(fn$today) + (1) It is clear that the function FN$TODAY can do some things that "NOW" can't. Signed, The Wombat Wizard (JHG)