Annotation of researchv10no/cmd/spitbol/dif.spt, revision 1.1

1.1     ! root        1: -TITLE SPITBOL TEST PROGRAM #10 -- FILE COMPARATOR
        !             2: -IN80
        !             3: *   THIS PROGRAM PERFORMS THE INVALUABLE SERVICE OF COMPARING TWO
        !             4: *   TEXT FILES FOR DIFFERENCES WHICH ARE PRINTED OUT IF FOUND. ITS
        !             5: *   SEMANTICS ARE THOSE OF THE DEC-10 PROGRAM FILCOM, BUT THIS VERSION
        !             6: *   BEING IN SPITBOL IS PORTABLE.
        !             7: *
        !             8: **      THE PROGRAM IS BASICALLY THE WORK OF
        !             9: **      P.R. TALLETT
        !            10: **      DATACALL LTD
        !            11: **      KIRKSTALL RD
        !            12: **      LEEDS, ENGLAND.
        !            13: **
        !            14: **      IT HAS BEEN ELABORATED SOMEWHAT BY A.P. MCCANN.
        !            15: *
        !            16: ************************************************************************
        !            17: **                       INSTRUCTIONS FOR USE                          *
        !            18: **  THE PROGRAM STARTS BY ATTEMPTING TO READ A COMMAND LINE FROM  THE  *
        !            19: **  STANDARD  INPUT  FILE.   IF  THIS  FAILS, A "*" IS PRINTED ON THE  *
        !            20: **  TERMINAL AS A PROMPT FOR A  REPLY.   THE  COMMAND  LINE  SUPPLIED  *
        !            21: **  EITHER  IN  A  BATCH  OR TERMINAL RUN SHOULD CONSIST OF A COMMAND  *
        !            22: **  LINE OF FORM                                                       *
        !            23: **  OFILE=INFILE1,INFILE2                                              *
        !            24: **  WHERE OFILE IS THE FILE TO RECEIVE LIST OF  DIFFERENCES,  INFILE1  *
        !            25: **  AND INFILE2 ARE FILES TO BE COMPARED.                              *
        !            26: **                                                                     *
        !            27: **       IN ADDITION, THE COMMAND LINE  MAY  CONTAIN  AT  ANY  POINT,  *
        !            28: **  SWITCHES  TO  CONTROL  OPTIONS.  THESE ARE LISTED BELOW, WHERE ()  *
        !            29: **  ENCLOSES OPTIONAL ITEMS AND N STANDS FOR AN INTEGER.               *
        !            30: **                                                                     *
        !            31: **       /B         BLANK LINES MUST MATCH IN COMPARED FILES. DEFAULT  *
        !            32: **       IS THAT BLANK LINES ARE IGNORED IN MATCHING PROCESS.          *
        !            33: **                                                                     *
        !            34: **       /L(N)(+)   N  LINES  MUST  BE  FOUND  IDENTICAL   BEFORE   A  *
        !            35: **  DIFFERENCE LIST IS TERMINATED.  DEFAULT IS N=3.                    *
        !            36: **                                                                     *
        !            37: **       +  SIGNIFIES THAT THESE N LINES ARE TO BE  LISTED.   DEFAULT  *
        !            38: **  IS THAT ONLY THE FIRST OF THE N LINES IS LISTED.                   *
        !            39: **                                                                     *
        !            40: **       /D(N)(-)   A DOUBLE COLUMN LISTING FORMAT IS  USED  FOR  THE  *
        !            41: **  DIFFERENCES, GIVING THE FIRST N CHARACTERS OF DIFFERING LINES (OR  *
        !            42: **  THE WHOLE LINE IF LESS THAN N IN LENGTH).  THE TOTAL LINE  LENGTH  *
        !            43: **  IS 2N+2 INCLUDING SEPARATING CHARACTERS.  DEFAULT IS N=65.         *
        !            44: **                                                                     *
        !            45: **       -  SIGNIFIES THAT DIFFERENCES SHOULD BE SEPARATED BY A SHORT  *
        !            46: **  MARKER  LINE.   DEFAULT IS TO USE A SUFFICIENTLY LONG MARKER LINE  *
        !            47: **  TO SEPARATE DIFFERENCES TO GIVE A NEAT "BOXED"  PRINTER  LISTING.  *
        !            48: **  THE SHORTER FORMAT IS USEFUL ON SLOW TERMINALS.                    *
        !            49: **                                                                     *
        !            50: **       /RN        ACCEPT INPUT LINES OR  PRINT  OUTPUT  RECORDS  OF  *
        !            51: **  MAXIMUM LENGTH N CHARACTERS.  DEFAULT IS 133 CHARACTERS.           *
        !            52: **                                                                     *
        !            53: **       AFTER TASK COMPLETION, AN ATTEMPT IS  MADE  TO  READ  A  NEW  *
        !            54: **  COMMAND  LINE FOR ANOTHER SET OF FILES.  THE RUN IS TERMINATED BY  *
        !            55: **  SUPPLYING A NULL COMMAND LINE.                                     *
        !            56: ************************************************************************
        !            57: *
        !            58: *   IF PROGRAM IS RUN FROM A TERMINAL, ERRORS IN COMMAND LINE
        !            59: *   CAN BE CORRECTED INTERACTIVELY. IT MAY ALSO BE RUN AS A BATCH JOB,
        !            60: *   BUT IN THIS CASE ERROR RECOVERY IS NOT POSSIBLE.
        !            61: *
        !            62: *   NOTE IMPORTANT COMMENT PRECEDING START OF MAIN PROGRAM.
        !            63: *
        !            64: *
        !            65:         &ANCHOR = &TRIM = 1; &STLIMIT = 999999
        !            66:         DIGIT   = "0123456789"; BLD = " " DIGIT
        !            67:         SWPAT   = "" $ SL BREAK("/") $ N "/" $ SL
        !            68: +           ("L" (SPAN(BLD) $ NN | "") ("+" $ NNP | "")
        !            69: +           *?(NN = CONVERT(NN,"INTEGER")) |
        !            70: +           "D" (SPAN(BLD) $ LEN *?(LEN = CONVERT(LEN,"INTEGER")) |
        !            71: +           *?(LEN = 65)) ("-" $ LENM | "") |
        !            72: +           ("R" SPAN(DIGIT)) $ RECL |
        !            73: +           "B" $ BLANKS)
        !            74:         CMDPAT  = BREAK("=") $ F1 LEN(1) BREAK(",") $ F2 LEN(1) REM $ F3
        !            75:         STARS   = "****"
        !            76:         SETEXIT(.ERR); &ERRLIMIT = 5
        !            77: *
        !            78: *   HERE ARE THE DATATYPES USED TO MAINTAIN LIST OF LINES WHICH ARE
        !            79: *   NOT YET COMPLETELY PROCESSED, TOGETHER WITH POINTERS INTO THEM.
        !            80: *   HEAD, CURRENT, TAIL ARE POINTERS TO INITIAL LINE, CURRENT LINE
        !            81: *   FOR MATCHING, AND LAST LINE IN THE LINKED LIST OF LINES BUILT
        !            82: *   FROM ELEMS.
        !            83: *   COUNT IS NO. OF LINES IN THE LIST.
        !            84: *   EOF IS SET NON-NULL WHEN END FILE IS MET.
        !            85: *   INP IS INPUT ASSOCD FOR READING LINES.
        !            86: *
        !            87:         DATA("ELEM(OBJECT,LINK)")
        !            88:         DATA("LIST(HEAD,CURRENT,TAIL,COUNT,EOF,INP)")
        !            89: *
        !            90: *   ROUTINE TO ADD AN OBJECT TO A LIST. RETURNS A POINTER TO OBJECT.
        !            91: *   IF BLANKS IS NULL, IT DOES NOT ADD BLANK LINES BUT FINDS
        !            92: *   AND ADDS NEXT NON-BLANK. FAILS IF INPUT EXHAUSTED IN THIS PROCESS.
        !            93: *
        !            94:         DEFINE("ADD(LISTX,OBJ)")                        :(ADDEND)
        !            95: ADD     COUNT(LISTX) = (DIFFER(BLANKS),DIFFER(OBJ)) COUNT(LISTX) + 1:S(ADD0)
        !            96:         OBJ     = $INP(LISTX)                           :S(ADD)F(FRETURN)
        !            97: *
        !            98: ADD0    ADD     = TAIL(LISTX) = HEAD(LISTX) =
        !            99: +           IDENT(HEAD(LISTX)) ELEM(OBJ)                :S(RETURN)
        !           100: *   ADD TO EXISTING LIST IF ARRIVE HERE
        !           101:         ADD     = TAIL(LISTX) = LINK(TAIL(LISTX)) = ELEM(OBJ):(RETURN)
        !           102: ADDEND
        !           103: *
        !           104: *   ROUTINE TO FIND AN OBJECT IN THATL. FAILS IF NOT FOUND
        !           105: *   OTHERWISE RETURNS POINTER INTO THATL OF MATCHING ITEM.
        !           106: *
        !           107:         DEFINE("MATCH(OBJ)")                            :(MATEND)
        !           108: MATCH   IDENT(THAP = HEAD(THATL))                       :S(FRETURN)
        !           109:         CD      = 1
        !           110: *
        !           111: *   ATTEMPT TO MATCH OBJECT WITH THAT POINTED AT IN THATL. NOTE POINTER.
        !           112: *
        !           113: MATC1   MATCH   = THAPT = IDENT(OBJ,OBJECT(THAP)) THAP  :S(MATC3)
        !           114: *
        !           115: *   ADVANCE DOWN THE LIST TO TRY AGAIN.
        !           116: *
        !           117: MATC2   CD      = CD + 1
        !           118:         IDENT(THAP = LINK(THAP))                        :F(MATC1)S(FRETURN)
        !           119: *
        !           120: *   FIRST LINE MATCHED . CHECK REMAINING
        !           121: *   NN-1 LINES OR TO END OF THISL.
        !           122: *
        !           123: MATC3   THIPT   = CURRENT(THISL)
        !           124:         CDEC    = CD
        !           125: *
        !           126: *   MATCHED IF RUN OFF END OF THISL BUT NOT OFF END OF THATL.
        !           127: *
        !           128: MATC4   IDENT(THIPT = LINK(THIPT))                      :S(RETURN)
        !           129:         IDENT(THAPT = LINK(THAPT))                      :S(FRETURN)
        !           130:         CDEC    = CDEC + 1
        !           131:         IDENT(OBJECT(THIPT),OBJECT(THAPT))              :S(MATC4)F(MATC2)
        !           132: MATEND
        !           133: *
        !           134: *   ROUTINE TO PRINT DIFFERENCE WHEN FOUND. IT OUTPUTS BOTH LISTS
        !           135: *   UP TO FIELD "CURRENT(LISTX)". ON FIRST ENTRY ONLY, IT PLACES
        !           136: *   INPUT FILE NAMES ON THE LISTING.
        !           137: *
        !           138:         DEFINE("OUTFIL(LISTX,MARK,STARS)X")             :(OUTEND)
        !           139: OUTFIL  OUT     = "FILE 1)  " F2
        !           140:         OUT     = "FILE 2)  " F3
        !           141:         OUT     = DEFINE("OUTFIL(LISTX,MARK,STARS)X",.OUTFIL2)
        !           142: *
        !           143: *   THIS ENTRY IS USED ON ALL OCCASIONS AFTER FIRST
        !           144: *
        !           145: OUTFIL2 OUT     = STARS
        !           146: OUTFIL3 OUT     = MARK OBJECT(DIFFER(X = HEAD(LISTX)) X):F(RETURN)
        !           147:         HEAD(LISTX) = LINK(X)
        !           148:         IDENT(CURRENT(LISTX),X)                         :S(RETURN)F(OUTFIL3)
        !           149: OUTEND
        !           150: *
        !           151: *   ROUTINE TO PUT LINES TO OUTPUT FILE.
        !           152: *
        !           153:         DEFINE("PUT()X,Y,XO,YO")                        :(ERREND)
        !           154: PUT     DIFFER(LEN)                                     :S(PUTDB)
        !           155:         DIFFS   = DIFFS + 1
        !           156:         OUTFIL(FILE1,"1)   ",STSTARS)
        !           157:         OUTFIL(FILE2,"2)   ",STARS)                     :(RETURN)
        !           158: *
        !           159: *   HERE TO OUTPUT DIFFERENCES IN DOUBLE COLUMN FORMAT
        !           160: *
        !           161: PUTDB   OUT     = RPAD("FILE 1) " F2,LEN) "| " "FILE 2) " F3
        !           162:         DEFINE("PUT()X,Y,XO,YO",.PUTD)
        !           163: *
        !           164: *   ENTRY USED FOR DOUBLE COLUMN FORMAT AFTER INITIAL ENTRY
        !           165: *
        !           166: PUTD    DIFFS   = DIFFS + 1; OUT = STSTARS
        !           167:         XO      = X = HEAD(FILE1); YO = Y = HEAD(FILE2)
        !           168: *
        !           169: *   CHECK WHETHER BOTH LISTS FINISHED
        !           170: *
        !           171: PUTD1   HEAD(FILE1) = IDENT(X,IDENT(Y))  CURRENT(FILE1) :F(PUTD2)
        !           172:         HEAD(FILE2) = CURRENT(FILE2)                    :(RETURN)
        !           173: *
        !           174: *   PRINT A LINE GIVING DIFFERENCES IN ADJACENT COLUMNS
        !           175: *
        !           176: PUTD2   OUT     = (DIFFER(X) GT(SIZE(XO = OBJECT(X)),LEN)
        !           177: +           SUBSTR(XO,1,LEN),RPAD(XO,LEN))
        !           178: +           "| "
        !           179: +           (DIFFER(Y) GT(SIZE(YO = OBJECT(Y)),LEN) SUBSTR(YO,1,LEN),YO)
        !           180:         X       = (IDENT(X),(DIFFER(CURRENT(FILE1),X) LINK(X),XO = ))
        !           181:         Y       = (IDENT(Y),(DIFFER(CURRENT(FILE2),Y) LINK(Y),YO = )):(PUTD1)
        !           182: *
        !           183: *   THIS ROUTINE IS ENTERED IF A SPITBOL ERROR OCCURS - USED FOR BUGS
        !           184: *
        !           185: ERR     SETEXIT(EQ(&ERRTYPE,116) .ERR)                  :S(CMER)
        !           186:         TERMINAL = OUTPUT =  "ERROR: " &ERRTEXT " IN STMT " &LASTNO
        !           187:         COLLECT()
        !           188:         DUMP(2)                                         :(END)
        !           189: ERREND
        !           190: *
        !           191: *
        !           192: *   MAIN PROGRAM
        !           193: *   ============
        !           194: *
        !           195: *   NORMAL ENTRY POINT TO MAIN PROGRAM
        !           196: *
        !           197: INIT    LEN     = LENM = NNP = DIFFS = BLANKS =
        !           198:         NN      = 3; RECL = "R133"
        !           199: *
        !           200: *   READ COMMAND LINE EITHER FROM INPUT FILE OR TERMINAL.
        !           201: *   IF ERROR AND IF BATCH, PRINT ERROR MESSAGE AND STOP.
        !           202: *
        !           203:         OUTPUT  = DIFFER(BATCH) TERMINAL                :S(END)
        !           204:         X       = BATCH = INPUT                         :F(TERMI)
        !           205:         DETACH(.TERMINAL)                               :(DIFFX)
        !           206: *
        !           207: *   READ COMMAND LINE FROM TERMINAL
        !           208: *
        !           209: TERMI   TERMINAL = "*"; X = TERMINAL                    :F(END)
        !           210: *
        !           211: *   CHECK FOR NULL COMMAND LINE
        !           212: *
        !           213: DIFFX   DIFFER(X)                                       :F(END)
        !           214: *
        !           215: *   LOOP TO PROCESS SWITCHES. NO. OF LINES IN MATCH IS 3 BY DEFAULT.
        !           216: *
        !           217: SWPAT   X SWPAT = N                                     :S(SWPAT)
        !           218:         TERMINAL = DIFFER(SL) "? INVALID SWITCH"        :S(INIT)
        !           219:         X CMDPAT                                        :S(GO)
        !           220: *
        !           221: *   MERGE FROM ERR IF BAD FILENAMES
        !           222: *
        !           223: CMER    TERMINAL = "?COMMAND ERROR IN " X               :(INIT)
        !           224: GO      OUTPUT(.OUT,3,F1)                      :S(GO1)
        !           225:         TERMINAL = "?CAN'T ENTER OUTPUT FILE " F1       :(INIT)
        !           226: GO1     INPUT(.IN1,1,F2)                :S(GO2)
        !           227:         TERMINAL = "?CAN'T READ INPUT FILE 1 " F2       :(INIT)
        !           228: GO2     INPUT(.IN2,2,F3)                :S(START)
        !           229:         TERMINAL = "?CAN'T READ INPUT FILE 2 "  F3      :(INIT)
        !           230: *
        !           231: START   TERMINAL =
        !           232:         STSTARS = DUPL("*",(DIFFER(LEN,IDENT(LENM)) 2 * LEN + 2,12))
        !           233:         THISL   = FILE1 = LIST(,,,,,.IN1)
        !           234:         THATL   = FILE2 = LIST(,,,,,.IN2)
        !           235: *
        !           236: *   HUNT THROUGH FILES TILL DIFFERING LINES FOUND (IF ANY)
        !           237: *
        !           238: PHASE1  THIS    = $INP(THISL)                           :F(THISEND)
        !           239: *
        !           240: THAT    THAT    = $INP(THATL)                           :F(THATEND)
        !           241: *
        !           242: IDENT   IDENT(THIS,THAT)                                :S(PHASE1)
        !           243: *
        !           244: *   MAKE SURE DIFFERENCE IS NOT MERELY BLANK LINES IF BLANKS NULL.
        !           245: *
        !           246:         DIFFER(BLANKS)                                  :S(DIFF)
        !           247:         IDENT(THAT)                                     :S(THAT)
        !           248:         DIFFER(THIS)                                    :S(DIFF)
        !           249:         THIS    = $INP(THISL)                           :S(IDENT)F(THISEND)
        !           250: *
        !           251: *   ARRIVE HERE WHEN A DIFFERENCE IS ENCOUNTERED. PHASE 2
        !           252: *   ASSESSES HOW MUCH DIFFERENCE THERE IS AND PRINTS DIFFERENCES.
        !           253: *   IT OPERATES BY READING A LINE ALTERNATELY FROM EACH OF THE
        !           254: *   TWO INPUT FILES, ADDING IT TO THE APPROPRIATE LIST AND ATTEMPTING
        !           255: *   TO MATCH A CURRENT LINE AGAINST LINES HELD FOR THE OTHER FILE.
        !           256: *   AT ALL TIMES SUFFICIENT LINES ARE KEPT FOLLOWING THE CURRENT LINE
        !           257: *   SO THAT A COMPLETE MATCH CHECK CAN BE MADE.
        !           258: *
        !           259: DIFF    CURRENT(THATL) = ADD(THATL,THAT)
        !           260: *
        !           261: *   MERGE AGAIN AFTER DEALING WITH ONE DIFFERENCE TO DO ANOTHER
        !           262: *
        !           263: ENTER   CURRENT(THISL) = ADD(THISL,THIS)
        !           264: *
        !           265: *   ENTER ANOTHER LINE INTO THISL LIST, ADVANCE CURRENT(THISL)
        !           266: *   TO CORRESPOND AND SEE IF NEW CURRENT LINE MATCHES
        !           267: *   ANY LINE IN OTHER LIST. THIS FILE IS EXHAUSTED EITHER IF
        !           268: *   CURRENT IS ALREADY NULL OR IF LINK OF CURRENT IS NULL.
        !           269: *
        !           270: PHASE2  ADD(THISL,THIS = $INP(THISL))
        !           271:         (IDENT(X = CURRENT(THISL)),IDENT(X = CURRENT(THISL)
        !           272: +           = LINK(X)))                                 :S(THISEND)
        !           273: *
        !           274: *   LOOP HERE TILL NN LINES AVAILABLE INCLUDING "CURRENT" LINE
        !           275: *   OF EACH LIST SO THAT MATCH TEST CAN BE DONE.
        !           276: *
        !           277: ADD1    LE(NN + 1,COUNT(THISL))                         :S(ADD2)
        !           278:         ADD(THISL,$INP(THISL))                          :S(ADD1)
        !           279: ADD2    LE(NN,COUNT(THATL))                             :S(TRYMAT)
        !           280:         ADD(THATL,$INP(THATL))                          :S(ADD2)
        !           281: *
        !           282: *   ATTEMPT A MATCH
        !           283: *
        !           284: TRYMAT  X       = MATCH(OBJECT(X))                      :S(PHASE3)
        !           285: *
        !           286: *   ARRIVE HERE WHILST STILL ATTEMPTING MATCH. IF END FILE NOT READ
        !           287: *   ON THAT LIST THEN SWAP LISTS AND TRY MATCHING USING IT INSTEAD.
        !           288: *
        !           289:         DIFFER(EOF(THATL))                              :S(PHASE2)
        !           290:         X       = THISL; THISL = THATL; THATL = X       :(PHASE2)
        !           291: *
        !           292: *   MATCH ATTEMPT WAS SUCCESSFUL SO OUTPUT  THIS LIST
        !           293: *   AND PORTION OF THAT LIST UP TO AND INCLUDING MATCHING LINE.
        !           294: *   THEN ADVANCE HEAD OF THATL PAST THE FURTHER NN-1 LINES MATCHED
        !           295: *   WHICH ARE NO LONGER OF INTEREST AND CLEAR THISL SINCE ALL ITS LINES
        !           296: *   ARE DEALT WITH.
        !           297: *
        !           298: PHASE3  Y       = CURRENT(THATL)
        !           299:         CURRENT(THATL) = (IDENT(NNP) X,THAPT)
        !           300:         CURRENT(THISL) = DIFFER(NNP) TAIL(THISL)
        !           301:         PUT()
        !           302:         CURRENT(THATL) = Y
        !           303:         HEAD(THATL) = LINK(THAPT)
        !           304:         COUNT   = COUNT(THATL) = COUNT(THATL) - CDEC
        !           305:         CURRENT(THATL) = LT(COUNT,NN) HEAD(THATL)
        !           306:         HEAD(THISL) = COUNT(THISL) =
        !           307: *
        !           308: *   NOW POSITION FILES TO ANOTHER DIFFERENCE OR UNTIL THATL EMPTY.
        !           309: *   RIGHT NOW, THISL IS EMPTY.
        !           310: *
        !           311: POSIT   IDENT(X = HEAD(THATL))                          :S(PHASE1)
        !           312:         THIS    = $INP(THISL)                           :F(THISEND)
        !           313:         IDENT(THIS,OBJECT(X))                           :F(ENTER)
        !           314:         HEAD(THATL) = LINK(X)
        !           315:         CURRENT(THATL) = LT(COUNT(THATL) = COUNT(THATL) - 1,NN) HEAD(THATL)
        !           316: +                                                       :(POSIT)
        !           317: *
        !           318: *   HERE TO SET EOF FLAG FOR THISL. DONE BY SWAPPING LISTS
        !           319: *   AND JUMPING INTO CODE FOR THATL.
        !           320: *
        !           321: THISEND X       = THISL; THISL = THATL; THATL = X       :(EOF)
        !           322: *
        !           323: *   MARK ENDFILE OF THATL BY SETTING EOF NON-NULL.
        !           324: *   ON ARRIVAL HERE FIRST STORE LINE JUST READ FROM THIS FILE
        !           325: *
        !           326: THATEND CURRENT(THISL) = ADD(THISL,THIS)
        !           327: *
        !           328: *   TEST FOR END CONDITION WHICH IS THAT WE HAVE EOF ON BOTH LISTS.
        !           329: *   WE KNOW WE HAVE EOF ON THAT LIST SINCE WE ARE ABOUT TO SET FLAG.
        !           330: *
        !           331: *
        !           332: EOF     EOF(THATL) = "EOF"
        !           333:         IDENT(EOF(THISL))                               :S(PHASE2)
        !           334: *
        !           335: *   EOF REACHED ON BOTH FILES. OUTPUT BOTH LISTS AND PACK UP.
        !           336: *
        !           337:         IDENT(HEAD(THISL),IDENT(HEAD(THATL)))           :S(CLOSE)
        !           338:         CURRENT(THISL) = TAIL(THISL)
        !           339:         CURRENT(THATL) = TAIL(THATL)
        !           340:         PUT()
        !           341: *
        !           342: *   FINISH BY TYPING OUT DIFFERENCE COUNT
        !           343: *
        !           344: CLOSE   TERMINAL = IDENT(DIFFS) "NO DIFFERENCES FOUND"  :F(DIFFS)
        !           345:         OUT     = DIFFER(BATCH) TERMINAL                :(STOP)
        !           346: *
        !           347: DIFFS   OUT     = STSTARS
        !           348:         TERMINAL = "% " DIFFS "  DIFFERENCE" (NE(DIFFS,1) "S",) " FOUND"
        !           349:         OUT     = DIFFER(BATCH) TERMINAL
        !           350: *
        !           351: STOP    TERMINAL = DEFINE("OUTFIL(LISTX,MARK,STARS)X")
        !           352: +           DEFINE("PUT()X,Y,XO,YO")                    :(INIT)
        !           353: END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.