;*** PROGRAM TO COPY INPUT FILE TO OUTPUT FILE. ***
  ;       (USING BIN%/BOUT% AND IGNORING NULLS)

          TITLE FILEIO            ;TITLE OF PROGRAM
          SEARCH MONSYM           ;SEARCH SYSTEM JSYS-SYMBOL LIBRARY
          SEARCH MACSYM
          .REQUIRE SYS:MACREL

  ;*** IMPURE DATA STORAGE AND DEFINITIONS ***


  INJFN:  BLOCK 1                 ;STORAGE FOR INPUT JFN
  OUTJFN: BLOCK 1                 ;STORAGE FOR OUTPUT JFN
          PDLEN=3                 ;STACK HAS LENGTH 3
  PDLST:  BLOCK PDLEN             ;SET ASIDE STORAGE FOR STACK

          STDAC.                  ;DEFINE STANDARD ACs. SEE MACSYM.

  ;*** PROGRAM INITILIZATION ***

  START:  RESET%                  ;CLOSE FILES, ETC.
          MOVE P,[IOWD PDLEN,PDLST] ;ESTABLISH STACK

  ;***  GET INPUT FILE ***

  INFIL:                          ;PROMPT FOR INPUT FILE
          TMSG <
  INPUT FILE: >                   ;ON CONTROLLING TERMINAL
          MOVX T1,GJ%OLD+GJ%FNS+GJ%SHT ;SEARCH MODES FOR GTJFN
                                  ;EXISTING FILE ONLY, FILE-NRs IN B
                                  ;SHORT CALL
          MOVE T2,[.PRIIN,,.PRIOU] ;GTJFN'S I/O WITH CONTROLLING TERM
          GTJFN%                  ;GET JOB FILE NUMBER (JFN)
           ERJMPS [ PUSHJ P,WARN  ;IF ERROR, GIVE WARNING
                    JRST INFIL]   ;AND LET HIM TRY AGAIN
          MOVEM T1,INJFN          ;SUCCESS, SAVE THE JFN

  ;*** GET OUTPUT FILE ***

  OUTFIL:                         ;PRINT PROMPT FOR
          TMSG <
  OUTPUT FILE: >                  ;OUTPUT FILE
          MOVX T1,GJ%FOU+GJ%MSG+GJ%CFM+GJ%FNS+GJ%SHT ;GTJFN SEARCH MODES
                                  ;[DEFAULT TO NEW GENERATION, PRINT
                                  ; MESSAGE, REQUIRE CONFIRMATION
                                  ; FILE-NR'S IN T2, SHORT CALL ]
          MOVE T2,[.PRIIN,,.PRIOU] ;I/O WITH CONTROLLING TERMINAL
          GTJFN%                  ;GET JOB FILE NUMBER
           ERJMPS [ PUSHJ P,WARN  ;IF ERROR, GIVE WARNING
                   JRST OUTFIL]   ;AND LET HIM TRY AGAIN
          MOVEM T1,OUTJFN         ;SAVE THE JFN

  ;NOW, OPEN THE FILES WE JUST GOT

  ;   INPUT

          MOVE T1,INJFN           ;RETRIEVE THE INPUT JFN
          MOVX T2,FLD(7,OF%BSZ)+OF%RD ;MODES FOR OPENF
                                  ;[7-BIT BYTES + INPUT]
          OPENF%                  ;OPEN THE FILE
           ERJMPS FATAL           ;IF ERROR, GIVE MESSAGE AND STOP

  ;   OUTPUT

          MOVE T1,OUTJFN          ;GET THE OUTPUT JFN
          MOVX T2,FLD(7,OF%BSZ)+OF%WR ;MODES FOR OPENF
                                  ;[7-BIT BYTES + OUTPUT]
          OPENF%                  ;OPEN THE FILE
           ERJMPS FATAL           ;IF ERROR, GIVE MESSAGE AND STOP


  ;*** MAIN LOOP: COPY BYTES FROM INPUT TO OUTPUT ***

  LOOP:   MOVE T1,INJFN           ;GET THE INPUT JFN
          BIN%                    ;TAKE A BYTE FROM THE SOURCE
          JUMPE T2,DONE           ;IF 0, CHECK FOR END OF FILE
          MOVE T1,OUTJFN          ;GET THE OUTPUT JFN
          BOUT                    ;OUTPUT THE BYTE TO DESTINATION
           ERCALS ERROR
          JRST LOOP               ;LOOP, STOP ONLY ON A 0 BYTE
                                  ;(FOUND AT LOOP+2)


  ;*** TEST FOR END OF FILE, ON SUCCESS FINISH UP ***

  DONE:   GTSTS%                  ;GET THE STATUS OF INPUT FILE
          TXNN T2,GS%EOF          ;AT END OF FILE?
          JRST LOOP               ;NO, FLUSH NULL AND CONTINUE COPY

  CLOSIF: MOVE T1,INJFN           ;YES, RETRIEVE INPUT JFN
          CLOSF%                  ;CLOSE INPUT FILE
           ERJMPS FATAL           ;IF ERROR, GIVE MESSAGE AND STOP

  CLOSOF: MOVE T1,OUTJFN          ;RETRIEVE OUTPUT JFN
          CLOSF%                  ;CLOSE OUTPUT FILE
           ERJMPS FATAL           ;IF ERROR, GIVE MESSAGE AND STOP
          TMSG <
  [DONE]>                         ;SUCCESSFULLY DONE
          JRST ZAP                ;STOP

  ;*** ERROR HANDLING ***

  FATAL:  TMSG <
  ?>                              ;FATAL ERRORS PRINT ? FIRST
          PUSHJ P,ERROR           ;THEN PRINT ERROR MESSAGE
          JRST ZAP                ;AND STOP

  WARN:   TMSG <
  %>                              ;WARNINGS PRINT % FIRST
                                  ;AND FALL THRU 'ERROR'
                                  ;BACK TO CALLER

  ERROR:  MOVEI T1,.PRIOU         ;DECLARE PRINCIPAL OUTPUT DEVICE
                                  ;FOR ERROR MESSAGE
          MOVE T2,[.FHSLF,,-1]    ;CURRENT FORK,, LAST ERROR
          SETZ T3,                ;NO LIMIT,, FULL MESSAGE
          ERSTR%                  ;PRINT THE MESSAGE
           JFCL                   ;IGNORE UNDEFINED ERROR NUMBER
           JFCL                   ;IGNORE ERROR DURING EXE OF ERSTR
          POPJ P,                 ;RETURN TO CALLER

  ZAP:    HALTF%                  ;STOP
          JRST START              ;WE ARE RESTARTABLE
          END START               ;TELL LINKING LOADER START ADDRESS