;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Copyright 2010, 2013 Fidelity Information Services, Inc ; ; ; ; This source code contains the intellectual property ; ; of its copyright holder(s), and is made available ; ; under a license. If you do not know the terms of ; ; the license, please stop and do not read further. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; map: ;create maps for put and show, names for get and show PUTMAKE k lexnams n t1 d SHOWMAKE s s1=$ztr($zj("",SIZEOF("mident"))," ",$zch(255)),t1=$ztr($zj("",SIZEOF("mident"))," ",$zch(0)) f s s2=s1,s1=$o(map(s1),-1),map(s2_$ze(t1,$zl(s2)+1,SIZEOF("mident")))=map(s1) q:s1="$" k map(s1) s map("#)"_$ze(t1,3,SIZEOF("mident")))=map("#)"),map("%"_$ze(t1,2,SIZEOF("mident")))=map("$") f s2="#","#)","$" k map(s2) q ;---------------------------------------------------------------------------------------------------------------------------------- SHOWMAKE n lexnams s s="" f s s=$o(nams(s)) q:'$zl(s) d lexins(s) s map("$")=nams("*"),map("#")=nams("#") s i=1 f s i=$o(lexnams(i)) q:'$zl(i) d showstar(i) s s="" f s s=$o(lexnams(0,s),-1) q:'$zl(s) d pointins(s,lexnams(0,s)) s s1=$o(map(""),-1) f s s2=s1,s1=$o(map(s1),-1) q:s2="$" i map(s1)=map(s2) k map(s2) q ;---------------------------------------------------------------------------------------------------------------------------------- SHOWNAM n lexnams,t1,map d SHOWMAKE s s1=$ztr($zj("",SIZEOF("mident"))," ",$zch(255)),t1=$ztr($zj("",SIZEOF("mident"))," ",$zch(0)) f s s2=s1,s1=$o(map(s1),-1),map(s2)=map(s1) q:s1="$" k map(s1) k map("#") i '$$MAP2NAM(.map) zm gdeerr("GDECHECK")\2*2 q ;---------------------------------------------------------------------------------------------------------------------------------- MAP2NAM(list) n maxMap,currMap,currMapLen,prevMap,prevMapLen,currReg,prevPrefix,currPrefix n namSpc,currNam,currNamLen,stopLoop,i,startMap,midentSize,prevPrevMap s currMap=$o(list("")) q:currMap'="#)" 0 s currMap=$o(list(currMap)) i currMap="%" s list("$")=list("%") ; if "$" is missing, assign it the same value as "%" e q:currMap'="$" 0 s maxMap=$ztr($zj("",SIZEOF("mident"))," ",$zch(255)),currMap=$o(list(""),-1) q:currMap'=maxMap 0 k nams f q:currMap="$" s prevMap=$o(list(currMap),-1) d s currMap=prevMap . s currReg=list(currMap) . ; Note that with the above mapping, all keys in the range [prevMap,currMap) are mapped to currReg. . ; where [ denotes closed interval and ) denotes open interval i.e. prevMap <= key < currMap . ; Case (1a) : If currMap contains ")" (e.g. "abc)"), it most likely means prevMap would be "abc". . ; In this case, just add "abc" as a namespace. No more processing needed for currMap. . ; Case (1b) : But it is also possible prevMap is not "abc". . ; In this case, do the "abc" namespace addition (as if prevMap was "abc"). . ; But also proceed with the current iteration of the for loop as if "currMap" was "abc". . s currMapLen=$zl(currMap) . i $ze(currMap,currMapLen)=")" d q:prevMap=namSpc . . s namSpc=$ze(currMap,1,currMapLen-1),nams(namSpc)=currReg . . i prevMap'=namSpc s currMap=namSpc,currMapLen=currMapLen-1 . ; Case (3) : If prevMap contains ")" (e.g. "abc)"), then check to see if its previous entry (say prevPrevMap) . ; is the same region as currReg. If so, we can coalesce the entire range [prevPrevMap,currMap) into one with the . ; exception of "abc" for which add an explicit namespace. Do this for as many ")" prevMap entries that you can find . ; as long as its prevPrevMap entry is the same region as currReg. This could potentially coalesce a lot of intervals. . ; Note: Need to handle a situation like Case (1b) here too. We do this by keeping prevMap as it is but adjusting . ; just prevMapLen to be 1 byte less (to remove trailing ")"). . s stopLoop=0 . f d q:stopLoop . . s prevMapLen=$zl(prevMap) . . i $ze(prevMap,prevMapLen)'=")" s stopLoop=1 q . . s namSpc=$ze(prevMap,1,$i(prevMapLen,-1)) . . s prevPrevMap=$o(list(prevMap),-1) . . i prevPrevMap'=namSpc s stopLoop=1 q . . s nams(namSpc)=list(prevMap) . . i list(prevMap)'=currReg s stopLoop=1 q . . s prevMap=$o(list(prevMap),-1) . . i prevMap="$" s stoploop=1,prevMapLen=1 q . ; Note: At this point prevMap could contain a trailing ")" but in that case prevMapLen would have been adjusted to . ; not consider that last byte. As long as all following usages of prevMap are of the form $ze(prevMap,1,prevMapLen) . ; we will never see the ")" in prevMap. . ; Case (4) : The map entry "currMap" exists and "prevMap" is the previous map entry. . ; Determine the namespaces that potentially lie between the two map entries. . ; And add them to the "nams" array. . f i=1:1:currMapLen i $ze(currMap,i)'=$ze(prevMap,i) q . s matchLen=i-1 ; the length of the maximal common prefix between prevMap and currMap . ; Subcase (4a) : matchLen == prevMapLen . ; In this case we are guaranteed that prevMapLen < currMapLen, and we need to add only ONE namespace. . ; Example prevMap="ag", currMap="agk". Here, matchLen=2, prevMapLen=2, currMapLen=3. Add only "ag*". . i (matchLen=prevMapLen)&(prevMapLenprevMapLen d . . s currPrefix=prevPrefix_"z",prevPrefix=$ze(prevMap,1,i) . . f q:currPrefix=prevPrefix s namSpc=currPrefix_"*",nams(namSpc)=currReg,currPrefix=$$lexprev(currPrefix) . . ; Do optimization check at each sub-namespaces level. If it succeeds, stop processing any higher level sub-namespaces. . . s startMap=$$findStartMap(currPrefix) . . i list(startMap)=currReg s i=prevMapLen q ; set i to force quit out of for loop . s namSpc=currPrefix_"*",nams(namSpc)=currReg ; Update "nams" variable to contain # of elements in "nams" array ; Take this opportunity to remove redundant namespaces. ; Example : If "a*" and "ab*" both map to the same region, the namespace "ab*" can be safely removed. ; But if "a*" maps to AREG, "aa*" maps to BREG, and "aaa*" maps to AREG, we cannot remove "aaa*" because ; "a*" and "aaa*" maps to the same reg. This is because there is a more restrictive mapping "aa*" which ; maps to a different region than "aaa*". That should prevail. ; Similarly if "ab*" and "abc" both map to the same region, the namespace "abc" can be safely removed. ; But if "abc*" also is mapped and to a different region than "abc", then "abc" cannot be removed. s currNam="",nams=0 ; With SIZEOF("mident")=32, we allow a max of 31-byte global name specifications. ; But with SIZEOF("mident")=8 (for older versions with no longnames support, we allow a max of 8-byte global names. ; Handle this 1-byte discrepancy for the 8-byte case by setting the variable midentSize accordingly. s midentSize=$s(SIZEOF("mident")=8:9,1:SIZEOF("mident")) s nams("*")=list("$") f s currNam=$o(nams(currNam)) q:currNam="" s nams=nams+1 d . s currNamLen=$zl(currNam) . s currReg=nams(currNam) . s killed=0,quitLoop=0 . f i=$s($ze(currNam,currNamLen)="*":(currNamLen-2),1:currNamLen):-1:0 d q:quitLoop . . s currPrefix=$ze(currNam,1,i)_"*" . . s prevReg=$g(nams(currPrefix)) . . i (""'=prevReg) d . . . s quitLoop=1 . . . i currReg=prevReg k nams(currNam) s nams=nams-1,killed=1 . i 'killed,currNamLen'