home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / mumps / program.doc < prev    next >
Text File  |  1986-08-15  |  85KB  |  1,759 lines

  1.  
  2. VA FileMan  V.17 - Apr 1986           Programmer's Manual  (1)
  3.  
  4.                    V A   F I L E M A N
  5.                    PROGRAMMER'S MANUAL
  6.                 Version 17 - April, 1986
  7.  
  8.                         CONTENTS
  9.  
  10.     I.   SETTING UP FILEMAN
  11.  
  12.     II.  MUMPS PROGRAMMING CONVENTIONS
  13.          A. Routine Size
  14.          B. Non-Standard MUMPS Features
  15.          C. Other Routines Used
  16.          D. Routine and Variable Names
  17.          E. First-Line Documentation
  18.          F. Semicolon Lines within Routines
  19.          G. Continuation Routines
  20.          H. Argument-Passing Variables
  21.          I. Delimiters within Strings
  22.  
  23.     III. GLOBAL FILE STRUCTURE
  24.          A. File Entries
  25.          B. Cross-references
  26.          C. File Descriptor
  27.          D. Attribute Dictionary
  28.      
  29.     IV.  PROGRAMMER ROUTINES
  30.          A. File Lookup ('DIC')
  31.          B. Data Edit ('DIE')
  32.          C. Data Print ('DIP')
  33.          D. Data Display ('DIQ')
  34.          E. Word-Processing Formatting and Output ('DIWP')
  35.          F. Form Document Print ('DIWF')
  36.          G. File Re-crossreference and
  37.             Entry Deletion ('DIK')
  38.          H. Date Conversion ('%DT')
  39.          I. Date Compare ('%DTC')
  40.          J. MUMPS Validation ('DIM')
  41.  
  42.     V.   ADVANCED FILE-DEFINITION FEATURES
  43.          A. Storing Data in a Global Other Than '^DIZ'
  44.          B. Assigning Where Fields Are Stored in a Global
  45.          C. Assigning 'Sub-Dictionary' Numbers
  46.          D. MUMPS 'Computed Fields'
  47.          E. "Screened" Pointers
  48.          F. "Input Transform"
  49.          G. "Output Transform"
  50.  
  51.     VI.  OTHER PROGRAMMER UTILITIES
  52.          A. Creating Functions
  53.          B. Code Generation - Input Routines
  54.          C. Code Generation - Output Routines
  55.          D. Creating Routines "Packages" for Export
  56.      
  57. VA FileMan  V.17 - Apr 1986      Programmer's Manual  (1)
  58.  
  59.  
  60.  
  61.  
  62.                       I.  SETTING UP FILEMAN
  63.  
  64.  
  65. VA FileMan consists of approximately 150 MUMPS routines.  These routines, as 
  66. they are run, set up all the MUMPS Globals that they require.
  67.  
  68. One of the VA FileMan routines is called "DINTEG".  It will be seen to contain a
  69. list of all the routine names in the package.  If your MUMPS system allows use 
  70. of the "ZLOAD" command, you can run "DINTEG" to check on the "integrity" of the
  71. routines you have loaded.  If "DINTEG" detects any discrepancy between the 
  72. number of bits it thinks a routine should contain, and the number in the 
  73. routine on file, it will display a message, which will look something like:
  74.  
  75.     DIC ROUTINE IS OFF BY 123 BITS
  76.  
  77. Such messages indicate that your copy of VA FileMan is not identical to the one
  78. distributed by the developer.  In this case, your most prudent course is to
  79. obtain a fresh copy of the routines.
  80.  
  81. After first loading the VA FileMan routines, the routines called "DIDT", 
  82. "DIDTC", and "DIRCR" must be re-filed in the manager's account (UCI) with the 
  83. names "%DT", "%DTC", and "%RCR", respectively.  A device-selection routine 
  84. called "%ZIS" must also be present on your system (see Chapter II, Section C).  Either:
  85.          
  86.            
  87.           1. You already have a "%ZIS" (supplied to VA and "Kernel"
  88.              users).  You're all set.
  89.            
  90.           2. You have a device selection routine supplied by your MUMPS
  91.              vendor.  You may use the routine provided that it returns the
  92.              variables expected by VA FileMan from such a device selection
  93.              program.  These variables are listed in Chapter II, Section
  94.              C.  In this case you can simply create a "%ZIS" routine which
  95.              calls the vendor supplied routine.
  96.            
  97.           3. You do not have a device selection routine.  Re-file the
  98.              routine "DIIS" as your temporary "%ZIS" routine.  This will
  99.              mean that all VA FileMan output will go to the terminal that
  100.              requests it, and will assume that the terminal is a 24-line
  101.              CRT.  Later on, you may want to write your own version of
  102.              "%ZIS", following the input/output conventions set forth in
  103.              Chapter II, Section C.
  104.           
  105.  
  106. Run the "DINIT" routine.  It will ask you for an (arbitrary) site name and
  107. number, pause for 1-90 minutes, and then ask you for the
  108.  
  109.         TYPE OF MUMPS SYSTEM YOU ARE USING:
  110.  
  111. Type a "?" at this point to see your possible choices ("DSM", "M/11", "M/VX",
  112. "MICRONETICS", etc.).  If you don"t see your MUMPS operating system vendor
  113. listed, or are unsure, enter "OTHER" in answer to this query.  You can always
  114. re-run the "DINIT" routine (although other users should be off the system when
  115. you do), to re-answer its questions.  In fact, you must re-run "DINIT"
  116. whenever you load a new Version of VA FileMan.
  117.  
  118. VA FileMan is now ready to use.  "DI" is the general Option driver (see User 
  119. Manual, Chapter III).  To restrict user access to files and fields (User 
  120. Manual, Chapter X), you can have a MUMPS routine set the local variables "DUZ" 
  121. and "DUZ(0)" before calling "DI".
  122.  
  123. A note on installing VA FileMan under Digital Equipment Corporation's "DSM": 
  124. Version 2.2 of DSM is not supported by VA FileMan as a special MUMPS Operating 
  125. System.  If you are running a DSM version with a number lower than 3, answer
  126. "OTHER" to the "TYPE OF MUMPS SYSTEM YOU ARE USING:" question.  DSM-11 Version 
  127. 3 supports "routine mapping", whereby the Sysgen procedure tells the Operating 
  128. System to load certain routines permanently into Main Memory.  The VA FileMan 
  129. routines beginning with "DIFRO*", "DIEZ*" and "DIPZ*" should not be mapped into 
  130. memory.
  131. VA FileMan  V.17 - Apr 1986                         Programmer's Manual  (2)
  132.  
  133.  
  134.  
  135.  
  136.                  II. MUMPS PROGRAMMING CONVENTIONS
  137.  
  138.  
  139. Before proceeding to an explanation of the internal workings of FileMan, we will
  140. list some general MUMPS programming conventions which have guided the
  141. organization of the routines comprising FileMan.  A knowledge of the MUMPS
  142. programming language is presumed throughout the remainder of this manual.
  143.  
  144.  
  145. A.  ROUTINE SIZE:
  146.  
  147. Most MUMPS routines in FileMan package do not exceed 2048 characters in size, 
  148. and none is bigger than 2800 characters.  In most cases, the routines should 
  149. run in a 8000-character partition.  A very complicated Sort/Print run, however, 
  150. can take up as much as 10K of stack and local symbol table.  No routine line is 
  151. longer than 245 bytes.
  152.  
  153.  
  154. B.  NON-STANDARD MUMPS FEATURES:
  155.  
  156. "Z-commands" and "Z-functions" are avoided throughout FileMan routines.  For
  157. certain purposes (such as allowing terminal "breaking", and spooling to a disk
  158. "SDP" device), FileMan tries to execute lines of non-Standard MUMPS code out 
  159. of a "File of operating systems" that it maintains.  The non-Standard code used 
  160. (if any) depends on the answer to the question:
  161.  
  162.          TYPE OF MUMPS SYSTEM YOU ARE USING:
  163.  
  164. which appears at the end of the 'DINIT' initialization routine.  Answering
  165. "OTHER" to this question will ensure that FileMan uses only Standard MUMPS code.
  166.  
  167. String-valued subscripts (up to 30 characters long) are used extensively, but
  168. only in the $NEXT collating sequence approved by the MUMPS Development Committee
  169. (non-negative integer & fractional canonic numbers collate ahead of all other
  170. strings).  The "$ORDER" function is used at several points in the code.  Also,
  171. FileMan routines assume that reference to an undefined global subscript level
  172. sets the "naked indicator" to that level, rather than leaving it undefined.  In
  173. all other respects, the FileMan code conforms to the 1977 ANS Standard for the
  174. MUMPS language.
  175.  
  176.  
  177. C.  OTHER ROUTINES USED:
  178.  
  179. FileMan routines make use of four "%" utility routines:
  180.  
  181. %DT & %DTC are used to manipulate date/time data values, which FileMan
  182. conventionally stores in a "YYYMMDD.HHMM" format, where:
  183.  
  184.     YYY is number of years since 1700 (hence always 3 digits)
  185.     MM is month number (00-12)
  186.     DD is day number (00-31)
  187.     HH is hour number (00-23)
  188.     MM is minute number (00-59)
  189.  
  190. These utilities are explained in Chapter IV Sections H and I.
  191.  
  192. %RCR is used in a few places to move arrays from local to global storage, and
  193. vice versa.  %XY^%RCR is invoked with
  194.  
  195.     %X = name of existing array (e.g., "X(") and
  196.  
  197.     %Y = name of target array (e.g., "^UTILITY($J,")
  198.  
  199. The '%RCR' routine is also used by FileMan to save local variables temporarily,
  200. so that modules may call themselves recursively.
  201.  
  202. %ZIS is called at several points in the routines to select I/O device 
  203. parameters:
  204.     
  205.       
  206.      IO is returned as the output device name (numeric in DEC systems).  If
  207.      'IO' is null (""), no input or output occurs.
  208.       
  209.      IOM is returned as the margin length (e.g., "80")
  210.       
  211.      IOSL is returned as the screen length (e.g., "24")
  212.       
  213.      IOF is returned as the indirect argument of a WRITE statement to
  214.      generate a top-of-page (e.g., "#")
  215.       
  216.      IOST is returned as the output device type (e.g. "CRT") If 'IOST'
  217.      begins with "C", the Inquire, Search, and Print output programs will
  218.      wait for "return" after each screen's worth of display.  If 'IOST'
  219.      begins with "P", output will terminate with a page feed.  If 'IOST'
  220.      contains "SINGLE", output will stop after each page feed, and wait for
  221.      a 'RETURN' to be hit; if the output terminal is other than the terminal
  222.      requesting the output, and 'IOST' does not contain "K", the 'RETURN'
  223.      will be read from the requesting terminal.
  224.       
  225.      IOPAR is returned as the parameter that should follow the first colon
  226.      in the argument of the OPEN command.  For most devices, this string
  227.      should be null.
  228.       
  229.      IOT may be returned (optionally) equal to a string naming the "terminal
  230.      type" (for example IOT="TRM").  This variable must be returned equal
  231.      to the string "SDP" in order for the FileMan "multiple-copies" feature
  232.      to be called for.
  233.       
  234.      IOP can be defined prior to calling %ZIS and if it is equal to a device
  235.      name when "%ZIS" is invoked, the above parameters are automatically
  236.      returned, without any terminal interaction.
  237.      
  238.  
  239. The FileMan package includes versions of these four routines, named "DIDT",
  240. "DIDTC", "DIRCR", and "DIIS" respectively.
  241.  
  242.  
  243. D.  ROUTINE AND VARIABLE NAMES:
  244.  
  245. In keeping with the convention that all programs that are part of the same
  246. applications or utility package should start with the same two letters, all
  247. FileMan routine names begin with "DI".  Also, routine "DI" itself is the main
  248. "Option reader", and "DINIT" is the "Initializer".  Except in these two 
  249. routines, no unargumented or "exclusive" KILL commands will be found.  
  250. Furthermore, all multi-character local variable names created by the routines 
  251. begin with the letter "D" (except that 'IO(0)', by convention, contains the $I 
  252. value of the sign-on device).
  253.  
  254. Two local variable names, DUZ and DT, are of special importance in the
  255. routines, since the programmer is allowed to set them prior to invoking FileMan
  256. modules:
  257.          
  258.            
  259.           DT     if defined, is assumed to be the current date.
  260.                  (e.g., for June 1, 1985, DT=285061)
  261.            
  262.           DUZ    if defined, is assumed to be the 'User Number', a positive
  263.                  number uniquely identifying the current user.
  264.            
  265.           DUZ(0) if defined, is assumed to be the 'FileMan Access Code', a
  266.                  character string describing the user's "security clearance"
  267.                  with regard to Read Access, Write Access and Delete Access for 
  268.                  each File, and, within a File, for each data Field.  Consult
  269.                  the section on "Data Security" in the FileMan User's Manual,
  270.                  and note that setting 'DUZ(0)' equal to the single "@" 
  271.                  character overrides all security checks and allows special 
  272.                  "programmer" features, as described below.  FileMan sets these
  273.                  variables, if they are not defined, to the following defaults:
  274.            
  275.                         DT = today's date
  276.                         DUZ = 0
  277.                         DUZ(0) = <null string>
  278.           
  279.  
  280. FileMan routines explicitly refer to globals named "^DD", "^DIC", "^DIBT",
  281. "^DIE", "^DIPT", "^DISV", "^DIZ", "^DOPT", "^DOSV".  The routines also use, for
  282. temporary "scratch space", the global "^UTILITY".  ^DD stores all Attribute
  283. Dictionaries.  ^DIC stores the dictionary of files.  ^DIBT stores the results of
  284. File Searches and SORT Template specifications.  ^DIE stores input templates and
  285. ^DIPT stores output templates.  ^DISV stores (by $I identification) the most
  286. recent lookup value in any File or Sub-File, for retrieval with the "space-bar"
  287. input; no harm can occur in killing this global at any time.  ^DIZ stores new
  288. data of files as they are created.  ^DOPT stores various option lists.  ^DOSV
  289. stores statistical results.
  290.  
  291.  
  292. E.  FIRST-LINE DOCUMENTATION:
  293.  
  294. The tag of the first line of each routine in the package is identical to the 
  295. name of the routine.  The remainder of each such first line consists of:
  296.  
  297.     ; <Programmer/Site> <Brief Description> ; <Date/Time of last edit>
  298.  
  299. F.  SEMICOLON LINES WITHIN ROUTINES:
  300.  
  301. Logical blocks of code within routines are set off from each other by lines
  302. consisting only of a semicolon (completely blank routine lines are not allowed 
  303. by the MUMPS standard).  Lines that are entry points for a DO or GO from other
  304. routines consist only of a tag and semicolon (usually, the tag is "EN"), so that
  305. they can be easily noticed.
  306.  
  307.  
  308. G.  CONTINUATION ROUTINES:
  309.  
  310. When a routine is "Done" or "Gone to" only from one other routine, then its
  311. routine name is the same as that of the invoking routine, except for the final,
  312. numeric character.  Thus, for example, "DIO" is the only routine which calls
  313. "DIO1".
  314.  
  315.  
  316. H.  ARGUMENT-PASSING VARIABLES:
  317.  
  318. When a given routine, subroutine, or Xecutable code string can be thought of as 
  319. a "black box" that transforms some value into some other value, then the "input
  320. value" is usually found in the local variable 'X' when the routine is invoked,
  321. and the "output value" in the local variable 'Y' upon return.  If the 'X' value
  322. is "rejected" by the black box, then either 'X' is killed within the routine, or
  323. 'Y' is returned with the value of "-1".  When the routine needs other data with
  324. which to evaluate "X", that data is usually put into a local variable or array
  325. which has the same name as the routine being invoked.
  326.  
  327.  
  328. I.  DELIMITERS WITHIN STRINGS:
  329.  
  330. The "^" character is conventionally used to delimit data elements which are
  331. strung together to be stored in a single global node.  A corollary of this rule
  332. is that the routines almost never allow input data to contain up-arrows 
  333. (remember that the user types "^" to change or terminate the sequence of 
  334. questions being asked).  Within "^"-pieces, semicolons are usually used as 
  335. secondary delimiters, and colons as tertiary delimiters.  FileMan routines use 
  336. the local variable 'U' as equal to the single "^" character.
  337. VA FileMan  V.17 - Apr 1986                        Programmer's Manual  (3)
  338.  
  339.  
  340.  
  341.  
  342.                     III.  GLOBAL FILE STRUCTURE
  343.  
  344.  
  345. FileMan stores the data of every "File" descendant from a single MUMPS global
  346. array (or from a node of a global array).  When the routines, internally and
  347. externally, make reference to a File in global notation, they expect a format
  348. like
  349.  
  350.               ^GLOBAL(
  351.  
  352. for an entire global, or
  353.  
  354.               ^GLOBAL(X,Y,
  355.  
  356. note the terminating "(" or ",".  Indirection ("@") is always used by FileMan
  357. routines in referring to data Files.
  358.  
  359. We will now consider four basic components of a database, and describe, by way 
  360. of example, how the rudiments of a patient File could be "mapped" into a global
  361. called "^DPT" using FileMan.  We will assign File Number 2 to this file.
  362.  
  363.  
  364. A.  FILE DESCRIPTOR
  365.  
  366. All FileMan files, regardless of the global used for data storage, have an entry
  367. in the Dictionary of Files - the ^DIC global - descendant from the file's DD
  368. number.  The zeroth subscript contains the File Name and File Number.  The "GL"
  369. node descendant from subscript zero is set to the "root" of the global used to
  370. store data for this file.  Thus for the above Patient file will have the
  371. following:
  372.  
  373.          ^DIC(2,0)="PATIENT^2"
  374.          ^DIC(2,0,"GL")="^DPT("
  375.  
  376. A descriptor string is also stored in the zeroth subscript of the File Global
  377. (^DPT in this example).  This is simply a string containing:  (1) File Name,
  378. (2) ^DD number, (3) most recently assigned Entry Number, and (4) total number of
  379. Entries, each separated by up-arrows ("^").  Note that the most recently 
  380. assigned number is not necessarily the largest Entry Number.  The ^DD number is 
  381. the number of the Attribute Dictionary (see D. below) that describes the data 
  382. Fields that this File contains.  Hence, for a File with three patients in it 
  383. and the most recently added patient was assigned entry number 9, we have:
  384.  
  385.               ^DPT(0)="PATIENT^2^9^3^"
  386.  
  387.  
  388. B.  FILE ENTRIES     
  389.  
  390. Each entry in the file corresponds to a positive-valued key subscript, the
  391. "Internal Entry Number", of the File global.  All Data pertaining to an Entry
  392. will be stored in global nodes descendant from that subscript.  The Name of an
  393. Entry is always stored in the first "^"-piece of subscript zero, descendant from
  394. the "Internal Entry Number" subscript.  Thus, for Entry #1, a patient named 
  395. "John Jones", we would have:
  396.  
  397.               ^DPT(1,0)="JONES,JOHN^"
  398.  
  399. If we wanted also to store the patient's sex in the 2nd "^"-piece of subscript
  400. zero, and his date of birth in the third "^"-piece, we would have:
  401.  
  402.               ^DPT(1,0)="JONES,JOHN^M^2341225^"
  403.  
  404. (Where the 7-digit number is our internal way of representing "12/25/1934")
  405.  
  406. How would we store multiple-valued data, such as "Diagnosis", for example?  
  407. There can be one or five or ten diagnoses on file for a given patient, and they
  408. obviously cannot all be stored (in the general case) in a single subscript.  Our
  409. answer is to make the "diagnosis" list a "sub-File" within the patient Entry!
  410. This requires adding subscripts beyond the first internal key subscript which 
  411. are different in value from the "0" subscript in which we have chosen to store 
  412. each patient's name, sex, and birthdate.  For example, if John Jones currently 
  413. has two (free-text) diagnoses on file, we can consider those to be Entries #1 & 
  414. #2 in a little 2-Entry File, which we can extend at a lower level from any 
  415. unused subscript, say from "DX":
  416.  
  417.               ^DPT(1,0)="JONES,JOHN^M^2341225^"
  418.               ^DPT(1,"DX",0)="^2.01A^2^2"
  419.               ^DPT(1,"DX",1,0)="DIABETES^"
  420.               ^DPT(1,"DX",2,0)="ANGINA^"     
  421.  
  422. Notice that the data global "^DPT" has ^DPT(1,"DX",0) for the Diagnosis multiple
  423. whose 2nd "^"-piece is the same as ^DD(2,3,0) - the Data Dictionary entry for 
  424. the Diagnosis field in the principal patient dictionary (see Page 12).  This 
  425. zeroth node of the data global tells FileMan which subsidiary dictionary to use 
  426. for the data stored in this node.  The actual data (the patient's diagnoses in 
  427. our example) is stored in the next lower level of subscripting.  In the same 
  428. manner that entries in the Patient File have internal entry numbers, entries in 
  429. the multiple field also have "internal entry numbers" in the subfile.  Thus in 
  430. our example, "DIABETES" is the first entry and "ANGINA" the second.
  431.  
  432.  
  433. C.  CROSS-REFERENCES     
  434.  
  435. The MUMPS capabilities of string-valued array subscripting offer a simple,
  436. general way to cross-reference FileMan files.  To minimize the number of global
  437. names used by the system, we store each Cross-reference set as a descendant of 
  438. an alphanumeric subscript of the global File.  A File, such as a patient file, 
  439. that should be accessible by Name, is set up by the system so that there is a
  440. subscript "B", which in turn is subscripted by strings corresponding to every
  441. unique Entry Name currently in the File.  For each such string-valued subscript,
  442. the next level of subscripting contains the Internal Entry Numbers of the 
  443. Entries that contain the Name.  Let's suppose, in our previous example, that we 
  444. have a second patient, patient number 9, who also happens to have the Name John 
  445. Jones, and a third patient, Internal Number 7, whose name is Sam Smith.  Then we
  446. would have:
  447.  
  448.               ^DPT(1,0)="JONES,JOHN^M^2341225^"     
  449.                          .     
  450.                          .
  451.               ^DPT(7,0)="SMITH,SAM^M^2231109^"     
  452.               ^DPT(9,0)="JONES,JOHN^M^2500803^"     
  453.               ^DPT("B","JONES,JOHN",1)=""     
  454.               ^DPT("B","JONES,JOHN",9)=""     
  455.               ^DPT("B","SMITH,SAM",7)=""     
  456.  
  457. Note that "all the data is in the subscripting", and the global nodes under
  458. ^DPT("B") are simply null strings.  Actually, the system allows for these 
  459. strings to be non-null in the case where we are Cross-referencing a mnemonic 
  460. (alias) for the Name.  Multiple cross-references ("C", "D", etc.) are also 
  461. allowed.
  462.  
  463. D. ATTRIBUTE DICTIONARY     
  464.  
  465. The Attribute Dictionary describes the data fields which a file contains within
  466. the global ^DD (for "Data Dictionary").  Each Attribute Dictionary is stored
  467. descendant from a positive-valued first-level node of this global.  Each
  468. Attribute Dictionary, in itself, is also in the form of a File, and hence
  469. consists of Entries, Cross-references, Descriptor, and a reference to the
  470. "zeroth" Data Dictionary (^DD(0)) which is a dictionary of the Attributes of
  471. Attributes.  For the most part, FileMan "packs" data into subscripts using the
  472. "^" ("up-arrow") character as the "$PIECE" delimiter.  Thus, we will refer to a
  473. Data Element as being stored in such-and-such "^"-piece of a global node.  Each
  474. Entry in the Attribute Dictionary is a descriptor of one of the Data Fields
  475. pertaining to Entries in the main File.  The system always assigns the Internal
  476. Number ".01" to the Name Field, and lets the user assign numbers to the other
  477. Data Attributes as he sees fit.  In our example the patient file has three other
  478. elements; Sex, Birthdate, and Diagnosis; and that Diagnosis is multiple valued.
  479. Let us suppose that the Attribute Dictionary for this File is stored in ^DD(2).
  480. In this File, an Entry Name is always found as the first "^"-piece in subscript
  481. zero, so we would have:
  482.  
  483.          ^DD(2,.01,0)="NAME^"     
  484.          ^DD(2,1,0)="SEX^"     
  485.          ^DD(2,2,0)="DOB^"     
  486.          ^DD(2,3,0)="DIAGNOSIS^"     
  487.  
  488. The rest of the zeroth subscript for any Field consists of:
  489.  
  490. "^"-piece #2: a string containing
  491.  
  492.     
  493.       
  494.      "BC"       if the Data is true-false ("Boolean") "computed"
  495.      "C"        if the Data is "computed"
  496.      "Cm"       if the Data is multi-line "computed"
  497.      "D"        if the Data is date-valued
  498.      "DC"       if the Data is date-valued "computed"
  499.      "F"        if the Data is free-text
  500.      "I"        if the Data is "uneditable" (Utility Option 9)
  501.      "J"n       to specify a print length of "n" characters
  502.      "J"n","d"  to specify printing "n" characters with "d" decimals
  503.      "N"        if the Data is numeric-valued
  504.      "O"        if the field has an output transform
  505.      "P"n       if the Data is a "pointer" reference to File 'n'
  506.      "P"n"'"    if LAYGO to the pointed to file is not allowed
  507.      "P"n"*"    if the pointer field is defined to have a "screen"
  508.      "R"        if the Data is "required" (can't skip input)
  509.      "S"        if the Data is from a discrete "set"
  510.      "W"        if the Data is "Word-Processing"
  511.      "WL"       if the Data is "Word-Processing" which is normally
  512.               printed in "line-mode"
  513.      "X"        if the syntax-check has been modified under the
  514.               Utility Option
  515.       
  516.      
  517.      This "^"-piece begins with a numeric if the data is multiple-valued.
  518.  
  519. "^"-piece 3:   either the global "pointer" reference if the data type
  520.               is "P", or the "set" of allowed "responses" and their 
  521.               meanings, if the data type is "S", or nothing.
  522.  
  523. "^"-piece 4:   subscript location and "^"-piece, separated by a ";", or
  524.               subscript location and character-positions, also separated
  525.               by a ";" where "Em,n" designates character positions m thru
  526.               n, or subscript location, followed by ";", followed by zero,
  527.               to designate multiple-valued data.
  528.  
  529. "^"-piece #5:  MUMPS code to check an input in the variable 'X'.  'X' is
  530.               killed by the code if input is invalid.  In the case of a
  531.               "computed" Field, the code creating the variable 'X' is
  532.               stored here.
  533.  
  534. Subscript #0.1 (at the third level), if it exists, contains the full-length
  535. "Title".
  536.  
  537. Subscript #1, if it exists, contains, at lower subscript levels, Executable 
  538. MUMPS code to create and kill cross-references based on the value of the Field 
  539. (in the variable 'X').
  540.  
  541. Subscript #2, if it exists, contains the "output transform" --MUMPS code to
  542. display the Field value in a format differently from the way in which it is
  543. stored (See Chapter V.G).
  544.  
  545. Subscript #3, if it exists, contains a prompting message to be displayed when 
  546. the user types "?".
  547.  
  548. Subscript #4, if it exists, contains MUMPS code that will be executed in 
  549. addition to displaying the "canned" prompt when the user types "?".
  550.  
  551. Subscript #5, if it exists, contains, at lower subscript levels, pointers to
  552. "Trigger" Cross-references to this Field.
  553.  
  554. Subscript #8, if it exists, is the "Read Access" for the Field.
  555.  
  556. Subscript #8.5, if it exists, is the "Delete Access" for the Field.
  557.  
  558. Subscript #9, if it exists, is the "Write Access" for the Field.
  559.  
  560. Subscripts #9.2 thru #9.9, if they exist, are the 'overflow' Xecutable MUMPS 
  561. code that may be part of the specification of a "Computed"-type field.
  562.  
  563. Finally, a programmer can set the "DEL" subscript for the .01 (NAME) field to a
  564. string of Xecutable MUMPS code that will determine if the entry can be deleted.
  565. It must contain a MUMPS "IF" command to set the value of "$T".  If "$T" is set 
  566. to "1", the entry can not be deleted.  Normally, the ^DD format is:
  567.  
  568.     ^DD(File #,.01,"DEL",field number,0)="executable MUMPS code"
  569.  
  570. where field number is the field to be tested by the MUMPS code to determine if
  571. deletion is allowed.
  572.  
  573. Thus, for our example:
  574.  
  575.     ^DD(2,.01,0)="NAME^FR^^0;1^I X'?1A.AP1",".AP K X"
  576.     ^DD(2,.01,.1)="PATIENT'S NAME"
  577.     ^DD(2,.01,1,1,0)="2^B"
  578.     ^DD(2,.01,1,1,1)="S ^DPT("B",$E(X,1,30),DA)="""
  579.     ^DD(2,.01,1,1,2)="K ^DPT("B",$E(X,1,30),DA)"
  580.     ^DD(2,.01,3,1)="TYPE NAME IN THE FORMAT: LAST,FIRST"
  581.     ^DD(2,1,0)="SEX^RS^M:MALE;F:FEMALE^0;2^Q"
  582.     ^DD(2,2,0)="DOB^D^^0;3^S %DT="EX" D ^%DT S X=Y I X<1400000!(X>2770000) K X"
  583.     ^DD(2,2,.1)="DATE OF BIRTH"
  584.  
  585. can be translated into the following words:     
  586.  
  587. The first Field is NAME ("PATIENT'S NAME", in the long form).  It is a free-text
  588. Datum which must consist of at least 1 alpha, followed by other alpha and
  589. punctuation characters & containing a comma.  It is always required from the
  590. user, and is stored in subscript 0, "^"-piece 1, of each Patient's File.  If the
  591. user types a "?" when asked for the Name, he will see:
  592.  
  593.               TYPE NAME IN THE FORMAT: LAST,FIRST     
  594.  
  595. The Patient File is Cross-referenced by Name, so that every time a Name is
  596. changed, the corresponding subscript under ^DPT("B") is also changed.  'DA' will
  597. always be the Internal Number of the patient when the Cross-referencing code is
  598. executed.  If a second Cross-reference for 'Name' existed (for example, a
  599. "trigger"), it would be descendant from
  600.  
  601.               ^DD(2,.01,1,2
  602.  
  603. The second Field is SEX.  It is stored as either "M" or "F" in the 2nd "^"-piece
  604. position of subscript 0 of each Patient File.  The user is required to enter it,
  605. and can type "MALE" instead of "M", and "FEMALE" instead of "F".  He will see 
  606. the two choices displayed if he types a "?" when asked for Sex.
  607.  
  608. The third Field is DOB (full title: "DATE OF BIRTH"), which, if it is entered 
  609. (it is not required), must be in the format of a date somewhere between 1840 and
  610. 1977.  It is stored in the 3rd "^"-piece of subscript 0 of the File.
  611.  
  612. A multiple-valued Field like "Diagnosis" (see Chapter I of the User's Manual) is
  613. described by a separate Data Dictionary.  FileMan creates this new Data
  614. Dictionary descendant from a non-integer subscript of ^DD.  In the case of the
  615. patient File described by ^DD(2), it would store "subsidiary" Data Dictionaries
  616. in ^DD(2.01), ^DD(2.02), etc.  The subsidiary Data Dictionary for the multiple-
  617. valued "diagnosis" Field could look like this:
  618.  
  619.          ^DD(2.01,0)="DIAGNOSIS SUB-FIELD^NL^.01^1"     
  620.          ^DD(2.01,.01,0)="DIAGNOSIS^MF^^0;1^K:$L(X)>30!($L(X)<3) X"     
  621.          ^DD(2.01,.01,3)="ANSWER MUST BE BETWEEN 3 TO 30 CHARACTERS IN LENGTH"     
  622.  
  623. The only new element here is the "M" in the second '^'-piece of ^DD(2.01,.01,0).
  624. This is the flag corresponding to the 'YES' answer to the question:
  625.  
  626.     HAVING ENTERED OR EDITED ONE DIAGNOSIS, SHOULD USER BE ASKED ANOTHER?
  627.  
  628. It says that the Diagnosis Field should be "multiply-asked", until the user hits
  629. <null> to the
  630.  
  631.          DIAGNOSIS:     
  632.  
  633. query on a patient.
  634.  
  635. There will also be an Entry corresponding to Diagnosis in the "principal" 
  636. patient Data Dictionary:
  637.  
  638.     ^DD(2,3,0)="DIAGNOSIS^2.01A^^DX;0"
  639.  
  640. The "2.01" here points off to the subsidiary Data Dictionary of that number; it
  641. says that, to find the data descriptors of Diagnosis (and all Fields pertaining
  642. to Diagnosis, e.g., Age at Onset), we must look in ^DD(2.01).  The "A" tells us
  643. that everytime the user enters a new diagnosis, it will be Automatically added 
  644. to the file and he will not be asked
  645.  
  646.          ARE YOU ADDING A NEW DIAGNOSIS?     
  647.  
  648. The "DX;0" in the fourth '^'-piece tells us that the entire Diagnosis sub-File
  649. will be stored descendant from the "DX" subscript in each patient's record.
  650.  
  651. VA FileMan  V.17 - Apr 1986                       Programmer's Manual  (4)
  652.  
  653.  
  654.  
  655.  
  656.                      IV.  PROGRAMMER ROUTINES
  657.  
  658.  
  659. Certain modules within FileMan are callable by other MUMPS routines.  The
  660. programmer of such routines must keep in mind the variable-naming conventions
  661. listed above.  If he has his own local variables that he wishes to be
  662. preserved by a call to any of the routines described here, he should be sure
  663. to give them multi-character names beginning with letters other than 'D'.
  664.  
  665.  
  666. A.  FILE LOOKUP PROGRAM -- "DIC"
  667.  
  668. This routine searches a global file name specified by the variable 'DIC' and
  669. returns the variable 'Y' either as:
  670.  
  671.          Y=-1    if the input is not found, or else
  672.          Y=N^S   where 'N' is the Internal Entry Number, and
  673.                  'S' is the full Entry Name.
  674.  
  675. The variable 'DIC' must be defined prior to invoking the "DIC" routine.  The
  676. variable  'DIC' must be either the File number (integer or fractional), or
  677. else an explicit global reference in the form "^GLOBAL(" or "^GLOBAL(X,Y,".
  678.  
  679. The routine "DIC" always creates the variable 'U', and leaves it defined as
  680. the single-character string "^" (up-arrow) upon return.  Except for the
  681. 'DIC("W")' variable (see below), which is killed, the 'DIC' array is left
  682. unchanged by the "DIC" routine.
  683.  
  684. The variable 'DIC(0)' must also be defined as a string of alphabetic
  685. characters according to the following:
  686.  
  687. If the variable 'DIC(0)' contains the character "A", the program asks for
  688. input from the terminal and re-asks in case of erroneous input other than
  689. <null> or a string containing the up-arrow ("^").  This input 'X' is returned
  690. when "DIC" quits.  If, however, 'DIC(0)' does not contain the character "A",
  691. the input to the "DIC" program will be assumed to be in the local variable
  692. 'X'.  If 'DIC("A")' is defined, it will be displayed prior to the reading of
  693. the 'X' input; otherwise the name of the File ($P(^GLOBAL(0),"^",1)) followed
  694. by a space, the 'Label' of the .01 field then a colon will be displayed.  If
  695. the File Name is the same as the 'Label' of the .01 field, then only the File
  696. Name will be displayed.  Also, if 'DIC(0)' contains "A" and 'DIC("B")' is
  697. defined and is non-null, the value of 'DIC("B")' will be prompted as the
  698. default answer, and, in this case, if the terminal user enters just "escape",
  699. the 'DIC("B")' default value will be used, and returned in 'X'.  If the
  700. numeric-valued variable 'DTIME' is defined, terminal input will "time out"
  701. after 'DTIME' seconds if the user hasn't finished responding; in case of such
  702. a termination, the "DIC" routine will return with 'Y' equal to "-1" and 'X'
  703. equal to "^" (as though the user had typed "^"), and with the variable 'DTOUT'
  704. defined equal to '1'.
  705.  
  706. If 'DIC(0)' contains "E", the File Entry names that match the input will be
  707. echoed back to the terminal, and if there is more than one such name, the user
  708. will be asked to choose which Entry he wants.
  709.  
  710. If 'DIC(0)' contains "Q", and if erroneous input other than <null> or up-arrow
  711. is entered, "??" will be displayed, and the bell rung.
  712.  
  713. If 'DIC(0)' contains "X", for "exact match", the input value must be found
  714. exactly.  Otherwise, the routine will look for any Entries which begin with
  715. the input 'X'.  Unless "X-act match" is specified, lower-case input that fails
  716. in the lookup will automatically be converted to upper-case, for a second
  717. lookup attempt.
  718.  
  719. If 'DIC(0)' contains "L", then "DIC" will allow the user to add a new Entry to
  720. the File at this point ("Learn-As-You-Go"), as long as at least one of four
  721. security-check conditions apply:
  722.    
  723.      
  724.     1. The File has no "LAYGO Access Code"
  725.     
  726.     2. The local variable 'DUZ(0)' is equal to "@"
  727.     
  728.     3. Some character in 'DUZ(0)' can be found in the file's "LAYGO Access Code"
  729.     
  730.     4. The variable 'DLAYGO' is defined equal to the File number.
  731.     
  732.  
  733. The user's input must, of course, be in valid format for an Entry Name, and he
  734. must respond with "Y" to the question
  735.  
  736.          ARE YOU ADDING A NEW ENTRY?
  737.  
  738. If such a new entry is indeed made in the invoking of "DIC", the variable 'Y'
  739. will be returned to the calling program as:
  740.  
  741.          N^S^1
  742.  
  743. where 'N' is the Internal Entry Number and 'S' the Entry Name, and "1" is the
  744. literal character "1".
  745.  
  746. Normally, "DIC" does its lookup using the "B"-node cross-reference of the File
  747. (see Chapter III.B., above).  The "B" cross-reference may include "MNEMONIC"
  748. cross-references to a field other than the .01 field, as indicated in Chapter
  749. VIII.B. of the User's Manual.  Suppose that "MAIDEN NAME" is, as in the
  750. example given there, a "MNEMONIC" cross-reference.  Then a patient whose
  751. MAIDEN NAME is "DAVIS" will be found by "DIC" in the "B" cross-reference if
  752. the user types "DAVIS".  However, if her "real" (married) name were
  753. "DAVIDSON", her married name only would be displayed.  This "cross-reference
  754. suppression" can be overridden by including a "C" in the "DIC(0)" string.
  755.  
  756. If 'DIC(0)' contains "M", "DIC" will do a "multi-lookup" on all of the File's
  757. cross-reference indices, from "B" on to the end of the alphabet.  Thus, for
  758. example, if a given File is indexed both by Name and by Social Security
  759. Number, and the user inputs "123-45-6789", "DIC", failing to find this input
  760. as a "Name", will automatically go on to look it up as a Social Security
  761. Number.
  762.  
  763. If 'DIC(0)' contains "N", the input is allowed to be a File Entry Number, even
  764. if the File in question isn't normally referenced by Number.  If 'DIC(0)' does
  765. not contain an "N", the user is still allowed to select by File Entry Number
  766. by preceding the number with the "`" (accent grave) character.
  767.  
  768. If 'DIC(0)' contains "Z" and if the lookup is successful (i.e., the variable
  769. 'Y' is returned as something other than "-1"), then the variable 'Y(0)' will
  770. also be returned.  It will be set equal to the entire "zeroeth node" of the
  771. Entry that has been found.  To use the example on Chapter III.B., if the
  772. programmer writes:
  773.  
  774.          SET DIC="^DPT(",DIC(0)="QEZ",X="SMITH" DO ^DIC
  775.  
  776. he will get back:
  777.  
  778.          Y="7^SMITH,SAM"
  779.          Y(0)="SMITH,SAM^M^2231109"
  780.  
  781. Also,the "Z" parameter forces the "naked reference" to be set at the level of
  782. this "zeroeth node", so the calling program can easily make reference to some
  783. other node at the same level.  (Not a recommended practice)
  784.  
  785. A valuable feature of the "DIC" routine is that, if an entry is found, its
  786. number gets saved in the global "^DISV".  To be precise, "^DISV($I,DIC)" gets
  787. set equal to the entry number.  This allows the terminal user to do a
  788. subsequent lookup of the same entry at the same terminal simply by hitting the
  789. "space bar".  The cost of this feature, of course, is the time required to set
  790. the global.  If the programmer invoking "DIC" wishes to be spared this cost,
  791. he should simply include an "F" in 'DIC(0)', in which case the lookup will not
  792. set ^DISV($I,DIC).
  793.  
  794. To summarize the 'DIC(0)' options, then:
  795.          
  796.            
  797.           A   =   ASK and (if erroneous) re-ask Entry
  798.           C   =   CROSS-REFERENCE SUPPRESSION is turned off
  799.           E   =   ECHO back information
  800.           F   =   FORGET the lookup value, as far as ^DISV is concerned
  801.           L   =   LEARNING a new Entry is allowed
  802.           M   =   MULTI-INDEX lookup allowed
  803.           N   =   NUMBER allowed
  804.           Q   =   QUESTION erroneous input (with '??')
  805.           X   =   Exact match required
  806.           Z   =   ZEROETH node returned in 'Y(0)'
  807.           
  808.  
  809. There are a few other "lookup" features available to programmers using 'DIC':
  810.  
  811. 1.  If 'DIC("S")' is defined, it will be understood to be a string of
  812. executable code, which the "DIC" routine will execute to "screen" an Entry
  813. chosen.  'DIC("S")' must contain a MUMPS 'IF' command to set the value of $T.
  814. Those Entries for which the 'IF' sets $T=0 will not be displayed or
  815. selectable.  At the moment the 'DIC("S")' code is executed, the local variable
  816. 'Y' is the Entry number of the Entry being "screened", and the MUMPS "naked
  817. indicator" is at the global level @DIC"Y,0)".  Therefore, to use the previous
  818. example again, if we only wanted to find a male patient whose name begins
  819. with "SMITH", we would have:
  820.  
  821. S DIC="^DPT(",DIC(0)="QEZ",X="SMITH",DIC("S")="I $P(^(0),U,2)=""M""" D ^DIC
  822.  
  823. 2.  If 'DIC("W")' is defined as a MUMPS command string, it will be Xecuted
  824. when 'DIC' displays each of several Entries that match the user's input.  The
  825. condition of the variable 'Y' and of the naked indicator is as specified in
  826. the previous paragraph.  If 'DIC("W")' is defined, it will override the
  827. display of any identifiers of the file.
  828.  
  829. 3.  When calling "DIC" with "LAYGO" allowed, you can specify that a certain
  830. list of Fields will be asked in the case that the user enters a brand-new
  831. Entry.  This list is specified by setting the variable 'DIC("DR")' equal to a
  832. string that looks exactly like the 'DR' string of Fields that is specified
  833. when calling 'DIE' (see next Section).  Such a list of "forced identifiers"
  834. overrides any Identifiers that would normally be asked for new Entries in
  835. this File.
  836.  
  837. 4.  Note that, if 'DIC(0)' is null, no terminal output will be generated by
  838. the "DIC" routine.  Otherwise, when the input contains a "?", a prompting
  839. message (including any output specified by 'DIC("W")') will be displayed.
  840.  
  841. 5.  One last feature: normally, as mentioned, 'DIC' does its lookup using the
  842. "B" cross-reference of the File.  You can make it do a lookup only on
  843. cross-reference "C", for example, by setting the local variable 'D' equal to
  844. "C" and entering at 'IX^DIC'.
  845.  
  846.  
  847. B.  DATA EDIT PROGRAM -- "DIE"
  848.  
  849. A programmer can call the "Data Entry and Editing" Function of FileMan to
  850. handle input of selected data elements for a given File Entry.  This is done
  851. by invoking the routine "DIE".  The program needs three local variables set as
  852. input parameters (in addition to 'DT' and 'DUZ' -- see Chapter II.D.):
  853.          
  854.            
  855.           DIE   The Global Name of the File in the form "^GLOBAL(" OR
  856.                 ^GLOBAL (X,Y," or else the Number of the File
  857.            
  858.           DA    The Internal Entry Number of the File Entry to be Edited
  859.                 ('DA(1)' may also be needed if editing is occurring at a
  860.                 lower level of the File.)
  861.            
  862.           DR    A String Specifying which Data Fields will be asked, for the
  863.                 given Entry.
  864.           
  865.  
  866. The "DR" string consists of either:
  867.  
  868. 1.  A single number corresponding to the Internal Number of a Field of the
  869. File (Remember that the Internal Number of any File's Name Field is .01).
  870.  
  871. or 2.  A Field number as above, followed by "//" (two slashes), followed by
  872. the default prompt which should be displayed to the user when that Field is
  873. asked.  For example, if there is a File Entry stored descendant from
  874. ^FILE(777), and Field #27 for this File is "DATE OF ADMISSION", and the
  875. programmer wishes the user to see:
  876.  
  877.     DATE OF ADMISSION: TODAY//
  878.  
  879. then the calling program should say:
  880.  
  881.     SET DR="27//TODAY",DIE="^FILE(",DA=777 DO ^DIE
  882.  
  883. If the user just hits 'RETURN' when he sees the prompt, "DIE" will act as
  884. though he had typed in the word "TODAY".  Naturally, if a different 
  885. admission date were already on file for #777, it would be that date that
  886. would be displayed after the "//", rather than "TODAY".
  887.  
  888. or 3.  A Field Number followed by "///" (three slashes), followed by a value
  889. which will be automatically inserted into the database.  In the above
  890. example, if we had
  891.  
  892.          DR="27///TODAY"
  893.  
  894. the terminal user would see no query, but the current date would automatically
  895. be "stuffed" into Field 27 of Entry 777, even if other data previously
  896. existed there.
  897.  
  898. or 4.  A range of Field Numbers, in the form M:N, where M is the First and N
  899. the Last Number of the Inclusive Range.  All Fields whose Numbers lie within
  900. this range will be asked.
  901.  
  902. or 5.  A "Place-holder" like "@1" (see below),
  903.  
  904. or 6.  A line of MUMPS code (see below),
  905.  
  906. or 7.  A sequence of any of the above 4 types, separated by semicolons.  If,
  907. say, Field Numbers .01, 1, 2, 4, 10, 30, and 101 exist for the File stored in
  908. ^FILE, and the programmer wants to have Fields 4, .01, 10, 30, and 101 asked
  909. (in that order) for Entry Number 777, he simply writes:
  910.  
  911.          SET DIE="^FILE(",DA=777,DR="4;.01;10:999" DO ^DIE
  912.  
  913. and he returns with the appropriate subscripts of ^FILE(777) entered or
  914. edited.  Note that the 'DR' string contains the semicolon delimiter to specify
  915. specific field number and the colon to specify a range of fields.
  916.  
  917. or finally 8.  If 'DR' is simply the name of an Input Template, preceded by
  918. "[" and followed by "]", then all the fields in that Template will be asked.
  919.  
  920. Note that the Fields specified by 'DR' will be asked whether or not FileMan
  921. "Write Access" security protection has been assigned to the Fields.
  922.  
  923. The programmer can include "branching logic" within 'DR'.  He does this by
  924. inserting an executable MUMPS statement in one of the "semicolon-pieces" of
  925. 'DR'.  The MUMPS code will be executed when this piece of 'DR' is encountered
  926. by the "DIE" routine.  If the MUMPS code sets the variable 'Y', "DIE" will
  927. jump to the Field whose Label (or Number) matches 'Y'.  (The Field must be
  928. specified elsewhere within the 'DR' variable).  'Y' may look like a
  929. "place-holder", e.g., "@1".  If 'Y' is set to zero ("0") or to the null string
  930. (""), "DIE" will exit.  If 'Y' is KILLed, or never set, no branching will
  931. occur.  The MUMPS code can calculate 'Y' based on 'X', which will at that
  932. moment be equal to the internal value of the Field previously asked for (as
  933. specified by the previous "semicolon-piece" of 'DR').  Take the above example,
  934. and suppose that we don't want the user to be asked for Fields .01 or 10 if
  935. his answer to Field Number 4 was "YES".  We therefore write:
  936.  
  937.          S DIE="^FILE(",DA=777,DR=1;4;I X=""YES"" S Y=30;.01;10;30;101"
  938.          DO ^DIE
  939.  
  940. Suppose one of the fields to be edited is a multiple, and you want to edit
  941. only selected subfields in the multiple.  In the above specifications for the
  942. 'DR' string, all the subfields of the multiple will be asked.  To do this,
  943. we set 'DR' in the usual manner and in addition we set a subscripted value of
  944. 'DR' equal to the subfields we want to edit.  For example, if field #4 is a
  945. multiple and the subdictionary number for the multiple is 16001.02.  If we
  946. want the user to be prompted only for subfields ".01" and "7" then we:
  947.  
  948.          SET DR=".01;4;6;8" 
  949.          SET DR(2,16001.02)=".01;7"
  950.  
  951. where the first subscript ("2") means the 2nd level and the second subscript
  952. is the subdictionary number of the multiple field (#4).
  953.  
  954. If there are more than 250 characters in a 'DR' string, the programmer can set
  955. continuation strings by defining the 'DR' array at the third level.  For
  956. example, the first continuation node of DR(2,16001.02) would be
  957. DR(2,16000.02,1), the second would be DR(2,16001.02,2) and so on.
  958.  
  959. 'DA', 'DIE', and 'DR' are left intact by "DIE", except that if the Entry is
  960. killed within "DIE" (which can happen if the user answers "@" when he is
  961. editing the Entry's name), the variable 'DA' is also killed.
  962.  
  963. The programmer can determine, upon return from "DIE", whether the user exited
  964. the routine by typing an up-arrow.  If he did so, the subscripted variable 'Y'
  965. will be defined; if all questions were asked and answered in normal sequence,
  966. $D(Y) will be zero.
  967.  
  968. The programmer can force the user to answer all questions, with no
  969. "up-arrowing" allowed.  He does this by setting the variable 'DIE("NO^")'
  970. equal to some value before invoking '^DIE'.  If 'DIE("NO^") is equal to the
  971. 5-character string "OUTOK", then the user is allowed to enter a simple
  972. up-arrow ("^"), but not to use the up-arrow to branch to fields out of the
  973. normal sequence.
  974.  
  975.  
  976. C.  DATA PRINT -- "DIP"
  977.  
  978. A programmer can invoke the "File Print" program, "DIP", at the entry point
  979. "EN1" to display a range of Entries in columnar (or template) format.
  980.  
  981. Input variables must be defined as follows (in addition to 'DUZ' & 'DT'):
  982.  
  983. L        Set L=0 or some string whose numeric value is 0, like "LIST DRUGS".
  984.          the string can appear to the terminal user in messages like:
  985.  
  986.                    LIST DRUGS BY: NAME//
  987.  
  988. DIC      The Global Name of the File in the usual format.
  989.  
  990. FLDS     The various Fields to be printed, separated by commas, (e.g.,
  991.          FLDS="NAME,DOB,SEX;C20" or FLDS="[DIQ]") as a user would normally
  992.          have answered the "PRINT FIELD:" questions within the File Print
  993.          Option of 'DI'.
  994.  
  995. BY       The name of the "SORT BY" field (or null).  Again, to force answers,
  996.          separate them with commas (e.g., BY="DIAGNOSIS,DATE OF ONSET").  If
  997.          one of the "comma-pieces" of the "BY" string is the character "@",
  998.          the terminal-user will be asked for that "SORT-BY" response.  Thus,
  999.          if you want to sort by DIAGNOSIS but allow the user to order the
  1000.          Sort within DIAGNOSIS, set BY="DIAGNOSIS,@".
  1001.  
  1002. FR       The "START WITH:" value of the "SORT BY" field (or null) this
  1003.          variable is undefined, the terminal user will be asked the "START
  1004.          WITH:" question.  Multiple answers can be separated with commas; if
  1005.          you want the terminal user to be asked one of the multiples, use "?"
  1006.          as a place holder for that multiple.  Thus, in the example just
  1007.          above, if we set FR=",?" we will be sorting from the first
  1008.          DIAGNOSIS, but the user will be asked START WITH DATE OF ONSET:
  1009.  
  1010. TO       The "GO TO:" value of the "SORT BY" field (or null) If this variable
  1011.          is undefined, the terminal user will be asked the "GO TO:" question.
  1012.          Multiple answers can be separated with commas, as above.
  1013.  
  1014. DHD      The Header desired for the output ("@" if no header desired)
  1015.          Remember the "[TEMPLATE NAME]" syntax for using a Print Template as
  1016.          a header.
  1017.  
  1018. PG       Starting Page number.  If variable is undefined, "Page 1" will be
  1019.          assumed.
  1020.  
  1021. DIOEND   A string of MUMPS code which is executed after the printout has
  1022.          finished but before returning to the calling program.
  1023.  
  1024. Thus, the programmer can call "EN1^DIP" to "pre-answer" some or all of the
  1025. Print Option information that the user normally would enter.  He should note
  1026. that the "^%ZIS" routine will still be invoked by "^DIP" (actually, "^DIP3")
  1027. to determine which device the output should go to.  If "%ZIS" chooses an 'SDP'
  1028. or other such "linear" device, and if multiple copies are desired, the
  1029. programmer can call for them by setting
  1030.  
  1031.     "DCOPIES" = number (greater than one) of copies desired.
  1032.  
  1033. All the input variables (except 'DUZ' and 'DT') are killed before "DIP"
  1034. returns to the calling program.
  1035.  
  1036.  
  1037. D.  DATA DISPLAY -- "DIQ"
  1038.  
  1039. Similar to the "DIE" routine, a programmer can call the "File Inquiry"
  1040. program, "DIQ", at the entry point "EN" to display a range of data elements in
  1041. captioned format.  Two local variables must be defined as input parameters:
  1042.  
  1043.     'DIC' = The Global Name of the File in the usual format
  1044.     'DA'  = The Internal Entry Number of the File Entry to be printed.
  1045.  
  1046. If, in addition to the above, the variable 'DR' is defined at input, it will
  1047. be understood to name the global subscript or subscripts which are to be
  1048. displayed by "DIQ".  If 'DR' contains a colon (:), the range of subscripts is
  1049. understood to be specified by what precedes and follows the colon; otherwise,
  1050. 'DR' is understood to be the literal name of the subscript.  All data Fields
  1051. stored within, and descendant from, the subscript(s) will be displayed, even
  1052. those which normally have "Read Access" security protection.
  1053.  
  1054. If, for example, Fields .01, 1, 2, and 4 are all stored in the zeroeth global
  1055. node of a particular File's Entries, the programmer can call for the display
  1056. of those Fields, for Entry Number 777, by writing:
  1057.  
  1058.          SET DIC="^FILE(",DA=777,DR=0 DO EN^DIQ
  1059.  
  1060.  
  1061. E.  WORD-PROCESSING FORMATTING AND OUTPUT -- "DIWP"
  1062.  
  1063. A programmer can call the "DIWP" routine to format and (optionally) output any
  1064. group of text lines.  Before calling "DIWP", the global ^UTILITY($J,"W")
  1065. should be KILLed.  Then, for each text line, "^DIWP" is invoked with the
  1066. following local variables defined:
  1067.  
  1068.        'X' = the string of text to be added as input to the formatter
  1069.  
  1070.        'DIWL' = the (integer-valued) left margin for the text
  1071.  
  1072.        'DIWR' = the (integer-valued) right margin for the text
  1073.  
  1074.        'DIWF' = a string of 'format control parameters' with effects as follows:
  1075.  
  1076. If 'DIWF' contains "W", the formatted text will be "written" out to the
  1077. current device, and will not be stored in ^UTILITY($J,"W").  The routine
  1078. "^DIWW" must be invoked after the last 'X' string is input to "^DIWP", so that
  1079. the final line of formatted text can be output.  If 'DIWF' does not contain
  1080. "W", no terminal output will occur, but the formatted text will be accumulated
  1081. in ^UTILITY($J,"W",DIWL).
  1082.  
  1083. If 'DIWF' contains "C" followed by an integer, 'N', the text will be
  1084. formatted in a "column width" of 'N', thus overriding the value of 'DIWR'.
  1085.  
  1086. If 'DIWF' contains "D", the text will be formatted "double-spaced".
  1087.  
  1088. If 'DIWF' contains "I" followed by an integer, 'N', the text will be
  1089. "indented" 'N' columns in from the left margin ('DIWL').
  1090.  
  1091. If 'DIWF' contains "N", each line will be printed as it appears in
  1092. the text. (No-wrap)
  1093.  
  1094. If 'DIWF' contains "R", the text will be formatted "right-justified".
  1095.  
  1096. To summarize the parameters 'DIWF' may contain:
  1097.  
  1098.     Cn   = text is formatted over a Column width of 'n'
  1099.     D   = Double-space the output
  1100.     In   = Indent 'n' columns from the left margin
  1101.     N   = No wrap; print each line exactly as it appears in the text
  1102.     R   = Right-justify the text over the right margin
  1103.     W   = Write out the formatted text to the current device.
  1104.  
  1105. The 'X' input strings may contain "|"-windows, as described in the User Manual
  1106. (for example, "|SETTAB(9,23,44)|").  The expressions within the "windows" will
  1107. be processed as long as they are not "context-dependent" (i.e., as long as
  1108. they do not refer symbolically to database Field Names).  Thus, "AUG 14,1986" 
  1109. will cause today's date to be inserted into the formatted text, but "|SSN|" 
  1110. will be printed out as it stands, because it can not be interpreted in context.
  1111.  
  1112.  
  1113. F.  FORM DOCUMENT PRINT -- "DIWF"
  1114.  
  1115. The "DIWF" routine is designed to use the contents of a Word-Processing field
  1116. as a "target document" into which data will be inserted at print time.  The
  1117. data may come from another FileMan file or provided by the user interactively
  1118. at the time the document is printed.  A File containing a Word-Processing type
  1119. field is first selected, and then an Entry in that File.  The Word-Processing
  1120. text in that Entry is then used as a "Form" with which to print output from
  1121. any other File.
  1122.  
  1123. The Word-Processing text used will typically include "windows" into which data
  1124. from the target file automatically gets inserted by "DIWF".  The "window"
  1125. delimiter is the vertical bar ("|").  Thus, if a Word-Processing document
  1126. contains "|NAME|" somewhere within it, "DIWF" will try to pick the NAME field
  1127. (if there is one) out of the file being printed.  Any non-multiple Field
  1128. Label or Computed-Field expression can be used within a "|" window.  If
  1129.  
  1130.     1)  an expression within the "|" window cannot be evaluated, and
  1131.  
  1132.     2)  the output of "DIWF" is being sent to a different terminal than
  1133.         the one used to call up the output,
  1134.  
  1135. then the user will be asked to type in a value for the window, for each data
  1136. entry printed.  Thus, the Word-Processing text used as a "target document"
  1137. might include the window "|SALUTATION|", where SALUTATION is not a valid field
  1138. name in the source file.  When "DIWF" encounters this window, and failing to
  1139. find a "SALUTATION" field in the source file, it will ask the user to enter
  1140. "SALUTATION" text which then immediately gets incorporated into the output in
  1141. place of that "window".  Note that we are referring to two Files - the
  1142. "document" file which contains the word-processing text and the "print from"
  1143. file which "DIWF" will use to try to "fill-in" data for the windows.
  1144.  
  1145. Invoking "DIWF" at the top (i.e. DO ^DIWF) will result is the following
  1146. dialogue:
  1147.     
  1148.     Select Document File: FORM LETTER  (a File with a W-P type field)
  1149.     Select DOCUMENT: APPOINTMENT REMINDER  (an entry in the FORM LETTER File)
  1150.     Print from what FILE: PATIENT
  1151.     WANT EACH ENTRY ON A SEPARATE PAGE? YES//
  1152.     SORT BY: NAME// FOLLOWUP DATE=MAY 1, 1986
  1153.     DEVICE:
  1154.  
  1155. In this example, the Word-Processing text found in the APPOINTMENT REMINDER
  1156. Entry of the FORM LETTER file is used to print a sheet of output for each
  1157. Entry in the PATIENT File whose FOLLOWUP DATE equals May 1, 1986.
  1158.  
  1159. If the "Document File" contains a Pointer field pointing to File #1, and if
  1160. the document entry selected has a value for that Pointer, then the File
  1161. pointed to will be automatically used to "print from" and the user will not be
  1162. asked "Print from what FILE:".
  1163.  
  1164. Note that the READ ACCESS is checked by DIWF for both files selected.
  1165.  
  1166. A programmer can invoke "DIWF" at two other entry points to pre-answer some or
  1167. all of the questions normally asked of the user.
  1168.  
  1169. EN1       This entry point is used when the calling program knows which File
  1170.          ("document file") contains the desired Word-Processing text to be
  1171.          used as a "target document".  If "DIWF" is entered at "EN1", the
  1172.          variable 'DIC' should be defined in its customary way -- that is, it
  1173.          identifies a file either by its file number or its global name
  1174.          "root".  (e.g. DIC=16001 or DIC="^DIZ(16001,").
  1175.  
  1176.          The file identified must contain a Word-Processing field.  The user
  1177.          will then be branched to "Select DOCUMENT: " in the dialogue
  1178.          described above to select a particular entry in the document file.
  1179.  
  1180. EN2       This entry point is used when the calling program knows both the
  1181.          "document" File and the Entry within that file which contains the
  1182.          desired Word-Processing text to be used as a "target document".  If
  1183.          "DIWF" is entered at "EN2", the variable 'DIWF' must be defined as
  1184.          naming the global "root" at which the desired text is stored.  Thus,
  1185.          in our example, if "APPOINTMENT REMINDER" is the third document in
  1186.          the FORM LETTER file (stored in "^DIZ(16001,") and that the word
  1187.          processing field is stored in subscript "1", we can:
  1188.  
  1189.                    SET DIWF="^DIZ(16001,3,1,"
  1190.  
  1191.          "DIWF" will then automatically use this entry and the user will not
  1192.          be asked to select the document file and which document in that
  1193.          file.
  1194.  
  1195. If the calling program wants to specify which file should be used to "print
  1196. from" for generating output, the number of that file should appear in the
  1197. variable 'DIWF(1)'.  Otherwise, the user will be asked the "Print from what
  1198. FILE:" question.  After this point, "EN1^DIP" is invoked; the calling program
  1199. can set the usual 'BY', 'FR', and 'TO' variables if it wants to control the
  1200. SORT sequence of the data file.
  1201.  
  1202.  
  1203. G.  FILE RE-INDEXING AND ENTRY DELETION -- "DIK"
  1204.  
  1205. A programmer can call the routine "DIK" at several entry points to delete
  1206. entries from a file or re-index the file.
  1207.  
  1208. To delete an entry from a file set the variable 'DIK' to a global reference
  1209. analogous to 'DIC' in the file lookup routine (^DIC) and the variable 'DA' to
  1210. the entry number you wish to delete then call "^DIK".  This will delete the
  1211. internal entry number 'DA' from the file specified by 'DIK'.  Thus, to delete
  1212. SAM SMITH from the Patient file in the example in Chapter III.B., the
  1213. programmer can write:
  1214.  
  1215.     SET DIK="^DPT(",DA=7 DO ^DIK
  1216.  
  1217. The variable 'DA(1)' will also be needed if deletion will occur at a lower
  1218. level of the file.  In this case, 'DIK' must be set to the "root" of the
  1219. global node at that level.  Returning to the rudimentary Patient file in
  1220. Chapter III, we see that patient JOHN JONES has two diagnoses on file.  To
  1221. delete the second diagnoses ("ANGINA") we would write:
  1222.     
  1223.     SET DA(1)=1,DA=2,DIK="^DPT(" DA(1) ",""DX""," DO ^DIK
  1224.  
  1225. where 'DA' is the diagnosis entry number in the sub-file and DA(1) is the
  1226. patient's internal entry in the Patient file.
  1227.  
  1228. Recall that in Chapter III, Section D we mentioned that each attribute
  1229. dictionary is also in the form of a file.  We can therefore use the routine
  1230. "DIK" to delete a single-valued field from a file.  To do this, the variable
  1231. 'DIK' is set to the file's Data Dictionary global node, 'DA' is set to the
  1232. number of the field to be deleted and 'DA(1)' is set to the File number.
  1233. Thus, to delete the field "SEX" from our Patient file example, one could
  1234. simply write:
  1235.  
  1236.     SET DIK="^DD(2,",DA=1,DA(1)=2 DO ^DIK
  1237.  
  1238. The routine "DIK" leaves the 'DA' array and 'DIK' defined.  One can therefore
  1239. loop through the file to delete several entries (or fields) as in:
  1240.  
  1241.     SET DIK="^DPT(" F DA=2,9,11 DO ^DIK
  1242.  
  1243. This will delete entries 2, 9 and 11 from the patient file.
  1244.  
  1245. Using the routine "DIK" to delete entries should be used with extreme caution.
  1246. It does not check "Delete Access" for the file nor does it update any pointers
  1247. to the deleted entries.  When used to delete fields from a file, the data is
  1248. also not deleted.  However, it does execute all cross-references and triggers.
  1249.  
  1250. Two other entry points to the routine "DIK" can be used to re-index a file,
  1251. they are:
  1252.  
  1253. IXALL^DIK     will crossreference all indices for all entries in the
  1254.               file named by 'DIK'.  The variable 'DIK', as above, should be
  1255.               set to the file global reference.
  1256.  
  1257. IX1^DIK       will crossreference all indices of the file named by 'DIK'
  1258.               but only for the entry named in the variable 'DA' which should
  1259.               be set to the internal entry number of the entry you wish to
  1260.               crossreference.  Only set logic will be executed.
  1261.  
  1262.  
  1263. H.  DATE CONVERSION -- "%DT"
  1264.  
  1265. %DT is used to validate date/time input and convert it to a conventional
  1266. storage format: "YYYMMDD.HHMM", where
  1267.  
  1268.     YYY is number of years since 1700 (hence always 3 digits)
  1269.     MM is month number (00-12)
  1270.     DD is day number (00-31)
  1271.     HH is hour number (00-23)
  1272.     MM is minute number (01-59).
  1273.  
  1274. It is to be noted that this format allows for representation of "imprecise"
  1275. dates like "JULY '78"  or  "1978"  (which would be equivalent to 2780700 &
  1276. 2780000 respectively), and that it is always returned as a canonic number
  1277. (no trailing fractional zeroes).
  1278.  
  1279. The input value to "%DT" (if any) is in the local variable 'X'.  The output is
  1280. in 'Y' (which is returned as "-1" if the input is invalid).  A variable named
  1281. %DT is used to direct the input and conversion of dates.
  1282.  
  1283. CODE     VALUE
  1284.  
  1285.  A       Ask for date input
  1286.  E       Echo the answer
  1287.  F       Future dates are assumed
  1288.  N       Pure numeric input (e.g., "121177") is not allowed
  1289.  P       Past dates are assumed
  1290.  R       Require time input
  1291.  T       Time input is allowed but not required
  1292.  X       Exact date (with month and day) is required
  1293.  
  1294.   Examples:
  1295.  
  1296. S %DT="",X="T" D ^%DT S DT=Y ;sets DT equal to today's date
  1297.  
  1298. S %DT="AEPT" D ^%DT G OUT:Y<0 ;asks for a date with optional time
  1299.  
  1300. Imprecise dates (without a day or month) may be entered unless %DT contains
  1301. "X".  Time input is allowed when %DT contains "T".  To require a time input,
  1302. %DT must contain "R"; the parameter "T" only allows but does not require the
  1303. response to include time.
  1304.  
  1305. Including "P" in %DT is suggested for dates in the past such as date of birth
  1306. or admission date.  This will properly convert a month/day entry with no year
  1307. to the past year and will convert two-digit years that are greater than the
  1308. current year (e.g., "JAN 1, 98") to years in the 1800's.
  1309.  
  1310. Including "F" in %DT is suggested for future dates such as "appointment
  1311. date/time", so that, for example, when the current date is February 20, 1986,
  1312. "MAR 4" gets converted to March 4, 1987.
  1313.  
  1314. %DT("A") can be set to a string that will replace the standard "DATE: " prompt
  1315. when the user is asked for input.  This is like the use of DIC("A") for the
  1316. ^DIC routine.
  1317.  
  1318. %DT("B") may be set as the default answer to the date prompt.  It is the
  1319. programmer's responsibility to ensure that %DT("B") contains a valid
  1320. Date/Time.  Allowable date input formats are explained in Chapter II of the
  1321. FileMan User's Manual.
  1322.  
  1323. If "%DT" reads a date/time response from the terminal ('%DT' contains "A"),
  1324. and if the numeric-valued variable 'DTIME' is defined, terminal input will
  1325. "time out" after 'DTIME' seconds if no response is made; in this case, 'Y'
  1326. will be returned as "-1" and 'DTOUT' will be returned as "1".  All variables
  1327. set before calling "%DT" are returned unchanged.
  1328.  
  1329. An option input parameter, '%DT(0)', can be used with the "%DT" routine.  This
  1330. variable prevents the input date value from being accepted if it is
  1331. chronologically before, or after, a particular date.  Set '%DT(0)' equal to a
  1332. FileMan-format date (e.g., %DT(0)=2690720) to allow input only of dates
  1333. greater than or equal to that date.  Set it negative (e.g.,
  1334. %DT(0)=-2831109.15) to allow only dates less than or equal to that
  1335. date/time.  Set it to "NOW" to allow dates from the current (input) time
  1336. forward.  Set it to "-NOW" to allow dates up to the current time.  Be sure to
  1337. 'KILL' this variable after returning from "%DT"!
  1338.  
  1339. There is a simple way to do the reverse of what "%DT" does, i.e., to turn a
  1340. date from "internal" YYYMMDD format to "external" format.  Simply set the
  1341. variable 'Y' equal to the internal date, and execute ^DD("DD").  Thus, for
  1342. example:
  1343.  
  1344.          SET Y=2690720.1630 XECUTE ^DD("DD")
  1345.  
  1346. will result in 'Y' being equal to "JUL 20,1969@16:30".
  1347.  
  1348.  
  1349. I.  DATE COMPARE -- "%DTC"
  1350.  
  1351. %DTC has a number of entry points.  The number of days between two dates can
  1352. be found by setting 'X1' and 'X2' to "YYYMMDD"-type dates and then calling
  1353. "%DTC".  The result is returned in 'X'; 'X1' and 'X2' are killed.  The result
  1354. can be thought of as X1-X2; it can be negative.  '%Y' is returned as 1 when
  1355. the dates both have month and day values, %Y=0 when either date is imprecise.
  1356.  
  1357. C^%DTC takes a date in 'X1' and adds 'X2' days, returning a "YYYMMDD"-type
  1358. date in 'X' and a $H format date in '%H'.
  1359.  
  1360. H^%DTC converts a "YYYMMDD" date in 'X' to a $H format date (output in %H).
  1361. '%Y' is returned with a value of -1 if 'X' was imprecise, otherwise '%Y' is a
  1362. day-of-week numeric value 0 to 6 for Sunday to Saturday.
  1363.  
  1364. DW^%DTC does what H^%DTC does, and then sets 'X' to a string day-of-week name.
  1365. 'X' will be null if the input date ('X') was imprecise.
  1366.  
  1367. YMD^%DTC converts a $H format date (in %H) to a "YYYMMDD"-type date output in
  1368. 'X'.
  1369.  
  1370. COMMA^%DTC can be called by any user program.  It formats a number (in 'X') to
  1371. a string that will separate billions, millions, and thousands with commas.  If
  1372. the parameter 'X2' exists, it can specify dollar sign and fractional digit
  1373. results:
  1374.  
  1375.     S X=12345.678 D COMMA^%DTC         ;result: X="  12,345.68 "
  1376.     S X=9876.54,X2="0$" D COMMA^%DTC   ;result: X="     $9,877 "
  1377.     S X=-3,X2="2$" D COMMA^%DTC        ;result: X="     ($3.00)"
  1378.  
  1379.  
  1380. J.  MUMPS VALIDATION -- "DIM"
  1381.  
  1382. FileMan includes a programmer-callable package to validate any line of MUMPS
  1383. code that conforms to the 1984 Standard.  Invoke "DIM" with the line to be
  1384. validated in the local variable 'X'.  "^DIM" will either kill 'X', or leave it
  1385. unchanged.  If $DATA(X) is zero on return from "DIM", the line of code was
  1386. invalid.  The converse is not always true; in other words, "^DIM" is not as
  1387. smart as a real MUMPS interpreter and sometimes "validates" strings when it
  1388. shouldn't.  This is really a "utility package", and uses only local variables
  1389. that begin with the "%" character.
  1390.  
  1391. Note:  "DIM" will not allow the killing of an unsubscripted global.
  1392. VA FileMan  V.17 - Apr 1986                        Programmer's Manual  (5)
  1393.  
  1394.  
  1395.  
  1396.  
  1397.               V.  ADVANCED FILE-DEFINITION FEATURES
  1398.  
  1399.  
  1400. If FileMan routines are invoked with the 'FileMan Access Code' -- the local
  1401. variable 'DUZ(0)' -- pre-set to the "@" character, the user will be understood
  1402. to be a 'MUMPS'-proficient programmer, who therefore can control certain
  1403. file-definition options which would otherwise be handled "invisibly" by the
  1404. system:
  1405.  
  1406.  
  1407. A.  STORING DATA IN A GLOBAL OTHER THAN '^DIZ'
  1408.  
  1409. When setting up a brand-new File (Modify File Attributes Option), a
  1410. programmer-user can tell the system whether he wishes:
  1411.     
  1412.       
  1413.      1)  to store the new file in the "^DIZ" global array, descendant from the
  1414.      File Number just assigned, or
  1415.       
  1416.      2)  to store the new file in a global array of his own choosing.
  1417.       
  1418. The dialogue looks like this:
  1419.       
  1420.                MODIFY WHAT FILE: TEST
  1421.                ARE YOU ADDING 'TEST' AS A NEW FILE? Y  (YES)
  1422.                FILE NUMBER: 24000//   (the number prompted will vary)
  1423.                INTERNAL GLOBAL REFERENCE: ^DIZ(24000,//
  1424.       
  1425. At this point, the user either "escapes" to choose option (1), or types an 
  1426. explicit global reference to choose option (2).  This reference is in the 
  1427. format:
  1428.       
  1429.                ^GLOBAL( or
  1430.                ^GLOBAL(subscript1,subscript2,...
  1431.       
  1432. The "^" preceding "GLOBAL(" need not be entered.  Extended global reference
  1433. ([UCI]) may be entered ahead of the Global name.  If the Global already exists 
  1434. with some data in it, a warning message is displayed.
  1435.       
  1436.       
  1437. B.  ASSIGNING WHERE FIELDS ARE STORED WITHIN A GLOBAL
  1438.       
  1439. When creating a new File Attribute, the programmer-user is asked for the
  1440. global subscript and "^"-piece position to specify where in each File Entry
  1441. the data element being defined will be stored.  If, for example, the user 
  1442. were creating, for a particular File, an Attribute that he wanted stored 
  1443. in the first "^"-piece position of the global subscript "DEMOG" for every 
  1444. Entry, then he would enter:
  1445.       
  1446.               SUBSCRIPT: DEMOG
  1447.               ^-PIECE POSITION: 1
  1448.       
  1449. To aid in the process, the system prompts the user with the "highest"
  1450. Subscript previously used for the File, and then, when Subscript has been
  1451. entered, it prompts the "^"-piece position one past the highest previously
  1452. assigned for that subscript.  FileMan ensures that no more than 250 
  1453. characters of data will be stored in any single Global node, and that no 
  1454. two data Attributes are assigned to the same Subscript and "^"-piece 
  1455. position.
  1456.  
  1457. The user may occasionally wish to store fixed-length data by character
  1458. position within the Global Subscript, rather than by "^"-piece position; he
  1459. specifies that an Attribute is to be stored, for example, in character
  1460. positions 1-3 of the indicated Subscript by answering:
  1461.  
  1462.                ^-PIECE POSITION: E1,3
  1463.       
  1464.       
  1465. C.  ASSIGNING 'SUB-DICTIONARY' NUMBERS
  1466.  
  1467. At the very end of Chapter III, it was mentioned that data specifications 
  1468. for multiple-valued sub-fields are stored in a "subsidiary Data 
  1469. Dictionary".  Such a "sub-dictionary" is stored descendant from a non-integer-
  1470. valued subscript of ^DD, for example ^DD(2.01).  Normally, when creating a new 
  1471. multiple-valued Attribute (Option 4), the system automatically assigns this 
  1472. fractional number.  The "@"-user, however, is allowed to pick the number he 
  1473. wants, in response to:
  1474.       
  1475.          SUB-DICTIONARY NUMBER: 2.01//
  1476.       
  1477.       
  1478. D.  MUMPS 'COMPUTED FIELDS'
  1479.       
  1480. The "@"-user who knows MUMPS can enter an executable line of code at any 
  1481. point where one would normally be allowed to use 'Computed-Field' syntax.  The 
  1482. code should create a variable 'X', which will be understood to be the value of 
  1483. the computation.  Incidentally, whenever a "@"-user adds a Computed Field to a
  1484. Data Dictionary under the Modify File Attributes Option, he will see a display
  1485. of the MUMPS code that will set up the variable 'X' when this Field is used.
  1486.       
  1487.       
  1488. E.  "SCREENED" POINTERS
  1489.       
  1490. The "@"-user who is MODIFYING a pointer-type Data Field (Option 4) will be
  1491. asked:
  1492.       
  1493.          SHOULD POINTER ENTRIES BE SCREENED? NO//
  1494.       
  1495. If you answer "YES" to this question, you will be allowed to enter a line 
  1496. of MUMPS code.  This code should set the variable 'DIC("S")', which in turn is
  1497. used in the "DIC" lookup routine to "screen out" certain Entries in the
  1498. 'pointed-to' File.  Using this trick, for example, you could make sure that
  1499. all providers being 'pointed to' from a Surgery File had an "S" code in some
  1500. auxiliary Field:
  1501.       
  1502.      MUMPS CODE THAT WILL SET 'DIC("S")': SET DIC("S")="I $P(^(0),U,5)[""S"""
  1503.       
  1504. F.  "INPUT TRANSFORM"
  1505.       
  1506. This sub-option of the Utilities Option allows the "@"-user to tinker with the
  1507. MUMPS code that checks incoming data for any specified Field.  What you see
  1508. when you select the Field is a MUMPS statement that "validates" the variable
  1509. 'X', and kills it if it is found to be invalid.  As a programmer, you can
  1510. re-write this line of code to your own individual requirements.  The code can
  1511. "transform" 'X' if you wish; that is you can take 'X' and re-set it to the
  1512. value you want filed.  An example would be a Name "transform" that deletes an
  1513. extraneous space character following a comma:
  1514.  
  1515.           INPUT TRANSFORM: K:$L(X)>30!($L(X)<3) X    Replace K
  1516.                With S:X[", " X=$P(X,", ",1) "," $P(X,", ",2) K
  1517.                Replace <return>
  1518.                S:X[", " X=$P(X,", ",1) "," $P(X,", ",2) K:$L(X)>30!($L(X)<3) X
  1519.       
  1520. Once an "Input Transform" has been created for a Field, the syntax-checking
  1521. that the Field does can no longer be modified using Option 4.  (A Data
  1522. Dictionary listing will show "XXXX" for such a Field.)
  1523.  
  1524. It should be noted that, for a Computed Field, the "Input Transform" is simply
  1525. the MUMPS code that gets executed whenever the Field is computed.  Hence, any
  1526. Computed Field calculation can be edited by a programmer using this
  1527. sub-option.
  1528.       
  1529.       
  1530. G.  "OUTPUT TRANSFORM"
  1531.       
  1532. Analogously with the above, the "@"-user can write a MUMPS Output Transform to
  1533. convert internal data values to a different external form.  Here, the variable
  1534. is 'Y', not 'X'.  To reverse the above example, suppose we wanted always to
  1535. display the Name Field with a space character following the comma, even
  1536. though the space was not stored.  We would do something like this:
  1537.  
  1538.                OUTPUT TRANSFORM: S Y=$P(Y,",",1) ", " $P(Y,",",2,9)
  1539.       
  1540. Incidentally, if your MUMPS Operating System supports "terminal break", a
  1541. "@"-user is allowed to "break" execution at any point, whereas a normal user
  1542. can only "break" during output routines.
  1543. VA FileMan  V.17 - Apr 1986                         Programmer's Manual  (6)
  1544.  
  1545.  
  1546.      
  1547.  
  1548.                  VI.  OTHER PROGRAMMER UTILITIES
  1549.      
  1550.       
  1551.       
  1552. A.  CREATING FUNCTIONS
  1553.       
  1554. As mentioned in the User Manual, the programmer-user of FileMan can create his
  1555. own Computed-Expression "Functions".  In some ways, a Function can be thought
  1556. of as an Output Transform (see previous page) that can work on any Field.  For
  1557. example, you may have a preference for seeing many dates displayed as, e.g.,
  1558. "20-7-69", rather than the "JUL 20,1969" that FileMan typically produces.
  1559. Since this date is internally stored in the form "2690720" (see Chapter
  1560. II.C.), you, the MUMPS programmer, know that it would be easy to write a line
  1561. of code that took the variable 'X', and transformed it into
  1562.  
  1563.          +$E(X,6,7) "-" +$E(X,4,5) "-" $E(X,2,3)
  1564.       
  1565. This is exactly what you are allowed to do when you go into the "Function"
  1566. File under Enter/Edit Option (Option #1).
  1567.  
  1568. To continue the above example, we show how one could create a "DASHDATE"
  1569. Function which could then be used by all users to display Date-valued Fields
  1570. and Expressions in the "DAY-MONTH-YEAR" format:
  1571.       
  1572.          Select OPTION: ENTER AND EDIT FILES
  1573.          INPUT TO WHAT FILE: FUNCTION
  1574.          EDIT WHICH ATTRIBUTE: ALL//
  1575.       
  1576.          Select COMPUTED-FIELD FUNCTION: DASHDATE
  1577.             YOU ADDING 'DASHDATE' AS A NEW COMPUTED-FIELD FUNCTION? Y  (YES)
  1578.          MUMPS CODE: S X=+$E(X,6,7) "-" +$E(X,4,5) "-" $E(X,2,3)
  1579.          EXPLANATION: PRINTS DATE IN "DD-MM-YY" FORMAT
  1580.          DATE-VALUED: NO
  1581.          NUMBER OF ARGUMENTS: 1
  1582.       
  1583. Notice that the crux of the matter here is the "MUMPS CODE", which is written
  1584. to transform the variable 'X' (the argument of the Function) into a different
  1585. 'X'.  If two arguments were required for the Function, the first would be
  1586. found in the variable 'X1' and the second in 'X'.  Note, too, that although
  1587. the new Function being created here, takes a Date-valued argument, it is not
  1588. itself considered to be Date-valued (since it doesn't produce values that look
  1589. like the standard FileMan internal representation of a date).
  1590.  
  1591. Note that a "function" can be defined as taking no arguments.  This is
  1592. analogous to MUMPS Special Variables like '$I' and '$H'.  For example, one
  1593. could define a function like "BELL":
  1594.  
  1595.          Select COMPUTED-FIELD FUNCTION: BELL
  1596.             ARE YOU ADDING A NEW COMPUTED-FIELD FUNCTION? Y (YES)
  1597.          MUMPS CODE: SET X=$C(7)
  1598.          EXPLANATION: CAUSES A 'BEEP' TO OCCUR ON OUTPUT
  1599.          DATE-VALUED: NO
  1600.          NUMBER OF ARGUMENTS: 0
  1601.       
  1602. Users could then embed "beeps" in output Templates by entering:
  1603.       
  1604.      FIRST PRINT FIELD: BELL      (note: no parentheses)
  1605.       
  1606. One can delete a Function that one has created, in the usual way (i.e., by
  1607. deleting the 'NAME' of the Function).  Such deletion doesn't harm any
  1608. Computed-Fields that already have been created using the Function.
  1609.       
  1610.       
  1611. B.  CODE GENERATION -- INPUT ROUTINES
  1612.       
  1613. If your MUMPS system has a way of "saving" routines, you can tell FileMan to
  1614. write a "hard-coded" MUMPS routine that will do just what a particular Input
  1615. Template tells the Enter/Edit Option to do.  The sole purpose of "DIEZ" is to
  1616. enhance system performance by reducing the amount of data-dictionary lookup
  1617. that accompanies FileMan inputting.  The routines created by "DIEZ" should run
  1618. anywhere from 20%-80% more efficiently than "DIE" does for the same input.
  1619.  
  1620. Call the "DIEZ" routine, and specify the maximum number of characters you want
  1621. in your routines, the name of the Input Template you are using, and the name
  1622. of the MUMPS routine you want to create.  If more code is compiled than will
  1623. fit into a single routine, "overflow" code will be incorporated in routines
  1624. with the same name, followed by '1', '2', etc.  Thus routine 'DGT' may call
  1625. 'DGT1', 'DGT2', etc.
  1626.       
  1627. Once "DIEZ" has created "hard code" routine for a particular Input Template,
  1628. FileMan will automatically use that routine in the Enter/Edit Option, whenever
  1629. the Template is specified for input.  However, it will cease using the routine
  1630. when any of its Field definitions have been altered by the Modify File
  1631. Attributes or Utility Option.  If a user edits and re-files the Template under
  1632. the Enter/Edit Option, the "hard-code" routine(s) will be re-compiled
  1633. immediately.
  1634.       
  1635. Note that the File of Input Templates (#.402) contains a Computed Field called
  1636. "UNCOMPILED".  Templates for which this Boolean-valued Field evaluates "TRUE"
  1637. are those which formerly existed in a compiled version, but which are
  1638. currently not using their compiled routine names.  Sorting File #.402 by
  1639. this field therefore allows one to see quickly which Templates might be in
  1640. need of re-compilation, owing to changes in definition of their components.
  1641.  
  1642. A "DIEZ"-compiled MUMPS routine may be called by any program that passes it
  1643. the 'DA', 'DT', and 'DUZ' variables that "DIE" customarily uses.  Thus, if an
  1644. Input Template called "PATIENT DATA" exists for File #2, and if "DIEZ" is used
  1645. to "compile" it into the MUMPS routine "PTDATA", the following two lines of
  1646. code are essentially equivalent:
  1647.       
  1648.      SET DA=987,DR="[PATIENT DATA]",DIE=2 DO ^DIE
  1649.      
  1650.      SET DA=987 DO ^PTDATA
  1651.       
  1652. Each invokes the Template for patient #987.
  1653.       
  1654.       
  1655. C.  CODE GENERATION -- OUTPUT ROUTINES
  1656.       
  1657. Print Templates can be "compiled" into MUMPS routines analogously to Input
  1658. Templates.  Call the "DIPZ" routine, and specify the maximum routine size, the
  1659. name of the Print Template to be used, the name of the MUMPS routine to be
  1660. created, and the Margin Width to be used for output (typically 80 or 132). 
  1661. Again, if you specify the routine name "XXX", and more code is generated that
  1662. can fit into that one routine 'overflow' routines, "XXX1" etc. will be
  1663. created.
  1664.  
  1665. Once "DIPZ" has been used to create a hard-coded output routine, that routine
  1666. will be automatically invoked by FileMan within the Print and Search Options
  1667. (and when called at EN1^DIP) whenever the corresponding Output Template is
  1668. used.  The exception is that if an output Margin Width is specified that is
  1669. smaller than the "compiled" margin, the compiled routine will not be used.
  1670. Another minor exception: if the Template is used with "ranked" sorting, the
  1671. compiled version is not used.  As with compiled Input Templates, as soon as
  1672. data dictionary definitions of fields used in the Print Template are changed,
  1673. the compiled version is no longer used.  If a user edits the Print Template,
  1674. it is recompiled into hard code immediately.  Note the "UNCOMPILED" field in
  1675. the File of Print Templates (#.4); its usefulness is analogous to the similar
  1676. field described for Input Templates, above.
  1677.  
  1678. Again, the purpose of this "DIPZ" code generation is simply to improve overall
  1679. system throughput.
  1680.  
  1681. A "DIPZ"-compiled MUMPS routine may be called by any program that passes to it
  1682. the 'DT', 'DUZ', 'IOSL' (screen length), 'U' ("^"), and 'D0' variables, where
  1683. 'D0' is the Entry number to be displayed.  Additionally, the variable 'DXS'
  1684. must be killed before calling the routine and after returning from it.  The
  1685. compiled routine writes out its report for that single entry.  The exception
  1686. is that routines compiled from Templates that include statistical totals
  1687. cannot be called in this way.
  1688.  
  1689.  
  1690. D.  CREATING ROUTINE "PACKAGES" FOR EXPORT
  1691.       
  1692. If you run FileMan on a system that includes non-Standard MUMPS commands to
  1693. build routines ("ZSAVE" or equivalent), you can use the "DIFROM" routine to
  1694. build a package of "initializer" routines that store data and data
  1695. dictionaries from a set of Files, and can then be run at another MUMPS site to
  1696. re-build these Files.  Another use for such routines is as a simple
  1697. archiving facility: one copies off a File and its contents into routines,
  1698. saves the routines on magtape or some other off-line medium, and then deletes
  1699. the Files from active use.
  1700.  
  1701. The "DIFROM" routine first asks you to enter a "two to four-letter package
  1702. name" (for example, "AA" or "DPT"), so that it will know how to name the
  1703. routines it creates.  (If you enter "AA", it will build routines whose names
  1704. begin with the letters "AAINI".) "DIFROM" then asks you, one by one, to
  1705. specify File names (or numbers), and for each File you specify, it will
  1706. further ask whether you wish to "transfer Entries as well as data dictionary".
  1707.  
  1708. Once you have finished listing the Files in your "package", "DIFROM" begins
  1709. writing out the routines, making sure to copy, along with data definitions,
  1710. any Templates you have set up for the specified Files.  As the routines are
  1711. created, warnings are displayed if any non-graphic characters are encountered.
  1712. Unless you answer "YES" to the query:
  1713.  
  1714.          WANT SECURITY CODES SENT ALONG? NO//
  1715.       
  1716. If the user accepts the default, "DIFROM" removes all Access Codes from Files,
  1717. Fields, and Templates in the copies it makes; so that the recipient of the
  1718. package need not follow the same conventions of password security as the
  1719. sender.
  1720.       
  1721. The size of the MUMPS routines that DIFROM creates will always be less than
  1722. 2000 characters, unless the user answers the query
  1723.  
  1724.      MAXIMUM ROUTINE SIZE (BYTES): 2000//
  1725.       
  1726. with a number greater than 2000.  For portability to all ANSI Standard MUMPS
  1727. systems, the 2000-character routine size limit should be maintained.
  1728.       
  1729. The recipient of the routines ("AAINIT", "AAINI001", etc., in the above
  1730. example) simply loads them and runs "AAINIT".  "AAINIT" (or whatever its name)
  1731. will initialize FileMan if necessary ("DINIT"), and will warn the recipient of
  1732. any gross inconsistencies between the Files it describes and whatever Files
  1733. may exist in the new environment.  If the "INIT" routines are bringing in new
  1734. data to data Files which the recipient already has defined, he will be asked:
  1735.  
  1736.      SHALL I ADD MY DATA TO YOURS?
  1737.       
  1738. If he answers "NO", no data for that File will be changed.  If he answers
  1739. "YES", the transferred data will be added to that File, without destroying any
  1740. data he already has.
  1741.       
  1742. As mentioned, DIFROM will transfer any Print, Input, or Sort Templates that
  1743. pertain to any of the files being transferred.  The recipient may already be
  1744. using versions of those Templates, and he is asked whether or not he wants the
  1745. 'new' versions to override the old ones.  As explained in Sections B and C
  1746. above, some Print and Input Templates can exist in a "compiled" form, i.e.,
  1747. they correspond to MUMPS routines that have been generated by the "DIEZ" or
  1748. "DIPZ" routine.  When DIFROM transfers such templates, it 'remembers' that
  1749. they should be compiled, and when it is through loading everything else, it in
  1750. fact attempts to re-compile such templates for the recipient.  It does this if
  1751. it knows that the recipient's MUMPS Operating System supports a "ZSAVE"
  1752. functionality.  It uses that systems's 'preferred routine size'.  The
  1753. dangerous aspect of this 're-compilation' is that the recipient could possibly
  1754. have different code stored in the routines whose names the compiled
  1755. Templates use.  For this reason, it is important that any sender of "DIFROM"
  1756. routines warn his recipient of the routine names used by any incoming
  1757. Templates.
  1758.  
  1759.