[613] | 1 | XPDZSUM ;WV/TOAD-KIDS check Before checksums ;12/01/2005 10:40
|
---|
| 2 | ;;8.0;KERNEL;**L34**;Jul 10,1995
|
---|
| 3 | ;
|
---|
| 4 | ; This routine is the prototype for a new KIDS option that compares the
|
---|
| 5 | ; checksums for routines being brought in by a patch to those currently
|
---|
| 6 | ; installed on the system. It parses the patch description, extracts
|
---|
| 7 | ; the checksums from the table and records them in the Checksum subfile
|
---|
| 8 | ; of the Patch Record file (437016). It then uses ^%ZOSF("RSUM") to
|
---|
| 9 | ; compare the before values and warn of any potential collisions. It
|
---|
| 10 | ; also records the patch list for each routine and records that, too, in
|
---|
| 11 | ; the Checksum subfile, and compares it to the current routine's
|
---|
| 12 | ; patch list.
|
---|
| 13 | ;
|
---|
| 14 | ; history
|
---|
| 15 | ;
|
---|
| 16 | ; 2005 11 29 Rick Marshall wrote outline, then shifted to routine
|
---|
| 17 | ; XPDZHFS to explore the algorithm
|
---|
| 18 | ; 2005 11 30 Rick Marshall complete algorithm exploration, copied
|
---|
| 19 | ; relevant code back to this routine, then worked on the
|
---|
| 20 | ; checksum and patch list extract and compare
|
---|
| 21 | ; 2005 12 01 Rick Marshall continues refining the extract & compare
|
---|
| 22 | ;
|
---|
| 23 | ; contents
|
---|
| 24 | ;
|
---|
| 25 | ; 1. prompt for KIDS text file
|
---|
| 26 | ; 2. load description into ^TMP($J)
|
---|
| 27 | ; 3. find routine table
|
---|
| 28 | ; 4. extract checksums and patch list
|
---|
| 29 | ; ; 5. file them in the Checksum subfile
|
---|
| 30 | ; ; 6. clear ^TMP($J)
|
---|
| 31 | ; 5. compare to current routines
|
---|
| 32 | ;
|
---|
| 33 | ; XPDZSUM contents
|
---|
| 34 | ;
|
---|
| 35 | ; FINDSUMS. find checksums & patch lists in a KIDS description file
|
---|
| 36 | ; DRIVEFS. test FINDSUMS
|
---|
| 37 | ; ISHEAD. return whether a line is a routine table header line
|
---|
| 38 | ; DRIVEIH. test ISHEAD
|
---|
| 39 | ; COLUMNS. extract column values from floating multi-space delimiters
|
---|
| 40 | ; DRIVEC. test COLUMNS
|
---|
| 41 | ;
|
---|
| 42 | ;
|
---|
| 43 | FINDSUMS(PATH,FILE) ; find checksums & patch lists in a KIDS description file
|
---|
| 44 | ; PATH_FILE = KIDS description file, input to $$FTG^%ZISH in F1
|
---|
| 45 | ;
|
---|
| 46 | ; called by DRIVEFS (tester), DIRSUMS^XPDZHFS
|
---|
| 47 | ; calls $$FTG^%ZISH, $$UP^XLFSTR, ANALYZE, $$COLUMNS
|
---|
| 48 | ;
|
---|
| 49 | ; FINDSUMS contents
|
---|
| 50 | ;
|
---|
| 51 | ; F1. transfer KIDS description file to ^TMP
|
---|
| 52 | ; F2. traverse description
|
---|
| 53 | ; F3. find routine table in description
|
---|
| 54 | ; F4. find end of routine table
|
---|
| 55 | ; F5. extract and display columns from the row
|
---|
| 56 | ; F6. compare before checksum & patch list to current routine
|
---|
| 57 | ;
|
---|
| 58 | ; F1. transfer KIDS description file to ^TMP
|
---|
| 59 | ;
|
---|
| 60 | K ^TMP("XPDZHFS",$J)
|
---|
| 61 | D
|
---|
| 62 | . N ROOT S ROOT=$NA(^TMP("XPDZHFS",$J,1,0))
|
---|
| 63 | . N SUB S SUB=3
|
---|
| 64 | . N SUCCESS S SUCCESS=$$FTG^%ZISH(PATH,FILE,ROOT,SUB)
|
---|
| 65 | . ; Device Handler: transfer a file to a global
|
---|
| 66 | ;
|
---|
| 67 | ; F2. traverse description
|
---|
| 68 | ;
|
---|
| 69 | N TABLE S TABLE=0 ; whether line is part of routine table
|
---|
| 70 | N ROUTINES ; to routine lines in table
|
---|
| 71 | N TYPE S TYPE=0 ; what type of routine table is this? (see ANALYZE)
|
---|
| 72 | N NUM S NUM=0 F D Q:'NUM
|
---|
| 73 | . S NUM=$O(^TMP("XPDZHFS",$J,NUM)) Q:'NUM
|
---|
| 74 | . ; W !,NUM,?5
|
---|
| 75 | . N LINE S LINE=$G(^TMP("XPDZHFS",$J,NUM,0))
|
---|
| 76 | . N UP S UP=$$UP^XLFSTR(LINE) ; Kernel: XLF library: upper case
|
---|
| 77 | . ;
|
---|
| 78 | . ; F3. find routine table in description
|
---|
| 79 | . ;
|
---|
| 80 | . I 'TABLE D Q:'TABLE ; find routine table header line
|
---|
| 81 | . . N ISHEAD ; whether it is a table header line
|
---|
| 82 | . . D ANALYZE(LINE,.ISHEAD,.TYPE) ; analyse the line
|
---|
| 83 | . . Q:'ISHEAD ; skip each line until we find the table
|
---|
| 84 | . . S TABLE=1 ; we have entered the routine table
|
---|
| 85 | . . S ROUTINES=-1 ; we have not yet seen the first routine lines
|
---|
| 86 | . I $TR(UP," -_=")'="" S ROUTINES=ROUTINES+1 ; count non-null table lines
|
---|
| 87 | . ; header line does not count (moves from -1 to 0)
|
---|
| 88 | . Q:'ROUTINES ; the rest of the loop only applies to routine lines
|
---|
| 89 | . ;
|
---|
| 90 | . ; F4. find end of routine table
|
---|
| 91 | . ;
|
---|
| 92 | . S TABLE=0 D Q:'TABLE ; assume it's the end, pass screens to continue
|
---|
| 93 | . . ; after first non-null routine line, next blank line is end:
|
---|
| 94 | . . Q:$TR(UP," -_=")="" ; I am concerned about whether this is too tight
|
---|
| 95 | . . Q:UP["LIST OF PRECEDING PATCHES"
|
---|
| 96 | . . Q:UP["NO ROUTINE"
|
---|
| 97 | . . Q:UP["CHECK^XTSUMBLD"
|
---|
| 98 | . . Q:UP["NOTE: "!(UP["NOTE ")
|
---|
| 99 | . . Q:UP["INSTALLATION"
|
---|
| 100 | . . S TABLE=1
|
---|
| 101 | . ;
|
---|
| 102 | . ; F5. extract and display columns from the row
|
---|
| 103 | . ;
|
---|
| 104 | . N COLUMNS S COLUMNS=$$COLUMNS(LINE) ; extract the columns
|
---|
| 105 | . ;
|
---|
| 106 | . N R S R=$P(COLUMNS,U) ; all four types start with routine
|
---|
| 107 | . W !?3,R ; routine
|
---|
| 108 | . ;
|
---|
| 109 | . N B,A,P S (B,P)="" ; order varies on the other 3 fields
|
---|
| 110 | . ;
|
---|
| 111 | . I TYPE>2 D ; for types 3 and 4, the before comes next
|
---|
| 112 | . . S B=$P(COLUMNS,U,2)
|
---|
| 113 | . . S A=$P(COLUMNS,U,3)
|
---|
| 114 | . . I TYPE=4 S P=$P(COLUMNS,U,4)
|
---|
| 115 | . E D ; for types 1 and 2, no before, after comes next
|
---|
| 116 | . . S A=$P(COLUMNS,U,2)
|
---|
| 117 | . . I TYPE=1 S P=$P(COLUMNS,U,3)
|
---|
| 118 | . ;
|
---|
| 119 | . W ?13,B,?28,A,?43,P ; sum before, sum after, patch list
|
---|
| 120 | . ;
|
---|
| 121 | . ; F6. compare before checksum & patch list to current routine
|
---|
| 122 | . ;
|
---|
| 123 | ;
|
---|
| 124 | QUIT ; end of FINDSUMS
|
---|
| 125 | ;
|
---|
| 126 | ;
|
---|
| 127 | DRIVEFS ; test FINDSUMS
|
---|
| 128 | ;
|
---|
| 129 | D FINDSUMS("c:\voe\patches\XU\","XU-8_SEQ-120_PAT-135.TXT")
|
---|
| 130 | QUIT ; end of DRIVEFS
|
---|
| 131 | ;
|
---|
| 132 | ;
|
---|
| 133 | ANALYZE(LINE,ISHEAD,TYPE,DEBUG) ; analyze a line from a KIDS description
|
---|
| 134 | ;
|
---|
| 135 | ; .ISHEAD = 1 if it is the routine table header line, else 0
|
---|
| 136 | ; .TYPE = set of codes: which type of routine table is it:
|
---|
| 137 | ; 1 = routine checksum after patch list
|
---|
| 138 | ; 2 = routine checksum after
|
---|
| 139 | ; 3 = routine checksum before checksum after
|
---|
| 140 | ; 4 = routine checksum before checksum after patch list
|
---|
| 141 | ;
|
---|
| 142 | ; and not yet handled:
|
---|
| 143 | ; 5 = routine sum & patches before sum & patches after
|
---|
| 144 | ; 6 = none (may have routines; consider how to handle later)
|
---|
| 145 | ; 7 = none (informational)
|
---|
| 146 | ; DEBUG (optional) = 1 to make ANALYZE write debugging info
|
---|
| 147 | ;
|
---|
| 148 | ; I1. quickly screen out poor candidates
|
---|
| 149 | ;
|
---|
| 150 | S ISHEAD=0 ; assume it is not a header line
|
---|
| 151 | I LINE'[" " Q ; unless there are columns, it's not a header line
|
---|
| 152 | S LINE=$$UP^XLFSTR(LINE) ; convert to upper case
|
---|
| 153 | ; better be checksums:
|
---|
| 154 | I LINE'["CHECKSUM",LINE'["BEFORE",LINE'["OLD",LINE'["CHKSUM" Q
|
---|
| 155 | I LINE["(V)" Q ; associated patches lines contain "BEFORE"
|
---|
| 156 | I LINE["CHECK^XTSUMBLD" Q ; extra header line contains "CHECKSUM"
|
---|
| 157 | I LINE["VERIFY CHECKSUMS IN TRANSPORT GLOBAL" Q ; install step line
|
---|
| 158 | ;
|
---|
| 159 | ; I2. extract columns
|
---|
| 160 | ;
|
---|
| 161 | N COLUMNS S COLUMNS=$$COLUMNS(LINE) ; extract columns
|
---|
| 162 | N LENGTH S LENGTH=$L(COLUMNS,U) ; how many columns?
|
---|
| 163 | I $G(DEBUG) W !,LENGTH ; for debugging
|
---|
| 164 | I LENGTH<2!(LENGTH>4) Q ; unless there are 2-4 columns, it's not
|
---|
| 165 | S TYPE=6 ; assume the routine table requires special handling
|
---|
| 166 | ;
|
---|
| 167 | S COLUMNS=$TR(COLUMNS," AEIOUC") ; condense: extract spaces, vowels, C
|
---|
| 168 | ; C because of all the variations of CHCKSUM/CHKSUM
|
---|
| 169 | ;
|
---|
| 170 | N R S R=$P(COLUMNS,U) ; routine name
|
---|
| 171 | N B S B=$P(COLUMNS,U,2) ; checksum before patch
|
---|
| 172 | N A S A=$P(COLUMNS,U,3) ; checksum after patch
|
---|
| 173 | N P S P=$P(COLUMNS,U,4) ; patch list after patch
|
---|
| 174 | ;
|
---|
| 175 | I LENGTH=2 D ; if only two columns, it's name and checksum after
|
---|
| 176 | . S A=B,B="" ; set checksum after and clear before
|
---|
| 177 | . S TYPE=2
|
---|
| 178 | E I LENGTH=3 D ; two different types have three columns
|
---|
| 179 | . S TYPE=3 ; assume it is name, before, and after
|
---|
| 180 | . I "^PTHLST^2NDLN^NDTR^LST^^"'[(U_A_U) D ; if patch list, it's type 1
|
---|
| 181 | . . S P=A,A=B,B="" ; set after & patches, clear before
|
---|
| 182 | . . S TYPE=1
|
---|
| 183 | E S TYPE=4 ; the preferred type, all four columns
|
---|
| 184 | ;
|
---|
| 185 | I $G(DEBUG) W !?3,R,?13,B,?28,A,?43,P ; for debugging
|
---|
| 186 | ;
|
---|
| 187 | ; I3. decide whether they look like routine table header columns
|
---|
| 188 | ;
|
---|
| 189 | D ; change that to no unless a pattern is met
|
---|
| 190 | . ;
|
---|
| 191 | . I "^NM^RTN^RTNNM^RNT^NM^RNTNM^PRGRM^"'[(U_R_U) D Q ; routine name
|
---|
| 192 | . . I $G(DEBUG) W "R: [",R,"] ",$L(R)
|
---|
| 193 | . I "^BFR^LD^HKSM^HKSMBFR^BFRPTH^^BFRHKSM^"'[(U_B_U) D Q
|
---|
| 194 | . . I $G(DEBUG) W "B: [",B,"] ",$L(B)
|
---|
| 195 | . I "^FTR^NW^HKSM^HKSMFTR^^FTRPTH^NWHKSM^FTRHKSM^"'[(U_A_U) D Q
|
---|
| 196 | . . I $G(DEBUG) W "A: ",A,"[ ",$L(A)
|
---|
| 197 | . I "^PTHLST^2NDLN^NDTR^LST^^"'[(U_P_U) D Q ; patch list after patch
|
---|
| 198 | . . I $G(DEBUG) W "P: ",P,"[ ",$L(P)
|
---|
| 199 | . ;
|
---|
| 200 | . S ISHEAD=1
|
---|
| 201 | Q:'ISHEAD
|
---|
| 202 | ;
|
---|
| 203 | ; I4. display canonical header
|
---|
| 204 | ;
|
---|
| 205 | W !,TYPE
|
---|
| 206 | W ?3,"routine"
|
---|
| 207 | I TYPE>2 W ?13,"sum before"
|
---|
| 208 | W ?28,"sum after"
|
---|
| 209 | I TYPE=1!(TYPE=4) W ?48,"patch list"
|
---|
| 210 | ;
|
---|
| 211 | QUIT ; end of ANALYZE
|
---|
| 212 | ;
|
---|
| 213 | ;
|
---|
| 214 | DRIVEA ; test ANALYZE
|
---|
| 215 | ;
|
---|
| 216 | N LINE S LINE=" Routine ChkSum 2nd Line"
|
---|
| 217 | N ISHEAD
|
---|
| 218 | D ISHEAD(LINE,.ISHEAD,.TYPE,1)
|
---|
| 219 | W !!,ISHEAD
|
---|
| 220 | QUIT ; end of DRIVEIH
|
---|
| 221 | ;
|
---|
| 222 | ;
|
---|
| 223 | COLUMNS(LINE) ; extract column values from floating multi-space delimiters
|
---|
| 224 | ; given a free text line containing floating columns of data
|
---|
| 225 | ; delimited by multiple spaces (2 or more), extract the columns and
|
---|
| 226 | ; return them ^-delimited. This could later be extended to choose the
|
---|
| 227 | ; delimiters (instead of spaces and ^s).
|
---|
| 228 | ;
|
---|
| 229 | ; we need to extend this tool to handle empty columns
|
---|
| 230 | ;
|
---|
| 231 | N COLUMNS S COLUMNS="" ; return value
|
---|
| 232 | S LINE=$$TRIM^XLFSTR(LINE,"LR") ; trim leading & trailing spaces
|
---|
| 233 | N COUNT ; count columns extracted
|
---|
| 234 | F COUNT=1:1 Q:LINE="" D ; continue until LINE reduced to empty
|
---|
| 235 | . N COLUMN S COLUMN=$P(LINE," ") ; copy first column
|
---|
| 236 | . S $P(COLUMNS,U,COUNT)=COLUMN ; place it into the return value
|
---|
| 237 | . S $P(LINE," ")="" ; remove it from LINE
|
---|
| 238 | . S LINE=$$TRIM^XLFSTR(LINE,"L") ; remove leading spaces from LINE
|
---|
| 239 | ;
|
---|
| 240 | QUIT COLUMNS ; end of COLUMNS, return extracted column values
|
---|
| 241 | ;
|
---|
| 242 | ;
|
---|
| 243 | DRIVEC ; test COLUMNS
|
---|
| 244 | ;
|
---|
| 245 | N LINE S LINE=" Routine Old New 2nd Line "
|
---|
| 246 | W !,"Before: ",LINE
|
---|
| 247 | W !!,"After: ",$$COLUMNS(LINE)
|
---|
| 248 | QUIT ; end of DRIVEC
|
---|
| 249 | ;
|
---|
| 250 | ;
|
---|
| 251 | QUIT ; end of routine XPDZSUM
|
---|