KIDS Distribution saved on Jul 26, 2013@12:38:30
Sam Habiel's packaging after MUnit fixes
**KIDS**:XT*7.3*81^

**INSTALL NAME**
XT*7.3*81
"BLD",9256,0)
XT*7.3*81^TOOLKIT^0^3130726^y^^
"BLD",9256,1,0)
^^634^634^3130726^
"BLD",9256,1,1,0)
Subject: Developer Utilities - M Unit
"BLD",9256,1,2,0)
 
"BLD",9256,1,3,0)
Category: 
"BLD",9256,1,4,0)
  - Routine
"BLD",9256,1,5,0)
  - Data Dictionary
"BLD",9256,1,6,0)
  - Other
"BLD",9256,1,7,0)
 
"BLD",9256,1,8,0)
Description:
"BLD",9256,1,9,0)
============
"BLD",9256,1,10,0)
 
"BLD",9256,1,11,0)
 This patch contains utility routines for programmers.
"BLD",9256,1,12,0)
   
"BLD",9256,1,13,0)
 XTMUNIT  - a unit tester for M code, with command line and GUI front 
"BLD",9256,1,14,0)
 ends.  
"BLD",9256,1,15,0)
   
"BLD",9256,1,16,0)
 XTMRPRNT - a routine lister that makes it easy to copy and paste 
"BLD",9256,1,17,0)
 routines.  
"BLD",9256,1,18,0)
   
"BLD",9256,1,19,0)
 XTMLOG,XTMLOG1,XTMLOPAR,XTMLOSKT - routines for event logging 
"BLD",9256,1,20,0)
 with the possibility of external control of the logging, similar to 
"BLD",9256,1,21,0)
 Log4J with Java.
"BLD",9256,1,22,0)
   
"BLD",9256,1,23,0)
 The patch also installs one Client/Server option (XTMUNIT, M Unit 
"BLD",9256,1,24,0)
 Tester) and two RPCs (XTMUNIT-TEST LOAD and XTMUNIT-TEST NEXT).
"BLD",9256,1,25,0)
   
"BLD",9256,1,26,0)
   
"BLD",9256,1,27,0)
 Test Sites: 
"BLD",9256,1,28,0)
   
"BLD",9256,1,29,0)
   
"BLD",9256,1,30,0)
   
"BLD",9256,1,31,0)
   
"BLD",9256,1,32,0)
 Blood Bank Team Coordination: 
"BLD",9256,1,33,0)
 =============================
"BLD",9256,1,34,0)
 Clearance - 
"BLD",9256,1,35,0)
   
"BLD",9256,1,36,0)
   
"BLD",9256,1,37,0)
   
"BLD",9256,1,38,0)
 The client-side software distribution includes: 
"BLD",9256,1,39,0)
   
"BLD",9256,1,40,0)
     Date      Time   Attrib    Bytes     CRC-32  Filename 
"BLD",9256,1,41,0)
  ---------- -------- ------ ----------- -------- --------
"BLD",9256,1,42,0)
  04/18/2006 11:19:20 A-----     405,694 F0A8CB7C XT_7_3_81.zip 
"BLD",9256,1,43,0)
   
"BLD",9256,1,44,0)
 SOFTWARE RETRIEVAL: 
"BLD",9256,1,45,0)
   
"BLD",9256,1,46,0)
 The software for this package is available for retrieval via FTP.  All VA
"BLD",9256,1,47,0)
 Medical Centers are encouraged to use the TCPIP FTP functionality to 
"BLD",9256,1,48,0)
 obtain the software from one of the following OI Field Office
"BLD",9256,1,49,0)
 ANONYMOUS.SOFTWARE directories:
"BLD",9256,1,50,0)
   
"BLD",9256,1,51,0)
        IRM Field Office          FTP Address 
"BLD",9256,1,52,0)
        ================          ===========
"BLD",9256,1,53,0)
        Albany                    ftp.fo-albany.med.va.gov 
"BLD",9256,1,54,0)
        Hines                     ftp.fo-hines.med.va.gov 
"BLD",9256,1,55,0)
        Salt Lake City            ftp.fo-slc.med.va.gov 
"BLD",9256,1,56,0)
        VistA Download Site       download.vista.med.va.gov 
"BLD",9256,1,57,0)
   
"BLD",9256,1,58,0)
   
"BLD",9256,1,59,0)
 Client Side: 
"BLD",9256,1,60,0)
 ============
"BLD",9256,1,61,0)
   
"BLD",9256,1,62,0)
 The following lists the files installed by unzipping XT_7_3_81.ZIP. 
"BLD",9256,1,63,0)
   
"BLD",9256,1,64,0)
     Date      Time   Attrib    Bytes     CRC-32  Filename 
"BLD",9256,1,65,0)
  ---------- -------- ------ ----------- -------- --------
"BLD",9256,1,66,0)
  04/18/2006 11:12:24 A-----     872,448 1E4B87B5 MUnit.exe 
"BLD",9256,1,67,0)
   
"BLD",9256,1,68,0)
   
"BLD",9256,1,69,0)
   
"BLD",9256,1,70,0)
 Installation Instructions: 
"BLD",9256,1,71,0)
   
"BLD",9256,1,72,0)
 1.   Users ARE allowed to be on the system during the installation.
"BLD",9256,1,73,0)
   
"BLD",9256,1,74,0)
 2.   Use the 'INSTALL/CHECK MESSAGE' option on the PackMan menu.  
"BLD",9256,1,75,0)
      This option will load the KIDS (Kernel Installation and Distribution
"BLD",9256,1,76,0)
      System) package onto your system.  
"BLD",9256,1,77,0)
   
"BLD",9256,1,78,0)
 3.   You DO NOT need to stop TaskMan or the background filers.  
"BLD",9256,1,79,0)
   
"BLD",9256,1,80,0)
 4.   The patch has now been loaded into a transport global on your 
"BLD",9256,1,81,0)
      system.  On the KIDS menu, select the 'Installation' menu and use 
"BLD",9256,1,82,0)
      the following options: 
"BLD",9256,1,83,0)
             Verify Checksums in Transport Global 
"BLD",9256,1,84,0)
             Print Transport Global 
"BLD",9256,1,85,0)
             Compare Transport Global to Current System 
"BLD",9256,1,86,0)
             Backup a Transport Global 
"BLD",9256,1,87,0)
   
"BLD",9256,1,88,0)
             Return to Programmers Prompt and use "D ^XPDKRN": 
"BLD",9256,1,89,0)
             Select KIDS OPTION: Install 
"BLD",9256,1,90,0)
                                 =======
"BLD",9256,1,91,0)
             Install Package(s) 
"BLD",9256,1,92,0)
             Select INSTALL NAME: XT*7.3*81 
"BLD",9256,1,93,0)
                                   ==========
"BLD",9256,1,94,0)
   
"BLD",9256,1,95,0)
 Want KIDS to Rebuild Menu Trees Upon Completion of Install? YES// NO
"BLD",9256,1,96,0)
                                                                   ==
"BLD",9256,1,97,0)
 Want KIDS to INHIBIT LOGONs during the install? YES// NO 
"BLD",9256,1,98,0)
                                                       ==
"BLD",9256,1,99,0)
 Want to DISABLE Scheduled Options, Menu Options, and Protocols? YES// NO
"BLD",9256,1,100,0)
                                                                       ==
"BLD",9256,1,101,0)
 
"BLD",9256,1,102,0)
Routine Information:
"BLD",9256,1,103,0)
====================
"BLD",9256,1,104,0)
The second line of each of these routines now looks like:
"BLD",9256,1,105,0)
 ;;7.3;TOOLKIT;**[Patch List]**;Apr 25, 1995;Build 17
"BLD",9256,1,106,0)
 
"BLD",9256,1,107,0)
The checksums below are new checksums, and
"BLD",9256,1,108,0)
 can be checked with CHECK1^XTSUMBLD.
"BLD",9256,1,109,0)
 
"BLD",9256,1,110,0)
Routine Name: XTMLOG
"BLD",9256,1,111,0)
    Before:       n/a   After:B133645760  **81,101**
"BLD",9256,1,112,0)
Routine Name: XTMLOG1
"BLD",9256,1,113,0)
    Before:       n/a   After: B46831784  **81**
"BLD",9256,1,114,0)
Routine Name: XTMLOG2
"BLD",9256,1,115,0)
    Before:       n/a   After:    Delete  
"BLD",9256,1,116,0)
Routine Name: XTMLOPAR
"BLD",9256,1,117,0)
    Before:       n/a   After: B19404303  **81**
"BLD",9256,1,118,0)
Routine Name: XTMLOSKT
"BLD",9256,1,119,0)
    Before:       n/a   After: B36861478  **81**
"BLD",9256,1,120,0)
Routine Name: XTMRPRNT
"BLD",9256,1,121,0)
    Before:       n/a   After:  B1220842  **101**
"BLD",9256,1,122,0)
Routine Name: XTMUNIT
"BLD",9256,1,123,0)
    Before:       n/a   After:  <to be filled in>
"BLD",9256,1,124,0)
Routine Name: XTMUNIT1
"BLD",9256,1,125,0)
    Before:       n/a   After:  <to be filled in>
"BLD",9256,1,126,0)
 
"BLD",9256,1,127,0)
****** XTMUNIT - A unit tester for M code.
"BLD",9256,1,128,0)
 
"BLD",9256,1,129,0)
A Unit Test framework permits small tests to be written to verify that the
"BLD",9256,1,130,0)
code you are testing is doing what you expect it to do.  Generally the tests
"BLD",9256,1,131,0)
are performed on the smaller blocks of the application, and not necessarily
"BLD",9256,1,132,0)
a test of all of the functionality within the application.  As changes are
"BLD",9256,1,133,0)
subsequently made in the code, these tests can be run frequently to validate
"BLD",9256,1,134,0)
that nothing has changed.  The concept of Unit testing was introduced by Kent 
"BLD",9256,1,135,0)
Beck (also the creator of eXtreme Programming methodology).  The common
"BLD",9256,1,136,0)
JUnit framework for Java, which other frameworks are based upon, was written 
"BLD",9256,1,137,0)
by Kent Beck and Erich Gamma.  The phrase 'Test-Driven Development' is 
"BLD",9256,1,138,0)
frequently used to indicate the strong use of unit testing during development,
"BLD",9256,1,139,0)
although some think of it as equivalent to the 'Test First Development' in
"BLD",9256,1,140,0)
which the tests for code are written prior to writing the code.  In the Test
"BLD",9256,1,141,0)
First Development, the test should initially fail (since nothing has been
"BLD",9256,1,142,0)
written) and then pass after the code has been written.
"BLD",9256,1,143,0)
 
"BLD",9256,1,144,0)
For client side languages, JUnit (for Java), DUnit (for Delphi), NUnit and 
"BLD",9256,1,145,0)
HarnessIt (for dotNet) all provide Unit Test frameworks.  The routine XTMUNIT
"BLD",9256,1,146,0)
included in this patch provides the same capabilities for unit testing M code.
"BLD",9256,1,147,0)
Initially the client side tests were console based (i.e., not windows but just
"BLD",9256,1,148,0)
text), and that is what XTMUNIT provides.  There is also, for those who like
"BLD",9256,1,149,0)
pretty windows, a GUI front end available as well (MUnit.exe) but this is 
"BLD",9256,1,150,0)
optional.
"BLD",9256,1,151,0)
 
"BLD",9256,1,152,0)
If you are going to modify sections of your code, or refactor (cleaning up the
"BLD",9256,1,153,0)
code without changing the behavior of the code - which is frequently done prior
"BLD",9256,1,154,0)
to changing the behavior - See Martin Fowler's book "Refactoring: Improving the
"BLD",9256,1,155,0)
Design of Existing Code"), it is best to create a unit test for those areas 
"BLD",9256,1,156,0)
that you want to work with.  Then as changes are made the unit tests can be run
"BLD",9256,1,157,0)
to insure that nothing unexpected has changed.  For modifications, the unit 
"BLD",9256,1,158,0)
tests can then be written to reflect the new expected behavior and used to
"BLD",9256,1,159,0)
insure that it is what is expected.  One of the major benefits of unit testing
"BLD",9256,1,160,0)
is finding those changes that weren't expected in other parts of your code due
"BLD",9256,1,161,0)
to the changes that are being made.
"BLD",9256,1,162,0)
 
"BLD",9256,1,163,0)
 
"BLD",9256,1,164,0)
The following is a very simple sample routine, however, it covers everything 
"BLD",9256,1,165,0)
necessary for generating a basic unit test, and examples of the various
"BLD",9256,1,166,0)
calls available.
"BLD",9256,1,167,0)
 
"BLD",9256,1,168,0)
---------------------------------------------------------------------------
"BLD",9256,1,169,0)
 
"BLD",9256,1,170,0)
XXXX    ;jli/fo-oak - demo code for a unit test routine ;9/25/03  15:44
"BLD",9256,1,171,0)
        ;;
"BLD",9256,1,172,0)
        ; makes it easy to run tests simply by running this routine and
"BLD",9256,1,173,0)
        ; insures that XTMUNIT will be run only where it is present
"BLD",9256,1,174,0)
        I $T(EN^XTMUNIT)'="" D EN^XTMUNIT("XXXX")
"BLD",9256,1,175,0)
        Q
"BLD",9256,1,176,0)
        ;
"BLD",9256,1,177,0)
STARTUP ; optional entry point
"BLD",9256,1,178,0)
        ; if present executed before any other entry point any variables
"BLD",9256,1,179,0)
        ; or other work that needs to be done for any or all tests in the
"BLD",9256,1,180,0)
        ; routine.  This is run only once at the beginning.
"BLD",9256,1,181,0)
        Q
"BLD",9256,1,182,0)
        ;
"BLD",9256,1,183,0)
SHUTDOWN        ; optional entry point
"BLD",9256,1,184,0)
        ; if present executed after all other processing is complete to remove
"BLD",9256,1,185,0)
        ; any variables, or undo work done in STARTUP.
"BLD",9256,1,186,0)
        Q
"BLD",9256,1,187,0)
        ;
"BLD",9256,1,188,0)
SETUP   ; optional entry point
"BLD",9256,1,189,0)
        ; if present it will be executed before each test entry to set up 
"BLD",9256,1,190,0)
        ; variables, etc.
"BLD",9256,1,191,0)
        Q
"BLD",9256,1,192,0)
        ;
"BLD",9256,1,193,0)
TEARDOWN        ; optional entry point
"BLD",9256,1,194,0)
        ; if present it will be exceuted after each test entry to clean up
"BLD",9256,1,195,0)
        ; variables, etc.
"BLD",9256,1,196,0)
        Q
"BLD",9256,1,197,0)
        ;
"BLD",9256,1,198,0)
ENTRY1  ; Example for use of CHKEQ call to check two values
"BLD",9256,1,199,0)
        ;
"BLD",9256,1,200,0)
        ; code to generate a test, e.g. to check the sum of 1 and 1
"BLD",9256,1,201,0)
        S X=1,Y=1
"BLD",9256,1,202,0)
        D CHKEQ^XTMUNIT(2,X+Y,"1+1 didn't yield 2") ;
"BLD",9256,1,203,0)
        ;
"BLD",9256,1,204,0)
        ; usage of CHKEQ^XTMUNIT
"BLD",9256,1,205,0)
        ;   first argument is the expected value
"BLD",9256,1,206,0)
        ;   second argument is the actual value
"BLD",9256,1,207,0)
        ;   third argument is text to be displayed if the first argument
"BLD",9256,1,208,0)
        ;     and second argument are not equal.
"BLD",9256,1,209,0)
        ;
"BLD",9256,1,210,0)
        ;   Multiple calls to CHKEQ^XTMUNIT may be made within one entry
"BLD",9256,1,211,0)
        ;   point.  Each of these is counted as a test.
"BLD",9256,1,212,0)
        ;
"BLD",9256,1,213,0)
        ;   Output for a failure shows the expected and actual values
"BLD",9256,1,214,0)
        Q
"BLD",9256,1,215,0)
        ;
"BLD",9256,1,216,0)
ENTRY2  ; Use of CHKTF call to check value for True or False
"BLD",9256,1,217,0)
        ;
"BLD",9256,1,218,0)
        S ERRMSG="Current user is not an active user on this system"
"BLD",9256,1,219,0)
        D CHKTF^XTMUNIT($$ACTIVE^XUSER(DUZ)>0,ERRMSG)
"BLD",9256,1,220,0)
        ;
"BLD",9256,1,221,0)
        ; usage of CHKTF^XTMUNIT 
"BLD",9256,1,222,0)
        ;    first argument is an expression evaluating to true or false value,
"BLD",9256,1,223,0)
        ;    second argument is text to be displayed if the first argument
"BLD",9256,1,224,0)
        ;      evaluates to false.
"BLD",9256,1,225,0)
        ;
"BLD",9256,1,226,0)
        ;    Multiple calls to CHKTF^XTMUNIT may be made within one entry 
"BLD",9256,1,227,0)
        ;    point.  Each of these is counted as a test.
"BLD",9256,1,228,0)
        Q
"BLD",9256,1,229,0)
        ;
"BLD",9256,1,230,0)
ENTRY3  ; Use of CHKTF call to check values that should NOT be equal
"BLD",9256,1,231,0)
        ;
"BLD",9256,1,232,0)
        ; if you want to test something that should fail, use a NOT
"BLD",9256,1,233,0)
        S X=1,Y=3
"BLD",9256,1,234,0)
        D CHKTF^XTMUNIT(X'=Y,"indicated 1 and 3 are equal")
"BLD",9256,1,235,0)
        Q
"BLD",9256,1,236,0)
        ;
"BLD",9256,1,237,0)
ENTRY4  ; @TEST - Use of the FAIL call to generate a failure message
"BLD",9256,1,238,0)
        ;
"BLD",9256,1,239,0)
        S X=1+2 I X'=3 D FAIL^XTMUNIT("System is doing bad addition on 1+2") Q
"BLD",9256,1,240,0)
        ; 
"BLD",9256,1,241,0)
        ; usage of FAIL^XTMUNIT
"BLD",9256,1,242,0)
        ;    the argument is text indicating why the failure was identified
"BLD",9256,1,243,0)
        Q
"BLD",9256,1,244,0)
        ;
"BLD",9256,1,245,0)
        ; Other routine names to be included in testing are listed one per line
"BLD",9256,1,246,0)
        ; with the name as the third semi-colon piece on the line and an
"BLD",9256,1,247,0)
        ; optional description of what the routine tests as the fourth semi-
"BLD",9256,1,248,0)
        ; colon piece, if desired this permits a suite of test routines to be
"BLD",9256,1,249,0)
        ; run by simply starting one of the routine the names may be repeated
"BLD",9256,1,250,0)
        ; in multiple routines, but will only be included once. The first line
"BLD",9256,1,251,0)
        ; without a third piece terminates the search for routine names (which
"BLD",9256,1,252,0)
        ; is why this is above the XTROU tag).
"BLD",9256,1,253,0)
XTROU   ;
"BLD",9256,1,254,0)
        ;;XXXY;description of what the routine tests
"BLD",9256,1,255,0)
        ;;XXXZ;
"BLD",9256,1,256,0)
        ;;XXXA
"BLD",9256,1,257,0)
        ;
"BLD",9256,1,258,0)
        ; Entry points for tests are specified as the third semi-colon piece,
"BLD",9256,1,259,0)
        ; a description of what it tests is optional as the fourth semi-colon
"BLD",9256,1,260,0)
        ; piece on a line. The first line without a third piece terminates the
"BLD",9256,1,261,0)
        ; search for TAGs to be used as entry points
"BLD",9256,1,262,0)
XTENT   ;
"BLD",9256,1,263,0)
        ;;ENTRY1;tests addition of 1 and 1
"BLD",9256,1,264,0)
        ;;ENTRY2;checks active user status
"BLD",9256,1,265,0)
        ;;ENTRY3;
"BLD",9256,1,266,0)
        Q
"BLD",9256,1,267,0)
 
"BLD",9256,1,268,0)
-----------------------------------------------------------------------------
"BLD",9256,1,269,0)
 
"BLD",9256,1,270,0)
Running XXXX as written above, results in the following
"BLD",9256,1,271,0)
 
"BLD",9256,1,272,0)
>D ^XXXX
"BLD",9256,1,273,0)
Referenced routine XXXY not found.
"BLD",9256,1,274,0)
Referenced routine XXXZ not found.
"BLD",9256,1,275,0)
Referenced routine XXXA not found.
"BLD",9256,1,276,0)
...
"BLD",9256,1,277,0)
 
"BLD",9256,1,278,0)
Ran 1 Routine, 4 Entry Tags
"BLD",9256,1,279,0)
Checked 3 tests, with 0 failures and encountered 0 errors.
"BLD",9256,1,280,0)
>
"BLD",9256,1,281,0)
 
"BLD",9256,1,282,0)
Normally, you won't see routines referenced that aren't there since you 
"BLD",9256,1,283,0)
wouldn't include them.  Passed tests are shown only with a dot, and the
"BLD",9256,1,284,0)
results are summarized at the bottom.
"BLD",9256,1,285,0)
 
"BLD",9256,1,286,0)
 
"BLD",9256,1,287,0)
Changing the code on line ENTRY+3 from (X'=Y)  to  (X=Y)  and running 
"BLD",9256,1,288,0)
XXXX shows that the test now fails.  The location of the tag and the 
"BLD",9256,1,289,0)
comment for failure are shown in the order of the tests.
"BLD",9256,1,290,0)
 
"BLD",9256,1,291,0)
 
"BLD",9256,1,292,0)
>D XXXX
"BLD",9256,1,293,0)
Referenced routine XXXY not found.
"BLD",9256,1,294,0)
Referenced routine XXXZ not found.
"BLD",9256,1,295,0)
Referenced routine XXXA not found.
"BLD",9256,1,296,0)
..
"BLD",9256,1,297,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"BLD",9256,1,298,0)
 
"BLD",9256,1,299,0)
 
"BLD",9256,1,300,0)
Ran 1 Routine, 4 Entry Tags
"BLD",9256,1,301,0)
Checked 3 tests, with 1 failure and encountered 0 errors.
"BLD",9256,1,302,0)
>
"BLD",9256,1,303,0)
 
"BLD",9256,1,304,0)
 
"BLD",9256,1,305,0)
 
"BLD",9256,1,306,0)
Now changing the code on line ENTRY1+3 so that S X=1,Y=1 
"BLD",9256,1,307,0)
becomes  X=1,Y=1 (removing S<space> and running shows the
"BLD",9256,1,308,0)
error that is generated due to our typing, as well as continuing
"BLD",9256,1,309,0)
on to show the failure we introduced at ENTRY3.  The test at ENTRY2
"BLD",9256,1,310,0)
still runs without a problem as indicated by the lone dot.
"BLD",9256,1,311,0)
 
"BLD",9256,1,312,0)
 
"BLD",9256,1,313,0)
>D XXXX
"BLD",9256,1,314,0)
Referenced routine XXXY not found.
"BLD",9256,1,315,0)
Referenced routine XXXZ not found.
"BLD",9256,1,316,0)
Referenced routine XXXA not found.
"BLD",9256,1,317,0)
 
"BLD",9256,1,318,0)
ENTRY1^XXXX - tests addition of 1 and 1 - Error: ENTRY1+3^XXXX:1, %DSM-E-COMAND,
"BLD",9256,1,319,0)
 bad command detected
"BLD",9256,1,320,0)
.
"BLD",9256,1,321,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"BLD",9256,1,322,0)
 
"BLD",9256,1,323,0)
 
"BLD",9256,1,324,0)
Ran 1 Routine, 4 Entry Tags
"BLD",9256,1,325,0)
Checked 3 tests, with 1 failure and encountered 1 error.
"BLD",9256,1,326,0)
>
"BLD",9256,1,327,0)
 
"BLD",9256,1,328,0)
 
"BLD",9256,1,329,0)
If the code at ENTRY4+2 is now modified to S X=1+1 and running it
"BLD",9256,1,330,0)
causes the FAIL call to be used.
"BLD",9256,1,331,0)
 
"BLD",9256,1,332,0)
>D XXXX
"BLD",9256,1,333,0)
Referenced routine XXXY not found.
"BLD",9256,1,334,0)
Referenced routine XXXZ not found.
"BLD",9256,1,335,0)
Referenced routine XXXA not found.
"BLD",9256,1,336,0)
 
"BLD",9256,1,337,0)
ENTRY1^XXXX - tests addition of 1 and 1 - Error: ENTRY1+3^XXXX:1, %DSM-E-COMAND,
"BLD",9256,1,338,0)
 bad command detected
"BLD",9256,1,339,0)
.
"BLD",9256,1,340,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"BLD",9256,1,341,0)
 
"BLD",9256,1,342,0)
ENTRY4^XXXX - example of FAIL^XTMUNIT call - System is doing bad addition on 1+2
"BLD",9256,1,343,0)
 
"BLD",9256,1,344,0)
 
"BLD",9256,1,345,0)
Ran 1 Routine, 4 Entry Tags
"BLD",9256,1,346,0)
Checked 4 tests, with 2 failures and encountered 1 error.
"BLD",9256,1,347,0)
>
"BLD",9256,1,348,0)
 
"BLD",9256,1,349,0)
 
"BLD",9256,1,350,0)
 
"BLD",9256,1,351,0)
 
"BLD",9256,1,352,0)
Restoring S<space> on line ENTRY1+3, and changing X=1 to X=2 and running
"BLD",9256,1,353,0)
it shows the output of the CHKEQ call.
"BLD",9256,1,354,0)
 
"BLD",9256,1,355,0)
>d XXXX
"BLD",9256,1,356,0)
Referenced routine XXXY not found.
"BLD",9256,1,357,0)
Referenced routine XXXZ not found.
"BLD",9256,1,358,0)
Referenced routine XXXA not found.
"BLD",9256,1,359,0)
 
"BLD",9256,1,360,0)
ENTRY1^XXXX - tests addition of 1 and 1 - <2> vs <3> - 1+1 didn't yield 2
"BLD",9256,1,361,0)
.
"BLD",9256,1,362,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"BLD",9256,1,363,0)
 
"BLD",9256,1,364,0)
ENTRY4^XXXX - example of FAIL^XTMUNIT call - System is doing bad addition on 1+2
"BLD",9256,1,365,0)
 
"BLD",9256,1,366,0)
 
"BLD",9256,1,367,0)
Ran 1 Routine, 4 Entry Tags
"BLD",9256,1,368,0)
Checked 4 tests, with 3 failures and encountered 0 errors.
"BLD",9256,1,369,0)
>
"BLD",9256,1,370,0)
 
"BLD",9256,1,371,0)
 
"BLD",9256,1,372,0)
 
"BLD",9256,1,373,0)
That covers the basics of generating a unit test routine to use with XTMUNIT.
"BLD",9256,1,374,0)
For sections of code which perform calculations, etc., this is all that will
"BLD",9256,1,375,0)
be required.  For other cases dependent upon database interactions, or of
"BLD",9256,1,376,0)
input and output via something like the RPCBroker, other approaches to 
"BLD",9256,1,377,0)
creating usable tests are required.  The use of 'objects' which can be used
"BLD",9256,1,378,0)
for consistency in such units tests are generally referred to as 'Mock 
"BLD",9256,1,379,0)
Objects'.
"BLD",9256,1,380,0)
 
"BLD",9256,1,381,0)
You do not want to include any code which requires user input.  You want the
"BLD",9256,1,382,0)
tests to be able to run completely without any user intervention other than
"BLD",9256,1,383,0)
starting them.  By referencing other related unit test routines within the
"BLD",9256,1,384,0)
one that is started, you can build suites of tests that can be used to cover
"BLD",9256,1,385,0)
the full range of your code.
"BLD",9256,1,386,0)
 
"BLD",9256,1,387,0)
Supported References in XTMUNIT are EN, RUNSET, CHKTF, CHKEQ, and FAIL. 
"BLD",9256,1,388,0)
 
"BLD",9256,1,389,0)
The  entry point EN^XTMUNIT(ROUNAME) starts the unit testing process.  The
"BLD",9256,1,390,0)
argument is the name of the routine where the testing should be started.  
"BLD",9256,1,391,0)
That routine must have at least one TAG or entry point and entry points 
"BLD",9256,1,392,0)
are specified in the line following the tag XTENT as the third semi-colon 
"BLD",9256,1,393,0)
piece on the line OR it can have tags with @TEST on the comment next to the tag. 
"BLD",9256,1,394,0)
 
"BLD",9256,1,395,0)
The test is performed on a conditional value by calling the entry point 
"BLD",9256,1,396,0)
CHKTF^XTMUNIT(testval,messag) with the first argument the conditional test 
"BLD",9256,1,397,0)
value (true or false) and the second argument a message that should be 
"BLD",9256,1,398,0)
displayed indicating what failed in the test.
"BLD",9256,1,399,0)
 
"BLD",9256,1,400,0)
The test is performed by checking two values for equivalence using the entry
"BLD",9256,1,401,0)
point CHKEQ^XTMUNIT(expected,actual,messag) with the first argument the 
"BLD",9256,1,402,0)
expected value, the second argument the actual value, and the third argument 
"BLD",9256,1,403,0)
the message for display on failure.
"BLD",9256,1,404,0)
 
"BLD",9256,1,405,0)
The entry point FAIL^XTMUNIT(messag) is used to simply generate a failure 
"BLD",9256,1,406,0)
with the argument as the message to be displayed for the failure.
"BLD",9256,1,407,0)
 
"BLD",9256,1,408,0)
For those who have problems keeping track of routine names for unit testing 
"BLD",9256,1,409,0)
and which application they are associated with, we have created a new file 
"BLD",9256,1,410,0)
(MUNIT TEST GROUP, #8992.8) which can be used to maintain groups of unit 
"BLD",9256,1,411,0)
test routines with the edit option "XTMUNIT GROUP EDIT" (MUnit Test Group 
"BLD",9256,1,412,0)
Edit).  These may be run from an option ("XTMUNIT GROUP RUN", Run MUnit Tests
"BLD",9256,1,413,0)
from Test Groups), from the a Supported Reference [D RUNSET^XTMUNIT(setname)],
"BLD",9256,1,414,0)
or from the GUI client described below (click the 'Select Group' button).
"BLD",9256,1,415,0)
 
"BLD",9256,1,416,0)
 
"BLD",9256,1,417,0)
 
"BLD",9256,1,418,0)
 
"BLD",9256,1,419,0)
****** XTMRPRNT -- a routine lister for capturing and copying routines
"BLD",9256,1,420,0)
 
"BLD",9256,1,421,0)
XTMRPRNT is a small utility routine for generating listings of routines that 
"BLD",9256,1,422,0)
can usually be captured, loaded into a text editor, edited if necessary and 
"BLD",9256,1,423,0)
subsequently copied and pasted into another account or back into the original
"BLD",9256,1,424,0)
account.  A ZREMOVE command precedes each routine, and a ZSAVE command with 
"BLD",9256,1,425,0)
the routine name follows each routine.  On some system and terminal emulator
"BLD",9256,1,426,0)
combinations, the initial tab line-start character may be captured as a space
"BLD",9256,1,427,0)
and this then requires additional work to use the routine for rapid copying.
"BLD",9256,1,428,0)
 
"BLD",9256,1,429,0)
 
"BLD",9256,1,430,0)
usage
"BLD",9256,1,431,0)
 
"BLD",9256,1,432,0)
D ^XTMRPRNT
"BLD",9256,1,433,0)
 
"BLD",9256,1,434,0)
routine(s) ?   >   XTM*
"BLD",9256,1,435,0)
searching directory ...
"BLD",9256,1,436,0)
routine(s) ?   >
"BLD",9256,1,437,0)
 
"BLD",9256,1,438,0)
ENTER RETURN TO START:
"BLD",9256,1,439,0)
ZR
"BLD",9256,1,440,0)
XTMLOG  ;JLI/FO-OAK - M LOGGING UTILITY ;9/25/03  7:48
"BLD",9256,1,441,0)
....
"BLD",9256,1,442,0)
<listing of routines ommitted>
"BLD",9256,1,443,0)
....
"BLD",9256,1,444,0)
ZS XTMUNIT
"BLD",9256,1,445,0)
 
"BLD",9256,1,446,0)
>
"BLD",9256,1,447,0)
 
"BLD",9256,1,448,0)
At the prompt for routines enter the routine set that you want to capture.
"BLD",9256,1,449,0)
At the prompt to ENTER RETURN TO START start the capture process then enter
"BLD",9256,1,450,0)
RETURN to start the listing.  At the programmer prompt following the listing
"BLD",9256,1,451,0)
terminate the capture process.  In a text editor you may want to remove the
"BLD",9256,1,452,0)
trailing '>' character, although it doesn't normally cause much problem.
"BLD",9256,1,453,0)
 
"BLD",9256,1,454,0)
 
"BLD",9256,1,455,0)
******  MUnit.exe
"BLD",9256,1,456,0)
 
"BLD",9256,1,457,0)
 
"BLD",9256,1,458,0)
 
"BLD",9256,1,459,0)
The GUI interface for XTMUNIT is available as a zip file (XT_7_3_81.zip) from 
"BLD",9256,1,460,0)
the anonymous directories (see belww).  It should be saved and the file 
"BLD",9256,1,461,0)
unzipped into any desired directory.  If desired a shortcut can be set up to 
"BLD",9256,1,462,0)
start MUnit.exe and this shortcut may contain specifications for a server and
"BLD",9256,1,463,0)
port (e.g, munit.exe s=server.med.va.gov p=9200).
"BLD",9256,1,464,0)
 
"BLD",9256,1,465,0)
Start the application either by double clicking on it or the shortcut.  
"BLD",9256,1,466,0)
 
"BLD",9256,1,467,0)
Select or Change the server/port specifications if necessary, and click on 
"BLD",9256,1,468,0)
the 'Connect' button.
"BLD",9256,1,469,0)
 
"BLD",9256,1,470,0)
Enter the name (case sensitive) of the primary routine to be used for unit 
"BLD",9256,1,471,0)
testing, or click on the 'Select Group' button to select an entry in the 
"BLD",9256,1,472,0)
MUnit Test Group file (#8992.8).
"BLD",9256,1,473,0)
 
"BLD",9256,1,474,0)
Click on the 'List' button and the routines and entry points for testing will
"BLD",9256,1,475,0)
be listed (this happens automatically if an entry in the MUnit Test Group file
"BLD",9256,1,476,0)
was selected).
"BLD",9256,1,477,0)
 
"BLD",9256,1,478,0)
Click on the 'Run' button and the tests will be run.
"BLD",9256,1,479,0)
 
"BLD",9256,1,480,0)
A colored band will appear - Green if all of the tests run without problem, 
"BLD",9256,1,481,0)
and Red if any test fails or any errors are encountered.
"BLD",9256,1,482,0)
 
"BLD",9256,1,483,0)
The results are summarized below the Run button: 'Tags' shows the number 
"BLD",9256,1,484,0)
of entry points called; 'Tests' shows the number of tests that were actually 
"BLD",9256,1,485,0)
performed (there may be more than one test per entry point); 'Errors' shows 
"BLD",9256,1,486,0)
the number of errors (non-expected code errors) encountered; 'Failed' shows 
"BLD",9256,1,487,0)
the number of failed tests encountered; and 'Elapsed' indicates the time it 
"BLD",9256,1,488,0)
took to perform all of the tests.
"BLD",9256,1,489,0)
 
"BLD",9256,1,490,0)
After the tests, the first page (labeled 'Test Hierarchy') listing the 
"BLD",9256,1,491,0)
routines and entry points will show Red (failed), Red-Brown (errors) or Green 
"BLD",9256,1,492,0)
(no problem) by each entry point or tag.  Routines will show Red (failed or 
"BLD",9256,1,493,0)
errors) and Green (no problem).
"BLD",9256,1,494,0)
 
"BLD",9256,1,495,0)
If any errors or failures are encountered, the second page 'Failures/Errors' 
"BLD",9256,1,496,0)
will list the entrypoint tag^routine, whether it was an error or failure, and 
"BLD",9256,1,497,0)
either the failure message entered in the call for the test that failed, or 
"BLD",9256,1,498,0)
the error message for an error.
"BLD",9256,1,499,0)
 
"BLD",9256,1,500,0)
After changes to the routines being tested, the 'Run' button can be clicked 
"BLD",9256,1,501,0)
again, or, if additional test entry points are added, the 'List' and 'Run' 
"BLD",9256,1,502,0)
buttons clicked to update the results.  If 'Select Groups' button was used 
"BLD",9256,1,503,0)
to identify the unit tests to be run, the button caption will have changed 
"BLD",9256,1,504,0)
to 'Clear Groups.'  This should be pressed to select a new group, or to enter
"BLD",9256,1,505,0)
a unit test routine name.
"BLD",9256,1,506,0)
 
"BLD",9256,1,507,0)
 
"BLD",9256,1,508,0)
 
"BLD",9256,1,509,0)
   The XTMLOG* routines provide a Log4M capability similar to Log4J.  The 
"BLD",9256,1,510,0)
logging commands can be embedded in the code and activated by initializing 
"BLD",9256,1,511,0)
logging in one of several different ways.  Otherwise, the logging commands 
"BLD",9256,1,512,0)
are checked and then ignored.
"BLD",9256,1,513,0)
 
"BLD",9256,1,514,0)
   Logging can lead to massive amounts of data, especially if the process 
"BLD",9256,1,515,0)
being logged is used by a number of users.  To reduce this, LOG4M for a given
"BLD",9256,1,516,0)
task can be limited to specific users if desired by setting up the USER 
"BLD",9256,1,517,0)
FILTER.  Also, while the process which logging is being performed on may have
"BLD",9256,1,518,0)
logging in a number of routines, but using the ROUTINE filter, a set of
"BLD",9256,1,519,0)
specific routines may be specified for which logging will be performed.
"BLD",9256,1,520,0)
 
"BLD",9256,1,521,0)
XTMLOG can be used to output a simple message: 
"BLD",9256,1,522,0)
 
"BLD",9256,1,523,0)
   D INFO^XTMLOG("ENTERED CHKWATCH")
"BLD",9256,1,524,0)
   
"BLD",9256,1,525,0)
will result in an output similar to
"BLD",9256,1,526,0)
 
"BLD",9256,1,527,0)
   20080207.145617 INFO CHKWATCH+3 XTDEBUG5 - ENTERED CHKWATCH
"BLD",9256,1,528,0)
   
"BLD",9256,1,529,0)
   
"BLD",9256,1,530,0)
XTMLOG can be used to output a message along with values for one or more
"BLD",9256,1,531,0)
comma separated variables
"BLD",9256,1,532,0)
 
"BLD",9256,1,533,0)
   D DEBUG^XTMLOG("DATA1","VALUE1,VALUE2")
"BLD",9256,1,534,0)
   
"BLD",9256,1,535,0)
   20080207.145617 DEBUG COMMANDS+11 XTDEBUG1 - DATA1 - VALUE1: 0
"BLD",9256,1,536,0)
   20080207.145617 DEBUG COMMANDS+11 XTDEBUG1 - DATA1 - VALUE2: XVAL=XTDEBV(1)
"BLD",9256,1,537,0)
 
"BLD",9256,1,538,0)
   
"BLD",9256,1,539,0)
XTMLOG can be used to output a message and values for variables including
"BLD",9256,1,540,0)
array values for the variables if they exist.
"BLD",9256,1,541,0)
 
"BLD",9256,1,542,0)
   D DEBUG^XTMLOG("DATA2","VALUE1,VALUE2,VALUE3,^TMP($J,""DATA"")",1)
"BLD",9256,1,543,0)
 
"BLD",9256,1,544,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE1: 3
"BLD",9256,1,545,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2: XVAL=XTDEBV(1)
"BLD",9256,1,546,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2("NEW"): 15
"BLD",9256,1,547,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2("OLD",1): 
"BLD",9256,1,548,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE3: <UNDEFINED>
"BLD",9256,1,549,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - ^TMP($J,"DATA",1): LAST,FIRST M
"BLD",9256,1,550,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - ^TMP($J,"DATA",2): 04/01/2001
"BLD",9256,1,551,0)
   
"BLD",9256,1,552,0)
 
"BLD",9256,1,553,0)
   The best way to control logging is through an entry in the LOG4M CONFIG 
"BLD",9256,1,554,0)
file (#8992.7).  
"BLD",9256,1,555,0)
 
"BLD",9256,1,556,0)
The NAME field (#.01) for an entry is used to control logging.  The NAME of 
"BLD",9256,1,557,0)
an entry (e.g., XTEXAMPLE) can be referenced in the initialization process 
"BLD",9256,1,558,0)
and if the file entry does not exist, the logging is not activated.  If the   
"BLD",9256,1,559,0)
If the entry exists and the ACTIVE field (#.02) is set to NO, logging will not 
"BLD",9256,1,560,0)
be activated.  Otherwise logging as instructed by the settings for this entry 
"BLD",9256,1,561,0)
will be activated for the current job, until logging for the entry is 
"BLD",9256,1,562,0)
terminated.  
"BLD",9256,1,563,0)
 
"BLD",9256,1,564,0)
  An XTMEXAMPLE entry could be created in the LOG4M CONFIG file.  It would 
"BLD",9256,1,565,0)
then be activated in the code, processing performed, and the logging turned
"BLD",9256,1,566,0)
off as in the example below.
"BLD",9256,1,567,0)
  
"BLD",9256,1,568,0)
  S X=$$FILEINIT^XTMLOG("XTMEXAMPLE")
"BLD",9256,1,569,0)
  D PROCESSING
"BLD",9256,1,570,0)
  D ENDLOG^XTMLOG("XTMEXAMPLE")
"BLD",9256,1,571,0)
 
"BLD",9256,1,572,0)
  If the XTMEXAMPLE entry does not exist in the LOG4M CONFIG file, logging will
"BLD",9256,1,573,0)
not be turned on.  If the XTMEXAMPLE entry does exist, the value of the 
"BLD",9256,1,574,0)
ACTIVE field (#.02) is checked, and if it is not specified or NO, logging 
"BLD",9256,1,575,0)
will not be turned on.
"BLD",9256,1,576,0)
 
"BLD",9256,1,577,0)
  If the ACTIVE field of the XTMEXAMPLE entry is E for YES, EASY CONFIG, 
"BLD",9256,1,578,0)
logging will be activated based on the values in the EASY ENTRY (#.03) and 
"BLD",9256,1,579,0)
EASY LEVEL (#.04) fields. [The alternative to the E or YES, EASY CONFIG for
"BLD",9256,1,580,0)
active logging is D or YES, DETAILED CONFIG which permits the user to specify
"BLD",9256,1,581,0)
a text based configuration, similar to that used for Log4J and Java, in a
"BLD",9256,1,582,0)
word processing field (DETAILED CONFIG field (#1)).  This alternative was 
"BLD",9256,1,583,0)
originally based on the use of config files for Log4J, but it is recommended 
"BLD",9256,1,584,0)
that the EASY CONFIG be used instead.]
"BLD",9256,1,585,0)
 
"BLD",9256,1,586,0)
  The EASY ENTRY field (#.03) can be used to easily specify the type(s) of 
"BLD",9256,1,587,0)
logging desired.  The value is a text string with semi-colon separated 
"BLD",9256,1,588,0)
specifiers for logging modes.
"BLD",9256,1,589,0)
 
"BLD",9256,1,590,0)
   C - indicates logging to the user's console.  Logging messages are sent 
"BLD",9256,1,591,0)
       to the console as they are generated. 
"BLD",9256,1,592,0)
   G - indicates logging to a global location and is followed by a comma 
"BLD",9256,1,593,0)
       and an identifer for the global location under ^XTMP("XTMLOG", [e.g., 
"BLD",9256,1,594,0)
       G,TEST4 would result in data being stored under the global location
"BLD",9256,1,595,0)
       ^XTMP("TEST4",DUZ,yymmdd.hhmmss,$J, where DUZ is the internal entry
"BLD",9256,1,596,0)
       number for the user in the NEW PERSON file (#200), and yymmdd.hhmmss is
"BLD",9256,1,597,0)
       the date and time the logging was initialized, and $J is the job number
"BLD",9256,1,598,0)
       of the user's process].  When logging is initialized for a subscript,
"BLD",9256,1,599,0)
       such as TEST4, the lifetime for the ^XTMP("TEST4" global is set or 
"BLD",9256,1,600,0)
       updated to a week from the current date.
"BLD",9256,1,601,0)
       
"BLD",9256,1,602,0)
  The EASY LEVEL field (#.04) can be used to specify the level of logging 
"BLD",9256,1,603,0)
desired.  The highest level (with respect to usual urgency) is FATAL.  
"BLD",9256,1,604,0)
The lowest level (again with respect to usual urgency) is DEBUG.  
"BLD",9256,1,605,0)
Between these two extremes are (in decreasing order of usual urgency) ERROR, 
"BLD",9256,1,606,0)
WARN, and INFO.  Choosing a specific level (e.g., INFO) will include all 
"BLD",9256,1,607,0)
higher levels as well (e.g., for INFO, any logging calls with a level of 
"BLD",9256,1,608,0)
FATAL, ERROR, WARN or INFO would be output).
"BLD",9256,1,609,0)
 
"BLD",9256,1,610,0)
 
"BLD",9256,1,611,0)
The ROUTINE FILTER field (#.05) may be used to control the routines which 
"BLD",9256,1,612,0)
logging is active in.  These controls permit the amount of 
"BLD",9256,1,613,0)
data logged to the system to be maintained at a reasonable amount, even if 
"BLD",9256,1,614,0)
a large number of users are actively using the code which is being logged.
"BLD",9256,1,615,0)
 
"BLD",9256,1,616,0)
If data has been entered in the USER FILTER field (#.06), logging will only 
"BLD",9256,1,617,0)
be activated for users whose internal entry number in file 200 are included 
"BLD",9256,1,618,0)
in the USER FILTER field.  
"BLD",9256,1,619,0)
 
"BLD",9256,1,620,0)
Specialized fields, which would not normally be required, bur are available, 
"BLD",9256,1,621,0)
are 
"BLD",9256,1,622,0)
 
"BLD",9256,1,623,0)
^DD(8992.7,.01,0)=NAME^RF^^0;1^K:$L(X)>30!(X?.N)!($L(X)<3)!'(X'?1P.E) X
"BLD",9256,1,624,0)
^DD(8992.7,.02,0)=ACTIVE^RS^N:NO;E:YES, EASY CONFIG;D:YES, DETAILED CONFIG;^0;2^
"BLD",9256,1,625,0)
Q
"BLD",9256,1,626,0)
^DD(8992.7,.03,0)=EZ ENTRY^F^^0;3^K:$L(X)>40!($L(X)<1) X
"BLD",9256,1,627,0)
^DD(8992.7,.04,0)=EZ LEVEL^S^FATAL:FATAL;ERROR:ERROR;WARN:WARN;INFO:INFO;DEBUG:D
"BLD",9256,1,628,0)
EBUG;^0;4^Q
"BLD",9256,1,629,0)
^DD(8992.7,.05,0)=ROUTINE FILTER^F^^0;5^K:$L(X)>80!($L(X)<3) X
"BLD",9256,1,630,0)
^DD(8992.7,.06,0)=USER FILTER^F^^0;6^K:$L(X)>60!($L(X)<1) X
"BLD",9256,1,631,0)
^DD(8992.7,.07,0)=OUTPUT ON CLOSE^S^N:NONE;P:PRINTER;M:MAIL MESSAGE;^0;7^Q
"BLD",9256,1,632,0)
^DD(8992.7,.08,0)=OUTPUT SPECS^F^^0;8^K:$L(X)>25!($L(X)<1) X
"BLD",9256,1,633,0)
^DD(8992.7,1,0)=DETAILED CONFIG^8992.71^^1;0
"BLD",9256,1,634,0)
^DD(8992.7,2.01,0)=PRINT LAYOUT^F^^2;1^K:$L(X)>40!($L(X)<5) X
"BLD",9256,4,0)
^9.64PA^8992.7^2
"BLD",9256,4,8992.7,0)
8992.7
"BLD",9256,4,8992.7,222)
y^y^f^^^^n
"BLD",9256,4,8992.8,0)
8992.8
"BLD",9256,4,8992.8,222)
y^y^f^^n^^y^m^n
"BLD",9256,4,"B",8992.7,8992.7)

"BLD",9256,4,"B",8992.8,8992.8)

"BLD",9256,6.3)
26
"BLD",9256,"KRN",0)
^9.67PA^8989.52^19
"BLD",9256,"KRN",.4,0)
.4
"BLD",9256,"KRN",.401,0)
.401
"BLD",9256,"KRN",.402,0)
.402
"BLD",9256,"KRN",.403,0)
.403
"BLD",9256,"KRN",.5,0)
.5
"BLD",9256,"KRN",.84,0)
.84
"BLD",9256,"KRN",3.6,0)
3.6
"BLD",9256,"KRN",3.8,0)
3.8
"BLD",9256,"KRN",9.2,0)
9.2
"BLD",9256,"KRN",9.8,0)
9.8
"BLD",9256,"KRN",9.8,"NM",0)
^9.68A^8^8
"BLD",9256,"KRN",9.8,"NM",1,0)
XTMRPRNT^^0^B1220842
"BLD",9256,"KRN",9.8,"NM",2,0)
XTMLOG^^0^B136006720
"BLD",9256,"KRN",9.8,"NM",3,0)
XTMUNIT^^0^B229505353
"BLD",9256,"KRN",9.8,"NM",4,0)
XTMLOG1^^0^B46831784
"BLD",9256,"KRN",9.8,"NM",5,0)
XTMLOG2^^1^
"BLD",9256,"KRN",9.8,"NM",6,0)
XTMLOPAR^^0^B19404303
"BLD",9256,"KRN",9.8,"NM",7,0)
XTMLOSKT^^0^B36861478
"BLD",9256,"KRN",9.8,"NM",8,0)
XTMUNIT1^^0^B8661103
"BLD",9256,"KRN",9.8,"NM","B","XTMLOG",2)

"BLD",9256,"KRN",9.8,"NM","B","XTMLOG1",4)

"BLD",9256,"KRN",9.8,"NM","B","XTMLOG2",5)

"BLD",9256,"KRN",9.8,"NM","B","XTMLOPAR",6)

"BLD",9256,"KRN",9.8,"NM","B","XTMLOSKT",7)

"BLD",9256,"KRN",9.8,"NM","B","XTMRPRNT",1)

"BLD",9256,"KRN",9.8,"NM","B","XTMUNIT",3)

"BLD",9256,"KRN",9.8,"NM","B","XTMUNIT1",8)

"BLD",9256,"KRN",19,0)
19
"BLD",9256,"KRN",19,"NM",0)
^9.68A^3^3
"BLD",9256,"KRN",19,"NM",1,0)
XTMUNIT^^0
"BLD",9256,"KRN",19,"NM",2,0)
XTMUNIT GROUP EDIT^^0
"BLD",9256,"KRN",19,"NM",3,0)
XTMUNIT GROUP RUN^^0
"BLD",9256,"KRN",19,"NM","B","XTMUNIT",1)

"BLD",9256,"KRN",19,"NM","B","XTMUNIT GROUP EDIT",2)

"BLD",9256,"KRN",19,"NM","B","XTMUNIT GROUP RUN",3)

"BLD",9256,"KRN",19.1,0)
19.1
"BLD",9256,"KRN",101,0)
101
"BLD",9256,"KRN",409.61,0)
409.61
"BLD",9256,"KRN",771,0)
771
"BLD",9256,"KRN",870,0)
870
"BLD",9256,"KRN",8989.51,0)
8989.51
"BLD",9256,"KRN",8989.52,0)
8989.52
"BLD",9256,"KRN",8994,0)
8994
"BLD",9256,"KRN",8994,"NM",0)
^9.68A^3^3
"BLD",9256,"KRN",8994,"NM",1,0)
XTMUNIT-TEST LOAD^^0
"BLD",9256,"KRN",8994,"NM",2,0)
XTMUNIT-TEST NEXT^^0
"BLD",9256,"KRN",8994,"NM",3,0)
XTMUNIT-TEST GROUP LOAD^^0
"BLD",9256,"KRN",8994,"NM","B","XTMUNIT-TEST GROUP LOAD",3)

"BLD",9256,"KRN",8994,"NM","B","XTMUNIT-TEST LOAD",1)

"BLD",9256,"KRN",8994,"NM","B","XTMUNIT-TEST NEXT",2)

"BLD",9256,"KRN","B",.4,.4)

"BLD",9256,"KRN","B",.401,.401)

"BLD",9256,"KRN","B",.402,.402)

"BLD",9256,"KRN","B",.403,.403)

"BLD",9256,"KRN","B",.5,.5)

"BLD",9256,"KRN","B",.84,.84)

"BLD",9256,"KRN","B",3.6,3.6)

"BLD",9256,"KRN","B",3.8,3.8)

"BLD",9256,"KRN","B",9.2,9.2)

"BLD",9256,"KRN","B",9.8,9.8)

"BLD",9256,"KRN","B",19,19)

"BLD",9256,"KRN","B",19.1,19.1)

"BLD",9256,"KRN","B",101,101)

"BLD",9256,"KRN","B",409.61,409.61)

"BLD",9256,"KRN","B",771,771)

"BLD",9256,"KRN","B",870,870)

"BLD",9256,"KRN","B",8989.51,8989.51)

"BLD",9256,"KRN","B",8989.52,8989.52)

"BLD",9256,"KRN","B",8994,8994)

"BLD",9256,"QDEF")
^^^^NO^^^^NO^^NO
"BLD",9256,"QUES",0)
^9.62^^
"BLD",9256,"REQB",0)
^9.611^^
"DATA",8992.8,1,0)
XLFCRC
"DATA",8992.8,1,1,0)
^8992.81^1^1
"DATA",8992.8,1,1,1,0)
ZZMTXLF9
"DATA",8992.8,2,0)
XLFDT
"DATA",8992.8,2,1,0)
^8992.81^4^2
"DATA",8992.8,2,1,1,0)
ZZMTXLF
"DATA",8992.8,2,1,4,0)
ZZMTXLF1
"DATA",8992.8,3,0)
XQAL ALERTS
"DATA",8992.8,3,1,0)
^8992.81^5^5
"DATA",8992.8,3,1,1,0)
ZZUTXQA2
"DATA",8992.8,3,1,2,0)
ZZUTXQA1
"DATA",8992.8,3,1,3,0)
ZZUTXQA3
"DATA",8992.8,3,1,4,0)
ZZUTXQA4
"DATA",8992.8,3,1,5,0)
ZZUTXQA5
"DATA",8992.8,3,2,0)
^8992.82^1^1^3120518^^
"DATA",8992.8,3,2,1,0)
Entry point to run all unit test routines: D ^ZZUTXQA1
"DATA",8992.8,4,0)
XTMRPAR SET
"DATA",8992.8,4,1,0)
^8992.81^2^2
"DATA",8992.8,4,1,1,0)
ZZUTXTM1
"DATA",8992.8,4,1,2,0)
ZZUTXTM2
"DATA",8992.8,5,0)
XLF LIBRARY
"DATA",8992.8,5,1,0)
^8992.81^1^1
"DATA",8992.8,5,1,1,0)
ZZMTXLF
"DATA",8992.8,6,0)
XPAR
"DATA",8992.8,6,1,0)
^8992.81^1^1
"DATA",8992.8,6,1,1,0)
ZZMYXPAR
"DATA",8992.8,6,2,0)
^^3^3^3040701^
"DATA",8992.8,6,2,1,0)
This routine will test the basic calls to XPAR.
"DATA",8992.8,6,2,2,0)
Before a fix is added a new test should be added to show the error and 
"DATA",8992.8,6,2,3,0)
fix.
"DATA",8992.8,7,0)
XML UNIT TEST
"DATA",8992.8,7,1,0)
^8992.81^1^1
"DATA",8992.8,7,1,1,0)
ZZMTXML
"DATA",8992.8,7,2,0)
^^1^1^3050106^
"DATA",8992.8,7,2,1,0)
This runs a set of tests on the MXMLPRSE routines.
"DATA",8992.8,8,0)
XLFSTR
"DATA",8992.8,8,1,0)
^8992.81^1^1
"DATA",8992.8,8,1,1,0)
ZZMTXLF8
"DATA",8992.8,8,2,0)
^^1^1^3060112^
"DATA",8992.8,8,2,1,0)
This will do unit tests on the API's in XLFSTR.
"DATA",8992.8,9,0)
XTDEBUG
"DATA",8992.8,9,1,0)
^8992.81^1^1
"DATA",8992.8,9,1,1,0)
ZZUTXTD1
"DATA",8992.8,9,2,0)
^^1^1^3080117^
"DATA",8992.8,9,2,1,0)
These are tests related to the M-Debugger for Eclipse (XTDEBUG*).
"DATA",8992.8,10,0)
Log4M
"DATA",8992.8,10,1,0)
^8992.81^4^4
"DATA",8992.8,10,1,1,0)
ZZUTXTL1
"DATA",8992.8,10,1,2,0)
ZZUTXTL2
"DATA",8992.8,10,1,3,0)
ZZUTXTL3
"DATA",8992.8,10,1,4,0)
ZZUTXTL4
"DATA",8992.8,10,2,0)
^^1^1^3080220^
"DATA",8992.8,10,2,1,0)
This tests the Log4M tool.
"DATA",8992.8,11,0)
XLFNAME
"DATA",8992.8,11,1,0)
^8992.81^1^1
"DATA",8992.8,11,1,1,0)
ZZUTNAME
"DATA",8992.8,11,2,0)
^^1^1^3081118^
"DATA",8992.8,11,2,1,0)
This is to test changes to the XLFNAME standardization code.
"DATA",8992.8,12,0)
USER NETNAME
"DATA",8992.8,12,1,0)
^8992.81^1^1
"DATA",8992.8,12,1,1,0)
ZZMTUSR1
"DATA",8992.8,12,2,0)
^^1^1^3090930^
"DATA",8992.8,12,2,1,0)
Do unit test on the NETNM^XUSER1.
"DATA",8992.8,13,0)
XQ MENU MANAGER
"DATA",8992.8,13,1,0)
^8992.81^2^2
"DATA",8992.8,13,1,1,0)
ZZUTXQ12
"DATA",8992.8,13,1,2,0)
ZZUTXQ00
"DATA",8992.8,13,2,0)
^^1^1^3120518^
"DATA",8992.8,13,2,1,0)
Entry point D ^ZZUTXQ00
"DATA",8992.8,14,0)
ZI DEVICE HANDLER
"DATA",8992.8,14,1,0)
^8992.81^1^1
"DATA",8992.8,14,1,1,0)
ZZUTZI00
"DATA",8992.8,14,2,0)
^^1^1^3120518^
"DATA",8992.8,14,2,1,0)
Entry point D ^ZZUTZI00
"DATA",8992.8,15,0)
XU BSE
"DATA",8992.8,15,1,0)
^8992.81^1^1
"DATA",8992.8,15,1,1,0)
ZZUTXU00
"DATA",8992.8,15,2,0)
^^2^2^3120601^
"DATA",8992.8,15,2,1,0)
Broker Security Enhancement
"DATA",8992.8,15,2,2,0)
D ^ZZUTXU00
"DATA",8992.8,16,0)
XLFIPV
"DATA",8992.8,16,1,0)
^8992.81^1^1
"DATA",8992.8,16,1,1,0)
ZZUTXL00
"DATA",8992.8,16,2,0)
^^1^1^3120806^
"DATA",8992.8,16,2,1,0)
IPv4 and IPv6 utilities.
"DATA",8992.8,17,0)
SINGLE SIGN ON UTILITIES
"DATA",8992.8,17,1,0)
^8992.81^1^1
"DATA",8992.8,17,1,1,0)
ZZUTESSO
"FIA",8992.7)
LOG4M CONFIG
"FIA",8992.7,0)
^XTV(8992.7,
"FIA",8992.7,0,0)
8992.7
"FIA",8992.7,0,1)
y^y^f^^^^n
"FIA",8992.7,0,10)

"FIA",8992.7,0,11)

"FIA",8992.7,0,"RLRO")

"FIA",8992.7,0,"VR")
7.3^XT
"FIA",8992.7,8992.7)
0
"FIA",8992.7,8992.71)
0
"FIA",8992.8)
M UNIT TEST GROUP
"FIA",8992.8,0)
^XTV(8992.8,
"FIA",8992.8,0,0)
8992.8
"FIA",8992.8,0,1)
y^y^f^^n^^y^m^n
"FIA",8992.8,0,10)

"FIA",8992.8,0,11)

"FIA",8992.8,0,"RLRO")

"FIA",8992.8,0,"VR")
7.3^XT
"FIA",8992.8,8992.8)
0
"FIA",8992.8,8992.81)
0
"FIA",8992.8,8992.82)
0
"KRN",19,11463,-1)
0^1
"KRN",19,11463,0)
XTMUNIT^M Unit Tester^^B^^^^^^^^TOOLKIT
"KRN",19,11463,"RPC",0)
^19.05P^3^3
"KRN",19,11463,"RPC",1,0)
XTMUNIT-TEST LOAD
"KRN",19,11463,"RPC",2,0)
XTMUNIT-TEST NEXT
"KRN",19,11463,"RPC",3,0)
XTMUNIT-TEST GROUP LOAD
"KRN",19,11463,"U")
M UNIT TESTER
"KRN",19,11464,-1)
0^2
"KRN",19,11464,0)
XTMUNIT GROUP EDIT^MUnit Test Group edit^^E^^^^^^^^TOOLKIT
"KRN",19,11464,1,0)
^19.06^6^6^3031030^^^
"KRN",19,11464,1,1,0)
This option can be used to maintain a listing of unit tests related to a 
"KRN",19,11464,1,2,0)
specific topic.  The Group identifies the topic, and the unit tests 
"KRN",19,11464,1,3,0)
related to that topic are added in the multiple.  Unit Tests can be run 
"KRN",19,11464,1,4,0)
by selecting a group, and all unit tests included in the multiple will be 
"KRN",19,11464,1,5,0)
used for the test.  In addition, any other references under the XTROU tag 
"KRN",19,11464,1,6,0)
in any of the included test routines will be included in the run.
"KRN",19,11464,30)
XTV(8992.8,
"KRN",19,11464,31)
AEMQL
"KRN",19,11464,50)
8992.8
"KRN",19,11464,51)
.01;1
"KRN",19,11464,99.1)
59472,40730
"KRN",19,11464,"U")
MUNIT TEST GROUP EDIT
"KRN",19,11465,-1)
0^3
"KRN",19,11465,0)
XTMUNIT GROUP RUN^Run MUnit Tests from Test Groups^^R^^^^^^^^TOOLKIT^^1
"KRN",19,11465,1,0)
^^2^2^3031030^
"KRN",19,11465,1,1,0)
Provides a means of initiating a unit test run from the menu system based 
"KRN",19,11465,1,2,0)
on entries in the MUNIT TEST GROUP file (#8992.8).
"KRN",19,11465,20)
S XTMUVERB=1
"KRN",19,11465,25)
PICKSET^XTMUNIT
"KRN",19,11465,99.1)
59472,49965
"KRN",19,11465,"U")
RUN MUNIT TESTS FROM TEST GROU
"KRN",8994,3100,-1)
0^1
"KRN",8994,3100,0)
XTMUNIT-TEST LOAD^GUILOAD^XTMUNIT^4^^^^1
"KRN",8994,3101,-1)
0^2
"KRN",8994,3101,0)
XTMUNIT-TEST NEXT^GUINEXT^XTMUNIT^4^^^^1
"KRN",8994,3102,-1)
0^3
"KRN",8994,3102,0)
XTMUNIT-TEST GROUP LOAD^GUISET^XTMUNIT^4^^^^1
"MBREQ")
0
"ORD",0,9.8)
9.8;;1;RTNF^XPDTA;RTNE^XPDTA
"ORD",0,9.8,0)
ROUTINE
"ORD",16,8994)
8994;16;1;;;;;;;RPCDEL^XPDIA1
"ORD",16,8994,0)
REMOTE PROCEDURE
"ORD",18,19)
19;18;;;OPT^XPDTA;OPTF1^XPDIA;OPTE1^XPDIA;OPTF2^XPDIA;;OPTDEL^XPDIA
"ORD",18,19,0)
OPTION
"PKG",5,-1)
1^1
"PKG",5,0)
TOOLKIT^XT^PROGRAMMERS OPTIONS, MULTI. TERM LOOKUP
"PKG",5,22,0)
^9.49I^1^1
"PKG",5,22,1,0)
7.3^3051119^2960604
"PKG",5,22,1,"PAH",1,0)
81^3130726^1
"PKG",5,22,1,"PAH",1,1,0)
^^634^634^3130726
"PKG",5,22,1,"PAH",1,1,1,0)
Subject: Developer Utilities - M Unit
"PKG",5,22,1,"PAH",1,1,2,0)
 
"PKG",5,22,1,"PAH",1,1,3,0)
Category: 
"PKG",5,22,1,"PAH",1,1,4,0)
  - Routine
"PKG",5,22,1,"PAH",1,1,5,0)
  - Data Dictionary
"PKG",5,22,1,"PAH",1,1,6,0)
  - Other
"PKG",5,22,1,"PAH",1,1,7,0)
 
"PKG",5,22,1,"PAH",1,1,8,0)
Description:
"PKG",5,22,1,"PAH",1,1,9,0)
============
"PKG",5,22,1,"PAH",1,1,10,0)
 
"PKG",5,22,1,"PAH",1,1,11,0)
 This patch contains utility routines for programmers.
"PKG",5,22,1,"PAH",1,1,12,0)
   
"PKG",5,22,1,"PAH",1,1,13,0)
 XTMUNIT  - a unit tester for M code, with command line and GUI front 
"PKG",5,22,1,"PAH",1,1,14,0)
 ends.  
"PKG",5,22,1,"PAH",1,1,15,0)
   
"PKG",5,22,1,"PAH",1,1,16,0)
 XTMRPRNT - a routine lister that makes it easy to copy and paste 
"PKG",5,22,1,"PAH",1,1,17,0)
 routines.  
"PKG",5,22,1,"PAH",1,1,18,0)
   
"PKG",5,22,1,"PAH",1,1,19,0)
 XTMLOG,XTMLOG1,XTMLOPAR,XTMLOSKT - routines for event logging 
"PKG",5,22,1,"PAH",1,1,20,0)
 with the possibility of external control of the logging, similar to 
"PKG",5,22,1,"PAH",1,1,21,0)
 Log4J with Java.
"PKG",5,22,1,"PAH",1,1,22,0)
   
"PKG",5,22,1,"PAH",1,1,23,0)
 The patch also installs one Client/Server option (XTMUNIT, M Unit 
"PKG",5,22,1,"PAH",1,1,24,0)
 Tester) and two RPCs (XTMUNIT-TEST LOAD and XTMUNIT-TEST NEXT).
"PKG",5,22,1,"PAH",1,1,25,0)
   
"PKG",5,22,1,"PAH",1,1,26,0)
   
"PKG",5,22,1,"PAH",1,1,27,0)
 Test Sites: 
"PKG",5,22,1,"PAH",1,1,28,0)
   
"PKG",5,22,1,"PAH",1,1,29,0)
   
"PKG",5,22,1,"PAH",1,1,30,0)
   
"PKG",5,22,1,"PAH",1,1,31,0)
   
"PKG",5,22,1,"PAH",1,1,32,0)
 Blood Bank Team Coordination: 
"PKG",5,22,1,"PAH",1,1,33,0)
 =============================
"PKG",5,22,1,"PAH",1,1,34,0)
 Clearance - 
"PKG",5,22,1,"PAH",1,1,35,0)
   
"PKG",5,22,1,"PAH",1,1,36,0)
   
"PKG",5,22,1,"PAH",1,1,37,0)
   
"PKG",5,22,1,"PAH",1,1,38,0)
 The client-side software distribution includes: 
"PKG",5,22,1,"PAH",1,1,39,0)
   
"PKG",5,22,1,"PAH",1,1,40,0)
     Date      Time   Attrib    Bytes     CRC-32  Filename 
"PKG",5,22,1,"PAH",1,1,41,0)
  ---------- -------- ------ ----------- -------- --------
"PKG",5,22,1,"PAH",1,1,42,0)
  04/18/2006 11:19:20 A-----     405,694 F0A8CB7C XT_7_3_81.zip 
"PKG",5,22,1,"PAH",1,1,43,0)
   
"PKG",5,22,1,"PAH",1,1,44,0)
 SOFTWARE RETRIEVAL: 
"PKG",5,22,1,"PAH",1,1,45,0)
   
"PKG",5,22,1,"PAH",1,1,46,0)
 The software for this package is available for retrieval via FTP.  All VA
"PKG",5,22,1,"PAH",1,1,47,0)
 Medical Centers are encouraged to use the TCPIP FTP functionality to 
"PKG",5,22,1,"PAH",1,1,48,0)
 obtain the software from one of the following OI Field Office
"PKG",5,22,1,"PAH",1,1,49,0)
 ANONYMOUS.SOFTWARE directories:
"PKG",5,22,1,"PAH",1,1,50,0)
   
"PKG",5,22,1,"PAH",1,1,51,0)
        IRM Field Office          FTP Address 
"PKG",5,22,1,"PAH",1,1,52,0)
        ================          ===========
"PKG",5,22,1,"PAH",1,1,53,0)
        Albany                    ftp.fo-albany.med.va.gov 
"PKG",5,22,1,"PAH",1,1,54,0)
        Hines                     ftp.fo-hines.med.va.gov 
"PKG",5,22,1,"PAH",1,1,55,0)
        Salt Lake City            ftp.fo-slc.med.va.gov 
"PKG",5,22,1,"PAH",1,1,56,0)
        VistA Download Site       download.vista.med.va.gov 
"PKG",5,22,1,"PAH",1,1,57,0)
   
"PKG",5,22,1,"PAH",1,1,58,0)
   
"PKG",5,22,1,"PAH",1,1,59,0)
 Client Side: 
"PKG",5,22,1,"PAH",1,1,60,0)
 ============
"PKG",5,22,1,"PAH",1,1,61,0)
   
"PKG",5,22,1,"PAH",1,1,62,0)
 The following lists the files installed by unzipping XT_7_3_81.ZIP. 
"PKG",5,22,1,"PAH",1,1,63,0)
   
"PKG",5,22,1,"PAH",1,1,64,0)
     Date      Time   Attrib    Bytes     CRC-32  Filename 
"PKG",5,22,1,"PAH",1,1,65,0)
  ---------- -------- ------ ----------- -------- --------
"PKG",5,22,1,"PAH",1,1,66,0)
  04/18/2006 11:12:24 A-----     872,448 1E4B87B5 MUnit.exe 
"PKG",5,22,1,"PAH",1,1,67,0)
   
"PKG",5,22,1,"PAH",1,1,68,0)
   
"PKG",5,22,1,"PAH",1,1,69,0)
   
"PKG",5,22,1,"PAH",1,1,70,0)
 Installation Instructions: 
"PKG",5,22,1,"PAH",1,1,71,0)
   
"PKG",5,22,1,"PAH",1,1,72,0)
 1.   Users ARE allowed to be on the system during the installation.
"PKG",5,22,1,"PAH",1,1,73,0)
   
"PKG",5,22,1,"PAH",1,1,74,0)
 2.   Use the 'INSTALL/CHECK MESSAGE' option on the PackMan menu.  
"PKG",5,22,1,"PAH",1,1,75,0)
      This option will load the KIDS (Kernel Installation and Distribution
"PKG",5,22,1,"PAH",1,1,76,0)
      System) package onto your system.  
"PKG",5,22,1,"PAH",1,1,77,0)
   
"PKG",5,22,1,"PAH",1,1,78,0)
 3.   You DO NOT need to stop TaskMan or the background filers.  
"PKG",5,22,1,"PAH",1,1,79,0)
   
"PKG",5,22,1,"PAH",1,1,80,0)
 4.   The patch has now been loaded into a transport global on your 
"PKG",5,22,1,"PAH",1,1,81,0)
      system.  On the KIDS menu, select the 'Installation' menu and use 
"PKG",5,22,1,"PAH",1,1,82,0)
      the following options: 
"PKG",5,22,1,"PAH",1,1,83,0)
             Verify Checksums in Transport Global 
"PKG",5,22,1,"PAH",1,1,84,0)
             Print Transport Global 
"PKG",5,22,1,"PAH",1,1,85,0)
             Compare Transport Global to Current System 
"PKG",5,22,1,"PAH",1,1,86,0)
             Backup a Transport Global 
"PKG",5,22,1,"PAH",1,1,87,0)
   
"PKG",5,22,1,"PAH",1,1,88,0)
             Return to Programmers Prompt and use "D ^XPDKRN": 
"PKG",5,22,1,"PAH",1,1,89,0)
             Select KIDS OPTION: Install 
"PKG",5,22,1,"PAH",1,1,90,0)
                                 =======
"PKG",5,22,1,"PAH",1,1,91,0)
             Install Package(s) 
"PKG",5,22,1,"PAH",1,1,92,0)
             Select INSTALL NAME: XT*7.3*81 
"PKG",5,22,1,"PAH",1,1,93,0)
                                   ==========
"PKG",5,22,1,"PAH",1,1,94,0)
   
"PKG",5,22,1,"PAH",1,1,95,0)
 Want KIDS to Rebuild Menu Trees Upon Completion of Install? YES// NO
"PKG",5,22,1,"PAH",1,1,96,0)
                                                                   ==
"PKG",5,22,1,"PAH",1,1,97,0)
 Want KIDS to INHIBIT LOGONs during the install? YES// NO 
"PKG",5,22,1,"PAH",1,1,98,0)
                                                       ==
"PKG",5,22,1,"PAH",1,1,99,0)
 Want to DISABLE Scheduled Options, Menu Options, and Protocols? YES// NO
"PKG",5,22,1,"PAH",1,1,100,0)
                                                                       ==
"PKG",5,22,1,"PAH",1,1,101,0)
 
"PKG",5,22,1,"PAH",1,1,102,0)
Routine Information:
"PKG",5,22,1,"PAH",1,1,103,0)
====================
"PKG",5,22,1,"PAH",1,1,104,0)
The second line of each of these routines now looks like:
"PKG",5,22,1,"PAH",1,1,105,0)
 ;;7.3;TOOLKIT;**[Patch List]**;Apr 25, 1995;Build 17
"PKG",5,22,1,"PAH",1,1,106,0)
 
"PKG",5,22,1,"PAH",1,1,107,0)
The checksums below are new checksums, and
"PKG",5,22,1,"PAH",1,1,108,0)
 can be checked with CHECK1^XTSUMBLD.
"PKG",5,22,1,"PAH",1,1,109,0)
 
"PKG",5,22,1,"PAH",1,1,110,0)
Routine Name: XTMLOG
"PKG",5,22,1,"PAH",1,1,111,0)
    Before:       n/a   After:B133645760  **81,101**
"PKG",5,22,1,"PAH",1,1,112,0)
Routine Name: XTMLOG1
"PKG",5,22,1,"PAH",1,1,113,0)
    Before:       n/a   After: B46831784  **81**
"PKG",5,22,1,"PAH",1,1,114,0)
Routine Name: XTMLOG2
"PKG",5,22,1,"PAH",1,1,115,0)
    Before:       n/a   After:    Delete  
"PKG",5,22,1,"PAH",1,1,116,0)
Routine Name: XTMLOPAR
"PKG",5,22,1,"PAH",1,1,117,0)
    Before:       n/a   After: B19404303  **81**
"PKG",5,22,1,"PAH",1,1,118,0)
Routine Name: XTMLOSKT
"PKG",5,22,1,"PAH",1,1,119,0)
    Before:       n/a   After: B36861478  **81**
"PKG",5,22,1,"PAH",1,1,120,0)
Routine Name: XTMRPRNT
"PKG",5,22,1,"PAH",1,1,121,0)
    Before:       n/a   After:  B1220842  **101**
"PKG",5,22,1,"PAH",1,1,122,0)
Routine Name: XTMUNIT
"PKG",5,22,1,"PAH",1,1,123,0)
    Before:       n/a   After:  <to be filled in>
"PKG",5,22,1,"PAH",1,1,124,0)
Routine Name: XTMUNIT1
"PKG",5,22,1,"PAH",1,1,125,0)
    Before:       n/a   After:  <to be filled in>
"PKG",5,22,1,"PAH",1,1,126,0)
 
"PKG",5,22,1,"PAH",1,1,127,0)
****** XTMUNIT - A unit tester for M code.
"PKG",5,22,1,"PAH",1,1,128,0)
 
"PKG",5,22,1,"PAH",1,1,129,0)
A Unit Test framework permits small tests to be written to verify that the
"PKG",5,22,1,"PAH",1,1,130,0)
code you are testing is doing what you expect it to do.  Generally the tests
"PKG",5,22,1,"PAH",1,1,131,0)
are performed on the smaller blocks of the application, and not necessarily
"PKG",5,22,1,"PAH",1,1,132,0)
a test of all of the functionality within the application.  As changes are
"PKG",5,22,1,"PAH",1,1,133,0)
subsequently made in the code, these tests can be run frequently to validate
"PKG",5,22,1,"PAH",1,1,134,0)
that nothing has changed.  The concept of Unit testing was introduced by Kent 
"PKG",5,22,1,"PAH",1,1,135,0)
Beck (also the creator of eXtreme Programming methodology).  The common
"PKG",5,22,1,"PAH",1,1,136,0)
JUnit framework for Java, which other frameworks are based upon, was written 
"PKG",5,22,1,"PAH",1,1,137,0)
by Kent Beck and Erich Gamma.  The phrase 'Test-Driven Development' is 
"PKG",5,22,1,"PAH",1,1,138,0)
frequently used to indicate the strong use of unit testing during development,
"PKG",5,22,1,"PAH",1,1,139,0)
although some think of it as equivalent to the 'Test First Development' in
"PKG",5,22,1,"PAH",1,1,140,0)
which the tests for code are written prior to writing the code.  In the Test
"PKG",5,22,1,"PAH",1,1,141,0)
First Development, the test should initially fail (since nothing has been
"PKG",5,22,1,"PAH",1,1,142,0)
written) and then pass after the code has been written.
"PKG",5,22,1,"PAH",1,1,143,0)
 
"PKG",5,22,1,"PAH",1,1,144,0)
For client side languages, JUnit (for Java), DUnit (for Delphi), NUnit and 
"PKG",5,22,1,"PAH",1,1,145,0)
HarnessIt (for dotNet) all provide Unit Test frameworks.  The routine XTMUNIT
"PKG",5,22,1,"PAH",1,1,146,0)
included in this patch provides the same capabilities for unit testing M code.
"PKG",5,22,1,"PAH",1,1,147,0)
Initially the client side tests were console based (i.e., not windows but just
"PKG",5,22,1,"PAH",1,1,148,0)
text), and that is what XTMUNIT provides.  There is also, for those who like
"PKG",5,22,1,"PAH",1,1,149,0)
pretty windows, a GUI front end available as well (MUnit.exe) but this is 
"PKG",5,22,1,"PAH",1,1,150,0)
optional.
"PKG",5,22,1,"PAH",1,1,151,0)
 
"PKG",5,22,1,"PAH",1,1,152,0)
If you are going to modify sections of your code, or refactor (cleaning up the
"PKG",5,22,1,"PAH",1,1,153,0)
code without changing the behavior of the code - which is frequently done prior
"PKG",5,22,1,"PAH",1,1,154,0)
to changing the behavior - See Martin Fowler's book "Refactoring: Improving the
"PKG",5,22,1,"PAH",1,1,155,0)
Design of Existing Code"), it is best to create a unit test for those areas 
"PKG",5,22,1,"PAH",1,1,156,0)
that you want to work with.  Then as changes are made the unit tests can be run
"PKG",5,22,1,"PAH",1,1,157,0)
to insure that nothing unexpected has changed.  For modifications, the unit 
"PKG",5,22,1,"PAH",1,1,158,0)
tests can then be written to reflect the new expected behavior and used to
"PKG",5,22,1,"PAH",1,1,159,0)
insure that it is what is expected.  One of the major benefits of unit testing
"PKG",5,22,1,"PAH",1,1,160,0)
is finding those changes that weren't expected in other parts of your code due
"PKG",5,22,1,"PAH",1,1,161,0)
to the changes that are being made.
"PKG",5,22,1,"PAH",1,1,162,0)
 
"PKG",5,22,1,"PAH",1,1,163,0)
 
"PKG",5,22,1,"PAH",1,1,164,0)
The following is a very simple sample routine, however, it covers everything 
"PKG",5,22,1,"PAH",1,1,165,0)
necessary for generating a basic unit test, and examples of the various
"PKG",5,22,1,"PAH",1,1,166,0)
calls available.
"PKG",5,22,1,"PAH",1,1,167,0)
 
"PKG",5,22,1,"PAH",1,1,168,0)
---------------------------------------------------------------------------
"PKG",5,22,1,"PAH",1,1,169,0)
 
"PKG",5,22,1,"PAH",1,1,170,0)
XXXX    ;jli/fo-oak - demo code for a unit test routine ;9/25/03  15:44
"PKG",5,22,1,"PAH",1,1,171,0)
        ;;
"PKG",5,22,1,"PAH",1,1,172,0)
        ; makes it easy to run tests simply by running this routine and
"PKG",5,22,1,"PAH",1,1,173,0)
        ; insures that XTMUNIT will be run only where it is present
"PKG",5,22,1,"PAH",1,1,174,0)
        I $T(EN^XTMUNIT)'="" D EN^XTMUNIT("XXXX")
"PKG",5,22,1,"PAH",1,1,175,0)
        Q
"PKG",5,22,1,"PAH",1,1,176,0)
        ;
"PKG",5,22,1,"PAH",1,1,177,0)
STARTUP ; optional entry point
"PKG",5,22,1,"PAH",1,1,178,0)
        ; if present executed before any other entry point any variables
"PKG",5,22,1,"PAH",1,1,179,0)
        ; or other work that needs to be done for any or all tests in the
"PKG",5,22,1,"PAH",1,1,180,0)
        ; routine.  This is run only once at the beginning.
"PKG",5,22,1,"PAH",1,1,181,0)
        Q
"PKG",5,22,1,"PAH",1,1,182,0)
        ;
"PKG",5,22,1,"PAH",1,1,183,0)
SHUTDOWN        ; optional entry point
"PKG",5,22,1,"PAH",1,1,184,0)
        ; if present executed after all other processing is complete to remove
"PKG",5,22,1,"PAH",1,1,185,0)
        ; any variables, or undo work done in STARTUP.
"PKG",5,22,1,"PAH",1,1,186,0)
        Q
"PKG",5,22,1,"PAH",1,1,187,0)
        ;
"PKG",5,22,1,"PAH",1,1,188,0)
SETUP   ; optional entry point
"PKG",5,22,1,"PAH",1,1,189,0)
        ; if present it will be executed before each test entry to set up 
"PKG",5,22,1,"PAH",1,1,190,0)
        ; variables, etc.
"PKG",5,22,1,"PAH",1,1,191,0)
        Q
"PKG",5,22,1,"PAH",1,1,192,0)
        ;
"PKG",5,22,1,"PAH",1,1,193,0)
TEARDOWN        ; optional entry point
"PKG",5,22,1,"PAH",1,1,194,0)
        ; if present it will be exceuted after each test entry to clean up
"PKG",5,22,1,"PAH",1,1,195,0)
        ; variables, etc.
"PKG",5,22,1,"PAH",1,1,196,0)
        Q
"PKG",5,22,1,"PAH",1,1,197,0)
        ;
"PKG",5,22,1,"PAH",1,1,198,0)
ENTRY1  ; Example for use of CHKEQ call to check two values
"PKG",5,22,1,"PAH",1,1,199,0)
        ;
"PKG",5,22,1,"PAH",1,1,200,0)
        ; code to generate a test, e.g. to check the sum of 1 and 1
"PKG",5,22,1,"PAH",1,1,201,0)
        S X=1,Y=1
"PKG",5,22,1,"PAH",1,1,202,0)
        D CHKEQ^XTMUNIT(2,X+Y,"1+1 didn't yield 2") ;
"PKG",5,22,1,"PAH",1,1,203,0)
        ;
"PKG",5,22,1,"PAH",1,1,204,0)
        ; usage of CHKEQ^XTMUNIT
"PKG",5,22,1,"PAH",1,1,205,0)
        ;   first argument is the expected value
"PKG",5,22,1,"PAH",1,1,206,0)
        ;   second argument is the actual value
"PKG",5,22,1,"PAH",1,1,207,0)
        ;   third argument is text to be displayed if the first argument
"PKG",5,22,1,"PAH",1,1,208,0)
        ;     and second argument are not equal.
"PKG",5,22,1,"PAH",1,1,209,0)
        ;
"PKG",5,22,1,"PAH",1,1,210,0)
        ;   Multiple calls to CHKEQ^XTMUNIT may be made within one entry
"PKG",5,22,1,"PAH",1,1,211,0)
        ;   point.  Each of these is counted as a test.
"PKG",5,22,1,"PAH",1,1,212,0)
        ;
"PKG",5,22,1,"PAH",1,1,213,0)
        ;   Output for a failure shows the expected and actual values
"PKG",5,22,1,"PAH",1,1,214,0)
        Q
"PKG",5,22,1,"PAH",1,1,215,0)
        ;
"PKG",5,22,1,"PAH",1,1,216,0)
ENTRY2  ; Use of CHKTF call to check value for True or False
"PKG",5,22,1,"PAH",1,1,217,0)
        ;
"PKG",5,22,1,"PAH",1,1,218,0)
        S ERRMSG="Current user is not an active user on this system"
"PKG",5,22,1,"PAH",1,1,219,0)
        D CHKTF^XTMUNIT($$ACTIVE^XUSER(DUZ)>0,ERRMSG)
"PKG",5,22,1,"PAH",1,1,220,0)
        ;
"PKG",5,22,1,"PAH",1,1,221,0)
        ; usage of CHKTF^XTMUNIT 
"PKG",5,22,1,"PAH",1,1,222,0)
        ;    first argument is an expression evaluating to true or false value,
"PKG",5,22,1,"PAH",1,1,223,0)
        ;    second argument is text to be displayed if the first argument
"PKG",5,22,1,"PAH",1,1,224,0)
        ;      evaluates to false.
"PKG",5,22,1,"PAH",1,1,225,0)
        ;
"PKG",5,22,1,"PAH",1,1,226,0)
        ;    Multiple calls to CHKTF^XTMUNIT may be made within one entry 
"PKG",5,22,1,"PAH",1,1,227,0)
        ;    point.  Each of these is counted as a test.
"PKG",5,22,1,"PAH",1,1,228,0)
        Q
"PKG",5,22,1,"PAH",1,1,229,0)
        ;
"PKG",5,22,1,"PAH",1,1,230,0)
ENTRY3  ; Use of CHKTF call to check values that should NOT be equal
"PKG",5,22,1,"PAH",1,1,231,0)
        ;
"PKG",5,22,1,"PAH",1,1,232,0)
        ; if you want to test something that should fail, use a NOT
"PKG",5,22,1,"PAH",1,1,233,0)
        S X=1,Y=3
"PKG",5,22,1,"PAH",1,1,234,0)
        D CHKTF^XTMUNIT(X'=Y,"indicated 1 and 3 are equal")
"PKG",5,22,1,"PAH",1,1,235,0)
        Q
"PKG",5,22,1,"PAH",1,1,236,0)
        ;
"PKG",5,22,1,"PAH",1,1,237,0)
ENTRY4  ; @TEST - Use of the FAIL call to generate a failure message
"PKG",5,22,1,"PAH",1,1,238,0)
        ;
"PKG",5,22,1,"PAH",1,1,239,0)
        S X=1+2 I X'=3 D FAIL^XTMUNIT("System is doing bad addition on 1+2") Q
"PKG",5,22,1,"PAH",1,1,240,0)
        ; 
"PKG",5,22,1,"PAH",1,1,241,0)
        ; usage of FAIL^XTMUNIT
"PKG",5,22,1,"PAH",1,1,242,0)
        ;    the argument is text indicating why the failure was identified
"PKG",5,22,1,"PAH",1,1,243,0)
        Q
"PKG",5,22,1,"PAH",1,1,244,0)
        ;
"PKG",5,22,1,"PAH",1,1,245,0)
        ; Other routine names to be included in testing are listed one per line
"PKG",5,22,1,"PAH",1,1,246,0)
        ; with the name as the third semi-colon piece on the line and an
"PKG",5,22,1,"PAH",1,1,247,0)
        ; optional description of what the routine tests as the fourth semi-
"PKG",5,22,1,"PAH",1,1,248,0)
        ; colon piece, if desired this permits a suite of test routines to be
"PKG",5,22,1,"PAH",1,1,249,0)
        ; run by simply starting one of the routine the names may be repeated
"PKG",5,22,1,"PAH",1,1,250,0)
        ; in multiple routines, but will only be included once. The first line
"PKG",5,22,1,"PAH",1,1,251,0)
        ; without a third piece terminates the search for routine names (which
"PKG",5,22,1,"PAH",1,1,252,0)
        ; is why this is above the XTROU tag).
"PKG",5,22,1,"PAH",1,1,253,0)
XTROU   ;
"PKG",5,22,1,"PAH",1,1,254,0)
        ;;XXXY;description of what the routine tests
"PKG",5,22,1,"PAH",1,1,255,0)
        ;;XXXZ;
"PKG",5,22,1,"PAH",1,1,256,0)
        ;;XXXA
"PKG",5,22,1,"PAH",1,1,257,0)
        ;
"PKG",5,22,1,"PAH",1,1,258,0)
        ; Entry points for tests are specified as the third semi-colon piece,
"PKG",5,22,1,"PAH",1,1,259,0)
        ; a description of what it tests is optional as the fourth semi-colon
"PKG",5,22,1,"PAH",1,1,260,0)
        ; piece on a line. The first line without a third piece terminates the
"PKG",5,22,1,"PAH",1,1,261,0)
        ; search for TAGs to be used as entry points
"PKG",5,22,1,"PAH",1,1,262,0)
XTENT   ;
"PKG",5,22,1,"PAH",1,1,263,0)
        ;;ENTRY1;tests addition of 1 and 1
"PKG",5,22,1,"PAH",1,1,264,0)
        ;;ENTRY2;checks active user status
"PKG",5,22,1,"PAH",1,1,265,0)
        ;;ENTRY3;
"PKG",5,22,1,"PAH",1,1,266,0)
        Q
"PKG",5,22,1,"PAH",1,1,267,0)
 
"PKG",5,22,1,"PAH",1,1,268,0)
-----------------------------------------------------------------------------
"PKG",5,22,1,"PAH",1,1,269,0)
 
"PKG",5,22,1,"PAH",1,1,270,0)
Running XXXX as written above, results in the following
"PKG",5,22,1,"PAH",1,1,271,0)
 
"PKG",5,22,1,"PAH",1,1,272,0)
>D ^XXXX
"PKG",5,22,1,"PAH",1,1,273,0)
Referenced routine XXXY not found.
"PKG",5,22,1,"PAH",1,1,274,0)
Referenced routine XXXZ not found.
"PKG",5,22,1,"PAH",1,1,275,0)
Referenced routine XXXA not found.
"PKG",5,22,1,"PAH",1,1,276,0)
...
"PKG",5,22,1,"PAH",1,1,277,0)
 
"PKG",5,22,1,"PAH",1,1,278,0)
Ran 1 Routine, 4 Entry Tags
"PKG",5,22,1,"PAH",1,1,279,0)
Checked 3 tests, with 0 failures and encountered 0 errors.
"PKG",5,22,1,"PAH",1,1,280,0)
>
"PKG",5,22,1,"PAH",1,1,281,0)
 
"PKG",5,22,1,"PAH",1,1,282,0)
Normally, you won't see routines referenced that aren't there since you 
"PKG",5,22,1,"PAH",1,1,283,0)
wouldn't include them.  Passed tests are shown only with a dot, and the
"PKG",5,22,1,"PAH",1,1,284,0)
results are summarized at the bottom.
"PKG",5,22,1,"PAH",1,1,285,0)
 
"PKG",5,22,1,"PAH",1,1,286,0)
 
"PKG",5,22,1,"PAH",1,1,287,0)
Changing the code on line ENTRY+3 from (X'=Y)  to  (X=Y)  and running 
"PKG",5,22,1,"PAH",1,1,288,0)
XXXX shows that the test now fails.  The location of the tag and the 
"PKG",5,22,1,"PAH",1,1,289,0)
comment for failure are shown in the order of the tests.
"PKG",5,22,1,"PAH",1,1,290,0)
 
"PKG",5,22,1,"PAH",1,1,291,0)
 
"PKG",5,22,1,"PAH",1,1,292,0)
>D XXXX
"PKG",5,22,1,"PAH",1,1,293,0)
Referenced routine XXXY not found.
"PKG",5,22,1,"PAH",1,1,294,0)
Referenced routine XXXZ not found.
"PKG",5,22,1,"PAH",1,1,295,0)
Referenced routine XXXA not found.
"PKG",5,22,1,"PAH",1,1,296,0)
..
"PKG",5,22,1,"PAH",1,1,297,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"PKG",5,22,1,"PAH",1,1,298,0)
 
"PKG",5,22,1,"PAH",1,1,299,0)
 
"PKG",5,22,1,"PAH",1,1,300,0)
Ran 1 Routine, 4 Entry Tags
"PKG",5,22,1,"PAH",1,1,301,0)
Checked 3 tests, with 1 failure and encountered 0 errors.
"PKG",5,22,1,"PAH",1,1,302,0)
>
"PKG",5,22,1,"PAH",1,1,303,0)
 
"PKG",5,22,1,"PAH",1,1,304,0)
 
"PKG",5,22,1,"PAH",1,1,305,0)
 
"PKG",5,22,1,"PAH",1,1,306,0)
Now changing the code on line ENTRY1+3 so that S X=1,Y=1 
"PKG",5,22,1,"PAH",1,1,307,0)
becomes  X=1,Y=1 (removing S<space> and running shows the
"PKG",5,22,1,"PAH",1,1,308,0)
error that is generated due to our typing, as well as continuing
"PKG",5,22,1,"PAH",1,1,309,0)
on to show the failure we introduced at ENTRY3.  The test at ENTRY2
"PKG",5,22,1,"PAH",1,1,310,0)
still runs without a problem as indicated by the lone dot.
"PKG",5,22,1,"PAH",1,1,311,0)
 
"PKG",5,22,1,"PAH",1,1,312,0)
 
"PKG",5,22,1,"PAH",1,1,313,0)
>D XXXX
"PKG",5,22,1,"PAH",1,1,314,0)
Referenced routine XXXY not found.
"PKG",5,22,1,"PAH",1,1,315,0)
Referenced routine XXXZ not found.
"PKG",5,22,1,"PAH",1,1,316,0)
Referenced routine XXXA not found.
"PKG",5,22,1,"PAH",1,1,317,0)
 
"PKG",5,22,1,"PAH",1,1,318,0)
ENTRY1^XXXX - tests addition of 1 and 1 - Error: ENTRY1+3^XXXX:1, %DSM-E-COMAND,
"PKG",5,22,1,"PAH",1,1,319,0)
 bad command detected
"PKG",5,22,1,"PAH",1,1,320,0)
.
"PKG",5,22,1,"PAH",1,1,321,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"PKG",5,22,1,"PAH",1,1,322,0)
 
"PKG",5,22,1,"PAH",1,1,323,0)
 
"PKG",5,22,1,"PAH",1,1,324,0)
Ran 1 Routine, 4 Entry Tags
"PKG",5,22,1,"PAH",1,1,325,0)
Checked 3 tests, with 1 failure and encountered 1 error.
"PKG",5,22,1,"PAH",1,1,326,0)
>
"PKG",5,22,1,"PAH",1,1,327,0)
 
"PKG",5,22,1,"PAH",1,1,328,0)
 
"PKG",5,22,1,"PAH",1,1,329,0)
If the code at ENTRY4+2 is now modified to S X=1+1 and running it
"PKG",5,22,1,"PAH",1,1,330,0)
causes the FAIL call to be used.
"PKG",5,22,1,"PAH",1,1,331,0)
 
"PKG",5,22,1,"PAH",1,1,332,0)
>D XXXX
"PKG",5,22,1,"PAH",1,1,333,0)
Referenced routine XXXY not found.
"PKG",5,22,1,"PAH",1,1,334,0)
Referenced routine XXXZ not found.
"PKG",5,22,1,"PAH",1,1,335,0)
Referenced routine XXXA not found.
"PKG",5,22,1,"PAH",1,1,336,0)
 
"PKG",5,22,1,"PAH",1,1,337,0)
ENTRY1^XXXX - tests addition of 1 and 1 - Error: ENTRY1+3^XXXX:1, %DSM-E-COMAND,
"PKG",5,22,1,"PAH",1,1,338,0)
 bad command detected
"PKG",5,22,1,"PAH",1,1,339,0)
.
"PKG",5,22,1,"PAH",1,1,340,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"PKG",5,22,1,"PAH",1,1,341,0)
 
"PKG",5,22,1,"PAH",1,1,342,0)
ENTRY4^XXXX - example of FAIL^XTMUNIT call - System is doing bad addition on 1+2
"PKG",5,22,1,"PAH",1,1,343,0)
 
"PKG",5,22,1,"PAH",1,1,344,0)
 
"PKG",5,22,1,"PAH",1,1,345,0)
Ran 1 Routine, 4 Entry Tags
"PKG",5,22,1,"PAH",1,1,346,0)
Checked 4 tests, with 2 failures and encountered 1 error.
"PKG",5,22,1,"PAH",1,1,347,0)
>
"PKG",5,22,1,"PAH",1,1,348,0)
 
"PKG",5,22,1,"PAH",1,1,349,0)
 
"PKG",5,22,1,"PAH",1,1,350,0)
 
"PKG",5,22,1,"PAH",1,1,351,0)
 
"PKG",5,22,1,"PAH",1,1,352,0)
Restoring S<space> on line ENTRY1+3, and changing X=1 to X=2 and running
"PKG",5,22,1,"PAH",1,1,353,0)
it shows the output of the CHKEQ call.
"PKG",5,22,1,"PAH",1,1,354,0)
 
"PKG",5,22,1,"PAH",1,1,355,0)
>d XXXX
"PKG",5,22,1,"PAH",1,1,356,0)
Referenced routine XXXY not found.
"PKG",5,22,1,"PAH",1,1,357,0)
Referenced routine XXXZ not found.
"PKG",5,22,1,"PAH",1,1,358,0)
Referenced routine XXXA not found.
"PKG",5,22,1,"PAH",1,1,359,0)
 
"PKG",5,22,1,"PAH",1,1,360,0)
ENTRY1^XXXX - tests addition of 1 and 1 - <2> vs <3> - 1+1 didn't yield 2
"PKG",5,22,1,"PAH",1,1,361,0)
.
"PKG",5,22,1,"PAH",1,1,362,0)
ENTRY3^XXXX - indicated 1 and 3 are equal
"PKG",5,22,1,"PAH",1,1,363,0)
 
"PKG",5,22,1,"PAH",1,1,364,0)
ENTRY4^XXXX - example of FAIL^XTMUNIT call - System is doing bad addition on 1+2
"PKG",5,22,1,"PAH",1,1,365,0)
 
"PKG",5,22,1,"PAH",1,1,366,0)
 
"PKG",5,22,1,"PAH",1,1,367,0)
Ran 1 Routine, 4 Entry Tags
"PKG",5,22,1,"PAH",1,1,368,0)
Checked 4 tests, with 3 failures and encountered 0 errors.
"PKG",5,22,1,"PAH",1,1,369,0)
>
"PKG",5,22,1,"PAH",1,1,370,0)
 
"PKG",5,22,1,"PAH",1,1,371,0)
 
"PKG",5,22,1,"PAH",1,1,372,0)
 
"PKG",5,22,1,"PAH",1,1,373,0)
That covers the basics of generating a unit test routine to use with XTMUNIT.
"PKG",5,22,1,"PAH",1,1,374,0)
For sections of code which perform calculations, etc., this is all that will
"PKG",5,22,1,"PAH",1,1,375,0)
be required.  For other cases dependent upon database interactions, or of
"PKG",5,22,1,"PAH",1,1,376,0)
input and output via something like the RPCBroker, other approaches to 
"PKG",5,22,1,"PAH",1,1,377,0)
creating usable tests are required.  The use of 'objects' which can be used
"PKG",5,22,1,"PAH",1,1,378,0)
for consistency in such units tests are generally referred to as 'Mock 
"PKG",5,22,1,"PAH",1,1,379,0)
Objects'.
"PKG",5,22,1,"PAH",1,1,380,0)
 
"PKG",5,22,1,"PAH",1,1,381,0)
You do not want to include any code which requires user input.  You want the
"PKG",5,22,1,"PAH",1,1,382,0)
tests to be able to run completely without any user intervention other than
"PKG",5,22,1,"PAH",1,1,383,0)
starting them.  By referencing other related unit test routines within the
"PKG",5,22,1,"PAH",1,1,384,0)
one that is started, you can build suites of tests that can be used to cover
"PKG",5,22,1,"PAH",1,1,385,0)
the full range of your code.
"PKG",5,22,1,"PAH",1,1,386,0)
 
"PKG",5,22,1,"PAH",1,1,387,0)
Supported References in XTMUNIT are EN, RUNSET, CHKTF, CHKEQ, and FAIL. 
"PKG",5,22,1,"PAH",1,1,388,0)
 
"PKG",5,22,1,"PAH",1,1,389,0)
The  entry point EN^XTMUNIT(ROUNAME) starts the unit testing process.  The
"PKG",5,22,1,"PAH",1,1,390,0)
argument is the name of the routine where the testing should be started.  
"PKG",5,22,1,"PAH",1,1,391,0)
That routine must have at least one TAG or entry point and entry points 
"PKG",5,22,1,"PAH",1,1,392,0)
are specified in the line following the tag XTENT as the third semi-colon 
"PKG",5,22,1,"PAH",1,1,393,0)
piece on the line OR it can have tags with @TEST on the comment next to the tag. 
"PKG",5,22,1,"PAH",1,1,394,0)
 
"PKG",5,22,1,"PAH",1,1,395,0)
The test is performed on a conditional value by calling the entry point 
"PKG",5,22,1,"PAH",1,1,396,0)
CHKTF^XTMUNIT(testval,messag) with the first argument the conditional test 
"PKG",5,22,1,"PAH",1,1,397,0)
value (true or false) and the second argument a message that should be 
"PKG",5,22,1,"PAH",1,1,398,0)
displayed indicating what failed in the test.
"PKG",5,22,1,"PAH",1,1,399,0)
 
"PKG",5,22,1,"PAH",1,1,400,0)
The test is performed by checking two values for equivalence using the entry
"PKG",5,22,1,"PAH",1,1,401,0)
point CHKEQ^XTMUNIT(expected,actual,messag) with the first argument the 
"PKG",5,22,1,"PAH",1,1,402,0)
expected value, the second argument the actual value, and the third argument 
"PKG",5,22,1,"PAH",1,1,403,0)
the message for display on failure.
"PKG",5,22,1,"PAH",1,1,404,0)
 
"PKG",5,22,1,"PAH",1,1,405,0)
The entry point FAIL^XTMUNIT(messag) is used to simply generate a failure 
"PKG",5,22,1,"PAH",1,1,406,0)
with the argument as the message to be displayed for the failure.
"PKG",5,22,1,"PAH",1,1,407,0)
 
"PKG",5,22,1,"PAH",1,1,408,0)
For those who have problems keeping track of routine names for unit testing 
"PKG",5,22,1,"PAH",1,1,409,0)
and which application they are associated with, we have created a new file 
"PKG",5,22,1,"PAH",1,1,410,0)
(MUNIT TEST GROUP, #8992.8) which can be used to maintain groups of unit 
"PKG",5,22,1,"PAH",1,1,411,0)
test routines with the edit option "XTMUNIT GROUP EDIT" (MUnit Test Group 
"PKG",5,22,1,"PAH",1,1,412,0)
Edit).  These may be run from an option ("XTMUNIT GROUP RUN", Run MUnit Tests
"PKG",5,22,1,"PAH",1,1,413,0)
from Test Groups), from the a Supported Reference [D RUNSET^XTMUNIT(setname)],
"PKG",5,22,1,"PAH",1,1,414,0)
or from the GUI client described below (click the 'Select Group' button).
"PKG",5,22,1,"PAH",1,1,415,0)
 
"PKG",5,22,1,"PAH",1,1,416,0)
 
"PKG",5,22,1,"PAH",1,1,417,0)
 
"PKG",5,22,1,"PAH",1,1,418,0)
 
"PKG",5,22,1,"PAH",1,1,419,0)
****** XTMRPRNT -- a routine lister for capturing and copying routines
"PKG",5,22,1,"PAH",1,1,420,0)
 
"PKG",5,22,1,"PAH",1,1,421,0)
XTMRPRNT is a small utility routine for generating listings of routines that 
"PKG",5,22,1,"PAH",1,1,422,0)
can usually be captured, loaded into a text editor, edited if necessary and 
"PKG",5,22,1,"PAH",1,1,423,0)
subsequently copied and pasted into another account or back into the original
"PKG",5,22,1,"PAH",1,1,424,0)
account.  A ZREMOVE command precedes each routine, and a ZSAVE command with 
"PKG",5,22,1,"PAH",1,1,425,0)
the routine name follows each routine.  On some system and terminal emulator
"PKG",5,22,1,"PAH",1,1,426,0)
combinations, the initial tab line-start character may be captured as a space
"PKG",5,22,1,"PAH",1,1,427,0)
and this then requires additional work to use the routine for rapid copying.
"PKG",5,22,1,"PAH",1,1,428,0)
 
"PKG",5,22,1,"PAH",1,1,429,0)
 
"PKG",5,22,1,"PAH",1,1,430,0)
usage
"PKG",5,22,1,"PAH",1,1,431,0)
 
"PKG",5,22,1,"PAH",1,1,432,0)
D ^XTMRPRNT
"PKG",5,22,1,"PAH",1,1,433,0)
 
"PKG",5,22,1,"PAH",1,1,434,0)
routine(s) ?   >   XTM*
"PKG",5,22,1,"PAH",1,1,435,0)
searching directory ...
"PKG",5,22,1,"PAH",1,1,436,0)
routine(s) ?   >
"PKG",5,22,1,"PAH",1,1,437,0)
 
"PKG",5,22,1,"PAH",1,1,438,0)
ENTER RETURN TO START:
"PKG",5,22,1,"PAH",1,1,439,0)
ZR
"PKG",5,22,1,"PAH",1,1,440,0)
XTMLOG  ;JLI/FO-OAK - M LOGGING UTILITY ;9/25/03  7:48
"PKG",5,22,1,"PAH",1,1,441,0)
....
"PKG",5,22,1,"PAH",1,1,442,0)
<listing of routines ommitted>
"PKG",5,22,1,"PAH",1,1,443,0)
....
"PKG",5,22,1,"PAH",1,1,444,0)
ZS XTMUNIT
"PKG",5,22,1,"PAH",1,1,445,0)
 
"PKG",5,22,1,"PAH",1,1,446,0)
>
"PKG",5,22,1,"PAH",1,1,447,0)
 
"PKG",5,22,1,"PAH",1,1,448,0)
At the prompt for routines enter the routine set that you want to capture.
"PKG",5,22,1,"PAH",1,1,449,0)
At the prompt to ENTER RETURN TO START start the capture process then enter
"PKG",5,22,1,"PAH",1,1,450,0)
RETURN to start the listing.  At the programmer prompt following the listing
"PKG",5,22,1,"PAH",1,1,451,0)
terminate the capture process.  In a text editor you may want to remove the
"PKG",5,22,1,"PAH",1,1,452,0)
trailing '>' character, although it doesn't normally cause much problem.
"PKG",5,22,1,"PAH",1,1,453,0)
 
"PKG",5,22,1,"PAH",1,1,454,0)
 
"PKG",5,22,1,"PAH",1,1,455,0)
******  MUnit.exe
"PKG",5,22,1,"PAH",1,1,456,0)
 
"PKG",5,22,1,"PAH",1,1,457,0)
 
"PKG",5,22,1,"PAH",1,1,458,0)
 
"PKG",5,22,1,"PAH",1,1,459,0)
The GUI interface for XTMUNIT is available as a zip file (XT_7_3_81.zip) from 
"PKG",5,22,1,"PAH",1,1,460,0)
the anonymous directories (see belww).  It should be saved and the file 
"PKG",5,22,1,"PAH",1,1,461,0)
unzipped into any desired directory.  If desired a shortcut can be set up to 
"PKG",5,22,1,"PAH",1,1,462,0)
start MUnit.exe and this shortcut may contain specifications for a server and
"PKG",5,22,1,"PAH",1,1,463,0)
port (e.g, munit.exe s=server.med.va.gov p=9200).
"PKG",5,22,1,"PAH",1,1,464,0)
 
"PKG",5,22,1,"PAH",1,1,465,0)
Start the application either by double clicking on it or the shortcut.  
"PKG",5,22,1,"PAH",1,1,466,0)
 
"PKG",5,22,1,"PAH",1,1,467,0)
Select or Change the server/port specifications if necessary, and click on 
"PKG",5,22,1,"PAH",1,1,468,0)
the 'Connect' button.
"PKG",5,22,1,"PAH",1,1,469,0)
 
"PKG",5,22,1,"PAH",1,1,470,0)
Enter the name (case sensitive) of the primary routine to be used for unit 
"PKG",5,22,1,"PAH",1,1,471,0)
testing, or click on the 'Select Group' button to select an entry in the 
"PKG",5,22,1,"PAH",1,1,472,0)
MUnit Test Group file (#8992.8).
"PKG",5,22,1,"PAH",1,1,473,0)
 
"PKG",5,22,1,"PAH",1,1,474,0)
Click on the 'List' button and the routines and entry points for testing will
"PKG",5,22,1,"PAH",1,1,475,0)
be listed (this happens automatically if an entry in the MUnit Test Group file
"PKG",5,22,1,"PAH",1,1,476,0)
was selected).
"PKG",5,22,1,"PAH",1,1,477,0)
 
"PKG",5,22,1,"PAH",1,1,478,0)
Click on the 'Run' button and the tests will be run.
"PKG",5,22,1,"PAH",1,1,479,0)
 
"PKG",5,22,1,"PAH",1,1,480,0)
A colored band will appear - Green if all of the tests run without problem, 
"PKG",5,22,1,"PAH",1,1,481,0)
and Red if any test fails or any errors are encountered.
"PKG",5,22,1,"PAH",1,1,482,0)
 
"PKG",5,22,1,"PAH",1,1,483,0)
The results are summarized below the Run button: 'Tags' shows the number 
"PKG",5,22,1,"PAH",1,1,484,0)
of entry points called; 'Tests' shows the number of tests that were actually 
"PKG",5,22,1,"PAH",1,1,485,0)
performed (there may be more than one test per entry point); 'Errors' shows 
"PKG",5,22,1,"PAH",1,1,486,0)
the number of errors (non-expected code errors) encountered; 'Failed' shows 
"PKG",5,22,1,"PAH",1,1,487,0)
the number of failed tests encountered; and 'Elapsed' indicates the time it 
"PKG",5,22,1,"PAH",1,1,488,0)
took to perform all of the tests.
"PKG",5,22,1,"PAH",1,1,489,0)
 
"PKG",5,22,1,"PAH",1,1,490,0)
After the tests, the first page (labeled 'Test Hierarchy') listing the 
"PKG",5,22,1,"PAH",1,1,491,0)
routines and entry points will show Red (failed), Red-Brown (errors) or Green 
"PKG",5,22,1,"PAH",1,1,492,0)
(no problem) by each entry point or tag.  Routines will show Red (failed or 
"PKG",5,22,1,"PAH",1,1,493,0)
errors) and Green (no problem).
"PKG",5,22,1,"PAH",1,1,494,0)
 
"PKG",5,22,1,"PAH",1,1,495,0)
If any errors or failures are encountered, the second page 'Failures/Errors' 
"PKG",5,22,1,"PAH",1,1,496,0)
will list the entrypoint tag^routine, whether it was an error or failure, and 
"PKG",5,22,1,"PAH",1,1,497,0)
either the failure message entered in the call for the test that failed, or 
"PKG",5,22,1,"PAH",1,1,498,0)
the error message for an error.
"PKG",5,22,1,"PAH",1,1,499,0)
 
"PKG",5,22,1,"PAH",1,1,500,0)
After changes to the routines being tested, the 'Run' button can be clicked 
"PKG",5,22,1,"PAH",1,1,501,0)
again, or, if additional test entry points are added, the 'List' and 'Run' 
"PKG",5,22,1,"PAH",1,1,502,0)
buttons clicked to update the results.  If 'Select Groups' button was used 
"PKG",5,22,1,"PAH",1,1,503,0)
to identify the unit tests to be run, the button caption will have changed 
"PKG",5,22,1,"PAH",1,1,504,0)
to 'Clear Groups.'  This should be pressed to select a new group, or to enter
"PKG",5,22,1,"PAH",1,1,505,0)
a unit test routine name.
"PKG",5,22,1,"PAH",1,1,506,0)
 
"PKG",5,22,1,"PAH",1,1,507,0)
 
"PKG",5,22,1,"PAH",1,1,508,0)
 
"PKG",5,22,1,"PAH",1,1,509,0)
   The XTMLOG* routines provide a Log4M capability similar to Log4J.  The 
"PKG",5,22,1,"PAH",1,1,510,0)
logging commands can be embedded in the code and activated by initializing 
"PKG",5,22,1,"PAH",1,1,511,0)
logging in one of several different ways.  Otherwise, the logging commands 
"PKG",5,22,1,"PAH",1,1,512,0)
are checked and then ignored.
"PKG",5,22,1,"PAH",1,1,513,0)
 
"PKG",5,22,1,"PAH",1,1,514,0)
   Logging can lead to massive amounts of data, especially if the process 
"PKG",5,22,1,"PAH",1,1,515,0)
being logged is used by a number of users.  To reduce this, LOG4M for a given
"PKG",5,22,1,"PAH",1,1,516,0)
task can be limited to specific users if desired by setting up the USER 
"PKG",5,22,1,"PAH",1,1,517,0)
FILTER.  Also, while the process which logging is being performed on may have
"PKG",5,22,1,"PAH",1,1,518,0)
logging in a number of routines, but using the ROUTINE filter, a set of
"PKG",5,22,1,"PAH",1,1,519,0)
specific routines may be specified for which logging will be performed.
"PKG",5,22,1,"PAH",1,1,520,0)
 
"PKG",5,22,1,"PAH",1,1,521,0)
XTMLOG can be used to output a simple message: 
"PKG",5,22,1,"PAH",1,1,522,0)
 
"PKG",5,22,1,"PAH",1,1,523,0)
   D INFO^XTMLOG("ENTERED CHKWATCH")
"PKG",5,22,1,"PAH",1,1,524,0)
   
"PKG",5,22,1,"PAH",1,1,525,0)
will result in an output similar to
"PKG",5,22,1,"PAH",1,1,526,0)
 
"PKG",5,22,1,"PAH",1,1,527,0)
   20080207.145617 INFO CHKWATCH+3 XTDEBUG5 - ENTERED CHKWATCH
"PKG",5,22,1,"PAH",1,1,528,0)
   
"PKG",5,22,1,"PAH",1,1,529,0)
   
"PKG",5,22,1,"PAH",1,1,530,0)
XTMLOG can be used to output a message along with values for one or more
"PKG",5,22,1,"PAH",1,1,531,0)
comma separated variables
"PKG",5,22,1,"PAH",1,1,532,0)
 
"PKG",5,22,1,"PAH",1,1,533,0)
   D DEBUG^XTMLOG("DATA1","VALUE1,VALUE2")
"PKG",5,22,1,"PAH",1,1,534,0)
   
"PKG",5,22,1,"PAH",1,1,535,0)
   20080207.145617 DEBUG COMMANDS+11 XTDEBUG1 - DATA1 - VALUE1: 0
"PKG",5,22,1,"PAH",1,1,536,0)
   20080207.145617 DEBUG COMMANDS+11 XTDEBUG1 - DATA1 - VALUE2: XVAL=XTDEBV(1)
"PKG",5,22,1,"PAH",1,1,537,0)
 
"PKG",5,22,1,"PAH",1,1,538,0)
   
"PKG",5,22,1,"PAH",1,1,539,0)
XTMLOG can be used to output a message and values for variables including
"PKG",5,22,1,"PAH",1,1,540,0)
array values for the variables if they exist.
"PKG",5,22,1,"PAH",1,1,541,0)
 
"PKG",5,22,1,"PAH",1,1,542,0)
   D DEBUG^XTMLOG("DATA2","VALUE1,VALUE2,VALUE3,^TMP($J,""DATA"")",1)
"PKG",5,22,1,"PAH",1,1,543,0)
 
"PKG",5,22,1,"PAH",1,1,544,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE1: 3
"PKG",5,22,1,"PAH",1,1,545,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2: XVAL=XTDEBV(1)
"PKG",5,22,1,"PAH",1,1,546,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2("NEW"): 15
"PKG",5,22,1,"PAH",1,1,547,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE2("OLD",1): 
"PKG",5,22,1,"PAH",1,1,548,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - VALUE3: <UNDEFINED>
"PKG",5,22,1,"PAH",1,1,549,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - ^TMP($J,"DATA",1): LAST,FIRST M
"PKG",5,22,1,"PAH",1,1,550,0)
   20080207.145617 DEBUG COMMANDS+22 XTDEBUG1 - DATA2 - ^TMP($J,"DATA",2): 04/01/2001
"PKG",5,22,1,"PAH",1,1,551,0)
   
"PKG",5,22,1,"PAH",1,1,552,0)
 
"PKG",5,22,1,"PAH",1,1,553,0)
   The best way to control logging is through an entry in the LOG4M CONFIG 
"PKG",5,22,1,"PAH",1,1,554,0)
file (#8992.7).  
"PKG",5,22,1,"PAH",1,1,555,0)
 
"PKG",5,22,1,"PAH",1,1,556,0)
The NAME field (#.01) for an entry is used to control logging.  The NAME of 
"PKG",5,22,1,"PAH",1,1,557,0)
an entry (e.g., XTEXAMPLE) can be referenced in the initialization process 
"PKG",5,22,1,"PAH",1,1,558,0)
and if the file entry does not exist, the logging is not activated.  If the   
"PKG",5,22,1,"PAH",1,1,559,0)
If the entry exists and the ACTIVE field (#.02) is set to NO, logging will not 
"PKG",5,22,1,"PAH",1,1,560,0)
be activated.  Otherwise logging as instructed by the settings for this entry 
"PKG",5,22,1,"PAH",1,1,561,0)
will be activated for the current job, until logging for the entry is 
"PKG",5,22,1,"PAH",1,1,562,0)
terminated.  
"PKG",5,22,1,"PAH",1,1,563,0)
 
"PKG",5,22,1,"PAH",1,1,564,0)
  An XTMEXAMPLE entry could be created in the LOG4M CONFIG file.  It would 
"PKG",5,22,1,"PAH",1,1,565,0)
then be activated in the code, processing performed, and the logging turned
"PKG",5,22,1,"PAH",1,1,566,0)
off as in the example below.
"PKG",5,22,1,"PAH",1,1,567,0)
  
"PKG",5,22,1,"PAH",1,1,568,0)
  S X=$$FILEINIT^XTMLOG("XTMEXAMPLE")
"PKG",5,22,1,"PAH",1,1,569,0)
  D PROCESSING
"PKG",5,22,1,"PAH",1,1,570,0)
  D ENDLOG^XTMLOG("XTMEXAMPLE")
"PKG",5,22,1,"PAH",1,1,571,0)
 
"PKG",5,22,1,"PAH",1,1,572,0)
  If the XTMEXAMPLE entry does not exist in the LOG4M CONFIG file, logging will
"PKG",5,22,1,"PAH",1,1,573,0)
not be turned on.  If the XTMEXAMPLE entry does exist, the value of the 
"PKG",5,22,1,"PAH",1,1,574,0)
ACTIVE field (#.02) is checked, and if it is not specified or NO, logging 
"PKG",5,22,1,"PAH",1,1,575,0)
will not be turned on.
"PKG",5,22,1,"PAH",1,1,576,0)
 
"PKG",5,22,1,"PAH",1,1,577,0)
  If the ACTIVE field of the XTMEXAMPLE entry is E for YES, EASY CONFIG, 
"PKG",5,22,1,"PAH",1,1,578,0)
logging will be activated based on the values in the EASY ENTRY (#.03) and 
"PKG",5,22,1,"PAH",1,1,579,0)
EASY LEVEL (#.04) fields. [The alternative to the E or YES, EASY CONFIG for
"PKG",5,22,1,"PAH",1,1,580,0)
active logging is D or YES, DETAILED CONFIG which permits the user to specify
"PKG",5,22,1,"PAH",1,1,581,0)
a text based configuration, similar to that used for Log4J and Java, in a
"PKG",5,22,1,"PAH",1,1,582,0)
word processing field (DETAILED CONFIG field (#1)).  This alternative was 
"PKG",5,22,1,"PAH",1,1,583,0)
originally based on the use of config files for Log4J, but it is recommended 
"PKG",5,22,1,"PAH",1,1,584,0)
that the EASY CONFIG be used instead.]
"PKG",5,22,1,"PAH",1,1,585,0)
 
"PKG",5,22,1,"PAH",1,1,586,0)
  The EASY ENTRY field (#.03) can be used to easily specify the type(s) of 
"PKG",5,22,1,"PAH",1,1,587,0)
logging desired.  The value is a text string with semi-colon separated 
"PKG",5,22,1,"PAH",1,1,588,0)
specifiers for logging modes.
"PKG",5,22,1,"PAH",1,1,589,0)
 
"PKG",5,22,1,"PAH",1,1,590,0)
   C - indicates logging to the user's console.  Logging messages are sent 
"PKG",5,22,1,"PAH",1,1,591,0)
       to the console as they are generated. 
"PKG",5,22,1,"PAH",1,1,592,0)
   G - indicates logging to a global location and is followed by a comma 
"PKG",5,22,1,"PAH",1,1,593,0)
       and an identifer for the global location under ^XTMP("XTMLOG", [e.g., 
"PKG",5,22,1,"PAH",1,1,594,0)
       G,TEST4 would result in data being stored under the global location
"PKG",5,22,1,"PAH",1,1,595,0)
       ^XTMP("TEST4",DUZ,yymmdd.hhmmss,$J, where DUZ is the internal entry
"PKG",5,22,1,"PAH",1,1,596,0)
       number for the user in the NEW PERSON file (#200), and yymmdd.hhmmss is
"PKG",5,22,1,"PAH",1,1,597,0)
       the date and time the logging was initialized, and $J is the job number
"PKG",5,22,1,"PAH",1,1,598,0)
       of the user's process].  When logging is initialized for a subscript,
"PKG",5,22,1,"PAH",1,1,599,0)
       such as TEST4, the lifetime for the ^XTMP("TEST4" global is set or 
"PKG",5,22,1,"PAH",1,1,600,0)
       updated to a week from the current date.
"PKG",5,22,1,"PAH",1,1,601,0)
       
"PKG",5,22,1,"PAH",1,1,602,0)
  The EASY LEVEL field (#.04) can be used to specify the level of logging 
"PKG",5,22,1,"PAH",1,1,603,0)
desired.  The highest level (with respect to usual urgency) is FATAL.  
"PKG",5,22,1,"PAH",1,1,604,0)
The lowest level (again with respect to usual urgency) is DEBUG.  
"PKG",5,22,1,"PAH",1,1,605,0)
Between these two extremes are (in decreasing order of usual urgency) ERROR, 
"PKG",5,22,1,"PAH",1,1,606,0)
WARN, and INFO.  Choosing a specific level (e.g., INFO) will include all 
"PKG",5,22,1,"PAH",1,1,607,0)
higher levels as well (e.g., for INFO, any logging calls with a level of 
"PKG",5,22,1,"PAH",1,1,608,0)
FATAL, ERROR, WARN or INFO would be output).
"PKG",5,22,1,"PAH",1,1,609,0)
 
"PKG",5,22,1,"PAH",1,1,610,0)
 
"PKG",5,22,1,"PAH",1,1,611,0)
The ROUTINE FILTER field (#.05) may be used to control the routines which 
"PKG",5,22,1,"PAH",1,1,612,0)
logging is active in.  These controls permit the amount of 
"PKG",5,22,1,"PAH",1,1,613,0)
data logged to the system to be maintained at a reasonable amount, even if 
"PKG",5,22,1,"PAH",1,1,614,0)
a large number of users are actively using the code which is being logged.
"PKG",5,22,1,"PAH",1,1,615,0)
 
"PKG",5,22,1,"PAH",1,1,616,0)
If data has been entered in the USER FILTER field (#.06), logging will only 
"PKG",5,22,1,"PAH",1,1,617,0)
be activated for users whose internal entry number in file 200 are included 
"PKG",5,22,1,"PAH",1,1,618,0)
in the USER FILTER field.  
"PKG",5,22,1,"PAH",1,1,619,0)
 
"PKG",5,22,1,"PAH",1,1,620,0)
Specialized fields, which would not normally be required, bur are available, 
"PKG",5,22,1,"PAH",1,1,621,0)
are 
"PKG",5,22,1,"PAH",1,1,622,0)
 
"PKG",5,22,1,"PAH",1,1,623,0)
^DD(8992.7,.01,0)=NAME^RF^^0;1^K:$L(X)>30!(X?.N)!($L(X)<3)!'(X'?1P.E) X
"PKG",5,22,1,"PAH",1,1,624,0)
^DD(8992.7,.02,0)=ACTIVE^RS^N:NO;E:YES, EASY CONFIG;D:YES, DETAILED CONFIG;^0;2^
"PKG",5,22,1,"PAH",1,1,625,0)
Q
"PKG",5,22,1,"PAH",1,1,626,0)
^DD(8992.7,.03,0)=EZ ENTRY^F^^0;3^K:$L(X)>40!($L(X)<1) X
"PKG",5,22,1,"PAH",1,1,627,0)
^DD(8992.7,.04,0)=EZ LEVEL^S^FATAL:FATAL;ERROR:ERROR;WARN:WARN;INFO:INFO;DEBUG:D
"PKG",5,22,1,"PAH",1,1,628,0)
EBUG;^0;4^Q
"PKG",5,22,1,"PAH",1,1,629,0)
^DD(8992.7,.05,0)=ROUTINE FILTER^F^^0;5^K:$L(X)>80!($L(X)<3) X
"PKG",5,22,1,"PAH",1,1,630,0)
^DD(8992.7,.06,0)=USER FILTER^F^^0;6^K:$L(X)>60!($L(X)<1) X
"PKG",5,22,1,"PAH",1,1,631,0)
^DD(8992.7,.07,0)=OUTPUT ON CLOSE^S^N:NONE;P:PRINTER;M:MAIL MESSAGE;^0;7^Q
"PKG",5,22,1,"PAH",1,1,632,0)
^DD(8992.7,.08,0)=OUTPUT SPECS^F^^0;8^K:$L(X)>25!($L(X)<1) X
"PKG",5,22,1,"PAH",1,1,633,0)
^DD(8992.7,1,0)=DETAILED CONFIG^8992.71^^1;0
"PKG",5,22,1,"PAH",1,1,634,0)
^DD(8992.7,2.01,0)=PRINT LAYOUT^F^^2;1^K:$L(X)>40!($L(X)<5) X
"QUES","XPF1",0)
Y
"QUES","XPF1","??")
^D REP^XPDH
"QUES","XPF1","A")
Shall I write over your |FLAG| File
"QUES","XPF1","B")
YES
"QUES","XPF1","M")
D XPF1^XPDIQ
"QUES","XPF2",0)
Y
"QUES","XPF2","??")
^D DTA^XPDH
"QUES","XPF2","A")
Want my data |FLAG| yours
"QUES","XPF2","B")
YES
"QUES","XPF2","M")
D XPF2^XPDIQ
"QUES","XPI1",0)
YO
"QUES","XPI1","??")
^D INHIBIT^XPDH
"QUES","XPI1","A")
Want KIDS to INHIBIT LOGONs during the install
"QUES","XPI1","B")
NO
"QUES","XPI1","M")
D XPI1^XPDIQ
"QUES","XPM1",0)
PO^VA(200,:EM
"QUES","XPM1","??")
^D MG^XPDH
"QUES","XPM1","A")
Enter the Coordinator for Mail Group '|FLAG|'
"QUES","XPM1","B")

"QUES","XPM1","M")
D XPM1^XPDIQ
"QUES","XPO1",0)
Y
"QUES","XPO1","??")
^D MENU^XPDH
"QUES","XPO1","A")
Want KIDS to Rebuild Menu Trees Upon Completion of Install
"QUES","XPO1","B")
NO
"QUES","XPO1","M")
D XPO1^XPDIQ
"QUES","XPZ1",0)
Y
"QUES","XPZ1","??")
^D OPT^XPDH
"QUES","XPZ1","A")
Want to DISABLE Scheduled Options, Menu Options, and Protocols
"QUES","XPZ1","B")
NO
"QUES","XPZ1","M")
D XPZ1^XPDIQ
"QUES","XPZ2",0)
Y
"QUES","XPZ2","??")
^D RTN^XPDH
"QUES","XPZ2","A")
Want to MOVE routines to other CPUs
"QUES","XPZ2","B")
NO
"QUES","XPZ2","M")
D XPZ2^XPDIQ
"RTN")
8
"RTN","XTMLOG")
0^2^B136006720
"RTN","XTMLOG",1,0)
XTMLOG ;JLI/FO-OAK - LOG4M M LOGGING UTILITY ;11/15/10  10:43
"RTN","XTMLOG",2,0)
 ;;7.3;TOOLKIT;**81**;Apr 25, 1995;Build 26
"RTN","XTMLOG",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMLOG",4,0)
 ;
"RTN","XTMLOG",5,0)
 ; Routine provides logging capability similar in various
"RTN","XTMLOG",6,0)
 ; respects to Log4J.
"RTN","XTMLOG",7,0)
 ;
"RTN","XTMLOG",8,0)
 D EN^XTMUNIT("XTMTSTL1")
"RTN","XTMLOG",9,0)
 Q
"RTN","XTMLOG",10,0)
 ;
"RTN","XTMLOG",11,0)
INITFILE(DIRREF,FILEREF,NAME) ; jli .SR -- Configuration is read a file (DIRREF is the directory, and FILEREF is the filename)
"RTN","XTMLOG",12,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",13,0)
 N HOSTGLOB
"RTN","XTMLOG",14,0)
 S HOSTGLOB=$NA(^TMP("XTMLOG1",$J)) K @HOSTGLOB S @HOSTGLOB@(0)=""
"RTN","XTMLOG",15,0)
 I '$$FTG^%ZISH(DIRREF,FILEREF,$NA(@HOSTGLOB@(1)),3) Q 0
"RTN","XTMLOG",16,0)
 Q $$INITIAL(HOSTGLOB,$G(NAME,"XTMLOG"),XTLOGLIN)
"RTN","XTMLOG",17,0)
 ;
"RTN","XTMLOG",18,0)
FILEINIT(NAMEFLD) ; jli .SR -- called as extrinsic function
"RTN","XTMLOG",19,0)
 ; NAMEFLD - input - Name of entry in LOG4M CONFIG file (#8992.7 )
"RTN","XTMLOG",20,0)
 ;                   to be used for setting up logging
"RTN","XTMLOG",21,0)
 ; returns - 0 if initiating logging failed
"RTN","XTMLOG",22,0)
 ;           1 if initiating logging was successful
"RTN","XTMLOG",23,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",24,0)
 N XTMLIEN,XTMLACTV,XTMLRES,XTMLERR,XTMLARR,XVAL
"RTN","XTMLOG",25,0)
 ; ZEXCEPT: XTLOGINP - KILLED IN ENDLOG
"RTN","XTMLOG",26,0)
 S XTMLIEN=$O(^XTV(8992.7,"B",NAMEFLD,0)) I XTMLIEN'>0 Q 0
"RTN","XTMLOG",27,0)
 ; get data from the LOG4M CONFIG file
"RTN","XTMLOG",28,0)
 D GETS^DIQ(8992.7,XTMLIEN_",",".02:.06;3.01:3.03","I","XTMLRES","XTMLERR")
"RTN","XTMLOG",29,0)
 S XTMLARR=$NA(XTMLRES(8992.7,XTMLIEN_","))
"RTN","XTMLOG",30,0)
 ; quit if logging set to NO or it is not there
"RTN","XTMLOG",31,0)
 I ($G(@XTMLARR@(.02,"I"))="N")!($G(@XTMLARR@(.02,"I"))="") Q 0
"RTN","XTMLOG",32,0)
 ; Following change made to make different fields for print or mail at request of DBA for files
"RTN","XTMLOG",33,0)
 ;S XVAL=@XTMLARR@(.07,"I") I (XVAL="M")!(XVAL="P") S XTLOGINP(NAMEFLD,"OUTTYPE")=XVAL,XTLOGINP(NAMEFLD,"OUTSPECS")=@XTMLARR@(.08,"I") ;121228
"RTN","XTMLOG",34,0)
 S XVAL=@XTMLARR@(3.01,"I") I (XVAL="M")!(XVAL="P") S XTLOGINP(NAMEFLD,"OUTTYPE")=XVAL S:XVAL="M" XTLOGINP(NAMEFLD,"OUTSPECS")=@XTMLARR@(3.02,"I") S:XVAL="P" XTLOGINP(NAMEFLD,"OUTSPECS")=@XTMLARR@(3.03,"I") ; 121228
"RTN","XTMLOG",35,0)
 I @XTMLARR@(.02,"I")="E" Q $$INITEASY($G(@XTMLARR@(.03,"I")),$G(@XTMLARR@(.04,"I")),NAMEFLD,XTLOGLIN,$G(@XTMLARR@(.05,"I")),$G(@XTMLARR@(.06,"I")))
"RTN","XTMLOG",36,0)
 Q $$INITIAL($NA(@XTMLARR@(1)),NAMEFLD,XTLOGLIN)
"RTN","XTMLOG",37,0)
 ;
"RTN","XTMLOG",38,0)
INITGLOB(HOSTGLOB,NAME,XTLOGLIN) ; Configuration data is read under a global root - HOSTGLOB is a closed global root
"RTN","XTMLOG",39,0)
 I '$D(XTLOGLIN) S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",40,0)
 Q $$INITIAL(HOSTGLOB,$G(NAME,"XTMLOG"),XTLOGLIN)
"RTN","XTMLOG",41,0)
 ;
"RTN","XTMLOG",42,0)
INITNONE(NAME) ; No configuration data to read - use defaults - console and global logging
"RTN","XTMLOG",43,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",44,0)
 Q $$INITIAL("",$G(NAME,"XTMLOG"),"",XTLOGLIN)
"RTN","XTMLOG",45,0)
 ;
"RTN","XTMLOG",46,0)
INITEASY(CONFIG,LEVEL,NAME,XTLOGLIN,XTMLROUS,XTMLUSRS) ;
"RTN","XTMLOG",47,0)
 ; for INITEASY indicate the type of appenders desired as a series of ';'-pieces with names or first
"RTN","XTMLOG",48,0)
 ; letters to identify the appender type [C(onsole), (G)lobal, and S(ocket)].
"RTN","XTMLOG",49,0)
 ;    Global and Socket may have additional specifications separated by a Comma after the name
"RTN","XTMLOG",50,0)
 ;    indicator
"RTN","XTMLOG",51,0)
 ;       Global  -- Top Subscript under XTMP, if not specified "XTMLOG" is the default
"RTN","XTMLOG",52,0)
 ;       Socket  -- Port number for output of the logging data, if not specified 8025 is the default
"RTN","XTMLOG",53,0)
 ;
"RTN","XTMLOG",54,0)
 ;    use of D INITEASY^XTMLOG1("C;G,LOGDATA;S,9450","WARN") would have logging sent to
"RTN","XTMLOG",55,0)
 ;            the console,
"RTN","XTMLOG",56,0)
 ;            stored under ^XTMP("LOGDATA",  for a week, and
"RTN","XTMLOG",57,0)
 ;            sent out on a socket at port 9450 on the current system in real time
"RTN","XTMLOG",58,0)
 ;            for calls with priority or level at WARN or above.
"RTN","XTMLOG",59,0)
 ;
"RTN","XTMLOG",60,0)
 ;  XTMLROUS - An optional string containing a comma-separated list of routine names or namespaces,
"RTN","XTMLOG",61,0)
 ;            namespaces are indicated by an asterick following the namespace characters.
"RTN","XTMLOG",62,0)
 ;
"RTN","XTMLOG",63,0)
 I '$D(XTLOGLIN) N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",64,0)
 S CONFIG="*"_CONFIG I $G(LEVEL)'="" S CONFIG=CONFIG_";,"_LEVEL
"RTN","XTMLOG",65,0)
 Q $$INITIAL(CONFIG,$G(NAME,"XTMLOG"),XTLOGLIN,$G(XTMLROUS),$G(XTMLUSRS))
"RTN","XTMLOG",66,0)
 ;
"RTN","XTMLOG",67,0)
INITIAL(HOSTGLOB,NAME,XTLOGLIN,XTMLROUS,XTMLUSRS) ;
"RTN","XTMLOG",68,0)
 N XX,TESTLIST,I,X,XTCMLCNT,XTMLROU,XTMLCNT,XTMLRCNT
"RTN","XTMLOG",69,0)
 N XTLOGSET
"RTN","XTMLOG",70,0)
 ; ZEXCEPT: XTLOGINP - KILLED IN ENDLOG
"RTN","XTMLOG",71,0)
 I $G(XTMLUSRS)'="",(","_XTMLUSRS_",")'[(","_DUZ_",") Q 0 ; DON'T LOG FOR THIS USER
"RTN","XTMLOG",72,0)
 I $G(XTLOGLIN)="" S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",73,0)
 S NAME=$G(NAME,"XTMLOG"),XTMLROUS=$G(XTMLROUS)
"RTN","XTMLOG",74,0)
 I $G(HOSTGLOB)'="",$E(HOSTGLOB)'="*" D PARSE(NAME,HOSTGLOB,.XTLOGINP) I '$D(XTLOGINP) Q 0
"RTN","XTMLOG",75,0)
 S TESTLIST="FATAL^ERROR^WARN^INFO^DEBUG",XTLOGSET=""
"RTN","XTMLOG",76,0)
 I $E(HOSTGLOB)="*" D EASYSET($E(HOSTGLOB,2,99),NAME,.XTLOGINP)
"RTN","XTMLOG",77,0)
 D DEFAULTS(NAME,.XTLOGINP) ; set defaults if values not present
"RTN","XTMLOG",78,0)
 F I=1:1:5 S X=$P(TESTLIST,U,I) S XTLOGSET=XTLOGSET_","_I I X=XTLOGINP(NAME,"PRIORITY") Q
"RTN","XTMLOG",79,0)
 S XTLOGINP(NAME,"LOGSET")=XTLOGSET_",",XTLOGINP(NAME,"COUNT")=0
"RTN","XTMLOG",80,0)
 S XTMLRCNT=0 F I=1:1 S XTMLROU=$P($G(XTMLROUS),",",I) Q:XTMLROU=""  S XTMLRCNT=XTMLRCNT+1,XTLOGINP(NAME,"ROUS",XTMLRCNT)=XTMLROU,XTLOGINP(NAME,"ROUS")=XTMLRCNT
"RTN","XTMLOG",81,0)
 Q 1
"RTN","XTMLOG",82,0)
 ;
"RTN","XTMLOG",83,0)
CHKRLST(LOCATION,ROUNAME) ; function - indicates whether ROUNAME is among selected routines for logging
"RTN","XTMLOG",84,0)
 I $O(@LOCATION@("ROUS",0))'>0 Q 1
"RTN","XTMLOG",85,0)
 N I,VAL,XTMLRNAM
"RTN","XTMLOG",86,0)
 S VAL=0 F I=0:0 S I=$O(@LOCATION@("ROUS",I)) Q:I'>0  D  Q:VAL
"RTN","XTMLOG",87,0)
 . I @LOCATION@("ROUS",I)["*" S XTMLRNAM=$P(@LOCATION@("ROUS",I),"*") I $E(ROUNAME,1,$L(XTMLRNAM))=XTMLRNAM S VAL=1
"RTN","XTMLOG",88,0)
 . I @LOCATION@("ROUS",I)'["*",@LOCATION@("ROUS",I)=ROUNAME S VAL=1
"RTN","XTMLOG",89,0)
 . Q
"RTN","XTMLOG",90,0)
 Q VAL
"RTN","XTMLOG",91,0)
 ;
"RTN","XTMLOG",92,0)
STOPLOG(XTLOGNAM,OUTTYPE,OUTSPECS) ; JUST ANOTHER NAME FOR ENDLOG
"RTN","XTMLOG",93,0)
 D ENDLOG($G(XTLOGNAM),$G(OUTTYPE),$G(OUTSPECS))
"RTN","XTMLOG",94,0)
 Q
"RTN","XTMLOG",95,0)
 ;
"RTN","XTMLOG",96,0)
ENDLOG(XTLOGNAM,OUTTYPE,OUTSPECS) ; OUTTYPE, AND OUTSPECS ARE OPTIONAL - REMOVES LOGNAM FROM LOGGING
"RTN","XTMLOG",97,0)
 ; ZEXCEPT: XTLOGINP - KILLED HERE, SET ELSEWHERE
"RTN","XTMLOG",98,0)
 S XTLOGNAM=$G(XTLOGNAM,"XTMLOG")
"RTN","XTMLOG",99,0)
 I $G(OUTTYPE)="M"!($G(XTLOGINP(XTLOGNAM,"OUTTYPE"))="M") D SENDMAIL(XTLOGNAM,$S($G(OUTSPECS)'="":OUTSPECS,$G(XTLOGINP(XTLOGNAM,"OUTSPECS"))'="":XTLOGINP(XTLOGNAM,"OUTSPECS"),1:""))
"RTN","XTMLOG",100,0)
 I $G(OUTTYPE)="P"!($G(XTLOGINP(XTLOGNAM,"OUTTYPE"))="P") D PRINTIT(XTLOGNAM,$S($G(OUTSPECS)'="":OUTSPECS,$G(XTLOGINP(XTLOGNAM,"OUTSPECS"))'="":XTLOGINP(XTLOGNAM,"OUTSPECS"),1:""))
"RTN","XTMLOG",101,0)
 K XTLOGINP(XTLOGNAM)
"RTN","XTMLOG",102,0)
 Q
"RTN","XTMLOG",103,0)
 ;
"RTN","XTMLOG",104,0)
EASYSET(CONFIG,NAME,XTLOGINP) ;
"RTN","XTMLOG",105,0)
 N X
"RTN","XTMLOG",106,0)
 F  Q:CONFIG=""  S X=$P(CONFIG,";"),CONFIG=$P(CONFIG,";",2,99) D
"RTN","XTMLOG",107,0)
 . I $E(X)="C" D SETCONSO("C",NAME,.XTLOGINP)
"RTN","XTMLOG",108,0)
 . I $E(X)="G" D SETGLOB("G",$P(X,",",2),NAME,.XTLOGINP)
"RTN","XTMLOG",109,0)
 . I $E(X)="S" D SETSOCK("S",$P(X,",",2),NAME,.XTLOGINP)
"RTN","XTMLOG",110,0)
 . I $E(X)="," D SETLEVEL($P(X,",",2),NAME,.XTLOGINP)
"RTN","XTMLOG",111,0)
 . Q
"RTN","XTMLOG",112,0)
 Q
"RTN","XTMLOG",113,0)
 ;
"RTN","XTMLOG",114,0)
DEFAULTS(NAME,XTLOGINP) ; XTLOGINP is passed by reference
"RTN","XTMLOG",115,0)
 I '$D(XTLOGINP(NAME,"PRIORITY")) S XTLOGINP(NAME,"PRIORITY")="DEBUG" ; default priority is DEBUG
"RTN","XTMLOG",116,0)
 I '$D(XTLOGINP(NAME,"APPENDER")) D SETCONSO("A",NAME,.XTLOGINP) ; default is CONSOLEAPPENDER
"RTN","XTMLOG",117,0)
 Q
"RTN","XTMLOG",118,0)
 ;
"RTN","XTMLOG",119,0)
SETCONSO(ID,NAME,XTLOGINP) ;
"RTN","XTMLOG",120,0)
 N NODE
"RTN","XTMLOG",121,0)
 S NODE=$NA(XTLOGINP(NAME,"APPENDER",ID))
"RTN","XTMLOG",122,0)
 S @NODE@("TYPE")="CONSOLEAPPENDER",@NODE@("LAYOUT")="PATTERNLAYOUT"
"RTN","XTMLOG",123,0)
 S @NODE@("LAYOUT.CONVERSIONPATTERN")="%d %-5p %L %F - %m%n"
"RTN","XTMLOG",124,0)
 Q
"RTN","XTMLOG",125,0)
 ;
"RTN","XTMLOG",126,0)
SETGLOB(ID,SUBSCRIP,NAME,XTLOGINP) ;
"RTN","XTMLOG",127,0)
 N NODE,INFO
"RTN","XTMLOG",128,0)
 S NODE=$NA(XTLOGINP(NAME,"APPENDER",ID))
"RTN","XTMLOG",129,0)
 S @NODE@("TYPE")="GLOBAL",@NODE@("LAYOUT")="PATTERNLAYOUT"
"RTN","XTMLOG",130,0)
 S @NODE@("LAYOUT.CONVERSIONPATTERN")="%d %-5p %L %F - %m%n"
"RTN","XTMLOG",131,0)
 S SUBSCRIP=$S($G(SUBSCRIP)="":"XTMLOG",1:SUBSCRIP)
"RTN","XTMLOG",132,0)
 S:'$D(INFO("$H")) INFO("$H")=$H
"RTN","XTMLOG",133,0)
 N XTMLOGDT,FORMAT S FORMAT="{yyMMdd.HHmmss",XTMLOGDT=$$GETDATE^XTMLOG1(.INFO,.FORMAT)
"RTN","XTMLOG",134,0)
 S @NODE@("CLOSEDROOT")=$NA(^XTMP(SUBSCRIP,DUZ,XTMLOGDT,$J)) ; use current $H as constant and $J
"RTN","XTMLOG",135,0)
 S ^XTMP(SUBSCRIP,0)=$$FMADD^XLFDT(DT,7) ; Mark it to be saved for a week
"RTN","XTMLOG",136,0)
 Q
"RTN","XTMLOG",137,0)
 ;
"RTN","XTMLOG",138,0)
SETSOCK(ID,PORT,NAME,XTLOGINP) ;
"RTN","XTMLOG",139,0)
 N NODE
"RTN","XTMLOG",140,0)
 S NODE=$NA(XTLOGINP(NAME,"APPENDER",ID))
"RTN","XTMLOG",141,0)
 S @NODE@("TYPE")="SOCKETAPPENDER",@NODE@("LAYOUT")="PATTERNLAYOUT"
"RTN","XTMLOG",142,0)
 S @NODE@("LAYOUT.CONVERSIONPATTERN")="%d %-5p %L %F - %m%n"
"RTN","XTMLOG",143,0)
 S PORT=$S($G(PORT)="":8025,1:PORT)
"RTN","XTMLOG",144,0)
 S @NODE@("PORT")=PORT
"RTN","XTMLOG",145,0)
 D START^XTMLOSKT(PORT) ; Start socket running if it isn't already
"RTN","XTMLOG",146,0)
 Q
"RTN","XTMLOG",147,0)
 ;
"RTN","XTMLOG",148,0)
SETLEVEL(LEVEL,NAME,XTLOGINP) ;
"RTN","XTMLOG",149,0)
 N X
"RTN","XTMLOG",150,0)
 S X=$$UP^XLFSTR($E(LEVEL)),X=$S(X="D":5,X="I":4,X="W":3,X="E":2,X="F":1,1:5)
"RTN","XTMLOG",151,0)
 S XTLOGINP(NAME,"PRIORITY")=$P("FATAL^ERROR^WARN^INFO^DEBUG",U,X)
"RTN","XTMLOG",152,0)
 Q
"RTN","XTMLOG",153,0)
 ;
"RTN","XTMLOG",154,0)
PARSE(NAME,GLOBREF,RESULTS) ; parse configuration file - RESULTS is passed by reference
"RTN","XTMLOG",155,0)
 N XTMROOT,FILTYPE,INDEX,XLINE
"RTN","XTMLOG",156,0)
 N APPENDER,APPENDID,APPENDTY,I,REST
"RTN","XTMLOG",157,0)
 S FILTYPE="PROPERTIES"
"RTN","XTMLOG",158,0)
 S INDEX="" F  S INDEX=$O(@GLOBREF@(INDEX)) Q:INDEX=""  S XLINE=$G(@GLOBREF@(INDEX)) S:XLINE="" XLINE=$G(@GLOBREF@(INDEX,0)) I XLINE'="" S:XLINE["<?xml" FILTYPE="XML" Q
"RTN","XTMLOG",159,0)
 ;
"RTN","XTMLOG",160,0)
 I FILTYPE="XML" D ENTRY^XTMLOPAR(NAME,GLOBREF,.RESULTS) Q  ; Handle xml separately
"RTN","XTMLOG",161,0)
 ;
"RTN","XTMLOG",162,0)
 S INDEX="" F  S INDEX=$O(@GLOBREF@(INDEX)) Q:INDEX=""  S XLINE=$G(@GLOBREF@(INDEX)) S:XLINE="" XLINE=$G(@GLOBREF@(INDEX,0)) D
"RTN","XTMLOG",163,0)
 . S XLINE=$P(XLINE,"#") Q:XLINE=""
"RTN","XTMLOG",164,0)
 . ; have to get the rootlogger info first
"RTN","XTMLOG",165,0)
 . I '$D(XTMROOT) Q:$$UP^XLFSTR(XLINE)'["ROOTLOGGER"  D  Q
"RTN","XTMLOG",166,0)
 . . S XLINE=$P(XLINE,"=",2),XLINE=$TR(XLINE," ","")
"RTN","XTMLOG",167,0)
 . . S RESULTS(NAME,"PRIORITY")=$$UP^XLFSTR($P(XLINE,",")),XTMROOT=""
"RTN","XTMLOG",168,0)
 . . F  S XLINE=$P(XLINE,",",2,99) Q:XLINE=""  S RESULTS(NAME,"APPENDER",$$UP^XLFSTR($P(XLINE,",")))=""
"RTN","XTMLOG",169,0)
 . . Q
"RTN","XTMLOG",170,0)
 . S APPENDER=$P($$UP^XLFSTR(XLINE),"APPENDER.",2),REST=$P(XLINE,"=",2,99),APPENDER=$P(APPENDER,"=")
"RTN","XTMLOG",171,0)
 . S APPENDID=$P(APPENDER,"."),APPENDTY=$P(APPENDER,".",2,99)
"RTN","XTMLOG",172,0)
 . I APPENDTY="" S APPENDTY=$P(REST,".",$L(REST,".")) D
"RTN","XTMLOG",173,0)
 . . N STR,STR1,STR2 S STR="CONSOLEAPPENDER^ROLLINGFILEAPPENDER",STR2="CONSOLE^ROLLFILE"
"RTN","XTMLOG",174,0)
 . . F I=1:1 S STR1=$P(STR,U,I) Q:STR1=""  I $$UP^XLFSTR(APPENDTY)=STR1 S RESULTS(NAME,"APPENDER",APPENDID,"TYPE")=$E(STR1,1,8) Q
"RTN","XTMLOG",175,0)
 . . I STR1="" S RESULTS(NAME,"APPENDER",APPENDID,"TYPE")="UNKNOWN"
"RTN","XTMLOG",176,0)
 . . Q
"RTN","XTMLOG",177,0)
 . I APPENDTY="LAYOUT" S RESULTS(NAME,"APPENDER",APPENDID,APPENDTY)=$$UP^XLFSTR($P(REST,".",$L(REST,".")))
"RTN","XTMLOG",178,0)
 . E  S RESULTS(NAME,"APPENDER",APPENDID,APPENDTY)=REST
"RTN","XTMLOG",179,0)
 . Q
"RTN","XTMLOG",180,0)
 Q
"RTN","XTMLOG",181,0)
 ;
"RTN","XTMLOG",182,0)
ENABLED(NAME) ; .SR returns 1 if NAME is active -- USAGE $$ENABLED^XTMLOG1(NAME)
"RTN","XTMLOG",183,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",184,0)
 Q $S($D(XTLOGINP(NAME)):1,1:0)
"RTN","XTMLOG",185,0)
 ;
"RTN","XTMLOG",186,0)
DEBNABLD(NAME) ; .SR  returns 1 if DEBUG is enabled, otherwise zero
"RTN","XTMLOG",187,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",188,0)
 Q XTLOGINP(NAME,"LOGSET")[",5,"
"RTN","XTMLOG",189,0)
 ;
"RTN","XTMLOG",190,0)
INFNABLD(NAME) ;
"RTN","XTMLOG",191,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",192,0)
 Q XTLOGINP(NAME,"LOGSET")[",4,"
"RTN","XTMLOG",193,0)
 ;
"RTN","XTMLOG",194,0)
WARNABLD(NAME) ;
"RTN","XTMLOG",195,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",196,0)
 Q XTLOGINP(NAME,"LOGSET")[",3,"
"RTN","XTMLOG",197,0)
 ;
"RTN","XTMLOG",198,0)
ERRNABLD(NAME) ;
"RTN","XTMLOG",199,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",200,0)
 Q XTLOGINP(NAME,"LOGSET")[",2,"
"RTN","XTMLOG",201,0)
 ;
"RTN","XTMLOG",202,0)
FATNABLD(NAME) ;
"RTN","XTMLOG",203,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",204,0)
 Q XTLOGINP(NAME,"LOGSET")[",1,"
"RTN","XTMLOG",205,0)
 ;
"RTN","XTMLOG",206,0)
DEBUG(MESG,VARS,XTMLOARR) ; .SR
"RTN","XTMLOG",207,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",208,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",209,0)
 N XTLOGINF
"RTN","XTMLOG",210,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",211,0)
 S XTLOGINF("PRIORITY")="DEBUG"
"RTN","XTMLOG",212,0)
 D LOG(MESG,5,XTLOGLIN,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG",213,0)
 Q
"RTN","XTMLOG",214,0)
 ;
"RTN","XTMLOG",215,0)
INFO(MESG,VARS,XTMLOARR) ; .SR
"RTN","XTMLOG",216,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",217,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",218,0)
 N XTLOGINF
"RTN","XTMLOG",219,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",220,0)
 S XTLOGINF("PRIORITY")="INFO"
"RTN","XTMLOG",221,0)
 D LOG(MESG,4,XTLOGLIN,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG",222,0)
 Q
"RTN","XTMLOG",223,0)
 ;
"RTN","XTMLOG",224,0)
WARN(MESG,VARS,XTMLOARR) ; .SR
"RTN","XTMLOG",225,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",226,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",227,0)
 N XTLOGINF
"RTN","XTMLOG",228,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",229,0)
 S XTLOGINF("PRIORITY")="WARN"
"RTN","XTMLOG",230,0)
 D LOG(MESG,3,XTLOGLIN,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG",231,0)
 Q
"RTN","XTMLOG",232,0)
 ;
"RTN","XTMLOG",233,0)
ERROR(MESG,VARS,XTMLOARR) ; .SR
"RTN","XTMLOG",234,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",235,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",236,0)
 N XTLOGINF
"RTN","XTMLOG",237,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",238,0)
 S XTLOGINF("PRIORITY")="ERROR"
"RTN","XTMLOG",239,0)
 D LOG(MESG,2,XTLOGLIN,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG",240,0)
 Q
"RTN","XTMLOG",241,0)
 ;
"RTN","XTMLOG",242,0)
FATAL(MESG,VARS,XTMLOARR) ; .SR
"RTN","XTMLOG",243,0)
 ; ZEXCEPT: XTLOGINP - CREATED IN INITIAL, KILLED IN ENDLOG
"RTN","XTMLOG",244,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",245,0)
 N XTLOGINF
"RTN","XTMLOG",246,0)
 N XTLOGLIN S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",247,0)
 S XTLOGINF("PRIORITY")="FATAL"
"RTN","XTMLOG",248,0)
 D LOG(MESG,1,XTLOGLIN,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG",249,0)
 Q
"RTN","XTMLOG",250,0)
 ;
"RTN","XTMLOG",251,0)
LOG(MESG,SET,XTLOGLIN,VARS,XTMLOARR) ; .SR  entry point for logging an item
"RTN","XTMLOG",252,0)
 ; this will be ignored unless SETUP^XTMLOG has been called previously
"RTN","XTMLOG",253,0)
 ; MESG - any text that should be recorded for the current location
"RTN","XTMLOG",254,0)
 ;        (Required)
"RTN","XTMLOG",255,0)
 ;
"RTN","XTMLOG",256,0)
 ; SET - a set number if desired (if none is specified, it will always
"RTN","XTMLOG",257,0)
 ;       be logged when logging is active) set numbers may be integer
"RTN","XTMLOG",258,0)
 ;       values used to indicate a group of logging calls which are
"RTN","XTMLOG",259,0)
 ;       similar and should be active at the same time.  Using SETS a
"RTN","XTMLOG",260,0)
 ;       number of log points may be set up, but only those in an
"RTN","XTMLOG",261,0)
 ;       active set, or with no set specified will be recorded.  Thus,
"RTN","XTMLOG",262,0)
 ;       input data might be logged in set 1, values associated with a
"RTN","XTMLOG",263,0)
 ;       process might be set 2, etc. Specific sets that are active are
"RTN","XTMLOG",264,0)
 ;       specified through the SET parameter in the SETUP call.
"RTN","XTMLOG",265,0)
 ;
"RTN","XTMLOG",266,0)
 I '$D(XTLOGINP) Q
"RTN","XTMLOG",267,0)
 N APPENDID,APPNAME,APPTYPE,NAME,XTMECNT,XTMGLOB
"RTN","XTMLOG",268,0)
 ; ZEXCEPT: XTLOGINF,XTLOGINP
"RTN","XTMLOG",269,0)
 I $G(XTLOGLIN)="" S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",270,0)
 N XTMACTIV
"RTN","XTMLOG",271,0)
 S NAME="" F  S NAME=$O(XTLOGINP(NAME)) Q:NAME=""  D
"RTN","XTMLOG",272,0)
 . I $G(XTLOGINP(NAME,"LOGSET"))'="",$G(SET)'="",XTLOGINP(NAME,"LOGSET")'[(","_SET_",") Q  ; only process if set is in those specified or is not specified
"RTN","XTMLOG",273,0)
 . I '$$CHKRLST($NA(XTLOGINP(NAME)),$P(XTLOGLIN,"^",2)) Q
"RTN","XTMLOG",274,0)
 . S XTMACTIV(NAME)=""
"RTN","XTMLOG",275,0)
 . Q
"RTN","XTMLOG",276,0)
 I '$D(XTMACTIV) Q
"RTN","XTMLOG",277,0)
 ;
"RTN","XTMLOG",278,0)
 I $D(XTLOGINP) S NAME="" F  S NAME=$O(XTMACTIV(NAME)) Q:NAME=""  D
"RTN","XTMLOG",279,0)
 . S XTLOGINP(NAME,"COUNT")=$G(XTLOGINP(NAME,"COUNT"))+1
"RTN","XTMLOG",280,0)
 . S XTLOGINF("PRIORITY")=$S($D(SET):$P("FATAL^ERROR^WARN^INFO^DEBUG",U,SET),1:"    ")
"RTN","XTMLOG",281,0)
 . S XTLOGINF("$H")=$H,XTLOGINF("LOCATION")=XTLOGLIN
"RTN","XTMLOG",282,0)
 . S XTLOGINF("COUNT")=XTLOGINP(NAME,"COUNT")
"RTN","XTMLOG",283,0)
 . S APPENDID=""
"RTN","XTMLOG",284,0)
 . F  S APPENDID=$O(XTLOGINP(NAME,"APPENDER",APPENDID)) Q:APPENDID=""  D
"RTN","XTMLOG",285,0)
 . . S APPNAME="APPENDER",APPTYPE=XTLOGINP(NAME,APPNAME,APPENDID,"TYPE")
"RTN","XTMLOG",286,0)
 . . I $T(@($E(APPTYPE,1,8)_"^XTMLOG1"))'="" D @($E(APPTYPE,1,8)_"^XTMLOG1($NA(XTLOGINP(NAME,APPNAME,APPENDID)),.XTLOGINF,$G(MESG),$G(VARS),$G(XTMLOARR))") I 1
"RTN","XTMLOG",287,0)
 . . E  I '$G(XTMECNT) S $ZE="APPENDER *"_APPTYPE_"* NOT SUPPORTED IN XTMLOG1" D ^%ZTER S XTMECNT=1 ; indicate that appender is not available
"RTN","XTMLOG",288,0)
 . . Q
"RTN","XTMLOG",289,0)
 . Q
"RTN","XTMLOG",290,0)
 Q
"RTN","XTMLOG",291,0)
 ;
"RTN","XTMLOG",292,0)
SENDMAIL(XTMLOGID,RECIP) ; internal - used to generate an e-mail report.
"RTN","XTMLOG",293,0)
 N XMY,XMSUB,XMTEXT,XTMMAIL,XTI
"RTN","XTMLOG",294,0)
 I $G(RECIP)="" S XMY(DUZ)=""
"RTN","XTMLOG",295,0)
 E  F XTI=1:1 Q:$P(RECIP,";",XTI)=""  S XMY($P(RECIP,";",XTI))=""
"RTN","XTMLOG",296,0)
 S XTMMAIL=$NA(^TMP($J,"XTMLOG")) K @XTMMAIL
"RTN","XTMLOG",297,0)
 S XMSUB="Logged Data: "_XTMLOGID,XMTEXT="^TMP($J,""XTMLOG"","
"RTN","XTMLOG",298,0)
 I '$$SETGLOB1(XTMLOGID,XTMMAIL) Q  ; NO GLOBAL DATA TO SEND
"RTN","XTMLOG",299,0)
 D ^XMD
"RTN","XTMLOG",300,0)
 Q
"RTN","XTMLOG",301,0)
 ;
"RTN","XTMLOG",302,0)
PRINTIT(XTMLOGID,LOC) ; internal - LOC is printer specification in format for IOP
"RTN","XTMLOG",303,0)
 N GLOBLOC,IOP,I
"RTN","XTMLOG",304,0)
 S GLOBLOC=$NA(^TMP($J,"XTMLOG")) K @GLOBLOC
"RTN","XTMLOG",305,0)
 I '$$SETGLOB1(XTMLOGID,GLOBLOC) Q  ; NO GLOBAL DATA TO SEND
"RTN","XTMLOG",306,0)
 I $G(LOC)'="" S IOP=LOC D ^%ZIS U IO
"RTN","XTMLOG",307,0)
 F I=0:0 S I=$O(@GLOBLOC@(I)) Q:I'>0  W !,^(I)
"RTN","XTMLOG",308,0)
 I $G(LOC)'="" D ^%ZISC
"RTN","XTMLOG",309,0)
 Q
"RTN","XTMLOG",310,0)
 ;
"RTN","XTMLOG",311,0)
SETGLOB1(XTMLOGID,GLOBLOC) ; internal - move current data into output format
"RTN","XTMLOG",312,0)
 ; GLOBLOC is a closed global reference under which the output will be stored without zero nodes
"RTN","XTMLOG",313,0)
 N ROOT,NCNT,X1,X2,X3,X4
"RTN","XTMLOG",314,0)
 ; ZEXCEPT: XTLOGINP - CREATED ON INITIALIZATION, KILLED IN ENDLOG
"RTN","XTMLOG",315,0)
 S ROOT=$G(XTLOGINP(XTMLOGID,"APPENDER","G","CLOSEDROOT"))
"RTN","XTMLOG",316,0)
 I ROOT="" Q 0 ; NO GLOBAL REFERENCE - SO NO DATA
"RTN","XTMLOG",317,0)
 S NCNT=0
"RTN","XTMLOG",318,0)
 ; X1=CURRENT DATE/TIME X2=LOG SEQUENCE NUMBER X3=LINE^ROUTINE X4=COUNT IN CURRENT LOGGING
"RTN","XTMLOG",319,0)
 S X1="" F  S X1=$O(@ROOT@(X1)) Q:X1=""  S X2="" F  S X2=$O(@ROOT@(X1,X2)) Q:X2=""  S X3="" F  S X3=$O(@ROOT@(X1,X2,X3)) Q:X3=""  S X4="" F  S X4=$O(@ROOT@(X1,X2,X3,X4)) Q:X4=""  S NCNT=NCNT+1,@GLOBLOC@(NCNT)=@ROOT@(X1,X2,X3,X4)
"RTN","XTMLOG",320,0)
 Q NCNT>0
"RTN","XTMLOG",321,0)
 ;
"RTN","XTMLOG",322,0)
REALERR ; entry to log a real error
"RTN","XTMLOG",323,0)
 N XTLOGLIN,NAME,XTLOGINF,MESG
"RTN","XTMLOG",324,0)
 ; ZEXCEPT: XTLOGINP - CREATED ON INITIALIZATION, KILLED IN ENDLOG
"RTN","XTMLOG",325,0)
 S XTLOGLIN=$P($STACK($STACK-1,"PLACE")," ")
"RTN","XTMLOG",326,0)
 S MESG="Encountered Error: "_$ZE
"RTN","XTMLOG",327,0)
 S XTLOGINF("PRIORITY")="FATAL"
"RTN","XTMLOG",328,0)
 D LOG(MESG,1) S NAME="" F  S NAME=$O(XTLOGINP(NAME)) Q:NAME=""  D ENDLOG(NAME)
"RTN","XTMLOG",329,0)
 S $ETRAP=""
"RTN","XTMLOG",330,0)
 G ERR^ZU
"RTN","XTMLOG",331,0)
 Q
"RTN","XTMLOG1")
0^4^B46831784
"RTN","XTMLOG1",1,0)
XTMLOG1 ;jli/fo-oak - handle appender functions for Log4M ;06/07/08  17:06
"RTN","XTMLOG1",2,0)
 ;;7.3;TOOLKIT;**81**;Apr 25, 1995;Build 26
"RTN","XTMLOG1",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMLOG1",4,0)
 Q
"RTN","XTMLOG1",5,0)
 ; Each appender name is truncated to a max of eight characters and is a tag for the processing
"RTN","XTMLOG1",6,0)
 ; for that appender.
"RTN","XTMLOG1",7,0)
 ; 1st Argument is closed root for the appender information in the XTMINPUT array.
"RTN","XTMLOG1",8,0)
 ;      i.e.,  XTMINPUT(NAME,"APPENDER",APPENDID) The full appender name is at @ROOT@("TYPE")
"RTN","XTMLOG1",9,0)
 ;
"RTN","XTMLOG1",10,0)
 ; 2nd Argument is INFO data
"RTN","XTMLOG1",11,0)
 ;
"RTN","XTMLOG1",12,0)
 ; 3rd Argument is Message sent by logging call
"RTN","XTMLOG1",13,0)
 ;
"RTN","XTMLOG1",14,0)
 ; 4th Argument (optional) is a string of comma separated variable names, which will be included in the output.
"RTN","XTMLOG1",15,0)
 ;      Global nodes should be entered using $NA(
"RTN","XTMLOG1",16,0)
 ;      Example:  "VALUE1,VALUE2"  or  "VALUE1,"_$NA(^TMP($J,"VALUE"))_",VALUE2"
"RTN","XTMLOG1",17,0)
 ;
"RTN","XTMLOG1",18,0)
 ; 5th Argument (optional) a value of 1 if the variable(s) should be considered to be arrays and the values
"RTN","XTMLOG1",19,0)
 ;      of array elements should be displayed if they exist.
"RTN","XTMLOG1",20,0)
 ;
"RTN","XTMLOG1",21,0)
CONSOLEA(ROOT,INFO,MESSAGE,VARS,XTMLOARR) ;
"RTN","XTMLOG1",22,0)
 N GLOBREF,XTMLOGI S GLOBREF=$NA(^TMP("CONSOLEA",$J)) K @GLOBREF
"RTN","XTMLOG1",23,0)
 D SETLINES(GLOBREF,ROOT,.INFO,MESSAGE,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG1",24,0)
 F XTMLOGI=0:0 S XTMLOGI=$O(@GLOBREF@(XTMLOGI)) Q:XTMLOGI'>0  W !,@GLOBREF@(XTMLOGI)
"RTN","XTMLOG1",25,0)
 Q
"RTN","XTMLOG1",26,0)
 ;
"RTN","XTMLOG1",27,0)
ROLLINGF(ROOT,INFO,MESSAGE) ;
"RTN","XTMLOG1",28,0)
 Q
"RTN","XTMLOG1",29,0)
 ;
"RTN","XTMLOG1",30,0)
DAILYROL(ROOT,INFO,MESSAGE) ;
"RTN","XTMLOG1",31,0)
 Q
"RTN","XTMLOG1",32,0)
 ;
"RTN","XTMLOG1",33,0)
GLOBAL(ROOT,INFO,MESSAGE,VARS,XTMLOARR) ;
"RTN","XTMLOG1",34,0)
 N GLOBREF,XTMLOGI
"RTN","XTMLOG1",35,0)
 S GLOBREF=$NA(^TMP("XTMLGLOB",$J)) K @GLOBREF
"RTN","XTMLOG1",36,0)
 D SETLINES(GLOBREF,ROOT,.INFO,MESSAGE,$G(VARS),$G(XTMLOARR))
"RTN","XTMLOG1",37,0)
 N XTMLOGDT S XTMLOGDT=$$GETDATE(.INFO,"{yyMMdd.HHmmss")
"RTN","XTMLOG1",38,0)
 S:INFO("LOCATION")="" INFO("LOCATION")=" "
"RTN","XTMLOG1",39,0)
 F XTMLOGI=0:0 S XTMLOGI=$O(@GLOBREF@(XTMLOGI)) Q:XTMLOGI'>0  S @(@ROOT@("CLOSEDROOT"))@(XTMLOGDT,INFO("COUNT"),INFO("LOCATION"),XTMLOGI)=@GLOBREF@(XTMLOGI)
"RTN","XTMLOG1",40,0)
 Q
"RTN","XTMLOG1",41,0)
 ;
"RTN","XTMLOG1",42,0)
SOCKETAP(ROOT,INFO,MESSAGE) ;
"RTN","XTMLOG1",43,0)
 S ^TMP("XTMLOSKT","DATA",@ROOT@("PORT"),$J,INFO("COUNT"))=$$FORMAT(ROOT,.INFO,MESSAGE)
"RTN","XTMLOG1",44,0)
 Q
"RTN","XTMLOG1",45,0)
 ;
"RTN","XTMLOG1",46,0)
SETLINES(XTMLGLOB,ROOT,INFO,MESSAGE,VARS,XTMLOARR) ; returns lines for output in XTMLGLOB
"RTN","XTMLOG1",47,0)
 N XTMLOGI,XTMLOGJ,XTMLOGVR,XTMLOCHR,XTMLOCNT,XTMLOPAR,XTMLOQUO,XTMLOSRT,VARDATA,VARDATAQ,XTMLBASE
"RTN","XTMLOG1",48,0)
 K @XTMLGLOB
"RTN","XTMLOG1",49,0)
 S XTMLBASE=$$FORMAT(ROOT,.INFO,MESSAGE)
"RTN","XTMLOG1",50,0)
 S XTMLOPAR=0,XTMLOQUO=0,XTMLOCNT=0,XTMLOSRT=1
"RTN","XTMLOG1",51,0)
 I $G(VARS)="" S @XTMLGLOB@(1)=XTMLBASE Q
"RTN","XTMLOG1",52,0)
 S XTMLOARR=+$G(XTMLOARR)
"RTN","XTMLOG1",53,0)
 F XTMLOGI=1:1 S XTMLOCHR=$E(VARS,XTMLOGI) Q:XTMLOCHR=""  D
"RTN","XTMLOG1",54,0)
 . S:XTMLOCHR="(" XTMLOPAR=XTMLOPAR+1 S:XTMLOCHR=")" XTMLOPAR=XTMLOPAR-1 S:XTMLOCHR="""" XTMLOQUO=$S(XTMLOQUO=0:1,1:0) I XTMLOPAR=0,XTMLOQUO=0,XTMLOCHR="," S XTMLOCNT=XTMLOCNT+1,VARS(XTMLOCNT)=$E(VARS,XTMLOSRT,XTMLOGI-1),XTMLOSRT=XTMLOGI+1
"RTN","XTMLOG1",55,0)
 . Q
"RTN","XTMLOG1",56,0)
 I XTMLOGI>XTMLOSRT S XTMLOCNT=XTMLOCNT+1,VARS(XTMLOCNT)=$E(VARS,XTMLOSRT,XTMLOGI)
"RTN","XTMLOG1",57,0)
 S XTMLOCNT=0
"RTN","XTMLOG1",58,0)
 F XTMLOGI=1:1 Q:'$D(VARS(XTMLOGI))  S XTMLOGVR=VARS(XTMLOGI) S XTMLOCNT=XTMLOCNT+1,@XTMLGLOB@(XTMLOCNT)=XTMLBASE_" - "_VARS(XTMLOGI)_": "_$S($D(@VARS(XTMLOGI))#2:@VARS(XTMLOGI),1:"<undefined>") I XTMLOARR D
"RTN","XTMLOG1",59,0)
 . S VARDATA=VARS(XTMLOGI) I $D(@VARDATA)>1 D
"RTN","XTMLOG1",60,0)
 . . S VARDATAQ=$S($E(VARDATA,$L(VARDATA))=")":$E(VARDATA,1,$L(VARDATA)-1),1:"")
"RTN","XTMLOG1",61,0)
 . . F XTMLOGJ=1:1 S VARDATA=$Q(@(VARDATA)) Q:VARDATA=""  Q:((VARDATAQ'="")&(VARDATA'[VARDATAQ))  S XTMLOCNT=XTMLOCNT+1,@XTMLGLOB@(XTMLOCNT)=XTMLBASE_" - "_VARDATA_": "_$S($D(@VARDATA)#2:@VARDATA,1:"<undefined>")
"RTN","XTMLOG1",62,0)
 . . Q
"RTN","XTMLOG1",63,0)
 . Q
"RTN","XTMLOG1",64,0)
 Q
"RTN","XTMLOG1",65,0)
 ;
"RTN","XTMLOG1",66,0)
FORMAT(ROOT,INFO,MESSAGE) ; Generate Formatted message
"RTN","XTMLOG1",67,0)
 N XTMLOGX,FRMT,LJUST,MINWID,CATEGORY,PREC,DATESTR
"RTN","XTMLOG1",68,0)
 S XTMLOGX="",FRMT=$G(@ROOT@("LAYOUT.CONVERSIONPATTERN"))
"RTN","XTMLOG1",69,0)
 ; anything before % is actual text
"RTN","XTMLOG1",70,0)
 F  Q:FRMT=""  S XTMLOGX=XTMLOGX_$P(FRMT,"%"),FRMT=$P(FRMT,"%",2,99) D
"RTN","XTMLOG1",71,0)
 . I $E(FRMT)="%" S XTMLOGX=XTMLOGX_"%",FRMT=$$RESTOF(FRMT) Q  ; %% yields %
"RTN","XTMLOG1",72,0)
 . S LJUST=$S($E(FRMT)="-":1,1:0) I LJUST S FRMT=$$RESTOF(FRMT) ; - left justify
"RTN","XTMLOG1",73,0)
 . S MINWID="" F  Q:'(FRMT?1N.E)  S MINWID=MINWID_$E(FRMT),FRMT=$$RESTOF(FRMT) ; digits min width
"RTN","XTMLOG1",74,0)
 . S MINWID=+MINWID
"RTN","XTMLOG1",75,0)
 . I $E(FRMT)="n" S FRMT=$$RESTOF(FRMT) Q  ; end of line
"RTN","XTMLOG1",76,0)
 . I $E(FRMT)="c" S FRMT=$$RESTOF(FRMT),PREC=$$GETPREC(.FRMT),CATEGORY=$G(INFO("CATEGORY")) S:PREC>0 CATEGORY=$P(CATEGORY,".",$L(CATEGORY,".")-PREC+1,$L(CATEGORY,".")) S XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,CATEGORY) Q
"RTN","XTMLOG1",77,0)
 . I $E(FRMT)="p" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,$G(INFO("PRIORITY"))) Q
"RTN","XTMLOG1",78,0)
 . I $E(FRMT)="t" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,$J) Q
"RTN","XTMLOG1",79,0)
 . I $E(FRMT)="m" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,MESSAGE) Q
"RTN","XTMLOG1",80,0)
 . I $E(FRMT)="L" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,$P($G(INFO("LOCATION")),U)) Q
"RTN","XTMLOG1",81,0)
 . I $E(FRMT)="M" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,$P($P($G(INFO("LOCATION")),U),"+")) Q
"RTN","XTMLOG1",82,0)
 . I $E(FRMT)="F" S FRMT=$$RESTOF(FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,$P($G(INFO("LOCATION")),U,2)) Q
"RTN","XTMLOG1",83,0)
 . I $E(FRMT)="d" S FRMT=$$RESTOF(FRMT),DATESTR=$$GETDATE(.INFO,.FRMT),XTMLOGX=$$ADDTEXT(XTMLOGX,LJUST,MINWID,DATESTR) Q
"RTN","XTMLOG1",84,0)
 . S FRMT=$$RESTOF(FRMT) ; if unknown, just remove
"RTN","XTMLOG1",85,0)
 . Q
"RTN","XTMLOG1",86,0)
 Q XTMLOGX
"RTN","XTMLOG1",87,0)
 ;
"RTN","XTMLOG1",88,0)
RESTOF(X) ;
"RTN","XTMLOG1",89,0)
 Q $E(X,2,$L(X))
"RTN","XTMLOG1",90,0)
 ;
"RTN","XTMLOG1",91,0)
GETDATE(INFO,X) ; INFO and X are passed by refernce
"RTN","XTMLOG1",92,0)
 N FRMT,DATEVAL,X1,FMDATE
"RTN","XTMLOG1",93,0)
 I $E(X)="{" S X=$$RESTOF(X) S FRMT=$$DATEFRMT(.X)
"RTN","XTMLOG1",94,0)
 E  S FRMT="yyyyMMdd.HHmmss"
"RTN","XTMLOG1",95,0)
 I FRMT'="" S FMDATE=$$HTFM^XLFDT(INFO("$H"))
"RTN","XTMLOG1",96,0)
 S DATEVAL="" F  Q:FRMT=""  S X1=$E(FRMT),FRMT=$$RESTOF(FRMT) D
"RTN","XTMLOG1",97,0)
 . I X1="y" S X1=$$YEAR(FMDATE,.FRMT)
"RTN","XTMLOG1",98,0)
 . I X1="M" S X1=$$MONTH(FMDATE,.FRMT)
"RTN","XTMLOG1",99,0)
 . I X1="d" S X1=$$DAY(FMDATE,.FRMT)
"RTN","XTMLOG1",100,0)
 . I X1="H" S X1=$$HOUR(FMDATE,.FRMT)
"RTN","XTMLOG1",101,0)
 . I X1="m" S X1=$$MIN(FMDATE,.FRMT)
"RTN","XTMLOG1",102,0)
 . I X1="s" S X1=$$SEC(FMDATE,.FRMT)
"RTN","XTMLOG1",103,0)
 . I X1="S" S X1=$$MILLISEC(FMDATE,.FRMT)
"RTN","XTMLOG1",104,0)
 . S DATEVAL=DATEVAL_X1
"RTN","XTMLOG1",105,0)
 . Q
"RTN","XTMLOG1",106,0)
 Q DATEVAL
"RTN","XTMLOG1",107,0)
 ;
"RTN","XTMLOG1",108,0)
DATEFRMT(X) ; X is passed by reference
"RTN","XTMLOG1",109,0)
 N XVAL,X1 S XVAL=""
"RTN","XTMLOG1",110,0)
 F  Q:X=""  S X1=$E(X),X=$$RESTOF(X) S:X1'="}" XVAL=XVAL_X1 I X1="}" Q
"RTN","XTMLOG1",111,0)
 Q XVAL
"RTN","XTMLOG1",112,0)
 ;
"RTN","XTMLOG1",113,0)
ADDTEXT(STR,LJUST,MINWID,NEW) ;
"RTN","XTMLOG1",114,0)
 N FILL
"RTN","XTMLOG1",115,0)
 I MINWID>0 S $P(FILL," ",MINWID)=" "
"RTN","XTMLOG1",116,0)
 I $L(NEW)<MINWID D
"RTN","XTMLOG1",117,0)
 . I LJUST S NEW=NEW_FILL,NEW=$E(NEW,1,MINWID)
"RTN","XTMLOG1",118,0)
 . E  S NEW=FILL_NEW,NEW=$E(NEW,$L(NEW)-MINWID+1,$L(NEW))
"RTN","XTMLOG1",119,0)
 Q STR_NEW
"RTN","XTMLOG1",120,0)
 ;
"RTN","XTMLOG1",121,0)
GETPREC(X) ; X passed by reference
"RTN","XTMLOG1",122,0)
 ; dummy stub
"RTN","XTMLOG1",123,0)
 Q -1
"RTN","XTMLOG1",124,0)
 ;
"RTN","XTMLOG1",125,0)
YEAR(FMDATE,FRMT) ;
"RTN","XTMLOG1",126,0)
 N N
"RTN","XTMLOG1",127,0)
 S N=1 F  Q:$E(FRMT)'="y"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",128,0)
 Q $E($E(FMDATE,1,3)+1700,5-N,4)
"RTN","XTMLOG1",129,0)
 ;
"RTN","XTMLOG1",130,0)
MONTH(FMDATE,FRMT) ;
"RTN","XTMLOG1",131,0)
 N N,XVAL
"RTN","XTMLOG1",132,0)
 S N=1 F  Q:$E(FRMT)'="M"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",133,0)
 S XVAL=$E(FMDATE,4,5)
"RTN","XTMLOG1",134,0)
 I N=3 S XVAL=$P("JAN^FEB^MAR^APR^MAY^JUN^JUL^AUG^SEP^OCT^NOV^DEC",U,+XVAL)
"RTN","XTMLOG1",135,0)
 I N>3 S XVAL=$P("JANUARY^FEBRUARY^MARCH^APRIL^MAY^JUNE^JULY^AUGUST^SEPTEMBER^OCTOBER^NOVEMBER^DECEMBER",U,+XVAL)
"RTN","XTMLOG1",136,0)
 Q XVAL
"RTN","XTMLOG1",137,0)
 ;
"RTN","XTMLOG1",138,0)
DAY(FMDATE,FRMT) ;
"RTN","XTMLOG1",139,0)
 N N,XVAL
"RTN","XTMLOG1",140,0)
 S N=1 F  Q:$E(FRMT)'="d"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",141,0)
 S XVAL=$E(FMDATE,6,7)
"RTN","XTMLOG1",142,0)
 ;I N>2 S XVAL=$P
"RTN","XTMLOG1",143,0)
 Q XVAL
"RTN","XTMLOG1",144,0)
 ;
"RTN","XTMLOG1",145,0)
HOUR(FMDATE,FRMT) ;
"RTN","XTMLOG1",146,0)
 N N,XVAL
"RTN","XTMLOG1",147,0)
 S N=1 F  Q:$E(FRMT)'="H"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",148,0)
 S XVAL=$E(FMDATE_"OOO",9,10)
"RTN","XTMLOG1",149,0)
 I N=1 S FRMT=FRMT_$S(XVAL>12:" PM",1:" AM"),XVAL=$S(XVAL>12:XVAL-12,1:XVAL)
"RTN","XTMLOG1",150,0)
 Q XVAL
"RTN","XTMLOG1",151,0)
 ;
"RTN","XTMLOG1",152,0)
MIN(FMDATE,FRMT) ;
"RTN","XTMLOG1",153,0)
 N N,XVAL
"RTN","XTMLOG1",154,0)
 S N=1 F  Q:$E(FRMT)'="m"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",155,0)
 S XVAL=$E(FMDATE_"00000",11,12)
"RTN","XTMLOG1",156,0)
 I N=1 S XVAL=+XVAL
"RTN","XTMLOG1",157,0)
 Q XVAL
"RTN","XTMLOG1",158,0)
 ;
"RTN","XTMLOG1",159,0)
SEC(FMDATE,FRMT) ;
"RTN","XTMLOG1",160,0)
 N N,XVAL
"RTN","XTMLOG1",161,0)
 S N=1 F  Q:$E(FRMT)'="s"  S N=N+1,FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",162,0)
 S XVAL=$E(FMDATE_"0000000",13,14)
"RTN","XTMLOG1",163,0)
 I N=1 S XVAL=+XVAL
"RTN","XTMLOG1",164,0)
 Q XVAL
"RTN","XTMLOG1",165,0)
 ;
"RTN","XTMLOG1",166,0)
MILLISEC(FMDATE,FRMT) ;
"RTN","XTMLOG1",167,0)
 ; NO WAY TO GET MILLISECONDS, JUST PUT NULLS
"RTN","XTMLOG1",168,0)
 F  Q:$E(FRMT)'="S"  S FRMT=$$RESTOF(FRMT)
"RTN","XTMLOG1",169,0)
 Q ""
"RTN","XTMLOG2")
1^5
"RTN","XTMLOPAR")
0^6^B19404303
"RTN","XTMLOPAR",1,0)
XTMLOPAR ;JLI/FO-OAK - HANDLE PARSING FOR LOG4M XML CONFIGURATION FILE ;06/07/08  17:05
"RTN","XTMLOPAR",2,0)
 ;;7.3;TOOLKIT;**81**;Apr 25, 1995;Build 26
"RTN","XTMLOPAR",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMLOPAR",4,0)
 Q
"RTN","XTMLOPAR",5,0)
ENTRY(XTMNAME,GLOBROOT,RESULTS) ; RESULTS is passed by reference
"RTN","XTMLOPAR",6,0)
 S ELNUM=0,COUNT=0,APPCOUNT=0,GLOROOT=$NA(^TMP("JLIXML",$J)),GLOROOT(0)=GLOROOT K @GLOROOT
"RTN","XTMLOPAR",7,0)
 S ARRAY("STARTDOCUMENT")="STARTDOC^XTMLOPAR",ARRAY("ENDDOCUMENT")="ENDDOC^XTMLOPAR"
"RTN","XTMLOPAR",8,0)
 S ARRAY("DOCTYPE")="DOCTYPE^XTMLOPAR",ARRAY("STARTELEMENT")="STARTEL^XTMLOPAR"
"RTN","XTMLOPAR",9,0)
 S ARRAY("ENDELEMENT")="ENDEL^XTMLOPAR",ARRAY("CHARACTERS")="CHARS^XTMLOPAR"
"RTN","XTMLOPAR",10,0)
 S ARRAY("PI")="PI^XTMLOPAR",ARRAY("NOTATION")="NOTATION^XTMLOPAR"
"RTN","XTMLOPAR",11,0)
 S ARRAY("EXTERNAL")="EXTERNAL^XTMLOPAR",ARRAY("COMMENT")="COMMENT^XTMLOPAR",ARRAY("ERROR")="ERROR^XTMLOPAR"
"RTN","XTMLOPAR",12,0)
 D EN^MXMLPRSE(GLOBROOT,.ARRAY,"V")
"RTN","XTMLOPAR",13,0)
 Q
"RTN","XTMLOPAR",14,0)
 ;
"RTN","XTMLOPAR",15,0)
STARTDOC ; STARTDOCUMENT
"RTN","XTMLOPAR",16,0)
 W !,"START DOC ENTRY"
"RTN","XTMLOPAR",17,0)
 Q
"RTN","XTMLOPAR",18,0)
 ;
"RTN","XTMLOPAR",19,0)
ENDDOC ; ENDDOCUMENT
"RTN","XTMLOPAR",20,0)
 W !,"END DOC ENTRY"
"RTN","XTMLOPAR",21,0)
 Q
"RTN","XTMLOPAR",22,0)
 ;
"RTN","XTMLOPAR",23,0)
DOCTYPE(ROOT,PUBID,SYSID) ; DOCTYPE
"RTN","XTMLOPAR",24,0)
 W !,"DOCTYPE ENTRY"
"RTN","XTMLOPAR",25,0)
 W !,"ROOT=",ROOT,"  PUBID=",PUBID,"  SYSID=",SYSID
"RTN","XTMLOPAR",26,0)
 Q
"RTN","XTMLOPAR",27,0)
 ;
"RTN","XTMLOPAR",28,0)
STARTEL(NAME,ATTRIBS) ; STARTELEMENT
"RTN","XTMLOPAR",29,0)
 ;W !,"START ELEMENT ",NAME,! ZW ATTRIBS
"RTN","XTMLOPAR",30,0)
 S ELNUM=$G(ELNUM)+1
"RTN","XTMLOPAR",31,0)
 S COUNT=COUNT+1
"RTN","XTMLOPAR",32,0)
 S GLOROOT(ELNUM)=$NA(@GLOROOT(ELNUM-1)@(NAME,COUNT))
"RTN","XTMLOPAR",33,0)
 S A="" F  S A=$O(ATTRIBS(A)) Q:A=""  S @GLOROOT(ELNUM)@(A)=ATTRIBS(A)
"RTN","XTMLOPAR",34,0)
 S FLAG=$G(FLAG),PARAMFLG=""
"RTN","XTMLOPAR",35,0)
 I $$UP^XLFSTR(NAME)="ROOT" S FLAG="ROOT"
"RTN","XTMLOPAR",36,0)
 I $$UP^XLFSTR(NAME)="APPENDER" S FLAG="APPENDER",APPNAME=""
"RTN","XTMLOPAR",37,0)
 I $$UP^XLFSTR(NAME)="PARAM" S PARAMFLG=1
"RTN","XTMLOPAR",38,0)
 I FLAG="ROOT" D ROOT(NAME,.ATTRIBS)
"RTN","XTMLOPAR",39,0)
 I FLAG="APPENDER" D APPENDER(NAME,.ATTRIBS)
"RTN","XTMLOPAR",40,0)
 Q
"RTN","XTMLOPAR",41,0)
 ;
"RTN","XTMLOPAR",42,0)
ENDEL(NAME) ; ENDELEMENT
"RTN","XTMLOPAR",43,0)
 W !,"END ELEMENT ",NAME
"RTN","XTMLOPAR",44,0)
 K GLOROOT(ELNUM)
"RTN","XTMLOPAR",45,0)
 S ELNUM=ELNUM-1
"RTN","XTMLOPAR",46,0)
 Q
"RTN","XTMLOPAR",47,0)
 ;
"RTN","XTMLOPAR",48,0)
CHARS(TEXT) ; CHARACTERS
"RTN","XTMLOPAR",49,0)
 ;W !,"IN CHARS: ",TEXT
"RTN","XTMLOPAR",50,0)
 Q
"RTN","XTMLOPAR",51,0)
 ;
"RTN","XTMLOPAR",52,0)
PI(TARGET,TEXT) ; PI
"RTN","XTMLOPAR",53,0)
 ;W !,"IN PI: TARGET=",TARGET,"  TEXT=",TEXT
"RTN","XTMLOPAR",54,0)
 Q
"RTN","XTMLOPAR",55,0)
 ;
"RTN","XTMLOPAR",56,0)
NOTATION(NAME,SYSID,PUBIC) ; NOTATION
"RTN","XTMLOPAR",57,0)
 ;W !,"IN NOTATION, NAME=",NAME,"  SYSID=,$G(SYSID),"  PUBIC=",$G(PUBIC)
"RTN","XTMLOPAR",58,0)
 Q
"RTN","XTMLOPAR",59,0)
 ;
"RTN","XTMLOPAR",60,0)
EXTERNAL(SYSID,PUBID,GLOBAL) ; EXTERNAL
"RTN","XTMLOPAR",61,0)
 ;W !,"IN EXTERNAL SYSID=",$G(SYSID),"  PUBID=",$G(PUBID),"  GLOBAL=",$G(GLOBAL)
"RTN","XTMLOPAR",62,0)
 S PUBID=SYSID,SYSID=""
"RTN","XTMLOPAR",63,0)
 Q
"RTN","XTMLOPAR",64,0)
 ;
"RTN","XTMLOPAR",65,0)
COMMENT(TEXT) ; COMMENT
"RTN","XTMLOPAR",66,0)
 ;W !,"IN COMMENT: TEXT=",TEXT
"RTN","XTMLOPAR",67,0)
 Q
"RTN","XTMLOPAR",68,0)
 ;
"RTN","XTMLOPAR",69,0)
ERROR(ERR) ; ERROR - ERR is a local array
"RTN","XTMLOPAR",70,0)
 ;W !,"IN ERROR",! ZW ERR
"RTN","XTMLOPAR",71,0)
 Q
"RTN","XTMLOPAR",72,0)
 ;
"RTN","XTMLOPAR",73,0)
ROOT(NAME,ATTRIBS) ;
"RTN","XTMLOPAR",74,0)
 N ATTNAME,COUNT
"RTN","XTMLOPAR",75,0)
 ;W !,"IN ROOT: NAME=",NAME,! ZW ATTRIBS
"RTN","XTMLOPAR",76,0)
 S ATTNAME="",COUNT=0 F  S ATTNAME=$O(ATTRIBS(ATTNAME)) Q:ATTNAME=""  S COUNT=COUNT+1,XNAME(COUNT)=ATTNAME
"RTN","XTMLOPAR",77,0)
 I COUNT=1 S RESULTS(XTMNAME,$$UP^XLFSTR(NAME))=$$UP^XLFSTR(ATTRIBS(XNAME(1)))
"RTN","XTMLOPAR",78,0)
 Q
"RTN","XTMLOPAR",79,0)
 ;
"RTN","XTMLOPAR",80,0)
APPENDER(NAME,ATTRIBS) ;
"RTN","XTMLOPAR",81,0)
 I APPNAME="" D  Q
"RTN","XTMLOPAR",82,0)
 . S ATTNAME="" F  S ATTNAME=$O(ATTRIBS(ATTNAME)) Q:ATTNAME=""  I $$UP^XLFSTR(ATTNAME)="NAME" S APPCOUNT=APPCOUNT+1,APPNAME=APPCOUNT,RESULTS(XTMNAME,"APPENDER",APPNAME,"TYPE")=$$UP^XLFSTR(ATTRIBS(ATTNAME))
"RTN","XTMLOPAR",83,0)
 . I APPNAME'="" S ATTNAME="" F  S ATTNAME=$O(ATTRIBS(ATTNAME)) Q:ATTNAME=""  I $$UP^XLFSTR(ATTNAME)'="NAME" S RESULTS(XTMNAME,"APPENDER",APPNAME,$$UP^XLFSTR(ATTNAME))=$$UP^XLFSTR(ATTRIBS(ATTNAME))
"RTN","XTMLOPAR",84,0)
 . Q
"RTN","XTMLOPAR",85,0)
 ; now parameters
"RTN","XTMLOPAR",86,0)
 I PARAMFLG D  Q
"RTN","XTMLOPAR",87,0)
 . S ATTNAME="",XNAME="",XVALUE="" F  S ATTNAME=$O(ATTRIBS(ATTNAME)) Q:ATTNAME=""  S:$$UP^XLFSTR(ATTNAME)="NAME" XNAME=ATTNAME S:$$UP^XLFSTR(ATTNAME)="VALUE" XVALUE=ATTNAME
"RTN","XTMLOPAR",88,0)
 . I XNAME'="",XVALUE'="" S RESULTS(XTMNAME,"APPENDER",APPNAME,$$UP^XLFSTR(ATTRIBS(XNAME)))=$$UP^XLFSTR(ATTRIBS(XVALUE))
"RTN","XTMLOPAR",89,0)
 . Q
"RTN","XTMLOPAR",90,0)
 E  D DEBUG^XTMLOG("IN APPENDER WITH NO FLAG")
"RTN","XTMLOPAR",91,0)
 Q
"RTN","XTMLOPAR",92,0)
 ;
"RTN","XTMLOPAR",93,0)
LOADGLOB ; Load input (pasted) text into a global
"RTN","XTMLOPAR",94,0)
 N XGLOB,COUNT,X
"RTN","XTMLOPAR",95,0)
 W !,"Paste your text.  When there are no more lines within 5 seconds, it will finish.",!,":"
"RTN","XTMLOPAR",96,0)
 S XGLOB=$NA(^TMP("XTMLOAD",$J)) K @XGLOB
"RTN","XTMLOPAR",97,0)
 S COUNT=0 F  R X:5 Q:'$T  W ! D
"RTN","XTMLOPAR",98,0)
 . F  Q:$E(X,$L(X))'=" "  S X=$E(X,1,$L(X)-1) ; remove trailing spaces
"RTN","XTMLOPAR",99,0)
 . I X'="" S COUNT=COUNT+1,@XGLOB@(COUNT)=X ; skip null lines and store text
"RTN","XTMLOPAR",100,0)
 . Q
"RTN","XTMLOPAR",101,0)
 W !!,COUNT," lines input and stored under ",XGLOB
"RTN","XTMLOPAR",102,0)
 Q
"RTN","XTMLOSKT")
0^7^B36861478
"RTN","XTMLOSKT",1,0)
XTMLOSKT ;SLC/KCM;OAK/JLI - Socket Appender borrowed from XWBTCPL ;06/07/08  17:02
"RTN","XTMLOSKT",2,0)
 ;;7.3;T0OLKIT;**81**;Apr 25, 1995;Build 26
"RTN","XTMLOSKT",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMLOSKT",4,0)
 ;ISC-SF/EG - DHCP Broker
"RTN","XTMLOSKT",5,0)
 ;
"RTN","XTMLOSKT",6,0)
 ; This routine is the background process that listens for client
"RTN","XTMLOSKT",7,0)
 ; requests to connect to M.  When a request is received, This
"RTN","XTMLOSKT",8,0)
 ; procedure will job a routine to handle the requests of the client.
"RTN","XTMLOSKT",9,0)
 ;
"RTN","XTMLOSKT",10,0)
 ; This job may be started in the background with:  D STRT^XWBTCP(PORT)
"RTN","XTMLOSKT",11,0)
 ;
"RTN","XTMLOSKT",12,0)
 ; When running, this job may be stopped with:      D STOP^XWBTCP(PORT)
"RTN","XTMLOSKT",13,0)
 ;
"RTN","XTMLOSKT",14,0)
 ; Where port is the known service port to listen for connections
"RTN","XTMLOSKT",15,0)
 ;
"RTN","XTMLOSKT",16,0)
EN(XWBTSKT) ; -- accept clients and start the individual message handler
"RTN","XTMLOSKT",17,0)
 ;N $ETRAP,$ESTACK S $ETRAP="D ^%ZTER J EN^XTMLOSKT($G(XWBTSKT)) HALT"
"RTN","XTMLOSKT",18,0)
 N RETRY,X,XWBVER,XWBVOL,LEN,MSG,XWBOS,DONE,DSMTCP,NATIP
"RTN","XTMLOSKT",19,0)
 S U="^",RETRY="START"
"RTN","XTMLOSKT",20,0)
 X ^%ZOSF("UCI") S XWBVOL=$P(Y,",",2) ;(*p7,p9*)
"RTN","XTMLOSKT",21,0)
 IF $G(XWBTSKT)="" S XWBTSKT=9400 ; default service port
"RTN","XTMLOSKT",22,0)
 S XWBTDEV=XWBTSKT
"RTN","XTMLOSKT",23,0)
 ;
"RTN","XTMLOSKT",24,0)
 Q:'$$SEMAPHOR(XWBTSKT,"LOCK")  ; -- quit if job is already running
"RTN","XTMLOSKT",25,0)
 ;
"RTN","XTMLOSKT",26,0)
 S XWBDEBUG=$$GET^XPAR("SYS","XWBDEBUG")
"RTN","XTMLOSKT",27,0)
 I XWBDEBUG D LOGSTART^XWBDLOG("XTMLOSKT")
"RTN","XTMLOSKT",28,0)
 D UPDTREC(XWBTSKT,3) ;updt RPC BROKER SITE PARAMETER record as RUNNING
"RTN","XTMLOSKT",29,0)
 D MARKER^XWBTCP(XWBTSKT,-1) ;Clear marker
"RTN","XTMLOSKT",30,0)
 ;
"RTN","XTMLOSKT",31,0)
 H 2 ;Hibernate so caller can clear (*p16)
"RTN","XTMLOSKT",32,0)
 D SETNM^%ZOSV($E("XTML_Port:"_XWBTSKT,1,15)) ;change process name
"RTN","XTMLOSKT",33,0)
 S ^TMP("XTMLOSKT","$J",$J)=""
"RTN","XTMLOSKT",34,0)
 ;
"RTN","XTMLOSKT",35,0)
RESTART ;
"RTN","XTMLOSKT",36,0)
 N $ESTACK S $ETRAP="D ETRAP^XTMLOSKT"
"RTN","XTMLOSKT",37,0)
 S DONE=0,X=0
"RTN","XTMLOSKT",38,0)
 S XWBOS=$S(^%ZOSF("OS")["DSM":"DSM",^("OS")["OpenM":"OpenM",^("OS")["GT.M":"GTM",^("OS")["MSM":"MSM",1:"")
"RTN","XTMLOSKT",39,0)
 ;
"RTN","XTMLOSKT",40,0)
 S %T=0,IOF="!" ;Check for Open success (*p35)
"RTN","XTMLOSKT",41,0)
 I XWBOS="DSM" O XWBTSKT:TCPCHAN:5 S %T=$T ;Open listener
"RTN","XTMLOSKT",42,0)
 I XWBOS="OpenM" S XWBTDEV="|TCP|"_XWBTSKT O XWBTDEV:(:XWBTSKT:"AT"::512:512:10):5 S %T=$T ;512 buffers, queue = 10 (*p35)
"RTN","XTMLOSKT",43,0)
 I XWBOS="GTM" D
"RTN","XTMLOSKT",44,0)
 . S @("$ZINTERRUPT=""I $$JOBEXAM^ZU($ZPOSITION)""")
"RTN","XTMLOSKT",45,0)
 . S XWBTDEV="SKD$"_$J,XWBTSKT=XWBTSKT,IOF="#"
"RTN","XTMLOSKT",46,0)
 . O XWBTDEV:(ZLISTEN=XWBTSKT_":TCP":ATTACH="listener"):5:"SOCKET" ;S %T=$T Q:'%T
"RTN","XTMLOSKT",47,0)
 . U XWBTDEV S XWBTDEV("LISTENER")=$KEY
"RTN","XTMLOSKT",48,0)
 . W /LISTEN(1)
"RTN","XTMLOSKT",49,0)
 . U XWBTDEV S XWBTDEV("STATUS")=$KEY
"RTN","XTMLOSKT",50,0)
 . Q
"RTN","XTMLOSKT",51,0)
 ;
"RTN","XTMLOSKT",52,0)
 I XWBDEBUG D LOG^XWBTCPC("Port Open: "_XWBTSKT)
"RTN","XTMLOSKT",53,0)
 F  D  Q:DONE
"RTN","XTMLOSKT",54,0)
 . ; -- listen for connect & get the initial message from the client
"RTN","XTMLOSKT",55,0)
 . I XWBOS="DSM" U XWBTSKT
"RTN","XTMLOSKT",56,0)
 . I XWBOS="MSM" S XWBTDEV=56 O 56 U 56::"TCP" W /SOCKET("",XWBTSKT)
"RTN","XTMLOSKT",57,0)
 . I XWBOS="OpenM" U XWBTDEV R *X
"RTN","XTMLOSKT",58,0)
 . I XWBOS="GTM" D
"RTN","XTMLOSKT",59,0)
 . . K XWBTDEV("SOCKET")
"RTN","XTMLOSKT",60,0)
 . . F  D  Q:$D(XWBTDEV("SOCKET"))
"RTN","XTMLOSKT",61,0)
 . . . ;Wait for connection, $KEY will be "CONNECT|socket_handle|remote_ipaddress"
"RTN","XTMLOSKT",62,0)
 . . . U XWBTDEV W /WAIT(10) S XWBTDEV("KEY")=$KEY
"RTN","XTMLOSKT",63,0)
 . . . I XWBTDEV("KEY")="" Q
"RTN","XTMLOSKT",64,0)
 . . . S XWBTDEV("SOCKET")=$P(XWBTDEV("KEY"),"|",2)
"RTN","XTMLOSKT",65,0)
 . . . S (XWBTDEV("IP"),IO("GTM-IP"))=$P(XWBTDEV("KEY"),"|",3)
"RTN","XTMLOSKT",66,0)
 . . . U XWBTDEV:(SOCKET=XWBTDEV("SOCKET"):WIDTH=512:NOWRAP:EXCEPTION="GOTO ETRAP")
"RTN","XTMLOSKT",67,0)
 . . . Q
"RTN","XTMLOSKT",68,0)
 . . Q
"RTN","XTMLOSKT",69,0)
 . I $D(^TMP("XTMLOSKT","DATA",XWBTSKT)) D
"RTN","XTMLOSKT",70,0)
 . . U XWBTSKT
"RTN","XTMLOSKT",71,0)
 . . D FLUSH
"RTN","XTMLOSKT",72,0)
 . . N I,X S JOB="" F  Q:DONE  S JOB=$O(^TMP("XTMLOSKT","DATA",XWBTSKT,JOB)) Q:JOB=""  F I=0:0 S I=$O(^TMP("XTMLOSKT","DATA",XWBTSKT,JOB,I)) Q:I'>0  D
"RTN","XTMLOSKT",73,0)
 . . . S X=^TMP("XTMLOSKT","DATA",XWBTSKT,JOB,I) K ^(I) D
"RTN","XTMLOSKT",74,0)
 . . . . N $ETRAP,$ESTACK S $ETRAP="D IGNOR^XTMLOSKT"
"RTN","XTMLOSKT",75,0)
 . . . . W X,$C(13,10),@IOF I $D(^TMP("XTMLOSKT","STOP",XWBTSKT)) S DONE=1 K ^(XWBTSKT)
"RTN","XTMLOSKT",76,0)
 . . . Q
"RTN","XTMLOSKT",77,0)
 . . Q
"RTN","XTMLOSKT",78,0)
 . H 1
"RTN","XTMLOSKT",79,0)
 . I $D(^TMP("XTMLOSKT","STOP",XWBTSKT)) S DONE=1 K ^(XWBTSKT)
"RTN","XTMLOSKT",80,0)
 . Q
"RTN","XTMLOSKT",81,0)
 ; -- loop end
"RTN","XTMLOSKT",82,0)
 ;
"RTN","XTMLOSKT",83,0)
 S %=$$SEMAPHOR(XWBTSKT,"UNLOCK") ; destroy 'running flag'
"RTN","XTMLOSKT",84,0)
 D UPDTREC(XWBTSKT,6) ;updt RPC BROKER SITE PARAMETER record as STOPPED
"RTN","XTMLOSKT",85,0)
 IF XWBOS="DSM" C XWBTSKT ;Do Close last in case it gets an error
"RTN","XTMLOSKT",86,0)
 Q
"RTN","XTMLOSKT",87,0)
IGNOR ;
"RTN","XTMLOSKT",88,0)
 S IGNOR=$G(IGNOR)+1
"RTN","XTMLOSKT",89,0)
 ; S ^TMP("XTMLOSKT","IGNOR",IGNOR)=$H
"RTN","XTMLOSKT",90,0)
 S $ET="",$EC=""
"RTN","XTMLOSKT",91,0)
 Q
"RTN","XTMLOSKT",92,0)
 ;
"RTN","XTMLOSKT",93,0)
 ;
"RTN","XTMLOSKT",94,0)
ETRAP ; -- on trapped error, send error info to client
"RTN","XTMLOSKT",95,0)
 N XWBERC,XWBERR ;S $ETRAP="D ^%ZTER J EN^XTMLOSKT($G(XWBTSKT)) HALT"
"RTN","XTMLOSKT",96,0)
 S XWBERC=$$EC^%ZOSV,XWBERR=$C(24)_"M  ERROR="_XWBERC_$C(13,10)_"LAST REF="_$$LGR^%ZOSV_$C(4)
"RTN","XTMLOSKT",97,0)
 S ECOUNT=$G(ECOUNT)+1
"RTN","XTMLOSKT",98,0)
 S ^TMP("XTMLOSKT","ETRAP",ECOUNT,$H)=XWBERR
"RTN","XTMLOSKT",99,0)
 I (XWBERC["WRITE")!(XWBERC["READ") S $ECODE="" Q  ;
"RTN","XTMLOSKT",100,0)
 D ^%ZTER ;Record error and clear $ECODE
"RTN","XTMLOSKT",101,0)
 I XWBERC["F-DUPLNAM" D  HALT
"RTN","XTMLOSKT",102,0)
 . S %=$$SEMAPHOR(XWBTSKT,"UNLOCK") ; destroy 'running flag'
"RTN","XTMLOSKT",103,0)
 . D UPDTREC(XWBTSKT,6) ;updt RPC BROKER SITE PARAMETER record as STOPPED
"RTN","XTMLOSKT",104,0)
 . Q
"RTN","XTMLOSKT",105,0)
 Q
"RTN","XTMLOSKT",106,0)
 ;
"RTN","XTMLOSKT",107,0)
FLUSH ;Flush the input buffer
"RTN","XTMLOSKT",108,0)
 F  R X:0 Q:'$T
"RTN","XTMLOSKT",109,0)
 Q
"RTN","XTMLOSKT",110,0)
 ;
"RTN","XTMLOSKT",111,0)
RELEASE(%) ;Now release the connection. (*p7*)
"RTN","XTMLOSKT",112,0)
 ;Parameter is zero to Release, one to Close
"RTN","XTMLOSKT",113,0)
 I XWBOS="DSM" D  Q  ;(*p35)
"RTN","XTMLOSKT",114,0)
 . I $G(%) C XWBTSKT Q
"RTN","XTMLOSKT",115,0)
 . U XWBTSKT:DISCONNECT ; release this socket
"RTN","XTMLOSKT",116,0)
 I XWBOS="OpenM" D  Q  ;(*p35)
"RTN","XTMLOSKT",117,0)
 . I $G(%) C XWBTDEV Q
"RTN","XTMLOSKT",118,0)
 . W *-3,*-2 ;Send any data and release the socket
"RTN","XTMLOSKT",119,0)
 I XWBOS="GTM" D  Q  ;(*p35)
"RTN","XTMLOSKT",120,0)
 . I $G(%) C XWBTDEV Q
"RTN","XTMLOSKT",121,0)
 . C XWBTDEV:(SOCKET=XWBTDEV("SOCKET")) ;release the socket
"RTN","XTMLOSKT",122,0)
 I XWBOS="MSM" C 56
"RTN","XTMLOSKT",123,0)
 Q
"RTN","XTMLOSKT",124,0)
 ;
"RTN","XTMLOSKT",125,0)
UPDTREC(XWBTSKT,STATE,XWBENV) ; -- update STATUS field and ^%ZIS X-ref of the
"RTN","XTMLOSKT",126,0)
 ;RPC BROKER SITE PARAMETER file
"RTN","XTMLOSKT",127,0)
 ;XWBTSKT: listener port
"RTN","XTMLOSKT",128,0)
 N C,XWBOXIEN,XWBPOIEN,XWBFDA
"RTN","XTMLOSKT",129,0)
 S C=",",U="^"
"RTN","XTMLOSKT",130,0)
 I $G(XWBENV)'="" S Y=XWBENV
"RTN","XTMLOSKT",131,0)
 E  D GETENV^%ZOSV ;get Y=UCI^VOL^NODE^BOXLOOKUP of current system
"RTN","XTMLOSKT",132,0)
 ;I STATE=3 S ^%ZIS(8994.171,"RPCB Listener",$P(Y,U,2),$P(Y,U),$P(Y,U,4),XWBTSKT)=$J
"RTN","XTMLOSKT",133,0)
 ;I STATE=6 K ^%ZIS(8994.171,"RPCB Listener",$P(Y,U,2),$P(Y,U),$P(Y,U,4),XWBTSKT)
"RTN","XTMLOSKT",134,0)
 ;
"RTN","XTMLOSKT",135,0)
 S XWBOXIEN=$$FIND1^DIC(8994.17,",1,","",$P(Y,U,4)) ;find rec for box
"RTN","XTMLOSKT",136,0)
 S XWBPOIEN=$$FIND1^DIC(8994.171,C_XWBOXIEN_",1,","",XWBTSKT)
"RTN","XTMLOSKT",137,0)
 D:XWBPOIEN>0  ;update STATUS field if entry was found
"RTN","XTMLOSKT",138,0)
 . D FDA^DILF(8994.171,XWBPOIEN_C_XWBOXIEN_C_1_C,1,"R",STATE,"XWBFDA")
"RTN","XTMLOSKT",139,0)
 . D FILE^DIE("","XWBFDA")
"RTN","XTMLOSKT",140,0)
 Q
"RTN","XTMLOSKT",141,0)
 ;
"RTN","XTMLOSKT",142,0)
 ;
"RTN","XTMLOSKT",143,0)
SEMAPHOR(XWBTSKT,XWBACT) ;Lock/Unlock listener semaphore
"RTN","XTMLOSKT",144,0)
 ;XWBTSKT: listener port, XWBACT: "LOCK" | "UNLOCK" action to perform
"RTN","XTMLOSKT",145,0)
 ;if LOCK is requested, it will be attempted with 1 sec timeout and if
"RTN","XTMLOSKT",146,0)
 ;lock was obtained RESULT will be 1, otherwise it will be 0.  For
"RTN","XTMLOSKT",147,0)
 ;unlock RESULT will always be 1.
"RTN","XTMLOSKT",148,0)
 N RESULT
"RTN","XTMLOSKT",149,0)
 S U="^",RESULT=1
"RTN","XTMLOSKT",150,0)
 D GETENV^%ZOSV ;get Y=UCI^VOL^NODE^BOXLOOKUP of current system
"RTN","XTMLOSKT",151,0)
 I XWBACT="LOCK" D
"RTN","XTMLOSKT",152,0)
 . L +^%ZIS(8994.171,"RPCB Listener",$P(Y,U,2),$P(Y,U),$P(Y,U,4),XWBTSKT):1
"RTN","XTMLOSKT",153,0)
 . S RESULT=$T
"RTN","XTMLOSKT",154,0)
 E  L -^%ZIS(8994.171,"RPCB Listener",$P(Y,U,2),$P(Y,U),$P(Y,U,4),XWBTSKT)
"RTN","XTMLOSKT",155,0)
 Q RESULT
"RTN","XTMLOSKT",156,0)
 ;
"RTN","XTMLOSKT",157,0)
NEWJOB() ;Check if OK to start a new job, Return 1 if OK, 0 if not OK.
"RTN","XTMLOSKT",158,0)
 N X,Y,J
"RTN","XTMLOSKT",159,0)
 S X=$O(^XTV(8989.3,1,4,"B",XWBVOL,0)),J=$S(X>0:^XTV(8989.3,1,4,X,0),1:"ROU^y^1")
"RTN","XTMLOSKT",160,0)
 I $D(^%ZOSF("ACTJ")) X ^("ACTJ") I $P(J,U,3),($P(J,U,3)'>Y) Q 0
"RTN","XTMLOSKT",161,0)
 Q 1
"RTN","XTMLOSKT",162,0)
 ;
"RTN","XTMLOSKT",163,0)
START(PORT) ;
"RTN","XTMLOSKT",164,0)
 J EN^XTMLOSKT(PORT)
"RTN","XTMLOSKT",165,0)
 Q
"RTN","XTMLOSKT",166,0)
 ;
"RTN","XTMLOSKT",167,0)
STOP(PORT) ;
"RTN","XTMLOSKT",168,0)
 S ^TMP("XTMLOSKT","STOP",PORT)=""
"RTN","XTMLOSKT",169,0)
 Q
"RTN","XTMLOSKT",170,0)
 ;
"RTN","XTMLOSKT",171,0)
SETDATA(STR,PORT,COUNT) ;
"RTN","XTMLOSKT",172,0)
 S PORT=$G(PORT,8025),OLDCOUNT=$G(COUNT,$G(OLDCOUNT))+1
"RTN","XTMLOSKT",173,0)
 S ^TMP("XTMLOSKT","DATA",PORT,$J,OLDCOUNT)=STR
"RTN","XTMLOSKT",174,0)
 Q
"RTN","XTMLOSKT",175,0)
 ;
"RTN","XTMRPRNT")
0^1^B1220842
"RTN","XTMRPRNT",1,0)
XTMRPRNT ;ISC-SF.SEA/JLI - ROUTINE LISTER ;11/23/09  15:55
"RTN","XTMRPRNT",2,0)
 ;;7.3;TOOLKIT;**101**;Apr 25, 1995;Build 26
"RTN","XTMRPRNT",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMRPRNT",4,0)
 ;
"RTN","XTMRPRNT",5,0)
ENTRY ;
"RTN","XTMRPRNT",6,0)
 N DIF,I,IOP,ROU,X,XCNP
"RTN","XTMRPRNT",7,0)
 ; ZEXCEPT: IOM - SYSTEM VARIABLE
"RTN","XTMRPRNT",8,0)
 N OLDIOM S OLDIOM=IOM
"RTN","XTMRPRNT",9,0)
 X ^%ZOSF("RSEL") Q:$O(^UTILITY($J,""))=""
"RTN","XTMRPRNT",10,0)
 R !,"ENTER RETURN TO START: ",X:300 Q:'$T
"RTN","XTMRPRNT",11,0)
 S IOP=";255;" D ^%ZIS Q:POP
"RTN","XTMRPRNT",12,0)
 S ROU=0
"RTN","XTMRPRNT",13,0)
 F  S ROU=$O(^UTILITY($J,ROU)) Q:ROU=""  D
"RTN","XTMRPRNT",14,0)
 . W !,"ZR"
"RTN","XTMRPRNT",15,0)
 . K ^TMP($J,0)
"RTN","XTMRPRNT",16,0)
 . S X=ROU,XCNP=0,DIF="^TMP($J,0," X ^%ZOSF("LOAD")
"RTN","XTMRPRNT",17,0)
 . F I=0:0 S I=$O(^TMP($J,0,I)) Q:I'>0  D
"RTN","XTMRPRNT",18,0)
 . . S X=^TMP($J,0,I,0)
"RTN","XTMRPRNT",19,0)
 . . S X=$P(X," ")_$C(9)_$P(X," ",2,999)
"RTN","XTMRPRNT",20,0)
 . . W !,X
"RTN","XTMRPRNT",21,0)
 . W !,"ZS ",ROU
"RTN","XTMRPRNT",22,0)
 W !
"RTN","XTMRPRNT",23,0)
 S IOP=";"_OLDIOM_";" D ^%ZIS ; restore original margin
"RTN","XTMRPRNT",24,0)
 Q
"RTN","XTMUNIT")
0^3^B229505353
"RTN","XTMUNIT",1,0)
XTMUNIT ;OAKLAND OIFO/JLI - MUNIT UNIT TESTING FOR M ROUTINES ;2013-07-26  12:06 PM
"RTN","XTMUNIT",2,0)
 ;;7.3;TOOLKIT;**81**;Apr 25, 1995;Build 26
"RTN","XTMUNIT",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMUNIT",4,0)
 ; 100622 JLI - corrected typo in comments where XTMUINPT was listed as XTMUINP
"RTN","XTMUNIT",5,0)
 ; 100622 JLI - removed a comment which indicated data could potentially be returned from the called routine
"RTN","XTMUNIT",6,0)
 ;              in the XTMUINPT array.
"RTN","XTMUNIT",7,0)
 ; 100622 JLI - added code to handle STARTUP and SHUTDOWN from GUI app
"RTN","XTMUNIT",8,0)
 ; 110719 JLI - modified separators in GUI handling from ^ to ~~^~~
"RTN","XTMUNIT",9,0)
 ;              in the variable XTGUISEP if using a newer version of the
"RTN","XTMUNIT",10,0)
 ;              GUI app (otherwise, it is simply set to ^) since results
"RTN","XTMUNIT",11,0)
 ;              with a series of ^ embedded disturbed the output reported
"RTN","XTMUNIT",12,0)
 Q
"RTN","XTMUNIT",13,0)
 ;
"RTN","XTMUNIT",14,0)
EN(XTMURNAM,XTMUVERB) ; .SR Entry point with primary test routine name, optional 1 for verbose output
"RTN","XTMUNIT",15,0)
 N XTMULIST,XTMUROU,XTMUNIT
"RTN","XTMUNIT",16,0)
 I $G(XTMUVERB)'=1 S XTMUVERB=0
"RTN","XTMUNIT",17,0)
 S XTMULIST=1,XTMUROU(XTMULIST)=XTMURNAM
"RTN","XTMUNIT",18,0)
 D SETUT
"RTN","XTMUNIT",19,0)
 D EN1(.XTMUROU,XTMULIST)
"RTN","XTMUNIT",20,0)
 Q
"RTN","XTMUNIT",21,0)
 ;
"RTN","XTMUNIT",22,0)
SETUT ;
"RTN","XTMUNIT",23,0)
 ; VEN/SMH 26JUL2013
"RTN","XTMUNIT",24,0)
 I '$D(IO) S IO=$P
"RTN","XTMUNIT",25,0)
 N DIQUIET S DIQUIET=1 D DT^DICRW
"RTN","XTMUNIT",26,0)
 ; VEN/SMH 26JUL2013 END
"RTN","XTMUNIT",27,0)
 ;
"RTN","XTMUNIT",28,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",29,0)
 S XTMUNIT("IO")=IO,XTMUNIT("DEV")="",XTMUNIT("DEVN")="" F  S XTMUNIT("DEVN")=$O(^TMP("XUDEVICE",$J,XTMUNIT("DEVN"))) Q:XTMUNIT("DEVN")=""  I $G(^(XTMUNIT("DEVN"),"IO"))=IO S XTMUNIT("DEV")=^(0) Q
"RTN","XTMUNIT",30,0)
 I XTMUNIT("DEV")="" S XTMUNIT("DEV")="XTMUNIT DEVICE" D SAVDEV^%ZISUTL(XTMUNIT("DEV"))
"RTN","XTMUNIT",31,0)
 S XTMUNIT=1 ; set to identify unit test being run check with $$ISUTEST^XTMUNIT()
"RTN","XTMUNIT",32,0)
 Q
"RTN","XTMUNIT",33,0)
 ;
"RTN","XTMUNIT",34,0)
EN1(XTMUROU,XTMULIST) ;
"RTN","XTMUNIT",35,0)
 ; VEN/SMH 26JUL2013 - This block is refactored to fix problems with 
"RTN","XTMUNIT",36,0)
 ; SETUP and TEARDOWN not happening at the right time
"RTN","XTMUNIT",37,0)
 N XTMUERRL,XTMUK,XTMUI,XTMUJ,OLDIO,OLDIOFLG,OLDIONAM,XTMUSTRT
"RTN","XTMUNIT",38,0)
 ; ZEXCEPT: XTMUVERB   -- ARGUMENT TO EN
"RTN","XTMUNIT",39,0)
 ; ZEXCEPT: XTMUGUI      -- CONDITIONALLY DEFINED BY GUINEXT
"RTN","XTMUNIT",40,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED IN EN
"RTN","XTMUNIT",41,0)
 ;
"RTN","XTMUNIT",42,0)
 ; Structure map for XTMUNIT
"RTN","XTMUNIT",43,0)
 ; -- CURR = Counter for routine number. Used as sub in XTMUROU
"RTN","XTMUNIT",44,0)
 ; -- ECNT = Entry point count in loop (cf. NERT); VEN/SMH - Needed?
"RTN","XTMUNIT",45,0)
 ; -- FAIL = Number of failures
"RTN","XTMUNIT",46,0)
 ; -- CHK  = Number of checks ran (TF/EQ/FAIL)
"RTN","XTMUNIT",47,0)
 ; -- NENT = Number of entry points ran
"RTN","XTMUNIT",48,0)
 ; -- ERRN = Number of errors
"RTN","XTMUNIT",49,0)
 S XTMUNIT("CURR")=0,XTMUNIT("ECNT")=0,XTMUNIT("FAIL")=0,XTMUNIT("CHK")=0,XTMUNIT("NENT")=0,XTMUNIT("ERRN")=0
"RTN","XTMUNIT",50,0)
 ;
"RTN","XTMUNIT",51,0)
 ; -- GET LIST OF ROUTINES --
"RTN","XTMUNIT",52,0)
 ; first get any tree of routines from this one
"RTN","XTMUNIT",53,0)
 D GETTREE^XTMUNIT1(.XTMUROU,.XTMULIST)
"RTN","XTMUNIT",54,0)
 ;
"RTN","XTMUNIT",55,0)
 ; -- STARTUP --
"RTN","XTMUNIT",56,0)
 ; 070224 - following code added to allow one overall STARTUP code JLI
"RTN","XTMUNIT",57,0)
 F  S XTMUNIT("CURR")=XTMUNIT("CURR")+1 Q:'$D(XTMUROU(XTMUNIT("CURR")))  D  I $G(XTMUSTRT)'="" D @XTMUSTRT Q
"RTN","XTMUNIT",58,0)
 . I $T(@("STARTUP^"_XTMUROU(XTMUNIT("CURR"))))'="" S XTMUSTRT="STARTUP^"_XTMUROU(XTMUNIT("CURR"))
"RTN","XTMUNIT",59,0)
 . Q
"RTN","XTMUNIT",60,0)
 ; 070224 - end of addition JLI
"RTN","XTMUNIT",61,0)
 ;
"RTN","XTMUNIT",62,0)
 ;
"RTN","XTMUNIT",63,0)
 ; Now process each routine that has been referenced
"RTN","XTMUNIT",64,0)
 S XTMUNIT("CURR")=0
"RTN","XTMUNIT",65,0)
 F  S XTMUNIT("CURR")=XTMUNIT("CURR")+1 Q:'$D(XTMUROU(XTMUNIT("CURR")))  D
"RTN","XTMUNIT",66,0)
 . N XTMUETRY ; Test list to run
"RTN","XTMUNIT",67,0)
 . ; 
"RTN","XTMUNIT",68,0)
 . ; Collect Test list.
"RTN","XTMUNIT",69,0)
 . D CHEKTEST^XTMUNIT1(XTMUROU(XTMUNIT("CURR")),.XTMUNIT,.XTMUETRY)
"RTN","XTMUNIT",70,0)
 . ;
"RTN","XTMUNIT",71,0)
 . ; if a SETUP entry point exists, save it off in XTMUNIT
"RTN","XTMUNIT",72,0)
 . N XTMSETUP S XTMSETUP="SETUP^"_XTMUROU(XTMUNIT("CURR"))
"RTN","XTMUNIT",73,0)
 . S XTMUNIT("LINE")=$T(@XTMSETUP) I XTMUNIT("LINE")'="" S XTMUNIT("SETUP")=XTMSETUP
"RTN","XTMUNIT",74,0)
 . K XTMSETUP ; we're done!
"RTN","XTMUNIT",75,0)
 . ;
"RTN","XTMUNIT",76,0)
 . ; if a TEARDOWN entry point exists, ditto
"RTN","XTMUNIT",77,0)
 . N XTMTEARDOWN S XTMTEARDOWN="TEARDOWN^"_XTMUROU(XTMUNIT("CURR"))
"RTN","XTMUNIT",78,0)
 . S XTMUNIT("LINE")=$T(@XTMTEARDOWN) I XTMUNIT("LINE")'="" S XTMUNIT("TEARDOWN")=XTMTEARDOWN
"RTN","XTMUNIT",79,0)
 . K XTMTEARDOWN ; done here.
"RTN","XTMUNIT",80,0)
 . ;
"RTN","XTMUNIT",81,0)
 . ; VEN/SMH 26JUL2013 - this block changed to correct running of setup and teardown
"RTN","XTMUNIT",82,0)
 . ; run each of the specified entry points
"RTN","XTMUNIT",83,0)
 . ;
"RTN","XTMUNIT",84,0)
 . ; == THIS FOR/DO BLOCK IS THE CENTRAL TEST RUNNER ==
"RTN","XTMUNIT",85,0)
 . S XTMUI=0
"RTN","XTMUNIT",86,0)
 . F  S XTMUI=$O(XTMUETRY(XTMUI)) Q:XTMUI'>0  S XTMUNIT("ENUM")=XTMUNIT("ERRN")+XTMUNIT("FAIL") D  I XTMUVERB,'$D(XTMUGUI),XTMUNIT("ENUM")=(XTMUNIT("ERRN")+XTMUNIT("FAIL")) D VERBOSE(.XTMUETRY,XTMUI)
"RTN","XTMUNIT",87,0)
 . . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",88,0)
 . . ; 
"RTN","XTMUNIT",89,0)
 . . ; Run Set-up Code (only if present)
"RTN","XTMUNIT",90,0)
 . . S XTMUNIT("ENT")=$G(XTMUNIT("SETUP")) ; Current entry
"RTN","XTMUNIT",91,0)
 . . S XTMUNIT("NAME")="Set-up Code"
"RTN","XTMUNIT",92,0)
 . . D:XTMUNIT("ENT")]"" @XTMUNIT("ENT")
"RTN","XTMUNIT",93,0)
 . . ;
"RTN","XTMUNIT",94,0)
 . . ; Run actual test
"RTN","XTMUNIT",95,0)
 . . S XTMUNIT("ECNT")=XTMUNIT("ECNT")+1
"RTN","XTMUNIT",96,0)
 . . S XTMUNIT("NAME")=XTMUETRY(XTMUI,"NAME")
"RTN","XTMUNIT",97,0)
 . . S XTMUNIT("ENT")=XTMUETRY(XTMUI)_"^"_XTMUROU(XTMUNIT("CURR"))
"RTN","XTMUNIT",98,0)
 . . D @XTMUNIT("ENT")
"RTN","XTMUNIT",99,0)
 . . ;
"RTN","XTMUNIT",100,0)
 . . ; Run Teardown Code (only if present)
"RTN","XTMUNIT",101,0)
 . . S XTMUNIT("ENT")=$G(XTMUNIT("TEARDOWN"))
"RTN","XTMUNIT",102,0)
 . . S XTMUNIT("NAME")="Teardown Code"
"RTN","XTMUNIT",103,0)
 . . D:XTMUNIT("ENT")]"" @XTMUNIT("ENT")
"RTN","XTMUNIT",104,0)
 . ;
"RTN","XTMUNIT",105,0)
 . ;
"RTN","XTMUNIT",106,0)
 . ; keep a XTMUCNT of number of entry points executed across all routines
"RTN","XTMUNIT",107,0)
 . S XTMUNIT("NENT")=XTMUNIT("NENT")+XTMUNIT("ENTN")
"RTN","XTMUNIT",108,0)
 . Q
"RTN","XTMUNIT",109,0)
 ;
"RTN","XTMUNIT",110,0)
 ; -- SHUTDOWN --
"RTN","XTMUNIT",111,0)
 ; 070224 - following code added to allow one overall SHUTDOWN code JLI
"RTN","XTMUNIT",112,0)
 N XTFINISH
"RTN","XTMUNIT",113,0)
 S XTMUNIT("CURR")=0
"RTN","XTMUNIT",114,0)
 F  S XTMUNIT("CURR")=XTMUNIT("CURR")+1 Q:'$D(XTMUROU(XTMUNIT("CURR")))  D  I $G(XTFINISH)'="" D @XTFINISH Q
"RTN","XTMUNIT",115,0)
 . I $T(@("SHUTDOWN^"_XTMUROU(XTMUNIT("CURR"))))'="" S XTFINISH="SHUTDOWN^"_XTMUROU(XTMUNIT("CURR"))
"RTN","XTMUNIT",116,0)
 . Q
"RTN","XTMUNIT",117,0)
 ; 070224 - End of addition JLI
"RTN","XTMUNIT",118,0)
 ;
"RTN","XTMUNIT",119,0)
 S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",120,0)
 I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",121,0)
 W !!,"Ran ",XTMULIST," Routine",$S(XTMULIST>1:"s",1:""),", ",XTMUNIT("NENT")," Entry Tag",$S(XTMUNIT("NENT")>1:"s",1:"")
"RTN","XTMUNIT",122,0)
 W !,"Checked ",XTMUNIT("CHK")," test",$S(XTMUNIT("CHK")>1:"s",1:""),", with ",XTMUNIT("FAIL")," failure",$S(XTMUNIT("FAIL")'=1:"s",1:"")," and encountered ",XTMUNIT("ERRN")," error",$S(XTMUNIT("ERRN")'=1:"s",1:""),"."
"RTN","XTMUNIT",123,0)
 I OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",124,0)
 Q
"RTN","XTMUNIT",125,0)
 ; -- end EN1
"RTN","XTMUNIT",126,0)
VERBOSE(XTMUETRY,XTMUI) ;
"RTN","XTMUNIT",127,0)
 N OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",128,0)
 ; ZEXCEPT: XTMUNIT - NEWED IN EN
"RTN","XTMUNIT",129,0)
 S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",130,0)
 I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",131,0)
 W !,"OK - ",XTMUETRY(XTMUI) I $G(XTMUETRY(XTMUI,"NAME"))'="" W " - ",XTMUETRY(XTMUI,"NAME")
"RTN","XTMUNIT",132,0)
 IF OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",133,0)
 Q
"RTN","XTMUNIT",134,0)
 ;
"RTN","XTMUNIT",135,0)
CHKTF(XTSTVAL,XTERMSG) ; Entry point for checking True or False values
"RTN","XTMUNIT",136,0)
 N OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",137,0)
 ; ZEXCEPT: XTMUERRL,XTMUGUI - CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",138,0)
 ; ZEXCEPT: XTMUNIT - NEWED IN EN
"RTN","XTMUNIT",139,0)
 I $G(XTSTVAL)="" D NVLDARG Q
"RTN","XTMUNIT",140,0)
 I $G(XTERMSG)="" S XTERMSG="no failure message provided"
"RTN","XTMUNIT",141,0)
 S XTMUNIT("CHK")=$G(XTMUNIT("CHK"))+1
"RTN","XTMUNIT",142,0)
 I '$D(XTMUGUI) D
"RTN","XTMUNIT",143,0)
 . S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",144,0)
 . I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",145,0)
 . I 'XTSTVAL W !,XTMUNIT("ENT")," - " W:XTMUNIT("NAME")'="" XTMUNIT("NAME")," - " D
"RTN","XTMUNIT",146,0)
 . . W XTERMSG,! S XTMUNIT("FAIL")=XTMUNIT("FAIL")+1,XTMUERRL(XTMUNIT("FAIL"))=XTMUNIT("NAME"),XTMUERRL(XTMUNIT("FAIL"),"MSG")=XTERMSG,XTMUERRL(XTMUNIT("FAIL"),"ENTRY")=XTMUNIT("ENT")
"RTN","XTMUNIT",147,0)
 . . Q
"RTN","XTMUNIT",148,0)
 . E  W "."
"RTN","XTMUNIT",149,0)
 . I OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",150,0)
 . Q
"RTN","XTMUNIT",151,0)
 I $D(XTMUGUI),'XTSTVAL S XTMUNIT("CNT")=XTMUNIT("CNT")+1,@XTMUNIT("RSLT")@(XTMUNIT("CNT"))=XTMUNIT("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG
"RTN","XTMUNIT",152,0)
 Q
"RTN","XTMUNIT",153,0)
 ;
"RTN","XTMUNIT",154,0)
CHKEQ(XTEXPECT,XTACTUAL,XTERMSG) ; Entry point for checking values to see if they are EQUAL
"RTN","XTMUNIT",155,0)
 N FAILMSG,OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",156,0)
 ; ZEXCEPT: XTMUERRL,XTMUGUI -CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",157,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED IN EN
"RTN","XTMUNIT",158,0)
 I '$D(XTEXPECT),'$D(XTACTUAL) D NVLDARG Q
"RTN","XTMUNIT",159,0)
 S XTACTUAL=$G(XTACTUAL),XTEXPECT=$G(XTEXPECT)
"RTN","XTMUNIT",160,0)
 I $G(XTERMSG)="" S XTERMSG="no failure message provided"
"RTN","XTMUNIT",161,0)
 S XTMUNIT("CHK")=XTMUNIT("CHK")+1
"RTN","XTMUNIT",162,0)
 I XTEXPECT'=XTACTUAL S FAILMSG="<"_XTEXPECT_"> vs <"_XTACTUAL_"> - "
"RTN","XTMUNIT",163,0)
 I '$D(XTMUGUI) D
"RTN","XTMUNIT",164,0)
 . S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",165,0)
 . I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",166,0)
 . I XTEXPECT'=XTACTUAL W !,XTMUNIT("ENT")," - " W:XTMUNIT("NAME")'="" XTMUNIT("NAME")," - " W FAILMSG,XTERMSG,! D
"RTN","XTMUNIT",167,0)
 . . S XTMUNIT("FAIL")=XTMUNIT("FAIL")+1,XTMUERRL(XTMUNIT("FAIL"))=XTMUNIT("NAME"),XTMUERRL(XTMUNIT("FAIL"),"MSG")=XTERMSG,XTMUERRL(XTMUNIT("FAIL"),"ENTRY")=XTMUNIT("ENT")
"RTN","XTMUNIT",168,0)
 . . Q
"RTN","XTMUNIT",169,0)
 . E  W "."
"RTN","XTMUNIT",170,0)
 . I OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",171,0)
 . Q
"RTN","XTMUNIT",172,0)
 I $D(XTMUGUI),XTEXPECT'=XTACTUAL S XTMUNIT("CNT")=XTMUNIT("CNT")+1,@XTMUNIT("RSLT")@(XTMUNIT("CNT"))=XTMUNIT("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_FAILMSG_XTERMSG
"RTN","XTMUNIT",173,0)
 Q
"RTN","XTMUNIT",174,0)
 ;
"RTN","XTMUNIT",175,0)
FAIL(XTERMSG) ; Entry point for generating a failure message
"RTN","XTMUNIT",176,0)
 N OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",177,0)
 ; ZEXCEPT: XTMUERRL,XTMUGUI -CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",178,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",179,0)
 I $G(XTERMSG)="" S XTERMSG="no failure message provided"
"RTN","XTMUNIT",180,0)
 S XTMUNIT("CHK")=XTMUNIT("CHK")+1
"RTN","XTMUNIT",181,0)
 I '$D(XTMUGUI) D
"RTN","XTMUNIT",182,0)
 . S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",183,0)
 . I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",184,0)
 . W !,XTMUNIT("ENT")," - " W:XTMUNIT("NAME")'="" XTMUNIT("NAME")," - " W XTERMSG,! D
"RTN","XTMUNIT",185,0)
 . . S XTMUNIT("FAIL")=XTMUNIT("FAIL")+1,XTMUERRL(XTMUNIT("FAIL"))=XTMUNIT("NAME"),XTMUERRL(XTMUNIT("FAIL"),"MSG")=XTERMSG,XTMUERRL(XTMUNIT("FAIL"),"ENTRY")=XTMUNIT("ENT")
"RTN","XTMUNIT",186,0)
 . . Q
"RTN","XTMUNIT",187,0)
 . I OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",188,0)
 . Q
"RTN","XTMUNIT",189,0)
 I $D(XTMUGUI) S XTMUNIT("CNT")=XTMUNIT("CNT")+1,@XTMUNIT("RSLT")@(XTMUNIT("CNT"))=XTMUNIT("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG
"RTN","XTMUNIT",190,0)
 Q
"RTN","XTMUNIT",191,0)
 ;
"RTN","XTMUNIT",192,0)
CHKLEAKS(XTMUCODE,XTMULOC,XTMUINPT) ; functionality to check for variable leaks on executing a section of code
"RTN","XTMUNIT",193,0)
 ; XTMUCODE - A string that specifies the code that is to be XECUTED and checked for leaks.
"RTN","XTMUNIT",194,0)
 ;            this should be a complete piece of code (e.g., "S X=$$NEW^XLFDT()" or "D EN^XTMUNIT(""ROUNAME"")")
"RTN","XTMUNIT",195,0)
 ; XTMULOC  - A string that is used to indicate the code tested for variable leaks
"RTN","XTMUNIT",196,0)
 ; XTMUINPT - An optional variable which may be passed by reference.  This may
"RTN","XTMUNIT",197,0)
 ;           be used to pass any variable values, etc. into the code to be
"RTN","XTMUNIT",198,0)
 ;           XECUTED.  In this case, set the subscript to the variable name and the
"RTN","XTMUNIT",199,0)
 ;           value of the subscripted variable to the desired value of the subscript.
"RTN","XTMUNIT",200,0)
 ;              e.g., (using NAME as my current namespace)
"RTN","XTMUNIT",201,0)
 ;                   S CODE="S XTMUINPT=$$ENTRY^ROUTINE(ZZVALUE1,ZZVALUE2)"
"RTN","XTMUNIT",202,0)
 ;                   S NAMELOC="ENTRY^ROUTINE leak test"   (or simply "ENTRY^ROUTINE")
"RTN","XTMUNIT",203,0)
 ;                   S NAMEINPT("ZZVALUE1")=ZZVALUE1
"RTN","XTMUNIT",204,0)
 ;                   S NAMEINPT("ZZVALUE2")=ZZVALUE2
"RTN","XTMUNIT",205,0)
 ;                   D CHKLEAKS^XTMUNIT(CODE,NAMELOC,.NAMEINPT)
"RTN","XTMUNIT",206,0)
 ;
"RTN","XTMUNIT",207,0)
 ;           If part of a unit test, any leaked variables in ENTRY^ROUTINE which result
"RTN","XTMUNIT",208,0)
 ;           from running the code with the variables indicated will be shown as FAILUREs.
"RTN","XTMUNIT",209,0)
 ;
"RTN","XTMUNIT",210,0)
 ;           If called outside of a unit test, any leaked variables will be printed to the
"RTN","XTMUNIT",211,0)
 ;           current device.
"RTN","XTMUNIT",212,0)
 ;
"RTN","XTMUNIT",213,0)
 N (XTMUCODE,XTMULOC,XTMUINPT,DUZ,IO,U,XTMUERRL,XTMUNIT,XTMUGUI,XTMUI,XTMUJ,XTMUK,XTMULIST,XTMUROU,XTMUSTRT)
"RTN","XTMUNIT",214,0)
 ; ZEXCEPT: XTMUNIT - part of exclusive NEW TESTS FOR EXISTENCE ONLY
"RTN","XTMUNIT",215,0)
 ; ZEXCEPT: XTMUVAR - handled by exclusive NEW
"RTN","XTMUNIT",216,0)
 ;
"RTN","XTMUNIT",217,0)
 ; ACTIVATE ANY VARIABLES PASSED AS SUBSCRIPTS TO XTMUINPT TO THEIR VALUES
"RTN","XTMUNIT",218,0)
 S XTMUVAR=" " F  S XTMUVAR=$O(XTMUINPT(XTMUVAR)) Q:XTMUVAR=""  S (@XTMUVAR)=XTMUINPT(XTMUVAR)
"RTN","XTMUNIT",219,0)
 X XTMUCODE
"RTN","XTMUNIT",220,0)
 N ZZUTVAR S ZZUTVAR="%"
"RTN","XTMUNIT",221,0)
 I $G(XTMUNIT)=1 D
"RTN","XTMUNIT",222,0)
 . I $D(@ZZUTVAR),'$D(XTMUINPT(ZZUTVAR)) D FAIL^XTMUNIT(XTMULOC_" VARIABLE LEAK: "_ZZUTVAR)
"RTN","XTMUNIT",223,0)
 . F  S ZZUTVAR=$O(@ZZUTVAR) Q:ZZUTVAR=""  I $E(ZZUTVAR,1,4)'="XTMU",'$D(XTMUINPT(ZZUTVAR)),",DUZ,IO,U,DTIME,ZZUTVAR,DT,"'[(","_ZZUTVAR_",") D FAIL^XTMUNIT(XTMULOC_" VARIABLE LEAK: "_ZZUTVAR)
"RTN","XTMUNIT",224,0)
 . Q
"RTN","XTMUNIT",225,0)
 I '($G(XTMUNIT)=1) D
"RTN","XTMUNIT",226,0)
 . I $D(@ZZUTVAR),'$D(XTMUINPT(ZZUTVAR)) W !,XTMULOC_" VARIABLE LEAK: "_ZZUTVAR
"RTN","XTMUNIT",227,0)
 . F  S ZZUTVAR=$O(@ZZUTVAR) Q:ZZUTVAR=""  I $E(ZZUTVAR,1,4)'="XTMU",'$D(XTMUINPT(ZZUTVAR)),",DUZ,IO,U,DTIME,ZZUTVAR,DT,"'[(","_ZZUTVAR_",") W !,XTMULOC_" VARIABLE LEAK: "_ZZUTVAR
"RTN","XTMUNIT",228,0)
 . Q
"RTN","XTMUNIT",229,0)
 Q
"RTN","XTMUNIT",230,0)
 ;
"RTN","XTMUNIT",231,0)
NVLDARG ; generate message for invalid arguments to test
"RTN","XTMUNIT",232,0)
 N XTERMSG,OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",233,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",234,0)
 ; ZEXCEPT: XTMUERRL,XTMUGUI -CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",235,0)
 S XTERMSG="NO VALUES INPUT TO CHKEQ^XTMUNIT - no evaluation possible"
"RTN","XTMUNIT",236,0)
 I '$D(XTMUGUI) D
"RTN","XTMUNIT",237,0)
 . S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",238,0)
 . I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",239,0)
 . W !,XTMUNIT("ENT")," - " W:XTMUNIT("NAME")'="" XTMUNIT("NAME")," - " W XTERMSG,! D
"RTN","XTMUNIT",240,0)
 . . S XTMUNIT("FAIL")=XTMUNIT("FAIL")+1,XTMUERRL(XTMUNIT("FAIL"))=XTMUNIT("NAME"),XTMUERRL(XTMUNIT("FAIL"),"MSG")=XTERMSG,XTMUERRL(XTMUNIT("FAIL"),"ENTRY")=XTMUNIT("ENT")
"RTN","XTMUNIT",241,0)
 . . Q
"RTN","XTMUNIT",242,0)
 . I OLDIO'=IO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",243,0)
 . Q
"RTN","XTMUNIT",244,0)
 I $D(XTMUGUI) S XTMUNIT("CNT")=XTMUNIT("CNT")+1,@XTMUNIT("RSLT")@(XTMUNIT("CNT"))=XTMUNIT("LOC")_XTGUISEP_"FAILURE"_XTGUISEP_XTERMSG
"RTN","XTMUNIT",245,0)
 Q
"RTN","XTMUNIT",246,0)
 ;
"RTN","XTMUNIT",247,0)
ERROR ; record errors
"RTN","XTMUNIT",248,0)
 ; ZEXCEPT: XTMUERRL,XTMUGUI,XTMUERR -CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",249,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",250,0)
 S XTMUNIT("CHK")=XTMUNIT("CHK")+1
"RTN","XTMUNIT",251,0)
 I '$D(XTMUGUI) D ERROR1
"RTN","XTMUNIT",252,0)
 I $D(XTMUGUI) D
"RTN","XTMUNIT",253,0)
 . S XTMUNIT("CNT")=XTMUNIT("CNT")+1
"RTN","XTMUNIT",254,0)
 . S XTMUERR=XTMUERR+1
"RTN","XTMUNIT",255,0)
 . S @XTMUNIT("RSLT")@(XTMUNIT("CNT"))=XTMUNIT("LOC")_XTGUISEP_"ERROR"_XTGUISEP_$ZE
"RTN","XTMUNIT",256,0)
 . Q
"RTN","XTMUNIT",257,0)
 S $ZE="",$EC=""
"RTN","XTMUNIT",258,0)
 Q
"RTN","XTMUNIT",259,0)
 ;
"RTN","XTMUNIT",260,0)
ERROR1 ;
"RTN","XTMUNIT",261,0)
 N OLDIO,OLDIOFLG,OLDIONAM
"RTN","XTMUNIT",262,0)
 ; ZEXCEPT: XTMUERRL -CREATED IN SETUP, KILLED IN END
"RTN","XTMUNIT",263,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",264,0)
 S OLDIO=IO,OLDIOFLG=0,OLDIONAM=""
"RTN","XTMUNIT",265,0)
 I IO'=XTMUNIT("IO") D SETIO(.OLDIOFLG,.OLDIONAM)
"RTN","XTMUNIT",266,0)
 W !,XTMUNIT("ENT")," - " W:XTMUNIT("NAME")'="" XTMUNIT("NAME")," - Error: " W $ZE,! D
"RTN","XTMUNIT",267,0)
 . S XTMUNIT("ERRN")=XTMUNIT("ERRN")+1,XTMUERRL(XTMUNIT("ERRN"))=XTMUNIT("NAME"),XTMUERRL(XTMUNIT("FAIL"),"MSG")=$ZE,XTMUERRL(XTMUNIT("FAIL"),"ENTRY")=XTMUNIT("ENT")
"RTN","XTMUNIT",268,0)
 . Q
"RTN","XTMUNIT",269,0)
 I IO'=OLDIO D RESETIO(OLDIOFLG,OLDIONAM)
"RTN","XTMUNIT",270,0)
 Q
"RTN","XTMUNIT",271,0)
SETIO(OLDIOFLG,OLDIONAM) ; BOTH PASSED BY REFERENCE
"RTN","XTMUNIT",272,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",273,0)
 N OLDION S OLDION="" F  S OLDION=$O(^TMP("XUDEVICE",$J,OLDION)) Q:OLDION=""  I $G(^(OLDION,"IO"))=IO S OLDIONAM=^(0),OLDIOFLG=1
"RTN","XTMUNIT",274,0)
 I 'OLDIOFLG S OLDIONAM="OLD MUNIT DEV" D SAVDEV^%ZISUTL(OLDIONAM)
"RTN","XTMUNIT",275,0)
 D USE^%ZISUTL(XTMUNIT("DEV"))
"RTN","XTMUNIT",276,0)
 Q
"RTN","XTMUNIT",277,0)
 ;
"RTN","XTMUNIT",278,0)
RESETIO(OLDIOFLG,OLDIONAM) ;
"RTN","XTMUNIT",279,0)
 D USE^%ZISUTL(OLDIONAM) I 'OLDIOFLG D RMDEV^%ZISUTL(OLDIONAM)
"RTN","XTMUNIT",280,0)
 Q
"RTN","XTMUNIT",281,0)
 ;
"RTN","XTMUNIT",282,0)
ISUTEST() ; .SUPPORTED API TO DETERMINE IF CURRENTLY IN UNIT TEST
"RTN","XTMUNIT",283,0)
 ; ZEXCEPT: XTMUNIT  -- NEWED ON ENTRY
"RTN","XTMUNIT",284,0)
 Q $G(XTMUNIT)=1
"RTN","XTMUNIT",285,0)
 ;
"RTN","XTMUNIT",286,0)
PICKSET ; .OPT Interactive selection of MUnit Test Group
"RTN","XTMUNIT",287,0)
 N DIC,Y,XTMUROU,XTMULIST,DIR
"RTN","XTMUNIT",288,0)
 S DIC=8992.8,DIC(0)="AEQM" D ^DIC Q:Y'>0  W !
"RTN","XTMUNIT",289,0)
 D GETSET(+Y,.XTMUROU,.XTMULIST)
"RTN","XTMUNIT",290,0)
 N DIC,Y,XTMUNIT
"RTN","XTMUNIT",291,0)
 D SETUT
"RTN","XTMUNIT",292,0)
 D EN1(.XTMUROU,XTMULIST)
"RTN","XTMUNIT",293,0)
 S DIR(0)="EA",DIR("A")="Enter RETURN to continue:" D ^DIR K DIR
"RTN","XTMUNIT",294,0)
 Q
"RTN","XTMUNIT",295,0)
 ;
"RTN","XTMUNIT",296,0)
RUNSET(SETNAME) ; .SR Run with Specified Selection of MUnit Test Group
"RTN","XTMUNIT",297,0)
 N Y,XTMUROU,XTMULIST
"RTN","XTMUNIT",298,0)
 Q:$G(SETNAME)=""
"RTN","XTMUNIT",299,0)
 S Y=+$$FIND1^DIC(8992.8,"","X",SETNAME) Q:Y'>0
"RTN","XTMUNIT",300,0)
 D GETSET(Y,.XTMUROU,.XTMULIST)
"RTN","XTMUNIT",301,0)
 N Y,SETNAME,XTMUNIT
"RTN","XTMUNIT",302,0)
 D SETUT
"RTN","XTMUNIT",303,0)
 D EN1(.XTMUROU,XTMULIST)
"RTN","XTMUNIT",304,0)
 Q
"RTN","XTMUNIT",305,0)
 ;
"RTN","XTMUNIT",306,0)
DOSET(IEN) ;
"RTN","XTMUNIT",307,0)
 N XTMUROU,XTMULIST
"RTN","XTMUNIT",308,0)
 S XTMULIST=0
"RTN","XTMUNIT",309,0)
 D GETSET($G(IEN),.XTMUROU,.XTMULIST)
"RTN","XTMUNIT",310,0)
 I XTMULIST>0  N IEN,XTMUNIT D SETUT,EN1(.XTMUROU,XTMULIST)
"RTN","XTMUNIT",311,0)
 Q
"RTN","XTMUNIT",312,0)
 ;
"RTN","XTMUNIT",313,0)
GETSET(IEN,XTMUROU,XTMULIST) ;
"RTN","XTMUNIT",314,0)
 N IENS,XTMROOT
"RTN","XTMUNIT",315,0)
 S IENS=IEN_"," D GETS^DIQ(8992.8,IENS,"1*","","XTMROOT")
"RTN","XTMUNIT",316,0)
 S XTMULIST=0,IENS="" F  S IENS=$O(XTMROOT(8992.81,IENS)) Q:IENS=""  S XTMULIST=XTMULIST+1,XTMUROU(XTMULIST)=XTMROOT(8992.81,IENS,.01)
"RTN","XTMUNIT",317,0)
 Q
"RTN","XTMUNIT",318,0)
 ;
"RTN","XTMUNIT",319,0)
GUISET(XTMURSLT,XTSET) ; Entry point for GUI start with selected Test Set IEN
"RTN","XTMUNIT",320,0)
 N XTMUROU,XTMULIST,XTMUNIT
"RTN","XTMUNIT",321,0)
 D SETUT
"RTN","XTMUNIT",322,0)
 S XTMUNIT("RSLT")=$NA(^TMP("MUNIT-XTMURSLT",$J)) K @XTMUNIT("RSLT")
"RTN","XTMUNIT",323,0)
 D GETSET(XTSET,.XTMUROU,.XTMULIST)
"RTN","XTMUNIT",324,0)
 D GETLIST(.XTMUROU,XTMULIST,XTMUNIT("RSLT"))
"RTN","XTMUNIT",325,0)
 S @XTMUNIT("RSLT")@(1)=(@XTMUNIT("RSLT")@(1))_"^1" ; 110719 mark as new version
"RTN","XTMUNIT",326,0)
 S XTMURSLT=XTMUNIT("RSLT")
"RTN","XTMUNIT",327,0)
 Q
"RTN","XTMUNIT",328,0)
 ;
"RTN","XTMUNIT",329,0)
GUILOAD(XTMURSLT,XTMUROUN) ; Entry point for GUI start with XTMUROUN containing primary routine name
"RTN","XTMUNIT",330,0)
 N XTMUROU,XTMUNIT
"RTN","XTMUNIT",331,0)
 D SETUT
"RTN","XTMUNIT",332,0)
 S XTMUNIT("RSLT")=$NA(^TMP("MUNIT-XTMURSLT",$J)) K @XTMUNIT("RSLT")
"RTN","XTMUNIT",333,0)
 S XTMUROU(1)=XTMUROUN
"RTN","XTMUNIT",334,0)
 D GETLIST(.XTMUROU,1,XTMUNIT("RSLT"))
"RTN","XTMUNIT",335,0)
 S @XTMUNIT("RSLT")@(1)=(@XTMUNIT("RSLT")@(1))_"^1" ; 110719 mark as new version
"RTN","XTMUNIT",336,0)
 S XTMURSLT=XTMUNIT("RSLT")
"RTN","XTMUNIT",337,0)
 Q
"RTN","XTMUNIT",338,0)
 ;
"RTN","XTMUNIT",339,0)
GETLIST(XTMUROU,XTMULIST,XTMURSLT) ;
"RTN","XTMUNIT",340,0)
 N I,XTMUROUL,XTMUROUN,XTMUNIT,XTCOMNT,XTVALUE,XTMUCNT
"RTN","XTMUNIT",341,0)
 S XTVALUE=$NA(^TMP("GUI-MUNIT",$J)) K @XTVALUE
"RTN","XTMUNIT",342,0)
 S XTMUCNT=0,XTCOMNT=""
"RTN","XTMUNIT",343,0)
 D GETTREE^XTMUNIT1(.XTMUROU,XTMULIST)
"RTN","XTMUNIT",344,0)
 F I=1:1 Q:'$D(XTMUROU(I))  S XTMUROUL(XTMUROU(I))=""
"RTN","XTMUNIT",345,0)
 S XTMUROUN="" F  S XTMUROUN=$O(XTMUROUL(XTMUROUN)) Q:XTMUROUN=""  D LOAD(XTMUROUN,.XTMUCNT,XTVALUE,XTCOMNT,.XTMUROUL)
"RTN","XTMUNIT",346,0)
 M @XTMURSLT=@XTVALUE
"RTN","XTMUNIT",347,0)
 K @XTMURSLT@("SHUTDOWN")
"RTN","XTMUNIT",348,0)
 K @XTMURSLT@("STARTUP")
"RTN","XTMUNIT",349,0)
 S @XTVALUE@("LASTROU")="" ; Use this to keep track of place in routines
"RTN","XTMUNIT",350,0)
 Q
"RTN","XTMUNIT",351,0)
 ;
"RTN","XTMUNIT",352,0)
 ; generate list of unit test routines, entry points and comments on test for entry point
"RTN","XTMUNIT",353,0)
LOAD(XTMUROUN,XTMUNCNT,XTVALUE,XTCOMNT,XTMUROUL) ;
"RTN","XTMUNIT",354,0)
 I $T(@("^"_XTMUROUN))="" S XTMUNCNT=XTMUNCNT+1,@XTVALUE@(XTMUNCNT)=XTMUROUN_"^^*** ERROR - ROUTINE NAME NOT FOUND" Q
"RTN","XTMUNIT",355,0)
 S XTMUNCNT=XTMUNCNT+1,@XTVALUE@(XTMUNCNT)=XTMUROUN_U_U_XTCOMNT
"RTN","XTMUNIT",356,0)
 N XTMUI,XTX1,XTX2,LINE
"RTN","XTMUNIT",357,0)
 ; 100622 JLI added code to identify STARTUP and TEARDOWN
"RTN","XTMUNIT",358,0)
 I $T(@("STARTUP^"_XTMUROUN))'="",'$D(@XTVALUE@("STARTUP")) S @XTVALUE@("STARTUP")="STARTUP^"_XTMUROUN
"RTN","XTMUNIT",359,0)
 I $T(@("SHUTDOWN^"_XTMUROUN))'="",'$D(@XTVALUE@("SHUTDOWN")) S @XTVALUE@("SHUTDOWN")="SHUTDOWN^"_XTMUROUN
"RTN","XTMUNIT",360,0)
 F XTMUI=1:1 S LINE=$T(@("XTENT+"_XTMUI_"^"_XTMUROUN)) S XTX1=$P(LINE,";",3) Q:XTX1=""  S XTX2=$P(LINE,";",4),XTMUNCNT=XTMUNCNT+1,@XTVALUE@(XTMUNCNT)=XTMUROUN_U_XTX1_U_XTX2
"RTN","XTMUNIT",361,0)
 F XTMUI=1:1 S LINE=$T(@("XTROU+"_XTMUI_"^"_XTMUROUN)) S XTX1=$P(LINE,";",3) Q:XTX1=""  S XTCOMNT=$P(LINE,";",4) I '$D(XTMUROUL(XTX1)) S XTMUROUL(XTX1)="" D LOAD(XTX1,.XTMUNCNT,XTVALUE,XTCOMNT,.XTMUROUL)
"RTN","XTMUNIT",362,0)
 Q
"RTN","XTMUNIT",363,0)
 ;
"RTN","XTMUNIT",364,0)
GUINEXT(XTMURSLT,XTMULOC,XTGUISEP) ; Entry point for GUI execute next test
"RTN","XTMUNIT",365,0)
 ; XTGUISEP - added 110719 to provide for changing separator for GUI
"RTN","XTMUNIT",366,0)
 ;            return from ^ to another value ~~^~~  so that data returned
"RTN","XTMUNIT",367,0)
 ;            is not affected by ^ values in the data - if not present
"RTN","XTMUNIT",368,0)
 ;            sets value to default ^
"RTN","XTMUNIT",369,0)
 N XTMUETRY,XTMUROUT,XTOLROU,XTVALUE,XTMUERR,XTMUGUI
"RTN","XTMUNIT",370,0)
 N XTMUNIT
"RTN","XTMUNIT",371,0)
 I $G(XTGUISEP)="" S XTGUISEP="^"
"RTN","XTMUNIT",372,0)
 D SETUT
"RTN","XTMUNIT",373,0)
 S XTMUNIT("CNT")=0,XTMUNIT("LOC")=XTMULOC
"RTN","XTMUNIT",374,0)
 S XTVALUE=$NA(^TMP("GUI-MUNIT",$J))
"RTN","XTMUNIT",375,0)
 S XTMUNIT("RSLT")=$NA(^TMP("GUINEXT",$J)) K @XTMUNIT("RSLT")
"RTN","XTMUNIT",376,0)
 S XTMURSLT=XTMUNIT("RSLT")
"RTN","XTMUNIT",377,0)
 S XTMUETRY=$P(XTMULOC,U),XTMUROUT=$P(XTMULOC,U,2),XTOLROU=$G(@XTVALUE@("LASTROU"))
"RTN","XTMUNIT",378,0)
 S XTMUGUI=1
"RTN","XTMUNIT",379,0)
 I XTMUROUT'=XTOLROU D  I XTMUROUT="" S @XTMURSLT@(1)="" K @XTVALUE Q
"RTN","XTMUNIT",380,0)
 . ; 100622 JLI added code to handle STARTUP for GUI app
"RTN","XTMUNIT",381,0)
 . I XTOLROU="",$D(@XTVALUE@("STARTUP")) D
"RTN","XTMUNIT",382,0)
 . . S XTMUNIT("LOC")=@XTVALUE@("STARTUP")
"RTN","XTMUNIT",383,0)
 . . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",384,0)
 . . D @(@XTVALUE@("STARTUP"))
"RTN","XTMUNIT",385,0)
 . . Q
"RTN","XTMUNIT",386,0)
 . I XTOLROU'="" I $T(@("TEARDOWN^"_XTOLROU))'="" D
"RTN","XTMUNIT",387,0)
 . . S XTMUNIT("LOC")="TEARDOWN^"_XTMUROUT
"RTN","XTMUNIT",388,0)
 . . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",389,0)
 . . D @("TEARDOWN^"_XTOLROU)
"RTN","XTMUNIT",390,0)
 . . Q
"RTN","XTMUNIT",391,0)
 . S @XTVALUE@("LASTROU")=XTMUROUT I XTMUROUT'="",$T(@("SETUP^"_XTMUROUT))'="" D
"RTN","XTMUNIT",392,0)
 . . S XTMUNIT("LOC")="SETUP^"_XTMUROUT
"RTN","XTMUNIT",393,0)
 . . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",394,0)
 . . D @("SETUP^"_XTMUROUT)
"RTN","XTMUNIT",395,0)
 . . Q
"RTN","XTMUNIT",396,0)
 . ; 100622 JLI added code to handle SHUTDOWN
"RTN","XTMUNIT",397,0)
 . I XTMUROUT="",$D(@XTVALUE@("SHUTDOWN")) D
"RTN","XTMUNIT",398,0)
 . . S XTMUNIT("LOC")=@XTVALUE@("SHUTDOWN")
"RTN","XTMUNIT",399,0)
 . . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",400,0)
 . . D @(@XTVALUE@("SHUTDOWN"))
"RTN","XTMUNIT",401,0)
 . . Q
"RTN","XTMUNIT",402,0)
 . Q
"RTN","XTMUNIT",403,0)
 S XTMUNIT("LOC")=XTMULOC
"RTN","XTMUNIT",404,0)
 S XTMUNIT("CHK")=0,XTMUNIT("CNT")=1,XTMUERR=0
"RTN","XTMUNIT",405,0)
 D  ; to limit range of error trap so we continue through other tests
"RTN","XTMUNIT",406,0)
 . N $ETRAP S $ETRAP="D ERROR^XTMUNIT"
"RTN","XTMUNIT",407,0)
 . D @XTMUNIT("LOC")
"RTN","XTMUNIT",408,0)
 S @XTMUNIT("RSLT")@(1)=XTMUNIT("CHK")_XTGUISEP_(XTMUNIT("CNT")-1-XTMUERR)_XTGUISEP_XTMUERR
"RTN","XTMUNIT",409,0)
 Q
"RTN","XTMUNIT1")
0^8^B8661103
"RTN","XTMUNIT1",1,0)
XTMUNIT1 ;JLI/FO-OAK-CONTINUATION OF UNIT TEST ROUTINE ;2013-07-26  11:34 AM
"RTN","XTMUNIT1",2,0)
 ;;7.3;TOOLKIT;**81**;APR 25 1995;Build 26
"RTN","XTMUNIT1",3,0)
 ;;Per VHA Directive 2004-038, this routine should not be modified
"RTN","XTMUNIT1",4,0)
 D EN^XTMUNIT("ZZUTXTMU")
"RTN","XTMUNIT1",5,0)
 Q
"RTN","XTMUNIT1",6,0)
 ;
"RTN","XTMUNIT1",7,0)
CHEKTEST(ROU,XTMUNIT,XTMUETRY) ; Collect Test list.
"RTN","XTMUNIT1",8,0)
 ; XTMROU - input - Name of routine to check for tags with @TEST attribute
"RTN","XTMUNIT1",9,0)
 ; XTMUNIT - input/output - passed by reference
"RTN","XTMUNIT1",10,0)
 ; XTMUETRY - input/output - passed by reference
"RTN","XTMUNIT1",11,0)
 ; 
"RTN","XTMUNIT1",12,0)
 ; Test list collected in two ways:
"RTN","XTMUNIT1",13,0)
 ; - @TEST on labellines
"RTN","XTMUNIT1",14,0)
 ; - Offsets of XTENT
"RTN","XTMUNIT1",15,0)
 ;
"RTN","XTMUNIT1",16,0)
 ; NB: VEN/SMH - first block moved from XTMUNIT
"RTN","XTMUNIT1",17,0)
 S XTMUNIT("ENTN")=0 ; Number of test, sub to XTMUETRY.
"RTN","XTMUNIT1",18,0)
 ;
"RTN","XTMUNIT1",19,0)
 F XTMUI=1:1 S XTMUNIT("ELIN")=$T(@("XTENT+"_XTMUI_"^"_XTMUROU(XTMUNIT("CURR")))) Q:$P(XTMUNIT("ELIN"),";",3)=""  D
"RTN","XTMUNIT1",20,0)
 . S XTMUNIT("ENTN")=XTMUNIT("ENTN")+1,XTMUETRY(XTMUNIT("ENTN"))=$P(XTMUNIT("ELIN"),";",3),XTMUETRY(XTMUNIT("ENTN"),"NAME")=$P(XTMUNIT("ELIN"),";",4)
"RTN","XTMUNIT1",21,0)
 ; VEN/SMH - END
"RTN","XTMUNIT1",22,0)
 ;
"RTN","XTMUNIT1",23,0)
 ; VEN/SMH - This code is far far more complex than it needs to be. Just use $TEXT.
"RTN","XTMUNIT1",24,0)
 ; get routine code into a location to check it
"RTN","XTMUNIT1",25,0)
 N CNT,LN,I,DIF,X,XCNP,TMP,LINE
"RTN","XTMUNIT1",26,0)
 S I=$$SETNAMES^XTECGLO(ROU,"") I I<0 Q "-1^Invalid Routine Name"
"RTN","XTMUNIT1",27,0)
 ; $$ROU(ROU) used a check of the ROUTINE file for file name
"RTN","XTMUNIT1",28,0)
 ; but routines with names longer than the standard always
"RTN","XTMUNIT1",29,0)
 ; show up as not found will trap the error instead if not present
"RTN","XTMUNIT1",30,0)
 ; I '$$ROU(ROU) Q "-1^Routine Not found" ; JLI 120806
"RTN","XTMUNIT1",31,0)
 N $ETRAP S $ETRAP="D CATCHERR^XTMUNIT1"
"RTN","XTMUNIT1",32,0)
 S DIF="TMP(",XCNP=0,X=ROU
"RTN","XTMUNIT1",33,0)
 X ^%ZOSF("LOAD")
"RTN","XTMUNIT1",34,0)
 I '$D(TMP(1,0)) Q
"RTN","XTMUNIT1",35,0)
 F I=1:1 Q:'$D(TMP(I,0))  S LINE=TMP(I,0) I $E(LINE)'=" ",$$UP^XLFSTR(LINE)["@TEST" D
"RTN","XTMUNIT1",36,0)
 . N TAGNAME,CHAR,NPAREN S TAGNAME="",NPAREN=0
"RTN","XTMUNIT1",37,0)
 . F  Q:LINE=""  S CHAR=$E(LINE),LINE=$E(LINE,2,999) Q:CHAR=""  Q:" ("[CHAR  S TAGNAME=TAGNAME_CHAR
"RTN","XTMUNIT1",38,0)
 . ; should be no paren or arguments
"RTN","XTMUNIT1",39,0)
 . I CHAR="(" Q
"RTN","XTMUNIT1",40,0)
 . F  Q:LINE=""  S CHAR=$E(LINE) Q:" ;"'[CHAR  S LINE=$E(LINE,2,999)
"RTN","XTMUNIT1",41,0)
 . I $$UP^XLFSTR($E(LINE,1,5))="@TEST" S LINE=$E(LINE,6,999) D
"RTN","XTMUNIT1",42,0)
 . . S XTMUNIT("ENTN")=XTMUNIT("ENTN")+1,XTMUETRY(XTMUNIT("ENTN"))=TAGNAME
"RTN","XTMUNIT1",43,0)
 . . F  Q:LINE=""  S CHAR=$E(LINE) Q:CHAR?1AN  S LINE=$E(LINE,2,999)
"RTN","XTMUNIT1",44,0)
 . . S XTMUETRY(XTMUNIT("ENTN"),"NAME")=LINE
"RTN","XTMUNIT1",45,0)
 . . Q
"RTN","XTMUNIT1",46,0)
 . Q
"RTN","XTMUNIT1",47,0)
 Q
"RTN","XTMUNIT1",48,0)
 ;
"RTN","XTMUNIT1",49,0)
CATCHERR ; catch error on trying to load file if it doesn't exist ; JLI 120806
"RTN","XTMUNIT1",50,0)
 S $ZE="",$EC=""
"RTN","XTMUNIT1",51,0)
 ;
"RTN","XTMUNIT1",52,0)
 ; VEN/SMH 26JUL2013 - Moved GETTREE here.
"RTN","XTMUNIT1",53,0)
GETTREE(XTMUROU,XTMULIST) ;
"RTN","XTMUNIT1",54,0)
 ; first get any other routines this one references for running subsequently
"RTN","XTMUNIT1",55,0)
 ; then any that they refer to as well
"RTN","XTMUNIT1",56,0)
 ; this builds a tree of all routines referred to by any routine including each only once
"RTN","XTMUNIT1",57,0)
 N XTMUK,XTMUI,XTMUJ,XTMURNAM,XTMURLIN
"RTN","XTMUNIT1",58,0)
 F XTMUK=1:1 Q:'$D(XTMUROU(XTMUK))  D
"RTN","XTMUNIT1",59,0)
 . F XTMUI=1:1 S XTMURLIN=$T(@("XTROU+"_XTMUI_"^"_XTMUROU(XTMUK))) S XTMURNAM=$P(XTMURLIN,";",3) Q:XTMURNAM=""  D
"RTN","XTMUNIT1",60,0)
 . . F XTMUJ=1:1:XTMULIST I XTMUROU(XTMUJ)=XTMURNAM S XTMURNAM="" Q
"RTN","XTMUNIT1",61,0)
 . . I XTMURNAM'="",$T(@("+1^"_XTMURNAM))="" W:'$D(XWBOS) "Referenced routine ",XTMURNAM," not found.",! Q
"RTN","XTMUNIT1",62,0)
 . . S:XTMURNAM'="" XTMULIST=XTMULIST+1,XTMUROU(XTMULIST)=XTMURNAM
"RTN","XTMUNIT1",63,0)
 . . Q
"RTN","XTMUNIT1",64,0)
 . Q
"RTN","XTMUNIT1",65,0)
 Q
"SEC","^DIC",8992.7,8992.7,0,"AUDIT")
@
"SEC","^DIC",8992.7,8992.7,0,"DD")
@
"SEC","^DIC",8992.7,8992.7,0,"DEL")
@
"SEC","^DIC",8992.7,8992.7,0,"LAYGO")
@
"SEC","^DIC",8992.7,8992.7,0,"WR")
@
"SEC","^DIC",8992.8,8992.8,0,"AUDIT")
@
"SEC","^DIC",8992.8,8992.8,0,"DD")
@
"SEC","^DIC",8992.8,8992.8,0,"DEL")
@
"SEC","^DIC",8992.8,8992.8,0,"LAYGO")
@
"SEC","^DIC",8992.8,8992.8,0,"WR")
@
"VER")
8.0^22.0
"^DD",8992.7,8992.7,0)
FIELD^^.06^11
"^DD",8992.7,8992.7,0,"DDA")
N
"^DD",8992.7,8992.7,0,"DT")
3121220
"^DD",8992.7,8992.7,0,"IX","B",8992.7,.01)

"^DD",8992.7,8992.7,0,"NM","LOG4M CONFIG")

"^DD",8992.7,8992.7,0,"VRPK")
XT
"^DD",8992.7,8992.7,.01,0)
NAME^RF^^0;1^K:$L(X)>30!($L(X)<3)!'(X'?1P.E) X
"^DD",8992.7,8992.7,.01,1,0)
^.1
"^DD",8992.7,8992.7,.01,1,1,0)
8992.7^B
"^DD",8992.7,8992.7,.01,1,1,1)
S ^XTV(8992.7,"B",$E(X,1,30),DA)=""
"^DD",8992.7,8992.7,.01,1,1,2)
K ^XTV(8992.7,"B",$E(X,1,30),DA)
"^DD",8992.7,8992.7,.01,3)
Answer must be 3-30 characters in length.
"^DD",8992.7,8992.7,.01,21,0)
^^6^6^3121220^
"^DD",8992.7,8992.7,.01,21,1,0)
This field holds the NAME used to identify a particular LOG4M CONFIG
"^DD",8992.7,8992.7,.01,21,2,0)
entry. The NAME is used within source code to specify logging startup, if
"^DD",8992.7,8992.7,.01,21,3,0)
the NAME exists within the LOG4M CONFIG file and if the ACTIVE field 
"^DD",8992.7,8992.7,.01,21,4,0)
(#.02) is set to a YES value (there are two choices for YES) then logging
"^DD",8992.7,8992.7,.01,21,5,0)
would be initiated.  If the file entry for a specific NAME does not exist,
"^DD",8992.7,8992.7,.01,21,6,0)
or if the ACTIVE field is set to NO, then no logging will be performed.
"^DD",8992.7,8992.7,.01,23,0)
^^14^14^3100114^
"^DD",8992.7,8992.7,.01,23,1,0)
The NAME field of the LOG4M CONFIG file is used within source code to 
"^DD",8992.7,8992.7,.01,23,2,0)
identify a specific logging session and to control whether logging is 
"^DD",8992.7,8992.7,.01,23,3,0)
initiated or not.  
"^DD",8992.7,8992.7,.01,23,4,0)
 
"^DD",8992.7,8992.7,.01,23,5,0)
The easiest way to initiate logging is to use the FILEINIT entry tag in 
"^DD",8992.7,8992.7,.01,23,6,0)
the XTMLOG routine and the NAME field for an entry in the LOG4M CONFIG 
"^DD",8992.7,8992.7,.01,23,7,0)
file as an argument to specify the configuration for the logging. The
"^DD",8992.7,8992.7,.01,23,8,0)
logging is terminated with a call to the ENDLOG tag again with the NAME 
"^DD",8992.7,8992.7,.01,23,9,0)
value as an argument.
"^DD",8992.7,8992.7,.01,23,10,0)
 
"^DD",8992.7,8992.7,.01,23,11,0)
   DO FILEINIT^XTMLOG(NAME)
"^DD",8992.7,8992.7,.01,23,12,0)
   ....
"^DD",8992.7,8992.7,.01,23,13,0)
   .... 
"^DD",8992.7,8992.7,.01,23,14,0)
   DO ENDLOG^XTMLOG(NAME)
"^DD",8992.7,8992.7,.01,"DT")
3121220
"^DD",8992.7,8992.7,.02,0)
ACTIVE^RS^N:NO;E:YES, EASY CONFIG;D:YES, DETAILED CONFIG;^0;2^Q
"^DD",8992.7,8992.7,.02,3)
Enter N to turn off this logging configuration.  It should be N while you are editing and then turned on. Use E for EASY config specs, D for Detailed in the Word Processing field.
"^DD",8992.7,8992.7,.02,21,0)
^^12^12^3100114^
"^DD",8992.7,8992.7,.02,21,1,0)
This field determines whether, on a call to FILEINIT^XTMLOG with the NAME 
"^DD",8992.7,8992.7,.02,21,2,0)
value for a file entry, the logging is started or not.  If the value for 
"^DD",8992.7,8992.7,.02,21,3,0)
the ACTIVE field is NO, logging is not started.  If the value is YES, 
"^DD",8992.7,8992.7,.02,21,4,0)
EASY CONFIG, then logging is started using the specifications in the EZ 
"^DD",8992.7,8992.7,.02,21,5,0)
ENTRY field (#.03) and EZ LEVEL field (#.04) to determine how the logging 
"^DD",8992.7,8992.7,.02,21,6,0)
will be handled and the level of logging effort.  If the value is YES, 
"^DD",8992.7,8992.7,.02,21,7,0)
DETAILED CONFIG, then logging is started using the specifications in the 
"^DD",8992.7,8992.7,.02,21,8,0)
DETAILED CONFIG field (#1), a word processing field that would contain 
"^DD",8992.7,8992.7,.02,21,9,0)
the specifications in the manner of a Log4J configuration file.
"^DD",8992.7,8992.7,.02,21,10,0)
 
"^DD",8992.7,8992.7,.02,21,11,0)
It is recommended that the YES, EASY CONFIG be used to set the logging 
"^DD",8992.7,8992.7,.02,21,12,0)
ACTIVE.
"^DD",8992.7,8992.7,.02,"DT")
3121220
"^DD",8992.7,8992.7,.03,0)
EZ ENTRY^F^^0;3^K:$L(X)>40!($L(X)<3) X
"^DD",8992.7,8992.7,.03,3)
Enter the configuration specification, 3 to 40 characters.
"^DD",8992.7,8992.7,.03,21,0)
^^9^9^3121220^
"^DD",8992.7,8992.7,.03,21,1,0)
The EZ ENTRY field holds a string of text that will be evaluated as a 
"^DD",8992.7,8992.7,.03,21,2,0)
specification for the logging method and location of data storage.  If 
"^DD",8992.7,8992.7,.03,21,3,0)
Easy Entry is not going to be used, there should be no text in this 
"^DD",8992.7,8992.7,.03,21,4,0)
field.  An easy configuration would be an entry such as "C;G,LOGDATA" 
"^DD",8992.7,8992.7,.03,21,5,0)
which would result in output to the Console (the C) and output to a Global
"^DD",8992.7,8992.7,.03,21,6,0)
(the G) location under ^XTMP("LOGDATA",$J, (the LOGDATA).  The top node 
"^DD",8992.7,8992.7,.03,21,7,0)
under ^XTMP could be a different name, e.g., an entry of "G,MYTEST"  would
"^DD",8992.7,8992.7,.03,21,8,0)
result in the data being stored under ^XTMP("MYTEST",$J,  with no output 
"^DD",8992.7,8992.7,.03,21,9,0)
to the console.
"^DD",8992.7,8992.7,.03,"DT")
3121220
"^DD",8992.7,8992.7,.04,0)
EZ LEVEL^S^F:FATAL;E:ERROR;W:WARN;I:INFO;D:DEBUG;^0;4^Q
"^DD",8992.7,8992.7,.04,3)
Select the level of reporting desired. A lower level (e.g., DEBUG) would include that level and all above it.
"^DD",8992.7,8992.7,.04,21,0)
^^10^10^3121220^
"^DD",8992.7,8992.7,.04,21,1,0)
The EZ LEVEL field indicates the lowest level of reporting (generally with
"^DD",8992.7,8992.7,.04,21,2,0)
the highest detail logging) that is desired.  The order being from the
"^DD",8992.7,8992.7,.04,21,3,0)
highest level (lowest detail) of FATAL, then down through ERROR, WARN,
"^DD",8992.7,8992.7,.04,21,4,0)
INFO, and finally the lowest level (highest detail) of DEBUG.  The desired
"^DD",8992.7,8992.7,.04,21,5,0)
level of reporting in the logging code is indicated by the tag which is
"^DD",8992.7,8992.7,.04,21,6,0)
called [e.g., DO FATAL^XTMLOG(  or DO DEBUG^XTMLOG( , with desired
"^DD",8992.7,8992.7,.04,21,7,0)
arguments following the parentheses].  If a specific level above DEBUG, 
"^DD",8992.7,8992.7,.04,21,8,0)
(e.g., WARN) has been indicated, then calls into lower levels (e.g., 
"^DD",8992.7,8992.7,.04,21,9,0)
DEBUG) will not be logged, while levels (e.g., FATAL) above that specified
"^DD",8992.7,8992.7,.04,21,10,0)
will be logged as well as the specified level.
"^DD",8992.7,8992.7,.04,"DT")
3121220
"^DD",8992.7,8992.7,.05,0)
ROUTINE FILTER^F^^0;5^K:$L(X)>80!($L(X)<3) X
"^DD",8992.7,8992.7,.05,3)
Enter a list of comma separated routines, or namespaces followed by astericks which will be used for logging (3-80 characters).
"^DD",8992.7,8992.7,.05,21,0)
^^6^6^3121220^
"^DD",8992.7,8992.7,.05,21,1,0)
The ROUTINE FILTER field can be used to specify a series of comma 
"^DD",8992.7,8992.7,.05,21,2,0)
separated routines which will limit the logging to those logging calls 
"^DD",8992.7,8992.7,.05,21,3,0)
which are present in one of the routines in the list.  This can be used 
"^DD",8992.7,8992.7,.05,21,4,0)
to reduce significantly the amount of logging output if the area of 
"^DD",8992.7,8992.7,.05,21,5,0)
interest is limited to a specific group of routines instead of a larger 
"^DD",8992.7,8992.7,.05,21,6,0)
number of routines.
"^DD",8992.7,8992.7,.05,"DT")
3121220
"^DD",8992.7,8992.7,.06,0)
USER FILTER^F^^0;6^K:$L(X)>60!($L(X)<1) X
"^DD",8992.7,8992.7,.06,3)
Enter a series of comma separated DUZ values which will be used for logging (other users will NOT be logged) (1-60 characters).
"^DD",8992.7,8992.7,.06,21,0)
^^4^4^3070518^
"^DD",8992.7,8992.7,.06,21,1,0)
This is a list of user DUZ values (comma-separated) which indicates which 
"^DD",8992.7,8992.7,.06,21,2,0)
users should have logging turned on.  This provides the capability to 
"^DD",8992.7,8992.7,.06,21,3,0)
turn on logging of a highly used piece of code for only selected users 
"^DD",8992.7,8992.7,.06,21,4,0)
instead of everyone (which is the default if this entry is a null string).
"^DD",8992.7,8992.7,.06,"DT")
3121220
"^DD",8992.7,8992.7,1,0)
DETAILED CONFIG^8992.71^^1;0
"^DD",8992.7,8992.7,2.01,0)
PRINT LAYOUT^K^^2;E1,245^K:$L(X)>245 X D:$D(X) ^DIM
"^DD",8992.7,8992.7,2.01,3)
To replace the default Print Layout enter a new one.  The Ans
"^DD",8992.7,8992.7,2.01,21,0)
^.001^45^45^3080220^^^^
"^DD",8992.7,8992.7,2.01,21,1,0)
The PRINT LAYOUT is a string of characters based on those used for Log4J 
"^DD",8992.7,8992.7,2.01,21,2,0)
to describe the data and order to be output for the log entries.  The 
"^DD",8992.7,8992.7,2.01,21,3,0)
type identifiers begin with % (%% will yield a literal %), are case 
"^DD",8992.7,8992.7,2.01,21,4,0)
sensitive and may have some positioning data before the type identifier.
"^DD",8992.7,8992.7,2.01,21,5,0)
 
"^DD",8992.7,8992.7,2.01,21,6,0)
  %n should be the final entry on the line and indicates the end of the 
"^DD",8992.7,8992.7,2.01,21,7,0)
     line.
"^DD",8992.7,8992.7,2.01,21,8,0)
  %p the priority (FATAL, ERROR, WARN, INFO, or DEBUG) of the log entry.
"^DD",8992.7,8992.7,2.01,21,9,0)
  %t the job number for the current job.
"^DD",8992.7,8992.7,2.01,21,10,0)
  %m the message to be displayed for the call to the logger..
"^DD",8992.7,8992.7,2.01,21,11,0)
  %L the location within the routine of the call to the logger (e.g., 
"^DD",8992.7,8992.7,2.01,21,12,0)
     TAG+3).
"^DD",8992.7,8992.7,2.01,21,13,0)
  %M the TAG entry within which the call to the logger occurs (note this 
"^DD",8992.7,8992.7,2.01,21,14,0)
     is included as part of %L).
"^DD",8992.7,8992.7,2.01,21,15,0)
  %F the name of the routine in which the call to the logger occurs.
"^DD",8992.7,8992.7,2.01,21,16,0)
  %d the date/time of the call to the logger if no format is supplied, the
"^DD",8992.7,8992.7,2.01,21,17,0)
     default format of yyyyMMdd.HHmmss will be used.  The format for date
"^DD",8992.7,8992.7,2.01,21,18,0)
     time is indicated by %d followed by one or more of the following
"^DD",8992.7,8992.7,2.01,21,19,0)
     indicators contained within curly braces { }.
"^DD",8992.7,8992.7,2.01,21,20,0)
 
"^DD",8992.7,8992.7,2.01,21,21,0)
       y  indicates a year digit yy or  yyyy would be the normal for two
"^DD",8992.7,8992.7,2.01,21,22,0)
          year digits or four digits
"^DD",8992.7,8992.7,2.01,21,23,0)
 
"^DD",8992.7,8992.7,2.01,21,24,0)
       M indicates a Month (MM is month digits, MMM is month 
"^DD",8992.7,8992.7,2.01,21,25,0)
         abbreviation and MMMM or more is the month name)
"^DD",8992.7,8992.7,2.01,21,26,0)
       d indicates the day number.
"^DD",8992.7,8992.7,2.01,21,27,0)
       H indicates hours.
"^DD",8992.7,8992.7,2.01,21,28,0)
       m indicates minutes
"^DD",8992.7,8992.7,2.01,21,29,0)
       s indicates seconds
"^DD",8992.7,8992.7,2.01,21,30,0)
 
"^DD",8992.7,8992.7,2.01,21,31,0)
  A hyphen following the % indicates left justified text, a number 
"^DD",8992.7,8992.7,2.01,21,32,0)
between the % and the parameter indicator is used to indicate a minimum 
"^DD",8992.7,8992.7,2.01,21,33,0)
character width for the data.  %-7p will show the PRIORITY in a minimum 
"^DD",8992.7,8992.7,2.01,21,34,0)
width of seven characters, with the text left justified.
"^DD",8992.7,8992.7,2.01,21,35,0)
 
"^DD",8992.7,8992.7,2.01,21,36,0)
Other text, spaces, etc. will be displayed as indicated in the print 
"^DD",8992.7,8992.7,2.01,21,37,0)
layout.
"^DD",8992.7,8992.7,2.01,21,38,0)
 
"^DD",8992.7,8992.7,2.01,21,39,0)
The default PRINT LAYOUT is
"^DD",8992.7,8992.7,2.01,21,40,0)
 
"^DD",8992.7,8992.7,2.01,21,41,0)
%d{yyyyMMdd.HHmmss} %-5p %L %F - %m%n
"^DD",8992.7,8992.7,2.01,21,42,0)
 
"^DD",8992.7,8992.7,2.01,21,43,0)
resulting in
"^DD",8992.7,8992.7,2.01,21,44,0)
 
"^DD",8992.7,8992.7,2.01,21,45,0)
date/time priority(left justified in 5 chars) tag+offset routine - message
"^DD",8992.7,8992.7,2.01,"DT")
3080220
"^DD",8992.7,8992.7,3.01,0)
OUTPUT ON CLOSE^S^N:NONE;P:PRINTER;M:MAIL MESSAGE;^3;1^Q
"^DD",8992.7,8992.7,3.01,3)
Where should the output go? enter M to send output to a mail message or P to send output to a printer (must enter specs in the 'OUTPUT SPECS' field) or N to do neither (the default)
"^DD",8992.7,8992.7,3.01,21,0)
^^11^11^3121220^^
"^DD",8992.7,8992.7,3.01,21,1,0)
This field may be used to specify an output option on ending the logging
"^DD",8992.7,8992.7,3.01,21,2,0)
session.  A global listing of the output must have been specified as at 
"^DD",8992.7,8992.7,3.01,21,3,0)
least one output option for the data, since it will be the global data 
"^DD",8992.7,8992.7,3.01,21,4,0)
used as the source of the output.  The current options are M for Mail 
"^DD",8992.7,8992.7,3.01,21,5,0)
Message or P for Printer.  Selection of N or no value will result in no 
"^DD",8992.7,8992.7,3.01,21,6,0)
direct output when the logging session is terminated.  If Printer output 
"^DD",8992.7,8992.7,3.01,21,7,0)
is selected, the desired output device must be specified in the 'MAIL 
"^DD",8992.7,8992.7,3.01,21,8,0)
OUTPUT SPECS' field.  If Mail Message output is selected, a user may be 
"^DD",8992.7,8992.7,3.01,21,9,0)
specified in the 'MAIL OUTPUT SPECS' field by either internal entry number 
"^DD",8992.7,8992.7,3.01,21,10,0)
or e-mail address, or no specification results in the mail message being 
"^DD",8992.7,8992.7,3.01,21,11,0)
sent to the current active user.
"^DD",8992.7,8992.7,3.01,"DT")
3121220
"^DD",8992.7,8992.7,3.02,0)
MAIL OUTPUT SPECS^F^^3;2^K:$L(X)>25!($L(X)<1) X
"^DD",8992.7,8992.7,3.02,3)
If Mail Message was specified for OUTPUT ON CLOSE enter DUZ number(s) for the desired recipients separated by commas with a max of 25 characters.
"^DD",8992.7,8992.7,3.02,21,0)
^.001^6^6^3121229^^
"^DD",8992.7,8992.7,3.02,21,1,0)
This field may be used to enter specifications related to the OUTPUT ON 
"^DD",8992.7,8992.7,3.02,21,2,0)
CLOSE field for mail output. If mail output was specified, then this
"^DD",8992.7,8992.7,3.02,21,3,0)
field must contain the DUZ value(s) comma separated for the intended 
"^DD",8992.7,8992.7,3.02,21,4,0)
recipients.
"^DD",8992.7,8992.7,3.02,21,5,0)
 
"^DD",8992.7,8992.7,3.02,21,6,0)
This field is ignored unless the OUTPUT ON CLOSE field contains an M.
"^DD",8992.7,8992.7,3.02,"DT")
3121220
"^DD",8992.7,8992.7,3.03,0)
PRINTER OUTPUT SPECS^F^^3;3^K:$L(X)>25!($L(X)<1) X
"^DD",8992.7,8992.7,3.03,3)
If PRINTER OUTPUT was specified for OUTPUT ON CLOSE enter the printer specification as if setting IOP with a max of 25 characters.
"^DD",8992.7,8992.7,3.03,21,0)
^.001^6^6^3121229^^
"^DD",8992.7,8992.7,3.03,21,1,0)
This field may be used to enter specifications related to the OUTPUT ON 
"^DD",8992.7,8992.7,3.03,21,2,0)
CLOSE field for printer output. If printer output was specified, then this
"^DD",8992.7,8992.7,3.03,21,3,0)
field must contain the specification for the desired printer in the form 
"^DD",8992.7,8992.7,3.03,21,4,0)
that would be used to set the IOP value.
"^DD",8992.7,8992.7,3.03,21,5,0)
 
"^DD",8992.7,8992.7,3.03,21,6,0)
This field is ignored unless the OUTPUT ON CLOSE field contains a P.
"^DD",8992.7,8992.7,3.03,"DT")
3121220
"^DD",8992.7,8992.71,0)
DETAILED CONFIG SUB-FIELD^^.01^1
"^DD",8992.7,8992.71,0,"DT")
3070427
"^DD",8992.7,8992.71,0,"NM","DETAILED CONFIG")

"^DD",8992.7,8992.71,0,"UP")
8992.7
"^DD",8992.7,8992.71,.01,0)
DETAILED CONFIG^WL^^0;1^Q
"^DD",8992.7,8992.71,.01,3)
This field is used to specify detailed configuration data based on the configuration for Log4J.  The entry may be either text or XML.
"^DD",8992.7,8992.71,.01,"DT")
3070427
"^DD",8992.8,8992.8,0)
FIELD^^2^3
"^DD",8992.8,8992.8,0,"DDA")
N
"^DD",8992.8,8992.8,0,"DT")
3040701
"^DD",8992.8,8992.8,0,"IX","B",8992.8,.01)

"^DD",8992.8,8992.8,0,"NM","M UNIT TEST GROUP")

"^DD",8992.8,8992.8,0,"VRPK")
XT
"^DD",8992.8,8992.8,.01,0)
NAME^RF^^0;1^K:$L(X)>30!(X?.N)!($L(X)<3)!'(X'?1P.E) X
"^DD",8992.8,8992.8,.01,1,0)
^.1
"^DD",8992.8,8992.8,.01,1,1,0)
8992.8^B
"^DD",8992.8,8992.8,.01,1,1,1)
S ^XTV(8992.8,"B",$E(X,1,30),DA)=""
"^DD",8992.8,8992.8,.01,1,1,2)
K ^XTV(8992.8,"B",$E(X,1,30),DA)
"^DD",8992.8,8992.8,.01,3)
Name must be 3-30 characters, not numeric or starting with punctuation.
"^DD",8992.8,8992.8,.01,21,0)
^^4^4^3121220^
"^DD",8992.8,8992.8,.01,21,1,0)
This is the name that will be used to identify the M Unit Test Group.  It 
"^DD",8992.8,8992.8,.01,21,2,0)
should have a name which actually reflects the purpose for the test(s) or 
"^DD",8992.8,8992.8,.01,21,3,0)
suite of tests.  [A suite of tests would run a combination of several 
"^DD",8992.8,8992.8,.01,21,4,0)
Unit tests as a group]
"^DD",8992.8,8992.8,.01,"DT")
3121220
"^DD",8992.8,8992.8,1,0)
TEST ROUTINE^8992.81^^1;0
"^DD",8992.8,8992.8,1,21,0)
^^2^2^3121220^
"^DD",8992.8,8992.8,1,21,1,0)
The TEST ROUTINE field is a multiple which will contain the names of all 
"^DD",8992.8,8992.8,1,21,2,0)
of the routines which should be included in this M Unit Test Group.
"^DD",8992.8,8992.8,2,0)
DESCRIPTION^8992.82^^2;0
"^DD",8992.8,8992.8,2,21,0)
^^4^4^3121220^
"^DD",8992.8,8992.8,2,21,1,0)
This field is optional and, if present, contains a description of the 
"^DD",8992.8,8992.8,2,21,2,0)
purpose of the current M Unit Test Group.  This could be a summary of one 
"^DD",8992.8,8992.8,2,21,3,0)
area of tests or a summary of the range of different tests included as a 
"^DD",8992.8,8992.8,2,21,4,0)
part of an M Unit Test Suite.
"^DD",8992.8,8992.81,0)
TEST ROUTINE SUB-FIELD^^.01^1
"^DD",8992.8,8992.81,0,"DT")
3031021
"^DD",8992.8,8992.81,0,"IX","B",8992.81,.01)

"^DD",8992.8,8992.81,0,"NM","TEST ROUTINE")

"^DD",8992.8,8992.81,0,"UP")
8992.8
"^DD",8992.8,8992.81,.01,0)
TEST ROUTINE^MF^^0;1^K:$L(X)>8!($L(X)<3) X
"^DD",8992.8,8992.81,.01,1,0)
^.1
"^DD",8992.8,8992.81,.01,1,1,0)
8992.81^B
"^DD",8992.8,8992.81,.01,1,1,1)
S ^XTV(8992.8,DA(1),1,"B",$E(X,1,30),DA)=""
"^DD",8992.8,8992.81,.01,1,1,2)
K ^XTV(8992.8,DA(1),1,"B",$E(X,1,30),DA)
"^DD",8992.8,8992.81,.01,3)
This is a routine to be used for the MUnit Test Group.  Answer must be 3-8 characters in length.
"^DD",8992.8,8992.81,.01,21,0)
^^2^2^3121220^
"^DD",8992.8,8992.81,.01,21,1,0)
This is the name of one of the routines that should be included in the 
"^DD",8992.8,8992.81,.01,21,2,0)
current M Unit Test Group when it is run.
"^DD",8992.8,8992.81,.01,"DT")
3121220
"^DD",8992.8,8992.82,0)
DESCRIPTION SUB-FIELD^^.01^1
"^DD",8992.8,8992.82,0,"DT")
3040701
"^DD",8992.8,8992.82,0,"NM","DESCRIPTION")

"^DD",8992.8,8992.82,0,"UP")
8992.8
"^DD",8992.8,8992.82,.01,0)
DESCRIPTION^W^^0;1
"^DD",8992.8,8992.82,.01,"DT")
3121220
"^DIC",8992.7,8992.7,0)
LOG4M CONFIG^8992.7
"^DIC",8992.7,8992.7,0,"GL")
^XTV(8992.7,
"^DIC",8992.7,8992.7,"%D",0)
^^15^15^3121220^
"^DIC",8992.7,8992.7,"%D",1,0)
This file is associated with the Log4M functionality which provides the 
"^DIC",8992.7,8992.7,"%D",2,0)
ability to include logging statements in code that can be left in when 
"^DIC",8992.7,8992.7,"%D",3,0)
released to the field.  There are several ways to control the logging, 
"^DIC",8992.7,8992.7,"%D",4,0)
but the best is through this file and using the Easy Config configuration 
"^DIC",8992.7,8992.7,"%D",5,0)
for the setup.  The functionality also includes the ability to specify 
"^DIC",8992.7,8992.7,"%D",6,0)
logging only for specific users (based on DUZ) and/or routines.  If 
"^DIC",8992.7,8992.7,"%D",7,0)
logging is specified but not turned on or only turned on for specific 
"^DIC",8992.7,8992.7,"%D",8,0)
users, the overhead is a call to the XTMLOG routine and the check for 
"^DIC",8992.7,8992.7,"%D",9,0)
existence of a specific variable which indicates that logging is active 
"^DIC",8992.7,8992.7,"%D",10,0)
for the session.  If the variable is not present, control returns 
"^DIC",8992.7,8992.7,"%D",11,0)
immediately to the calling routine.  Similarly, if a routine attempts to 
"^DIC",8992.7,8992.7,"%D",12,0)
initiate logging via reference to an entry in the file, the file entry is 
"^DIC",8992.7,8992.7,"%D",13,0)
checked  if it does not exist, or is turned off no logging is initiated.  
"^DIC",8992.7,8992.7,"%D",14,0)
Otherwise, logging is initiated at the level specified for the entry in 
"^DIC",8992.7,8992.7,"%D",15,0)
the file.
"^DIC",8992.7,"B","LOG4M CONFIG",8992.7)

"^DIC",8992.8,8992.8,0)
M UNIT TEST GROUP^8992.8
"^DIC",8992.8,8992.8,0,"GL")
^XTV(8992.8,
"^DIC",8992.8,8992.8,"%D",0)
^1.001^4^4^3121220^^
"^DIC",8992.8,8992.8,"%D",1,0)
This file provides a means to assist in keeping track of what routines
"^DIC",8992.8,8992.8,"%D",2,0)
have been named for M Unit tests.  It also allows a suite of tests to be
"^DIC",8992.8,8992.8,"%D",3,0)
created by adding at least one routine from each set of tests to be
"^DIC",8992.8,8992.8,"%D",4,0)
included in the suite.
"^DIC",8992.8,"B","M UNIT TEST GROUP",8992.8)

**END**
**END**
