______________________________________________________________________________ ______________________________________________________________________________ Contributions ______________________________________________________________________________ ______________________________________________________________________________ Contributions for the newsletter can be sent to either of the following addresses: Editor, DATATRIEVE Newsletter Joe H. Gallagher, Ph. D. c/o DECUS U. S. Chapter DATATRIEVE Newsletter Editor 249 Northboro Road, BP02 Director, Medical and Marlboro, MA 01752 Research Computing Cleveland Clinic Foundation 9500 Euclid Avenue Cleveland, Ohio 44106 Letters and articles for publication are requested from members of the SIG. They may include helpful hints, inquiries to other users, reports on SIG business, summaries of SPRs submitted to Digital or other information for members of the DATATRIEVE SIG. Machine readable input is highly desirable and machine-to-machine transfer of material is preferred, but most anything legible will be considered. However, this newsletter is not a forum for job and/or head hunting, nor is commercialism appropriate. ______________________________________________________________________________ ______________________________________________________________________________ Table of Contents ______________________________________________________________________________ Volume 6, Number 1 2 DATATRIEVE Wish List - 1984 Fall Symposium 5 From the Editor's Pen 6 Wombat Magic Session - 1984 Fall Symposium ______________________________________________________________________________ ______________________________________________________________________________ About the Cover ______________________________________________________________________________ The cover for this double issue was drawn by Bart Lederman of Bankers Trust Company. Our snow Wombat is trying to get through the winter with a little fun. And he is fishin' in the bayou outside of New Orleans before the Spring Symposium. Wombat Examiner Volume 6, Number 1 1 _____________________________________________________________________________ DATATRIEVE Wish List - 1984 Fall Symposium Bart Z. Lederman, Bankers Trust Company, New York, NY _____________________________________________________________________________ A wish list is a method by which the users can get their requests for changes or enhancements in a product back directly to the persons in DEC who work on the product. The DATATRIEVE wish list is somewhat informal, being collected during the symposium up until Thursday night, when a copy is given to a DEC developer. DEC then responds during the SIG closing session. The answers which follow are comments only, and must not be taken as a commitment by DEC to supply any new feature, but in the past most of the suggestions from the user community which appear useful or which address a need not presently satisfied have ended up in the product. In some cases (though there were not too many of them this time), DEC will suggest an alternative solution to the same problem. DEC will also often point out that the solution to a problem depends upon some other software product, and it sometimes is necessary to go to that group and let them know there is a problem, though DEC sometimes passes the information on internally. Please note that anything labeled "Editor's note" is my opinion only, not DEC's. 1. Provide a method to reset RUNNING-TOTAL or RUNNING-COUNT (at bottom and breaks). Comment: Good suggestion. Editor's note: There were two different workarounds described in the Wombat Magic session. 2. Change the READY command to allow READY *."Domain to ready" Comment: Not possible. Will consider for future. 3. When using the linear regression line in the DATATRIEVE graphics (PLOT LR), would like to see the equation on the plot. Comment: Not in the realm of DTR graphics (another package may be more appropriate for this type of graphics). 4. Put the release notes into the installation guide. Comment: Done in V3.1 [of VAX-DATATRIEVE]. 5. Would like to put "other" stuff into ReGIS memory so that our stuff can be put in with DTR plots. Comment: Will consider for future. Can work around by doing a PLOT to a file, edit, then plot to ReGIS device. 2 Wombat Examiner Volume 6, Number 1 6. Allow logical name for node and access control such as: $ASSIGN NODE "user password":: DTR_NODE DTR>READY YACHTS AT DTR_NODE Comment: Good suggestion, will consider. Newsletter editor's note: This is the same as wish 21 on the 1984 Spring Wishlist. 7. Allow the "STARTING WITH" Boolean expression for DTR-11 and PRO/DTR. Comment: Will pass [this wish] to the DTR-11 developers, but generally any new feature in DTR-11 will take away pool space. 8. Fix parenthetical arithmetical expression in Boolean statements. You cannot put parenthesis around only the left hand side of a statement. The statement IF (1 + 2) equal 3 then . . . does not give the expected result. Comment: Will investigate correcting this, might have to document it as a restriction. Putting parenthesis around the entire expression may act as a workaround. 9. Be able to specify not to split a record on two pages of a report (printing a list sometimes runs over the bottom of the page). Comment: Can't do in current architecture (it treats the inner list as a single field). Will consider a fix, a workaround could be to flatten the record with a CROSS or by writing to a temporary file. Newsletter Editor's note: The Report Writer in VAX-DATATRIEVE Version 3.0 handles inner print lists differently than Version 2.X. Some of this problem has been fixed in Version 3.0 where it skips to the next page when the inner print reaches the bottom of the page. 10. Add Group Fields to ADT Comment: Good suggestion, will consider. Editor's note: Some re-evaluation of how ADT is being used and what functionality is required may be done. Newsletter Editor's note: Group fields are supported in ADT in VAX- DATATRIEVE Version 3.0. Wombat Examiner Volume 6, Number 1 3 11. [Support for] FMS scrolling regions. Comment: Probably not in DTR, it has been looked at before and is very difficult. A workaround is possible by using a simple application program and callable DTR. Newsletter Editor's note: This is same as wish 7 on the 1984 Spring Wishlist. 12. On-line HELP for all supplied functions. Comment: Good suggestion. 13. Be able to divide by zero without getting "-1" as an answer. Comment: Good suggestion. (DTR-11 does this already.) 14. Support segmented strings and varying text. Comment: This is near the top on the priority list; it is being given serious attention. 15. Concatenate field with report name. Comment: Good suggestion, will consider. A sort of workaround is to explicitly print all of the text at the top of the report and use your own field for the title. Newsletter Editor's note: This is the same as wish 8 on the 1984 Spring Wishlist. 16. EXTRACT ALL (and EXTRACT ALL DOMAINS, EXTRACT ALL RECORDS, etc.) Comment: Good suggestion. DTR-11 has the QXTR utility for EXTRACT ALL Editor's note: Also see the magic in this issue. Newsletter Editor's note: This is the same as wish 3 on the 1984 Spring Wishlist. 17. A long suggestion which boils down to: add a $SPAWN word to DTR so that the user doesn't have to work out the way to spawn things on the VAX. Comment: Good suggestion, will look at. 18. Now that VMS V4 RMS supports quad-word keys, give that capability to DTR. (Especially for Dates.) Comment: High on the priority list, getting serious attention. 4 Wombat Examiner Volume 6, Number 1 19. Document the way DTR-32 stores midnight in the date. Other languages calling DTR use VAX "NOW" for the date which includes the time, and they don't get a match on date. Comment: Will attempt to clarify the documentation, some of which is already there. Editor's note: Some comments were also made that the whole matter of dealing with date and time matches is receiving attention. 20. In DTR/FMS interface, do validation on a per field rather than a per form basis. Comment: Can't do this with the current architecture. Will look at it for something in the future. _____________________________________________________________________________ From the Editor's Pen Joe H. Gallagher, Cleveland Clinic Foundation, Cleveland, OH _____________________________________________________________________________ While the winter in Cleveland has been your typically normal yucky winter, this has been a particularly bad winter for me. Being around the hospital all the time and exposed to all the good (and bad) bugs, I usually never get sick. But this year made up for it! I've been down three times with the flu since the first of the year and a chronic cough that I had had for years has finally been diagnosed as asthma. All my ills coupled with a new boss who thinks everything with IBM on it is great has made me consider giving up and heading southwest to a warmer, more hospitable climate. In addition, the Wombat Magic session at the Anaheim meeting did not get recorded. This meant a whole lot of extra work trying to get that material in shape for publication. I just kept putting off starting work on this issue of the Newsletter. Well, this is my back-handed way of saying I'll try to do better about getting the Wombat Examiner out on a more timely basis. I have put my requisition in for some 36 hour days, but nobody seem to be able to supply me any. Wombat Examiner Volume 6, Number 1 5 ______________________________________________________________________________ Wombat Magic Session - 1984 Fall Symposium Session Chairman: Dick Azzi Session Editor: Joe H. Gallagher ______________________________________________________________________________ Editor's note: Due to an oversight, the Wombat Magic Session at the 1984 Fall DECUS Symposium in Anaheim was not recorded. The following is a highly edited version of only a part of the material which was presented. I apologize to Anthony E. Scandora, Jr., Steven Cordiviola, Phil Dickerson, Ali Diba, Joe Meagher, and Bob Axelrod who presented very interesting magic. However, without an audio record of what transpired at the magic session, I found it impossible to reconstruct a meaningful representation of the presented material from only the transparencies. Material which appears in the text within square brackets [] is the Editor's interpretation of what was presented and may not necessarily represent what was presented by the speaker. [At the beginning of the Magic Session, a special challenge was issued to the group. The problem was to create a set of report writer commands which would have the apparent effect of resetting the RUNNING COUNT at the beginning of each group so that each group would be numbered starting at one. Two Wombat Wizard offered solutions to the problem. However, after closer inspections and testing by the Newsletter Editor, only one was found to correctly solve the stated problem. Congratulations to Katherine Wrobel, Colorado Support Center, Digital Equipment Corporation, for providing the following elegant, simple solution to the problem. The example to illustrate the solution was provided by the Newsletter Editor.] Katherine Wrobel, Digital Equipment Corporation, Colorado Springs, CO Consider a domain EXAMPLE with a record which consists of employee's name and employee's department like: 01 EXAMPLE-REC. 03 NAME PIC X(10). 03 DEPARTMENT PIC X(10). An effective reset of the RUNNING COUNT can be accomplished by: REPORT A IN EXAMPLE SORTED BY DEPARTMENT PRINT NAME, DEPARTMENT, ((RUNNING COUNT) - - (COUNT OF EXAMPLE WITH DEPARTMENT < A.DEPARTMENT), RUNNING COUNT END-REPORT 6 Wombat Examiner Volume 6, Number 1 This would give a report which looks like: Joe Accounting 1 1 Mary Accounting 2 2 Laura Accounting 3 3 Kathleen Accounting 4 4 Shirley Engineering 1 5 Mario Engineering 2 6 Frank Engineering 3 7 Henry Maintenance 1 8 Philip Maintenance 2 9 Chris Wool, E. I. duPont, Wilmington, DE The problem is to print a number using only two significant digits. The solution: define a PIC clause for the number like NUM PIC 99V99 and then PRINT CHOICE OF NUM LT 1 THEN FORMAT NUM USING .99 NUM LT 10 THEN FORMAT NUM USING 9.9 ELSE FORMAT NUM USING 99|"." END_CHOICE Philip Dickerson, Norther Telecom Inc., Concord, NH [We want to plot the running count of records against the value of a field to give a plot like] PLOT X_Y ALL RUNNING COUNT, FIELD Wombat Examiner Volume 6, Number 1 7 [However, this gives a graph which is in terms of the number of records. In this case 67. What we really want in a plot in terms of the percentage of running count. So we try] PLOT X_Y ALL ((RUNNING COUNT * 100)/COUNT), FIELD [But this is not quite right either, since the graph goes to 120 (percent) on the x-axis rather than stop at 100 (percent). The magic is to plot] PLOT X_Y ALL ((RUNNING COUNT * 99.99)/COUNT), FIELD 8 Wombat Examiner Volume 6, Number 1 Anthony E. Scandora, Jr., Wheaton, IL One Friday afternoon, I got a phone call from a poor soul who had initialized the wrong disk in a cluster, was sorry, and wanted it back. The volume was mounted on another CPU, but VMS let it be initialized, anyway. The system's TU77 had been busted for a few weeks, so the only tape backup was too old to be useful. I look at Mike Higgins' and Phil Cannon's disk recovery tools from old RSX SIG tapes, but they assumed that the index file was still available. unlike RSX, which creates a reasonably sized index file by default, VMS just creates a little index file by default and extends it a lot. Fortunately, the initialize command had no arguments in it (except, of course, the wrong device name), so all we had to do was find all of the blocks that were in the old index file and use them to recover their files. What does an index file block look like? I looked in STARLET.MLB for a macro describing it, but I couldn't find one (now I feel stupid for forgetting to look in LIB.MLB). The telephone support center had a huge manual on the subject, but they didn't want to read it to me over the phone. A long time ago, an ancient ODS-2 document for the PDP-11 fell into my hands. It was worth a shot. Sure enough, it still describes ODS-2. It even names the macro FHDO2$, which is in RSXMAC.SML. I translated that macro to VAX macro, and we were in business. I wrote SCAN2 to read every block on a disk, decide if it could have been in the index file, and if so, write some of the fields (see INDEXF.DTR) into a file called INDEXF.SEQ on a good disk. Then I converted it to INDEXF.IDX, and let DATATRIEVE analyze it. Good old ODS-2 has back file pointers, which point to files' directory files. We had DATATRIEVE write a report sorted by back file pointer and file name, which produced a great sigh of relief. The other half of the program, RECOVER2, reads every record in INDEXF.IDX, and for each record that is marked to be recovered, reads a file header by logical block numb (LBN) from the dead disk and restores the file to the directory logically named RECOVERED:. That program is driven by RECOVER2.COM, which takes two arguments: a directory name and its FID on the dead disk. It calls DATATRIEVE to mark all files whose back file pointer matches the directory's FID to be recovered, creates the destination directory and assigns the logical "RECIVERED" to it, runs RECOVER2, and calls DATATRIEVE again to change the status of all of the files to be recovered to done. Finally, we marked all unprocessed files to be recovered, and let RECOVER2 put them in SYSLOST. They only had an ancient PDP-11 DTR, which appears to read commands from its terminal, so I had to "MCR DTR @FILE" to call it. The DATATRIEVE procedures could be a lot better for VAX DATATRIEVE. The old DTR uses the size of the PIC to decide if COMP FIELDS are WORD or LONGs. There were no multi-header files on the disk, so RECOVER2 doesn't do them. it could be added. I started to have it create the file with XABs, but it got too complicated. I commented out that code and had it write the header. I think there is code in there for more than 64K files. The high byte of the relative volume is the high byte of a three byte file number. To do it right, the program should be changed to swap the bytes of the relative volume number and use that as the high work of a long file number. This was done on a commercial system, so this SIG tape submission does not contain any of their directories. [The programs described have been submitted to the VAX? SIG tape. The INDEXF record definition is as follows:] Wombat Examiner Volume 6, Number 1 9 define record indexf_record 01 indexf. 05 lbn usage is comp pic 9(6). 05 fnum usage is comp pic 9(5). 05 fseq usage is comp pic 9(4). 05 fseg usage is comp pic 9(4). 05 efnu usage is comp pic 9(5). 05 efsq usage is comp pic 9(4). 05 status pic x. 05 direct pic x. 05 bfnu usage is comp pic 9(5). 05 bfsq usage is comp pic 9(4). 05 fnam pic x(20). 05 crdt usage is date. 05 efbk usage is comp pic 9(5). 05 hibk usage is comp pic 9(5). ; $ ! recover2.com $ set noon $ if p1 .eqs. "" then inquire p1 "Directory to recover" $ if p2 .eqs. "" then inquire p2 "Directory file number" $ open/write dtrcom dtr.dtr $ write dtrcom "ready indexf write" $ write dtrcom "find indexf with bfnu = ", p2 $ write dtrcom "find current with status = "" """ $ write dtrcom "modify all using status = ""!""" $ write dtrcom "sort current by fnam" $ write dtrcom "print all fnam, efbk, hibk" $ write dtrcom "exit" $ close dtrcom $ mcr dtr @dtr.dtr $ del dtr.dtr;0 $ cr/dir 'p1' $ assign 'p1' recovered: $ run recover2 $ open/write dtrcom dtr.dtr $ write dtrcom "ready indexf write" $ write dtrcom "find indexf with bfnu = ",p2 $ write dtrcom "find current with status = ""!""" $ write dtrcom "modify all using status = ""*""" $ write dtrcom "sort current by fnam" $ write dtrcom "print all fnam, efbk, hibk" $ write dtrcom "exit" $ close dtrcom $ mcr dtr @dtr.dtr $ del dtr.dtr;0 10 Wombat Examiner Volume 6, Number 1 Dick Azzi, Motorola SPS, Phoenix, AZ [How do you determine the number of working days (week days) in a month excluding holidays? You do it as follows:] declare report_month pic 99. declare report_year pic 99. declare first_of_month usage is date. declare last_of_month usage is date. declare days_to_check usage is date. declare days pic 99. ! a table HOLIDAY-TABLE contains the dates of all holidays report_month = * report_year = * first_of_month = report_month|"/01/"|report_year last_of_month = first_of_month + 35 last_of_month = fn$month(last_of_month)|"/01/"|fn$year(last_of_month) last_of_month = last_of_month + (-1) days = 0 days_to_check = first_of_month while days_to_check le last_of_month begin if "S" ne (format days_to_check using w) and days_to_check not in HOLIDAY-TABLE days = days + 1 days_to_check = days_to_check + 1 end print days Jim McMillan, Arizona Supreme Court, Tuscon, AZ [How do you create reports in DATATRIEVE which have video or printing attributes? First, create a table with the desired attributes like define table attributes O:"[0m" ! all attributes off B:"[1m" ! bold U:"[4m" ! underscore K:"[5m" ! blink R:"[7m" ! reverse (inverse video) end-table then include within the record definition of the desired domain some PIC X fields between the other fields of the record to contain the video attributes or use a PRINT statement like print "O" via attributes | "Field One " | "O" via attributes | - "B" via attributes | "Field Two " | "O" via attributes | - "U" via attributes | "Field Three " | "O" via attributes | - "Field Four" which would give Field One Field Two Field Three Field Four Wombat Examiner Volume 6, Number 1 11 If the attributes where stored within a record and there was a computed by variable which contained the "VIA ATTRIBUTES" it would be shorter and more convenient to manage.] Pat Scopelliti, Corning Glass Works This presentation is called "Domainless DATATRIEVE or Using DATATRIEVE as an FMS forms interface without using domains or hardly even knowing what you're doing!" Step 1 is to crate an FMS form named BADGE like the following: +------------------------------------------------------------------+ | Domainless Datatrieve DEMO | | Create a Badge | | | | Name: XXXXXXXXXXXXXXX X XXXXXXXXXXXXXXXXXXXX | | Title: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | | Company: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | | City: XXXXXXXXXXXXXXXXXXX State: XX | | | | Ready? X | | | +------------------------------------------------------------------+ Step 2 is to create the field declarations by using FMS with the following command. $ FMS/DESCRIPTION/DECLARATIONS BADGE This will create a file BADGE.TXT which contains the following: 01 BADGE. 05 FNAME PIC X(15). 05 MI PIC X(1). 05 LASTNAME PIC X(20). 05 TITLE PIC X(30). 05 COMPANY PIC X(35). 05 CITY PIC X(19). 05 STATE PIC X(2). 05 JUNK PIC X(1). This file will now be used three times with minor editing to perform steps four, five, and six. Step 3. Create an empty procedure in DATATRIEVE by the following: DTR> DEFINE PROCEDURE MAKE_BADGE DFN> END-PROCEDURE DTR> EDIT MAKE_BADGE Now perform the next three steps using the editor [inside of DATATRIEVE] and making liberal use of the [editor] command 'INCLUDE BADGE.TXT' to retrieve the field names and definitions. 12 Wombat Examiner Volume 6, Number 1 Step 4. Add field declarations inside of MAKE_BADGE of the form DEFINE PROCEDURE MAKE_BADGE DECLARE FNAME PIC X(15). DECLARE MI PIC X(1). DECLARE LASTNAME PIC X(20). DECLARE TITLE PIC X(30). DECLARE COMPANY PIC X(35). DECLARE CITY PIC X(19). DECLARE STATE PIC X(2). DECLARE JUNK PIC X(1). END_PROCEDURE Step 5. Add retrieval from the FORM. [Add to the procedure the following:] REPEAT 100 BEGIN DISPLAY_FORM BADGE IN DEMO RETRIEVE USING BEGIN FNAME = GET_FORM FNAME MI = GET_FORM MI LASTNAME = GET_FORM LASTNAME TITLE = GET_FORM TITLE COMPANY = GET_FORM COMPANY CITY = GET_FORM CITY STATE = GET_FORM STATE JUNK = GET_FORM JUNK END END Step 6. Add an output section on txa6: print skip, "[1m","DECUS Symposium",skip,"[0m",skip, fname(-),mi(-),lastname(-),skip,title(-),skip,company(-),skip, city(-),state(-), skip, skip A typical badge would look like [Pat's example really contained double width characters which can't be reproduced in the newsletter] D E C U S S y m p o s i u m Theodore E Barr Systems Analyst Forestry Systems, Inc. Frostbite Fills Mn To make things even better, here is a BASIC program to do most of the work for you: Wombat Examiner Volume 6, Number 1 13 1 ! MAKEPROC ! SIMPLE program to turn an FMS forms declarations file (FMS/DESC/DECL) ! into a DTR procedure. This program is meant as a demo and as such ! does not handle data entry errors in any sort of a graceful manner. 900 DIM FIELD.NAME$(200) 1000 ON ERROR GOTO 19000 110 PRINT LINPUT "Form name";FORM_NAME$ PRINT LINPUT "Library name"; LIB_NAME$ 1110 OPEN FORM_NAME$+".TXT" FOR INPUT AS FILE #1%, ACCESS READ 1120 OPEN FORM_NAME$+".PRO" FOR OUTPUT AS FILE #2% 1130 PRINT LINPUT "What will the procedure name be";P$ 1140 print #2%, "DEFINE PROCEDURE ";P$ 1200 LINPUT #1%, L$ ! get a line GOTO 1200 IF MID(L$,5%,2%)<>"05" ! skip unless its an '05 field PIC 1210 L$ = EDIT$(RIGHT(L$,9%),16%) ! remove the 05, reduce blank to 1 T% = POS(L$," ",1%) ! find first blank FIELD.COUNT% = FIELD.COUNT% + 1% ! incr count of fields in stack FIELD.NAME$(FIELD.COUNT%) = LEFT(L$,T%-1%) ! put field in stack PRINT #2%, "DECLARE ";L$ ! print DECLARE line GOTO 1200 1300 PRINT #2%,"REPEAT 100 BEGIN" ! produce display & retrieval code PRINT #2%," DISPLAY_FORM ";FORM_NAME$;" IN ";LIB_NAME$ PRINT #2%," RETRIEVE USING BEGIN" PRINT #2%," ";FIELD.NAME$(I%);" = GET_FORM ";FIELD.NAME$(I%) & FOR I% = 1% TO FIELD.COUNT% PRINT #2%," END" ! produce the print code...simple form, let users edit as needed PRINT #2%," ON USER.FIL PRINT SKIP," PRINT #2%," ";FIELD.NAME$(I%);"(-),SKIP," & FOR I% = 1% TO FIELD.COUNT% PRINT #2%," SKIP" PRINT #2%," END" PRINT #2%,"END-PROCEDURE" CLOSE #1%, #2% GOTO 32767 19000 RESUME 1300 IF ERR=11% AND ERL=1200% ! go on after end-of-file 19900 ON ERROR GOTO 0 32767 END The procedure which is created by this BASIC program is like: DEFINE PROCEDURE TEST DECLARE FNAME PIC X(15). DECLARE MI PIC X(1). DECLARE LASTNAME PIC X(20). DECLARE TITLE PIC X(30). DECLARE COMPANY PIC X(35). DECLARE CITY PIC X(19). DECLARE STATE PIC X(2). DECLARE JUNK PIC X(1). 14 Wombat Examiner Volume 6, Number 1 REPEAT 100 BEGIN DISPLAY_FORM BADGE IN DEMO RETRIEVE USING BEGIN FNAME = GET_FORM FNAME MI = GET_FORM MI LASTNAME = GET_FORM LASTNAME TITLE = GET_FORM TITLE COMPANY = GET_FORM COMPANY CITY = GET_FORM CITY STATE = GET_FORM STATE JUNK = GET_FORM JUNK END ON USER.FIL PRINT SKIP, FNAME(-),SKIP, MI(-),SKIP, LASTNAME(-),SKIP, TITLE(-),SKIP, COMPANY(-),SKIP, CITY(-),SKIP, STATE(-), SKIP, JUNK(-),SKIP, SKIP END END-PROCEDURE William Porteous, Cabot Corporation, Andover, MA [One of the most common needs of DATATRIEVE users is to be able to access DCL functionality from within DATATRIEVE. Several magic presentations in the past and one of the examples in the DATATRIEVE manuals show how to get to specific DCL commands.] This magic shows how to perform to any one line DCL command with a FORTRAN front end to DATATRIEVE through the DATATRIEVE call interface. C C This program allows DTR to execute single word DCL C commands when they are preceded by a "$" C This is a portion of the code form DECUS program VAX-78 (FILTRA) C INTEGER*2 DTR_OPTIONS, INIT_OPTIONS INTEGER*4 DTR$DTR, RET_STATUS, DTR$GET_STRING INCLUDE 'DTR$LIBRARY:DAB.FOR' INCLUDE 'DTR$LIBRARY:INFO.FOR' C DECLARE NORMAL AND EXIT STATUS EXTERNAL SS$_NORMAL, DTR$_EXIT CHARACTER*80 LINE C C INITIALIZE THE INTERFACE C C SET OPTIONS INIT_OPTIONS = DTR$K_SEMI_COLON_OPT CALL DTR$INIT (DAB, 20, MSG_BUFF, AUX_BUFF, INIT_OPTIONS) Wombat Examiner Volume 6, Number 1 15 C C CREATE USER DEFINED KEYWORDS SEND=1, RECEIVE=2, FILTRA=3, C FTR=4, AND $ FOLLOWED BY VMS COMMAND=5, HST=6, MENU=7 C CALL DTR$CREATE_UDK (DAB, '$', 5, DTR$K_UDK_COMMAND) C C DECLARE THE OPTIONS FOR THE DTR$DTR CALL C DTR_OPTIONS = DTR$M_OPT_CONTROL_C 1 + DTR$M_OPT_STARTUP 2 + DTR$M_OPT_UDK 3 + DTR$M_OPT_BANNER 50 RET_STATUS = DTR$DTR (DAB, DTR_OPTIONS) IF (RET_STATUS .EQ. %LOC(DTR$_EXIT)) GO TO 5500 IF (DAB$W_UDK_INDEX .EQ. 5) GO TO 500 500 CONTINUE CALL DTR$GET_STRING (DAB, DTR$K_TOK_COMMAND, LINE) CALL LIB$SPAWN (LINE) CALL DTR$END_UDK (DAB) GO TO 50 C C CLEAN UP, AND END THE INTERFACE C 5500 CONTINUE CALL DTR$FINISH (DAB) STOP END [The instructions for linking a FORTRAN program, such as the one above, with the sharable DATATRIEVE image are contained in Chapter 3 "Sample FORTRAN Programs" of the VAX DATATRIEVE Guide to Programming and Customizing, AA-P863B-TE.] Basil Harris, Digital Equipment Corporation, Nashua, NH Problem: How do I get a plot output file to a system ReGIS device? Solution: DTR> PLOT WOMBAT ON WOMBAT.DAT ! or your favorite plot DTR> EXIT $ ! Use DECslide to $ SLIDE/NOINTERACT/PIX=WOMBAT.DAT $ ! This create a file WOMBAT.SLS that can be sent to a ReGIS printer 16 Wombat Examiner Volume 6, Number 1 Bert Rosberry, U. S. Coast Guard, New Orleans, LA This is an oldie but goodie for VAX systems. [to remind users how to temporarily stop a process, answer the PHONE (or perform some other DCL function), and then return to the previous process] DTR> READY YACHTS DTR> FIND YACHTS Jasmann is phoning you (HH:MM:SS) DTR> ^Y $ SPAWN %DCL-S-SPAWNED, process ROSEBERRY_1 spawn %DCL-S-ATTACHED, terminal now attached to process ROSEBERRY_1 $ PHONE ANSWER ! carry on a phone conversation with Jasmann $ LOGOUT Process ROSEBERRY_1, logged out at DD-MMM-YYYY HH:MM:SS.SS %DCL-S-RETURNED, control returned to process ROSEBERRY $ CONTINUE DTR> ! domains, collections, etc are all in the same state as before [Even if one does not use the SPAWN, there are certain DCL commands such as SET which do not change the environment so that it is still possible to use a CONTINUE. For example] $ SHOW DEFAULT DRA0:[SYS0.SYSEXE] $DTR DTR> READY YACHTS File not found ---- ! [YACHTS.DAT is in [SYS0.DTR] not [SYS0.SYSEXE] DTR> ^Y $ SET DEFAULT DRA0:[SYS0.DTR] ! [SET does not zap DTR] $ CONTINUE ! [re-start DTR DTR> READY YACHTS Dick Azzi, Motorola SPS, Phoenix, AZ [We want to send some notices to our users on a certain date and then keep track of whether we have sent the notice. But we didn't want to change the record layout. Thus, we needed to flag the records, but without adding another field to the record. This can be done by burying a flag in the least significant bits of a date, as follows:] ! Use a record definition like 03 OA_DATE USAGE IS DATE. 03 REDA REDEFINES OA_DATE. 05 FLAG USAGE IS QUAD. ! DATE and QUAD both take 8 bytes Wombat Examiner Volume 6, Number 1 17 [Then the statements to select and process records] FOR DOMAIN WITH (RSE on the OA_DATE and records) BEGIN IF FN$HUNDREDTH(OA_DATE) EQUAL 0 THEN BEGIN :SEND_NOTICES_PROCEDURE FLAG = FLAG + 1000000 ! -> 0.01 SECONDS END END [This will set the date (and time) slightly past midnight (0.01 seconds) for each of the dates which will indicate that a notices has been sent.] Diane Harris, Digital Equipment Corp, Colorado Springs, CO Work breakdown structures often consist of a task broken into subtask and further into work packages. We want to be able to do totaling "on top of" a field. That is, if the work is broken down as +-------+ | 1.0 | +---+---+ | +---------+----------+ | | | +-------+ +-------+ +-------+ | 1.1 | | 1.2 | | 1.3 | +-------+ +-------+ +-------+ | +---------+----------+ | | | +-------+ +-------+ +-------+ | 1.1.1 | | 1.1.2 | | 1.1.3 | <- level at which +-------+ +-------+ +-------+ data is stored To create a report with this "upward" summarization we need a domain like define domain foo using foo-record on foo.dat; define record foo-record using 01 foo-rec. 03 work_package pic x(5). 03 wp_bkd redefines work_package. 05 subtask pic x(3). 05 filler pic x(2). 03 t_bkd redefines work_package. 05 task pic x(2). 05 filler pic x(3). 03 amount pic 9(3). ; 18 Wombat Examiner Volume 6, Number 1 Then, create a report on the records like: REPORT FOO SORTED BY WORK_PACKAGE ON FOO.TMP SET NO NUMBER SET NO DATE PRINT COL 1, WORK_PACKAGE(-), COL 7, AMOUNT(-) AT BOTTOM OF SUBTASK PRINT COL 1, WP_BKD(-), COL 7, TOTAL AMOUNT(-) AT BOTTOM OF TASK PRINT COL 1, T_BKD(-), COL 7, TOTAL AMOUNT(-) END_REPORT which would give something like: 1.1.1 050 1.1.2 010 1.1.3 040 1.1 100 1.2.1 065 1.2.2 035 1.2 100 1. 200 Use an editor to remove the form feeds and the extra blank lines from FOO.TMP. Then create a second domain to work on this report as follows: define domain tmpfoo using tmpfoo-record on foo.tmp; define record tmpfoo-record using 01 tmpfoo-rec. 03 work_package pic x(5). 03 filler pic x(1). 03 amount pic 999 edit-string is zz9. ; Then report on the report with: report empfoo sorted by work_package on foo.rpt print work_package, amount end-report which gives the information is the desired hierarchical structure. 1. 200 1.1 100 1.1.1 050 1.1.2 010 1.1.3 040 1.2 100 1.2.1 065 1.2.2 035 Wombat Examiner Volume 6, Number 1 19 Bob Pearson [Bob's magic involves a special DCL functions ASKIT which is available on one of the VAX SIG tapes. With this function, it is possible to do some very cleaver commands like:] $ !* LIST.JCL $ !* Simple list of the file %%CLASS = ASKIT("Class code", "STR/UP", "A,B,F", "F", "") %%DATE = ASKIT("Cutoff date", "DAT", "", "TODAY", "") $ dtr ready CDD$TOP.SAMPLE_DOMAIN shared find SAMPLE_DOMAIN with class eq "%%CLASS" and date le "%%DATE" report current on list.lis;%%VERSION set report_name = "Simple listing"/"For class %%CLASS" print emp_no, name, cutoff_date end_report exit $ %%PRINT list.lis;%%VERSION $ exit Which when executed would produce Class code? X please choose from A,B,F Class code? B Cutoff date? 120284 Def SYS$PRINT BL2 Building two AC Accounting office NO No print Where shall we print this[Def]? AC Job submitted Would produce the job $ !* LIST.JCL $ !* Simple list of the file $ dtr ready CDD$TOP.SAMPLE_DOMAIN shared find SAMPLE_DOMAIN with class eq "B" and date le "12/02/84" report current on list.lis;12345 set report_name = "Sample listing"/"For class B" print emp_no, name, cutoff_date end_report exit $ print/delete/queue=ttc0 list.lis;12345 $ exit 20 Wombat Examiner Volume 6, Number 1 Walt Johnson, This is CDD magic. BACKUP skips files which are open for write. Our CDD is always open for write. Therefore, our CDD on the backup tape was rather stale!! [Laughter] Our assistant system manager couldn't identify a CDD dictionary, so he deleted it. The user them called up with a complaint about her last dictionary. So... We call Colorado Springs. They suggested restoring out stale CDD and pointing to it long enough to extract her definitions. Since the other users wouldn't be thrilled, we used another solution: We defined the restored old dictionary as a subdictionary file, and used DMU> COPY CDD$TOP.USER.CDD$TOP.USER... CDD$TOP.USER... which works just fine. Andy Schneider, Digital Equipment Corporation In DATATRIEVE-11, what does this do? DTR> ready yachts DTR> report yachts DTR> at top of page print new-page DTR> end-report Answer: It empties a box of paper in 30 seconds or less! Doug Cropper, Digital Equipment Corp Presented by Andy Schneider [VAX DATATRIEVE supports the EXTRACT ALL and the ability to extract the definition of a specific dictionary object. The last two wishlists have included requests to be able to perform commands like DTR> EXTRACT ALL DOMAINS on dom.def ! or DTR> EXTRACT ALL RECORDS on rec.def ! etc which would work for domains, records, tables, procedures, plots, and databases -- essentially all dictionary objects.] [Here is a way to do an EXTRACT on a class of dictionary objects.] First thing to do is to put all of these into a CDD dictionary and create the logical MAGIC$DIC to be the dictionary that contains them. Then to do an extract just issue the command :MAGIC$DIC.EXTRACT_whatever The procedure will prompt for a file name. It stores the file name in a variable FILE_NAME. Then it opens an output log file called DIC.DAT, does a SHOW whatever [whatever class of dictionary objects you are trying to extract] and then closes the log file. Then it readies the MAGIC$DIC.TEMP domain as OLD, defines a new file for TEMP with a key, then stores the old "whatever" Wombat Examiner Volume 6, Number 1 21 names in the new data file with the name as a key. This will allow me to erase the "DTR> SHOW whatever" and "DTR> CLOSE" lines and any blank lines. Then we finish all domains and open the new keyed data file. This file now has all the names of the particular [class of] dictionary objects requested. Then I loop through all the records ("Reduced to DIC_NAME" if only the highest version is requested), building one massive "EXTRACT ON FILE_NAME path_name, path_name, ... " command and put that in a file called EXTR.COM. I then execute the command file and everything is extracted on the one file. It takes longer to explain it than to execute. The domain, record, and procedures you need are as follows: ! ! the domain used ! REDEFINE DOMAIN TEMP USING TEMP_REC ON DIC.DAT; ! ! the record definition for temp_rec ! REDEFINE RECORD TEMP_REC USING 01 TOP. 03 DIC_NAME PIC X(45). ; ! ! the main extract procedure for extracting only highest version ! REDEFINE PROCEDURE EXTR DECLARE COMMA PIC 99. DECLARE NUMBER PC 9999. DECLARE FIRST_TIME PIC 9. FIRST_TIME = 1 NUMBER = COUNT OF TEMP REDUCED TO DIC_NAME ON EXTR.DTR BEGIN FOR TEMP REDUCED TO DIC_NAME BEGIN IF FIRST_TIME EQ 1 THEN BEGIN PRINT "extract on "|FILE_NAME FIRST_TIME = 0 END IF RUNNING COUNT NOT EQ NUMBER THEN PRINT DIC_NAME||", " ELSE PRINT DIC_NAME(-) END END END_PROCEDURE ! ! the main extract procedure for extracting all versions ! REDEFINE PROCEDURE EXTR_ALL DECLARE NUMBER PIC 9999. DECLARE END_STR PIC X(40). END_STR = ", -" NUMBER = COUNT OF TEMP ON EXTR.DTR BEGIN PRINT "extract -" FOR TEMP BEGIN IF RUNNING COUNT EQ NUMBER THEN END_STR = " on "|FILE_NAME 22 Wombat Examiner Volume 6, Number 1 PRINT DIC_NAME||END_STR END END END_PROCEDURE ! ! use this for extraction all version of all databases ! REDEFINE PROCEDURE EXTRACT_ALL_ALL_DATABASES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of dictionary items" SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW DATABASES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME READY MAGIC$DIC.TEMP.AS NEW WRITE NEW = OLD FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW DATABASES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR_ALL END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP END_PROCEDURE ! ! use this for extraction all version of all domains ! REDEFINE PROCEDURE EXTRACT_ALL_ALL_DOMAINS DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of dictionary items" SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW DOMAINS CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME Wombat Examiner Volume 6, Number 1 23 READY MAGIC$DIC.TEMP.AS NEW WRITE NEW = OLD FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW DOMAINS" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR_ALL END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP END_PROCEDURE ! ! use this for extraction all version of all procedures ! REDEFINE PROCEDURE EXTRACT_ALL_ALL_PROCEDURES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of dictionary items" SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW PROCEDURES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME READY MAGIC$DIC.TEMP.AS NEW WRITE NEW = OLD FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW PROCEDURES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR_ALL END SET COLUMNS-PAGE = 80 @EXTR.DTR 24 Wombat Examiner Volume 6, Number 1 FINISH TEMP END_PROCEDURE ! ! use this for extraction all version of all records ! REDEFINE PROCEDURE EXTRACT_ALL_ALL_RECORDS DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of dictionary items" SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW RECORDS CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME READY MAGIC$DIC.TEMP.AS NEW WRITE NEW = OLD FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW RECORDS" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR_ALL END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP END_PROCEDURE ! ! use this for extraction all version of all tables ! REDEFINE PROCEDURE EXTRACT_ALL_ALL_TABLES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of dictionary items" SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW TABLES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME READY MAGIC$DIC.TEMP.AS NEW WRITE NEW = OLD Wombat Examiner Volume 6, Number 1 25 FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW TABLES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR_ALL END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP END_PROCEDURE ! ! use this for extracting the highest version of all databases ! REDEFINE PROCEDURE EXTRACT_DATABASES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list databases SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW DATABASES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME (DUP) READY MAGIC$DIC.TEMP AS NEW WRITE BEGIN DECLARE COMMA PIC 99. FOR OLD STORE NEW USING BEGIN COMMA = FN$STR_LOC(DIC_NAME,";") DIC_NAME = FORMAT (FN$STR_EXTRACT(DIC_NAME,1,(COMMA - 1))) USING X(45) END END FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW DATABASES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT 26 Wombat Examiner Volume 6, Number 1 BEGIN :MAGIC$DIC.EXTR END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP RELEASE FILE_NAME END_PROCEDURE ! ! use this for extracting the highest version of all domains ! REDEFINE PROCEDURE EXTRACT_DOMAINS DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of domains SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW DOMAINS CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME (DUP) READY MAGIC$DIC.TEMP AS NEW WRITE BEGIN DECLARE COMMA PIC 99. FOR OLD STORE NEW USING BEGIN COMMA = FN$STR_LOC(DIC_NAME,";") DIC_NAME = FORMAT (FN$STR_EXTRACT(DIC_NAME,1,(COMMA - 1))) USING X(45) END END FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW DOMAINS" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP RELEASE FILE_NAME END_PROCEDURE Wombat Examiner Volume 6, Number 1 27 ! ! use this for extracting the highest version of all procedures ! REDEFINE PROCEDURE EXTRACT_PROCEDURES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of procedures SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW PROCEDURES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME (DUP) READY MAGIC$DIC.TEMP AS NEW WRITE BEGIN DECLARE COMMA PIC 99. FOR OLD STORE NEW USING BEGIN COMMA = FN$STR_LOC(DIC_NAME,";") DIC_NAME = FORMAT (FN$STR_EXTRACT(DIC_NAME,1,(COMMA - 1))) USING X(45) END END FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW PROCEDURES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP RELEASE FILE_NAME END_PROCEDURE ! ! use this for extracting the highest version of all records ! REDEFINE PROCEDURE EXTRACT_RECORDS DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of records SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW RECORDS CLOSE SET COLUMNS_PAGE = 85 28 Wombat Examiner Volume 6, Number 1 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME (DUP) READY MAGIC$DIC.TEMP AS NEW WRITE BEGIN DECLARE COMMA PIC 99. FOR OLD STORE NEW USING BEGIN COMMA = FN$STR_LOC(DIC_NAME,";") DIC_NAME = FORMAT (FN$STR_EXTRACT(DIC_NAME,1,(COMMA - 1))) USING X(45) END END FINISH READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW RECORDS" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP RELEASE FILE_NAME END_PROCEDURE ! ! use this for extracting the highest version of all tables ! REDEFINE PROCEDURE EXTRACT_TABLES DECLARE FILE_NAME PIC X(32). FILE_NAME = "file name" PRINT "ignore following list of tables SET COLUMNS_PAGE = 1 OPEN DIC.DAT SHOW TABLES CLOSE SET COLUMNS_PAGE = 85 PRINT "thank you" READY MAGIC$DIC.TEMP AS OLD DEFINE FILE FOR MAGIC$DIC.TEMP KEY = DIC_NAME (DUP) READY MAGIC$DIC.TEMP AS NEW WRITE BEGIN DECLARE COMMA PIC 99. FOR OLD STORE NEW USING BEGIN COMMA = FN$STR_LOC(DIC_NAME,";") DIC_NAME = FORMAT (FN$STR_EXTRACT(DIC_NAME,1,(COMMA - 1))) USING X(45) END END FINISH Wombat Examiner Volume 6, Number 1 29 READY MAGIC$DIC.TEMP WRITE FIND TEMP !erase the first 2 lines SELECT FIRST ERASE !erase the "DTR> SHOW TABLES" LINE SELECT NEXT ERASE SELECT LAST ERASE RELEASE CURRENT BEGIN :MAGIC$DIC.EXTR END SET COLUMNS-PAGE = 80 @EXTR.DTR FINISH TEMP RELEASE FILE_NAME END_PROCEDURE Diana Washburn, Hanes Hosiery, Winston-Salem, NC This is an example of using subscripting or indexing in DATATRIEVE. This is very handy when you need to get information for specific fields within a list, but hove no value within the list to use in the RSE with the 'ANY' Boolean expression. For instance, 12 months of data but no actual month identifier (1 - 12 or JAN - DEC). It should only be used when the normal DATATRIEVE list processing features can not be used. They said it couldn't be done, but watch: First I'll show you the domain and record that will be used in the example. DEFINE DOMAIN MAGIC USING MAGIC_REC ON DEVICE:MAGIC.DAT; DEFINE RECORD MAGIC_REC USING 01 MAGIC_REC. 02 MAGIC_KEY PIC X(5). 02 MAGIC_LIST OCCURS 4 TIMES. 03 MAGIC_LIST_FIELD PIC 9(4) QUERY_NAME QTY. ; 30 Wombat Examiner Volume 6, Number 1 The data that has been stored in the file looks like this: DTR> PRINT MAGIC MAGIC MAGIC LIST KEY FIELD 11111 0001 0002 0003 0004 22222 0010 0020 0030 0040 33333 0100 0200 0300 0400 44444 1000 2000 3000 4000 55555 1111 2222 3333 4444 Here is a very simple example that will allow you to enter one subscript. DEFINE PROCEDURE MAGIC_SUBSCRIPTING DECLARE COUNTER PIC 99. ! The counter is used to identify the level DECLARE SUBSCRIPT PIC 99. READY MAGIC SHARED SUBSCRIPT = *.'Subscript' ! The subscript is prompted here but could ! be taken from another source (screen,record) FOR MAGIC BEGIN COUNTER = 1 FOR MAGIC_LIST BEGIN IF COUNTER = SUBSCRIPT THEN PRINT MAGIC_LIST_FIELD COUNTER = COUNTER + 1 END END END_PROCEDURE Wombat Examiner Volume 6, Number 1 31 Here is what happens when you run the procedure: DTR> :MAGIC-SUBSCRIPTING DTR> :MAGIC-SUBSCRIPTING Enter Subscript : 1 Enter Subscript : 2 MAGIC MAGIC LIST LIST FIELD FIELD 0001 0002 0010 0020 0100 0200 1000 2000 DTR> :MAGIC-SUBSCRIPTING DTR> :MAGIC-SUBSCRIPTING Enter Subscript : 3 Enter Subscript : 4 MAGIC MAGIC LIST LIST FIELD FIELD 0003 0004 0030 0040 0300 0400 3000 4000 Now let's add a range of subscripts. In this case the values from the specified list levels are accumulated and the total is printed for each record: DEFINE PROCEDURE MAGIC_SUBSCRIPTING DECLARE COUNTER PIC 99. DECLARE BEG_SUBSCRIPT PIC 99. DECLARE END_SUBSCRIPT PIC 99. DECLARE MAGIC_TOTAL PIC S9(9). READY MAGIC SHARED BEG_SUBSCRIPT = *.'Beginning Subscript or Index' END_SUBSCRIPT = *.'Ending Subscript of Index' FOR MAGIC BEGIN MAGIC_TOTAL = 0 FOR MAGIC_LIST BEGIN IF COUNTER BT BEG_SUBSCRIPT AND END_SUBSCRIPT MAGIC_TOTAL = MAGIC_TOTAL + MAGIC_LIST_FIELD COUNTER = COUNTER + 1 END PRINT MAGIC_TOTAL END END_PROCEDURE 32 Wombat Examiner Volume 6, Number 1 Running this procedure gives you: DTR> :MAGIC-SUBSCRIPTING DTR> :MAGIC-SUBSCRIPTING Enter Beginning Subscript : 1 Enter Beginning Subscript : 2 Enter Ending Subscript : 2 Enter Ending Subscript : 4 MAGIC MAGIC TOTAL TOTAL 000000003 000000009 000000030 000000090 000000300 000000900 000003000 000009000 If you have data in a list that is not identified in the record but is in a fixed pattern, you can use a table lookup to get at the data without having to remember the order of the data in the list. Here is the table used in the next example: DEFINE TABLE MAGIC_CODE_TABLE USING 'AA':1 'BB':2 'CC':3 'DD':4 END_TABLE DEFINE PROCEDURE MAGIC_SUBSCRIPTING DECLARE COUNTER PIC 99. DECLARE SUBSCRIPT_CODE PIC XX. READY MAGIC SHARED SUBSCRIPT_CODE = *.'Translation code for subscript' FOR MAGIC BEGIN COUNTER = 1 PRINT COL 2, MAGIC_KEY(-) FOR MAGIC_LIST BEGIN IF COUNTER = SUBSCRIPT_CODE VIA MAGIC_CODE_TABLE PRINT COL 10, MAGIC_LIST_FIELD(-) COUNTER = COUNTER + 1 END END END_PROCEDURE Wombat Examiner Volume 6, Number 1 33 When you run the procedure you get: DTR> :MAGIC_SUBSCRIPTING Enter Translation code for subscript : CC 11111 0003 22222 0030 33333 0300 44444 3000 55555 3333 There are times when you may need to get the data in several of the levels of a list that are not contiguous. In this case you can use a DATATRIEVE function to pull the subscripts from a string: DEFINE PROCEDURE MAGIC_SUBSCRIPTING DECLARE COUNTER PIC 99. DECLARE SUBSCRIPTS PIC X(5). READY MAGIC SHARED SUBSCRIPTS = *.'Subscript(s) separated by commas' FOR MAGIC BEGIN COUNTER = 1 PRINT COL 2, MAGIC_KEY(-) FOR MAGIC_LIST BEGIN IF COUNTER = FN$STR_EXTRACT(SUBSCRIPTS,1,1), FN$STR_EXTRACT(SUBSCRIPTS,3,1), FN$STR_EXTRACT(SUBSCRIPTS,5,1) PRINT COL 10, MAGIC_LIST_FIELD(-) COUNTER = COUNTER + 1 END END END_PROCEDURE 34 Wombat Examiner Volume 6, Number 1 Here is what happens when this procedure is run: DTR> :MAGIC-SUBSCRIPTING Enter Subscript(s) separated by commas: 1,4 11111 0001 0004 22222 0010 0040 33333 0100 0400 44444 1000 4000 55555 1111 4444 In the last example you would have to set up the subscripts variable to be able to handle the maximum number of subscripts allowed. Remember to add 1 character per subscript for the separator (comma). In the example I allowed for 3 subscripts since the occurs is 4 and I would assume that the normal DTR list processing would be used if all entries in the list were desired. This gets a little more complicated when the subscripts itself can be a variable number of digits. The easiest way to handle this is to establish a fixed number of places for the subscript and require that leading zeros be entered. The concept of subscripting can be very helpful. I use this technique to build summary files and then report the data in the summarized file. I have not found a way yet to use this within the report command. To give you an idea of how it applies to a real life application, let me tell you how I use it. I have a record with 27 month worth of data. The record does not indicate the year/month represented in each level. This information is in another domain in a control record. My users request data from one date to another (i.e., December '82 to December '83 or September '82 to January '84). I have to locate the proper levels by using the control file. I convert the year/month to a number (1 to 27) for beginning and ending dates. Then based on a long series of if statements I accumulate the data for the appropriate months. [The next three magic presentations all have to do with using variable length strings. Each is slightly different, but each gets at the same (or similar) problem.] Wombat Examiner Volume 6, Number 1 35 Chris Wool, E. I. duPont, Wilmington, DE The problem is: We need to input a variable length character string and use it in a STARTING WITH Boolean expression. When one uses FIND domain with field STARTING WITH *."prompt_message" it works perfectly well. However, when one need to save the value that has been input to use several times, such as, DECLARE TEXT PIC X(10). TEXT = *."prompt_message" then FIND domain with field STARTING WITH TEXT no longer works, since the global variable contains blanks. However, it one uses FIND domain with field STARTING WITH TEXT||"" ! the null string everything works perfectly well again since the blank fills are effectively removed. Stephen Pacheco, Ship Analytics, North Stonington, CT To create a variable length character string to use in string comparisons, you may use DECLARE TEXT PIC X(40). TEXT = *."prompt_message"||"**" DECLARE MATCH COMPUTED BY (FN$STR_EXTRACT(TEXT ,1 ,FN$STR_LOC(TEXT, "**") - 1) . Then MATCH may be used in string comparisons. Philip Dickerson, Northern Telecom Incorporated, Concord NH In DATATRIEVE-11 where there is no STARTING WITH, a variable length, starting with comparison can be accomplished as follows: DECLARE A PIC X(10). DECLARE B PIC X(10) COMPUTED BY A||"zzzz" . A = *."string" FIND domain with field BETWEEN A AND B 36 Wombat Examiner Volume 6, Number 1