Trailing-Edge
-
PDP-10 Archives
-
AP-D471B-SB_1978
-
go.bli
There are no other files named go.bli in the archive.
!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
%%
%
THIS MODULE IMPLEMENTS THE GO COMMAND. IT LOOPS,
READING RECORDS FROM THE INPUT FILE, DECIDING IF
THE RECORD SHOULD BE PRINTED, AND PRINTS IT IF
NECESSARY, FOR EACH REPORT, IN PARALLEL.
ROUTINES IN THIS MODULE:
GOERR - GENERATES ERROR MESSAGES TO REPORT FILE
READR - READS A RECORD
READC - READS A CHUNK
ACCEPT - DECIDES IF RECORD BELONGS IN REPORT
PRINTR - PRINTS A RECORD
PRINTC - PRINTS A CHUNK
GO - CONTROLS EVERYBODY ELSE
JOURNAL RECORD FORMAT
======= ====== ======
INPUT RECORDS:
WORD 1 - WORD COUNT OF ALL THE WORDS IN THE RECORD
WORD 2 - CHECKSUM OF ALL WORDS IN THE RECORD (EXCLUDING THE CHECKSUM WORDS)
WORD 3 - TRANSACTION SEQUENCE NUMBER
WORD 4 - DATE OF THIS MESSAGE (RESULT OF DATE UUO)
WORD 5 - TIME OF THIS MESSAGE (RESULT OF MSTIME UUO)
WORDS 6 THROUGH 8 - SOURCE TERMINAL NAME (ASCIZ)
WORD 9 - SIZE OF TRANSACTION CODE IN CHARACTERS (CALL N THE LENGTH IN WORDS)
WORDS 10 THROUGH 9+N - TRANSACTION CODE (ASCII)
WORD 10+N - NUMBER OF CHUNKS IN RECORD
WORDS 11+N THROUGH M - CHUNKS IN THIS RECORD
WORD M+1 - CHECKSUM OF THIS RECORD, SAME AS WORD 2
OUTPUT RECORD:
WORD 1 - WORD COUNT
WORD 2 - CHECKSUM
WORD 3 - TRANSACTION SEQUENCE NUMBER
WORD 4 - DATE
WORD 5 - TIME
WORDS 6 THROUGH 7 - MESSAGE CLASS (ASCIZ)
WORDS 8 THROUGH 12 - FILE SPEC OF MPP THAT RAN
WORDS 8 AND 9 - DEVICE (ASCIZ)
WORDS 10 AND 11 - FILE (ASCIZ)
WORD 12 - DEC PPN
WORD 13 - COUNT OF DESTINATIONS IN THIS RECORD (CALL IT N)
WORDS 14 THROUGH 13+N*3 - THREE WORD DESTINATIONS (ASCIZ)
WORD 14+N*3 - CHUNK COUNT
WORDS 15+N*3 THROUGH M - CHUNKS IN THIS RECORD
WORD M+1 - CHECKSUM, SAME AS WORD 2
CHUNK FORMAT:
WORD 1:
BITS(0-5) - BYTE POSITION
BITS(6-11) - BYTE SIZE (ASSUMED TO BE 7)
BITS(12-17) - END INDICATOR OF MESSAGE
EPI = 4
EGI = 3
EMI = 2
ESI = 1
NONE = 0
BITS(18-35) - GARBAGE
BITS 0-11 FORM A PROTOTYPE BYTE POINTER TO SOMEWHERE IN THE FIRST WORD OF TEXT
WORD 2:
<LH> - NUMBER OF WORDS IN MESSAGE TEXT
<RH> - NUMBER OF CHARACTERS IN MESSAGE TEXT
WORDS 3 THROUGH 3+WORD 2 <LH> -1 : MESSAGE TEXT (ASCII)
CHECKSUM:
THE CHECKSUM IS THE EXCLUSIVE-OR OF ALL THE WORDS
IN THE RECORD (INCLUDING THE WORD COUNT) EXCEPT THE
TWO CHECKSUM WORDS THEMSELVES.
%
%%
MODULE GOX (MLIST,FSAVE,TIMER=EXTERNAL(SIX12)) =
BEGIN
REQUIRE COMMON.BLI;
REQUIRE ENTRY.BLI;
OWN WORDSREAD,WORDCNT,CHECKSUM,OLDCHECKSUM,RECORDTYPE,
CHUNKPTR,RECORD,RECORDNUM,FIRDST,IOCODE,LASTCSM,
LASTWRD,TCDERR,DSTERR,CHKERR;
MAP REPBLK CURREP,
CHUNK CHUNKPTR,
JOURNALREC RECORD;
MACRO READ(BYTEPOINTER,BYTECOUNT) =
IF (IOCODE _ INBYT(.INCHNL,BYTECOUNT,BYTEPOINTER)) ISNOT OK
THEN BEGIN ! WE HAVE NON-NORMAL RETURN
IF .IOCODE IS -1 ! IS IT I/O ERROR?
THEN BEGIN ! YES
ERTEXT(35); ! PRINT MSG
PRTSPC(.INCHNL)
END;
RETURN FALSE ! RETURN FALSE FOR BOTH ERROR AND EOF
END$;
COMMENT(GOERR);
! SUBROUTINE GOERR
! ========== =====
! THIS ROUTINE WRITES ERROR MESSAGES RESULTING FROM
! ERRORS IN THE JOURNAL FILE.
! LAST MODIFIED ON 30 AUG 74 BY JG.
ROUTINE GOERR (MSG) =
BEGIN
BIND MESSAGES = PLIT(
%TCDERR% PLIT ASCIZ '***** TRANSACTION CODE GREATER THAN 175 CHARACTERS IN NEXT RECORD.',
%DSTERR% PLIT ASCIZ '***** MORE THAN 100 DESTINATIONS IN NEXT RECORD.',
%CHKERR% PLIT ASCIZ '***** CHUNK TEXT GREATER THAN 150 CHARACTERS.',
%CSMERR% PLIT ASCIZ '***** CHECKSUM ERROR IN PREVIOUS RECORD.',
%WRDERR% PLIT ASCIZ '***** WORD COUNT ERROR IN PREVIOUS RECORD.',
%EOFERR% PLIT ASCIZ '***** UNEXPECTED EOF FROM INPUT FILE.',
%BSTERR% PLIT ASCIZ '***** IMPROPER START OF RECORD. ATTEMPTING TO RESYNC.'),
CHECKERR = PLIT ASCIZ 'CHECKSUM',
WORDERR = PLIT ASCIZ 'WORD COUNT';
LOCAL TEXTPTR,NUM[5],LINEPTR,HDRPTR;
MAP HEADER HDRPTR;
HDRPTR _ .CURREP[PAGEHEADPTR]; ! GET POINTER TO HEADER BLOCK
LINEPTR _ .HDRPTR[LINEOT]; ! AND THE OUTPUT LINE
TEXTPTR _ (.MESSAGES[.MSG])<FIRSTINCR>; ! CHOOSE THE PROPER MESSAGE TEXT
IF .MSG IS 3 %CSMERR% ! THIS MUST GO TO THE TTY ALSO
THEN IF .LASTCSM ISNOT .RECORDNUM ! BUT ONLY ONCE
THEN BEGIN
LASTCSM _ .RECORDNUM; ! MAKE SURE IT IS ONLY ONCE
CNVCHR(.RECORDNUM,NUM,10);
TTYOTS(0,CHECKERR); ERTEXT(38);
TTYOVR(NUM); TTYOTN(0,PLIT ASCII '.')
END;
IF .MSG IS 4 %WRDERR% ! SAME AS FOR CSMERR
THEN IF .LASTWRD ISNOT .RECORDNUM
THEN BEGIN
LASTWRD _ .RECORDNUM;
CNVCHR(.RECORDNUM,NUM,10);
TTYOTS(0,WORDERR); ERTEXT(38);
TTYOVR(NUM); TTYOTN(0,PLIT ASCII '.')
END;
IF NOT .CURREP[PRTSEL] AND .MSG ISNOT 5 %EOFERR%! SUPPRESS ALL BUT EOFERR FOR RECORDS NOT PRINTED
THEN RETURN TRUE;
IF .MSG LEQ 2 OR .MSG IS 5 ! SKIP A LINE IN THE OUTPUT FILE FOR THESE
THEN IF PUTSKP() IS FALSE
THEN RETURN FALSE;
IF UPDATE(.LINEPTR,1,.TEXTPTR,0) IS FALSE ! MOVE TEXT TO LINE
THEN RETURN FALSE;
PUTLIN(.LINEPTR,CLEAR) ! AND PRINT IT
END;
COMMENT(READR);
! SUBROUTINE READR
! ========== =====
! THIS ROUTINE READS THE FIRST PART OF EACH RECORD
! FROM THE JOURNAL FILE. IT FILLS IN THE RECORD
! BLOCK DIFFERENTLY, DEPENDING ON WHICH KIND OF
! RECORD IT IS. THE RECORD BLOCK FORMAT IS SUCH
! THAT WE HAVE ROOM FOR THE OUTPUT RECORD FIELDS
! AND THE FIRST 10 DESTINATIONS. THUS IF THE RECORD
! TYPE IS INPUT, THE UNUSED WORDS (35) ARE FILLED
! WITH THE TRANSACTION CODE. THIS IS WHY THE FIRST
! DESTINATION BLOCK IS KLUDGEY - IT REALLY SITS RIGHT
! AFTER THE RECORD ITSELF. BUT BY HAVING A POINTER
! TO IT IN THE RECORD BLOCK, WE DON'T HAVE TO
! SPECIAL CASE THE FIRST ONE. THE CHUNKS ARE
! NOT READ IN USING THIS ROUTINE
! LAST MODIFIED ON 3 SEP 74 BY JG.
GLOBAL ROUTINE READR =
BEGIN
LOCAL CODECNT,DESTSREAD,DSTBLKPTR,EXTRA,SPACE[3];
LABEL READDESTS;
MAP DESTBLOCK DSTBLKPTR;
% WE START BY READING THE FIRST 9 WORDS OF THE RECORD,
WHICH WE KNOW ARE CONSTANT LENGTH FIELDS FOR EACH TYPE %
DO
READ(WORDCNT,0) ! READ THE WORD COUNT
WHILE .WORDCNT EQL 0; ! SKIP ZERO WORD COUNTS
WHILE .WORDCNT NEQ -1 DO !IF NOT BOR (BEGIN OF RECORD)
BEGIN
GOERR(5); !COMPLAIN
DO ! AND TRY TO RESYNC
READ( WORDCNT,0)
UNTIL .WORDCNT EQL -1;
READ(WORDCNT,0)
END;
READ(WORDCNT,0); ! GET THE REAL WORD COUNT
READ(RECORD[SEQNUM]<WORDINCR>,7); ! READ 7 WORDS INTO THE RECORD BLOCK
WORDSREAD _ 9;
INCR I FROM RECORD[SEQNUM] TO RECORD[SEQNUM]+6 ! CHECKSUM THOSE 7 WORDS
DO CHECKSUM _ .CHECKSUM XOR ..I;
IF .RECORD[SEQNUM]<RH> IS 0
THEN BEGIN ! YES, IT'S AN INPUT RECORD
% FOR INPUT RECORDS WE HAVE ONLY TO READ
IN THE TRANSACTION CODE %
RECORDTYPE _ XINPUT; ! SET THE TYPE
CODECNT _ .RECORD[TCDSIZ]/5; ! CALCULATE TCDSIZ IN WORDS
IF .RECORD[TCDSIZ] MOD 5 GTR 0 ! ROUND UPWARD
THEN CODECNT _ .CODECNT+1;
% HERE WE ASSUME THAT CODECNT IS NOT GREATER THAN 35 %
EXTRA _ 0;
IF .CODECNT GTR 35 ! BUT LET US INFORCE OUR ASSUMPTIONS
THEN BEGIN
EXTRA _ .CODECNT-35; ! THE EXTRA STUFF WILL BE THROWN AWAY
CODECNT _ 35;
RECORD[TCDSIZ] _ 175; ! DON'T FORGET THE LENGTH IN CHARS
TCDERR _ TRUE ! GO WILL PRINT A MSG A THE RIGHT TIME
END;
READ(RECORD[TCDSTR]<WORDINCR>,.CODECNT);
INCR I FROM RECORD[TCDSTR] TO RECORD[TCDSTR]+.CODECNT-1
DO CHECKSUM _ .CHECKSUM XOR ..I;! NOW CHECKSUM THEM
WORDSREAD _ .WORDSREAD+.CODECNT; ! UPDATE THE TOTAL READ
IF .EXTRA GTR 0
THEN DECR I FROM .EXTRA-1 TO 0 ! READ AND THROW AWAY THE EXTRE WORDS
DO BEGIN
READ(SPACE,0);
CHECKSUM _ .CHECKSUM XOR .SPACE;
WORDSREAD _ .WORDSREAD+1
END
END
ELSE BEGIN ! ARRIVE HERE FOR OUTPUT RECORDS
% FOR OUTPUT RECORDS WE MUST READ THE REST OF
THE MPP FILE SPEC AND A VARIABLE NUMBER
OF THREE WORD DESTINATIONS %
RECORDTYPE _ XOUTPUT; ! SET THE TYPE
READ(RECORD[MPPFIL]<WORDINCR>,4); ! READ REST OF FIXED LENGTH PART OF RECORD
INCR I FROM RECORD[MPPFIL] TO RECORD[MPPFIL]+3
DO CHECKSUM _ .CHECKSUM XOR ..I;! CHECKSUM THEM
WORDSREAD _ .WORDSREAD+4; ! AND UPDATE THE COUNT
EXTRA _ 0;
IF .RECORD[DSTCNT] GTR 100 ! WE HAVE TO SET SOME LIMIT
THEN BEGIN
EXTRA _ .RECORD[DSTCNT]-100;
RECORD[DSTCNT] _ 100;
DSTERR _ TRUE ! REMIND GO
END;
DESTSREAD _ 0; ! HONEST, WE HAVEN'T READ ANY YET!
DSTBLKPTR _ .RECORD[DESPTR]; ! GET PTR TO KLUDGEY FIRST DEST BLOCK
READDESTS: REPEAT BEGIN ! LOOP UNTIL WE HAVE ALL OF THEM
INCR I FROM 1 TO 10 ! THEY MUST BE READ IN 10 AT A TIME
DO BEGIN
DESTSREAD _ .DESTSREAD+1;! WE ARE GOING TO READ ONE
IF .DESTSREAD GTR .RECORD[DSTCNT] ! BUT NOT IF WE HAVE THEM ALL
THEN LEAVE READDESTS;
READ(DSTBLKPTR[.I]<WORDINCR>,3);! READ 3 WORD DESTINATION
INCR J FROM DSTBLKPTR[.I] TO DSTBLKPTR[.I]+2
DO CHECKSUM _ .CHECKSUM XOR ..J;! CHECKSUM THE WORDS
WORDSREAD _ .WORDSREAD+3 ! AND UPDATE THE COUNT
END; ! FINISHED THESE 10
IF .DSTBLKPTR[DSTNEX] IS NULL ! ARE THERE ANY MORE DEST BLKS ON THE CHAIN?
THEN IF (DSTBLKPTR[DSTNEX] _ ALLOC(DSTBLKSIZ)) IS NULL ! NO, GET ONE
THEN RETURN FALSE; ! COUNDN'T GET ONE
DSTBLKPTR _ .DSTBLKPTR[DSTNEX] ! SWITCH DEST BLOCKS
END; ! LOOP UNTIL END OF DESTS OR WORLD
IF .EXTRA GTR 0
THEN DECR I FROM .EXTRA-1 TO 0 ! READ AND THROW AWAY THE EXTRA DESTINATIONS
DO BEGIN
READ(SPACE<WORDINCR>,3);
INCR J FROM SPACE TO SPACE+2
DO CHECKSUM _ .CHECKSUM XOR ..J;
WORDSREAD _ .WORDSREAD+3
END
END;
% WE NOW HAVE READ ALL THE INFORMATION THAT
CAN BE OF DIFFERENT FORMAT FOR EACH TYPE. WHAT
REMAINS IS THE CHUNKS COUNT AND THE CHUNKS
THEMSELVES, WHICH ARE READ IN FROM ANOTHER
ROUTINE %
READ(RECORD[CHKCNT],0); ! LAST ITEM BEFORE CHUNKS IS THE COUNT
CHECKSUM _ .CHECKSUM XOR .RECORD[CHKCNT]; ! DON'T FORGET THE CHECKSUM!
WORDSREAD _ .WORDSREAD+1; ! NOR THE COUNT
TRUE ! NO ERRORS
END;
COMMENT(READC);
! SUBROUTINE READC
! ========== =====
! THE ROUTINE READS CHUNK FROM THE JOURNAL FILE.
! IT IS INDEPENDENT OF THE RECORD TYPE.
! LAST MODIFIED ON 30 AUG 74 BY JG.
GLOBAL ROUTINE READC =
BEGIN
LOCAL COUNT,EXTRA,SPACE;
READ((.CHUNKPTR)<WORDINCR>,2); ! GET BYTE POINTER AND COUNT WORDS
CHECKSUM _ .CHECKSUM XOR ..CHUNKPTR; ! CHECKSUM THE FIRST
CHECKSUM _ .CHECKSUM XOR .(.CHUNKPTR+1); ! AND THE SECOND
WORDSREAD _ .WORDSREAD+2; ! MUST KEEP COUNT EVEN HERE
EXTRA _ 0;
IF .CHUNKPTR[MSGLNW] GTR 30 ! SHOULD NEVER HAPPEN, BUT ...
THEN BEGIN
EXTRA _ .CHUNKPTR[MSGLNW]-30;
CHUNKPTR[MSGLNW] _ 30;
CHUNKPTR[MSGLNC] _ 150; ! AGAIN, DON'T FORGET THE LENGTH IN CHARS
CHKERR _ TRUE ! REMIND GO TO PRINT MSG
END;
READ(CHUNKPTR[MESAGE]<WORDINCR>,.CHUNKPTR[MSGLNW]);! READ CHUNK TEXT
INCR I FROM CHUNKPTR[MESAGE] TO CHUNKPTR[MESAGE]+.CHUNKPTR[MSGLNW]-1
DO CHECKSUM _ .CHECKSUM XOR ..I; ! CHECKSUM THE TEXT
WORDSREAD _ .WORDSREAD+.CHUNKPTR[MSGLNW]; ! UPDATE COUNT BY LENGTH IN WORDS
IF .EXTRA GTR 0
THEN DECR I FROM .EXTRA-1 TO 0 ! READ AND THROW WAWY REST OF MSG TEXT
DO BEGIN
READ(SPACE,0);
CHECKSUM _ .CHECKSUM XOR .SPACE;
WORDSREAD _ .WORDSREAD+1
END;
TRUE ! NO PROBLEMS
END;
COMMENT(ACCEPT);
! SUBROUTINE ACCEPT
! ========== ======
! THIS ROUTINE DETERMINES IF THE JOURNAL RECORD
! PRESENT IS TO BE INCLUDED IN THE CURRENT REPORT.
! IT CONCERNS ITSELF ONLY WITH THE CONSTRAINT
! BLOCKS AND THE IOBSEL FLAG.
! LAST MODIFIED ON 15 AUG 74 BY JG.
GLOBAL ROUTINE ACCEPT =
BEGIN
IF .CURREP[IOBSEL] ISNOT XBOTH
THEN BEGIN
IF .CURREP[IOBSEL] IS XINPUT AND .RECORDTYPE ISNOT XINPUT
THEN RETURN FALSE;
IF .CURREP[IOBSEL] IS XOUTPUT AND .RECORDTYPE ISNOT XOUTPUT
THEN RETURN FALSE
END;
CURREP[PRTSEL] _ TRUE
END;
COMMENT(PRINTR);
! SUBROUTINE PRINTR
! ========== ======
! THE ROUTINE PRINTS THE SPECIFIED
! FIELDS OF THE JOURNAL RECORD.
! LAST MODIFIED ON 30 AUG 74 BY JG.
GLOBAL ROUTINE PRINTR =
BEGIN
LOCAL NUM[5],HDRPTR,LINEPTR,COL,DESTSPERLINE,
DESTSTHISBLOCK,DESTSPRINTED,DSTBLKPTR,
ROOM,CHARSLEFT,TCDBPTR;
LABEL PRINTDESTS;
MAP DESTBLOCK DSTBLKPTR,
HEADER HDRPTR,
PRINTLINE LINEPTR;
BIND ITYPE = PLIT ASCII 'I',
OTYPE = PLIT ASCII 'O',
COLON = PLIT ASCII ':',
LEFTB = PLIT ASCII '[',
COMMA = PLIT ASCII ',',
RIGHTB = PLIT ASCII ']',
RIGHTP = PLIT ASCII ')',
LEFTP = PLIT ASCII '(';
MACRO WRITE(LPTR,COLNUM,SPTR,CNT) =
IF UPDATE(LPTR,COLNUM,SPTR,CNT) ISNOT OK
THEN RETURN FALSE$;
HDRPTR _ .CURREP[PAGEHEADPTR]; ! GET PTR TO HEADER BLOCK
LINEPTR _ .HDRPTR[LINEP2]; ! GET PTR TO FIRST FIELD HEADER LINE
IF .LINEPTR[LINECT] IS 0 ! IF THERE ARE NO FIELDS TO BE PRINTED
AND (NOT .CURREP[TXTSEL] ! AND WE ARE NOT PRINING TEXTS
OR .RECORD[CHKCNT] LEQ 0) ! OR THERE ARE NO TEXTS TO PRINT
THEN RETURN TRUE; ! THEN WE DO NOTHING HERE
LINEPTR _ .HDRPTR[LINEOT]; ! NOW GET PTR TO OUTPUT LINE
IF PUTSKP() IS FALSE ! SKIP LINE BEFORE EACH TRANSACTION
THEN RETURN FALSE;
IF .CURREP[IOBSEL] IS XBOTH ! SET FIRST COLUMN TO "I" OR "O"
THEN IF .RECORDTYPE IS XINPUT
THEN (WRITE(.LINEPTR,1,ITYPE<FIRSTINCR>,1))
ELSE (WRITE(.LINEPTR,1,OTYPE<FIRSTINCR>,1));
IF .CURREP[SEQSEL] ISNOT 0 ! PRINT SEQUENCE NUMBERS
THEN BEGIN
CNVCHR(.RECORD[SEQNUM]<LH>,NUM,10); ! CONVERT TO CHAR
COL _ 8-.NUM[LANGTH]; ! WANT TO RIGHT JUSTIFY IN FIELD
WRITE(.LINEPTR,.COL,NUM[STRING]<FIRSTINCR>,.NUM[LANGTH]);
IF .RECORDTYPE IS XOUTPUT ! MEANS PRINT OUT SEQ NUM
THEN BEGIN
CNVCHR(.RECORD[SEQNUM]<RH>,NUM,10);! MAKE IT CHAR
WRITE(.LINEPTR,0,LEFTP<FIRSTINCR>,0);! INCLOSE IT IN ('S
WRITE(.LINEPTR,0,NUM[STRING]<FIRSTINCR>,.NUM[LANGTH]);
WRITE(.LINEPTR,0,RIGHTP<FIRSTINCR>,0)
END
END;
IF .CURREP[DATSEL] ISNOT 0 ! PRINT DATES
THEN BEGIN
IF COLUMN(.LINEPTR,.CURREP[DATSEL]) ISNOT OK ! FIND RIGHT COLUMN
THEN RETURN FALSE;
LINEPTR[LINEBP] _ CNVBDT(.RECORD[DATBIN],.LINEPTR[LINEBP]);! SHOVE CONVERTED DATE IN LINE
LINEPTR[LINECT] _ .LINEPTR[LINECT]+12; ! UPDATE CHAR CNT
LINEPTR[LINEPO] _ .LINEPTR[LINEPO]+12 ! UPDATE POSITION
END;
IF .CURREP[TIMSEL] ISNOT 0 ! PRINT TIMES
THEN BEGIN
IF COLUMN(.LINEPTR,.CURREP[TIMSEL]) ISNOT OK ! FIND RIGHT COLUMN
THEN RETURN FALSE;
LINEPTR[LINEBP] _ CNVBTM(.RECORD[TIMBIN],.LINEPTR[LINEBP]);! SHOVE CONVERTED TIME IN LINE
LINEPTR[LINECT] _ .LINEPTR[LINECT]+8; ! UPDATE CHAR CNT
LINEPTR[LINEPO] _ .LINEPTR[LINEPO]+8 ! UPDATE POSITION
END;
IF .CURREP[SORSEL] ISNOT 0 AND .RECORDTYPE IS XINPUT ! PRINT SOURCE TERMINAL FOR OUTPUT RECORDS
THEN BEGIN
WRITE(.LINEPTR,.CURREP[SORSEL],RECORD[SORNAM]<FIRSTINCR>,0)
END;
IF .CURREP[CODSEL] ISNOT 0 AND .RECORDTYPE IS XINPUT ! PRINT TRANSACTION CODES FOR INPUT RECORDS
THEN BEGIN
% SINCE IN READR WE ASSUMED THAT THE TRANSACTION
CODE COULD BE UP TO 175 CHARS (35 WORDS), WE MUST
INSURE THAT IT WILL NOT OVERFLOW THE PRINTLINE
BUFFER (AND THE PRINTED LINE). IF IT WILL, WE
MUST PRINT IT ON MORE THAN ONE LINE %
IF .RECORD[TCDSIZ] LEQ LINESIZE-.CURREP[CODSEL]+1
THEN BEGIN ! IT WILL FIT ON ONE LINE
WRITE(.LINEPTR,.CURREP[CODSEL],RECORD[TCDSTR]<FIRSTINCR>,0)
END
ELSE BEGIN ! HERE WE MUST BREAK IT UP
ROOM _ LINESIZE-.CURREP[CODSEL]+1;! CALCULATE HOW ROOM THERE IS ON LINE
CHARSLEFT _ .RECORD[TCDSIZ]; ! CHARS LEFT TO PRINT
WHILE .CHARSLEFT GTR .ROOM
DO BEGIN
TCDBPTR _ BYTOFF(RECORD[TCDSTR],.RECORD[TCDSIZ]-.CHARSLEFT);
NOTE THAT PREVIOUS LINES GET WRITTEN HERE, SEE LATER COMMENT ABOUT DESTS
WRITE(.LINEPTR,.CURREP[CODSEL],.TCDBPTR,.ROOM);! WRITE THIS PORTION
CHARSLEFT _ .CHARSLEFT-.ROOM ! DECREMENT CHARSLEFT BY AMOUNT PRINTED
END;
IF .CHARSLEFT GTR 0 ! A FEW LAST CHARS TO PICK UP
THEN BEGIN
TCDBPTR _ BYTOFF(RECORD[TCDSTR],.RECORD[TCDSIZ]-.CHARSLEFT);
WRITE(.LINEPTR,.CURREP[CODSEL],.TCDBPTR,.CHARSLEFT)
END
END
END;
IF .CURREP[MPPSEL] ISNOT 0 AND .RECORDTYPE IS XOUTPUT ! PRINT MPP'S FOR OUTPUT RECORDS
THEN BEGIN
IF COLUMN(.LINEPTR,.CURREP[MPPSEL]) ISNOT OK ! FIND RIGHT COLUMN
THEN RETURN FALSE;
IF .RECORD[MPPDEV] ISNOT NULL ! DEVICE MAY NOT BE THERE
THEN BEGIN
WRITE(.LINEPTR,0,RECORD[MPPDEV]<FIRSTINCR>,0);
WRITE(.LINEPTR,0,COLON<FIRSTINCR>,0)
END;
WRITE(.LINEPTR,0,RECORD[MPPFIL]<FIRSTINCR>,0);
WRITE(.LINEPTR,0,LEFTB<FIRSTINCR>,0);
CNVCHR(.RECORD[MPPPPN]<LH>,NUM,8);
WRITE(.LINEPTR,0,NUM[STRING]<FIRSTINCR>,0);
WRITE(.LINEPTR,0,COMMA<FIRSTINCR>,0);
CNVCHR(.RECORD[MPPPPN]<RH>,NUM,8);
WRITE(.LINEPTR,0,NUM[STRING]<FIRSTINCR>,0);
WRITE(.LINEPTR,0,RIGHTB<FIRSTINCR>,0)
END;
IF .CURREP[CLSSEL] ISNOT 0 AND .RECORDTYPE IS XOUTPUT ! PRINT MSG CLASS FOR OUTPUT RECORDS
THEN BEGIN
WRITE(.LINEPTR,.CURREP[CLSSEL],RECORD[MSGCLS]<FIRSTINCR>,0)
END;
% SEE HOW SNEAKY WE ARE IN PRINTING THE DESTINATIONS!
WHEN WE HAVE INSERTED ALL THE DESTINATIONS THAT WILL
FIT ON ONE LINE, WE SIMPLY GO BACK TO THE FIRST COLUMN
(CURREP[DSTSEL]) AND SHOVE MORE IN. UPDATE (WHICH
CALLS COLUMN) WILL AUTOMATICALLY WRITE OUT EACH LINE
WHEN THIS HAPPENS. NOTE HOWEVER THAT THE LAST LINE OF
DESTINATIONS (WHICH MAY BE THE ONLY ONE) WILL ALWAYS
BE LEFT FOR THE CALL TO PUTLIN FOLLOWING THIS SECTION %
IF .CURREP[DSTSEL] ISNOT 0 AND .RECORDTYPE IS XOUTPUT ! PRINT DESTS FOR OUTPUT RECORDS
THEN BEGIN
DESTSPERLINE _ (133-.CURREP[DSTSEL])/14;! SQUEEZE AS MANY AS POSIBLE ON LINE
DESTSTHISBLOCK _ 0; ! COUNTS UP TO 10 REPEATEDLY
DESTSPRINTED _ 1; ! MUST START AT ONE TO WORK RIGHT
DSTBLKPTR _ .RECORD[DESPTR]; ! GET PTR TO FIRST DEST BLOCK
PRINTDESTS: REPEAT INCR I FROM 1 TO .DESTSPERLINE ! LOOP BY LINE
DO BEGIN
IF .DESTSPRINTED GTR .RECORD[DSTCNT] ! THATS ALL!
THEN LEAVE PRINTDESTS;
IF .DESTSTHISBLOCK IS 10 ! MUST GET NEW BLOCK
THEN DSTBLKPTR _ .DSTBLKPTR[DSTNEX];
WRITE(.LINEPTR,.CURREP[DSTSEL]+(.I-1)*14,DSTBLKPTR[.DESTSPRINTED]<FIRSTINCR>,0);
DESTSTHISBLOCK _ .DESTSTHISBLOCK+1;! INCREMENT THIS BLOCK
DESTSPRINTED _ .DESTSPRINTED+1 ! AND TOTAL PRINTED
END
END;
IF .LINEPTR[LINEPO] GTR 2 ! I.E., THERE IS SOMETHING OTHER THAN "I" OR "O"
THEN PUTLIN(.LINEPTR,CLEAR) ! THEN PRINT IT
ELSE TRUE
END;
COMMENT(PRINTC);
! SUBROUTINE PRINTC
! ========== ======
! THIS ROUTINE PRINTS CHUNKS.
! LAST MODIFIED ON 23 AUG 74 BY JG.
GLOBAL ROUTINE PRINTC =
BEGIN
LOCAL BYTPTR,HDRPTR,LINEPTR;
BIND NONE = PLIT ASCIZ '(NONE)',
ESI = PLIT ASCIZ 'ESI',
EMI = PLIT ASCIZ 'EMI',
EGI = PLIT ASCIZ 'EGI',
EPI = PLIT ASCIZ 'EPI';
MAP HEADER HDRPTR;
HDRPTR _ .CURREP[PAGEHEADPTR]; ! GET HEADER PTR
LINEPTR _ .HDRPTR[LINEOT]; ! TO FIND THE LINE
BYTPTR _ CASE .CHUNKPTR[ENDIND] OF ! GET BYTE PTR TO PROPER END INDICATOR
SET
NONE<FIRSTINCR>;
ESI<FIRSTINCR>;
EMI<FIRSTINCR>;
EGI<FIRSTINCR>;
EPI<FIRSTINCR>;
TES;
IF UPDATE(.LINEPTR,17,.BYTPTR,0) IS FALSE ! PRINT THE END INDICATOR
THEN RETURN FALSE;
BYTPTR<24,12> _ .CHUNKPTR[PROBYT]; ! PROTOTYPE BYTE POPINTER
BYTPTR<RH> _ CHUNKPTR[MESAGE]; ! IS AN INCREMENT TYPE PTR
% WE MUST MAKE SURE THAT THE CHUNK TEXT, WHICH
COULD BE UP TO 150 CHARS (30 WORDS), DOES NOT
OVERFLOW THE PRINTLINE BUFFER AND THE PRINTED
LINE ITSELF %
IF .CHUNKPTR[MSGLNC] LEQ 108
THEN BEGIN ! WILL FIT ON ONE LINE
IF UPDATE(.LINEPTR,25,.BYTPTR,.CHUNKPTR[MSGLNC]) IS FALSE
THEN RETURN FALSE
END
ELSE BEGIN ! WELL IT MUST FIT ON TWO
IF UPDATE(.LINEPTR,25,.BYTPTR,108) IS FALSE
THEN RETURN FALSE;
BYTPTR _ ADDBYT(.BYTPTR,108);
IF UPDATE(.LINEPTR,25,.BYTPTR,.CHUNKPTR[MSGLNC]-108) IS FALSE
THEN RETURN FALSE
END;
IF PUTLIN(.LINEPTR,CLEAR) IS FALSE ! ACTUALLY WRITE THE LINE HERE
THEN RETURN FALSE;
TRUE ! EVERYTHING WENT OK
END;
COMMENT(GO);
! SUBROUTINE GO
! ========== ==
! THIS ROUTINE IS THE MAIN CONTROLER FOR THE
! GENERATION OF REPORTS. THE "SORT" AND "TALLY"
! OPTIONS HAVE NOT BEEN IMPLEMENTED.
! LAST MODIFIED ON 29 AUG 74 BY JG.
GLOBAL ROUTINE GO =
BEGIN
LOCAL TEMP,ENDCHECKSUM;
LABEL JOURNALREAD,FINAL,EOFERR;
ROUTINE TALLY1 = TRUE; ! DUMMY ROUTINE THAT TALLIES STATISTICS
ROUTINE TALLY2 = TRUE; ! DUMMY ROUTINE THAT PRINTS RESULTS OF TALLY1
IF .INCHNL IS -1 ! MUST HAVE AN INPUT FILE
THEN BEGIN
TTYOTS(0,PLIT ASCIZ 'INPUT'); ERTEXT(34);
IF SEMI() THEN ERTEXT(4);
RETURN FALSE
END;
IF .OTCHNL IS -1 ! MUST HAVE AN OUTPUT FILE
THEN BEGIN
TTYOTS(0,PLIT ASCIZ 'OUTPUT'); ERTEXT(34);
IF SEMI() THEN ERTEXT(4);
RETURN FALSE
END;
IF .FIRREP IS NULL ! MUST HAVE REPORTS TO DO, ALSO!
THEN BEGIN
ERTEXT(36);
IF SEMI() THEN ERTEXT(4);
RETURN FALSE
END;
CNVBDT(DATE(),CHRDAT<FIRSTINCR>); ! GET TODAY'S DATE
CNVBTM(MSTIME(),CHRTIM<FIRSTINCR>); ! GET NOW'S TIME
CURREP _ .FIRREP;
WHILE .CURREP ISNOT NULL ! LOOP FOR EVERY REPORT
DO BEGIN
IF MAKHDR() IS FALSE ! MAKE A PAGE HEADER
THEN RETURN FALSE;
IF PUTPAG(.CURREP[PAGEHEADPTR]) IS FALSE ! AND PRINT IT
THEN RETURN FALSE;
CURREP _ .CURREP[NEXTREPORT] ! GO TO NEXT REPORT
END;
IF (RECORD _ ALLOC(JRNRECSIZ)) IS NULL ! ALLOCATE WORKING STORAGE
THEN RETURN FALSE;
IF (CHUNKPTR _ ALLOC(CHUNKSIZ)) IS NULL ! " " "
THEN RETURN FALSE;
IF (FIRDST _ ALLOC(DSTBLKSIZ)) IS NULL ! " " "
THEN RETURN FALSE;
RECORDNUM _ 1;
LASTCSM _ 0;
LASTWRD _ 0;
JOURNALREAD:
REPEAT BEGIN ! LOOP UNTIL EOF OR I/O ERROR
RECORD[DESPTR] _ RECORD[DESPTR]+1; ! INITIALZE DESPTR IN CASE IT IS OUTPUT RECORD
RECORD[DESPTR]+1 _ .FIRDST;
TCDERR _ DSTERR _ CHKERR _ FALSE; ! CLEAR ANY ERROR FLAGS FROM READR OR READC
WORDSREAD _ 0; ! JUST STARTING THIS RECORD
IF READR() IS FALSE ! LEAVE ONLY ON EOF OR ERROR
THEN LEAVE JOURNALREAD;
CURREP _ .FIRREP;
WHILE .CURREP ISNOT NULL ! LOOP FOR EVERY REPORT
DO BEGIN
CURREP[PRTSEL] _ FALSE; ! RESET RECORD PRINT SELECT
IF ACCEPT() ! SEE IT WE USE IT
THEN BEGIN ! PRINT AND TALLY
IF .TCDERR THEN IF GOERR(0) IS FALSE
THEN LEAVE JOURNALREAD;
IF .DSTERR THEN IF GOERR(1) IS FALSE
THEN LEAVE JOURNALREAD;
IF PRINTR() IS FALSE
THEN LEAVE JOURNALREAD;
IF .CURREP[TALLYPTR] ISNOT NULL
THEN TALLY1()
END;
CURREP _ .CURREP[NEXTREPORT] ! PROCESS RECORD FOR REST OF REPORTS
END;
DECR I FROM .RECORD[CHKCNT]-1 TO 0 ! NOW WE TAKE CARE OF THE CHUNKS
DO BEGIN
IF READC() IS FALSE ! READ A CHUNK
THEN LEAVE JOURNALREAD;
CURREP _ .FIRREP;
WHILE .CURREP ISNOT NULL ! FOR EVERY REPORT
DO BEGIN ! IF ITS OK THEN PRINT IT
IF .CHKERR AND .CURREP[PRTSEL]
THEN IF GOERR(2) IS FALSE
THEN LEAVE JOURNALREAD;
IF .CURREP[PRTSEL] AND .CURREP[TXTSEL]
THEN IF PRINTC() IS FALSE
THEN LEAVE JOURNALREAD;
CURREP _ .CURREP[NEXTREPORT] ! NEXT REPORT
END
END;
IF (IOCODE _ INBYT(.INCHNL,0,ENDCHECKSUM)) ISNOT OK ! READ FINAL CHECKSUM
THEN BEGIN
IF .IOCODE IS -1 ! USUAL ERROR CHECKING
THEN BEGIN
ERTEXT(35);
PRTSPC(.INCHNL)
END
ELSE ERTEXT(37);
LEAVE JOURNALREAD
END;
WORDSREAD _ .WORDSREAD+1; ! LAST WORD TO COUNT
! IF .OLDCHECKSUM NEQ .CHECKSUM OR .OLDCHECKSUM NEQ .ENDCHECKSUM ! MUST BE CHECKSUM ERROR SOMEWHERE
! THEN BEGIN
! CURREP _ .FIRREP;
! WHILE .CURREP ISNOT NULL
! DO BEGIN
! IF GOERR(3) IS FALSE
! THEN LEAVE JOURNALREAD;
! CURREP _ .CURREP[NEXTREPORT]
! END
! END;
IF .WORDSREAD NEQ .WORDCNT ! MUST BE A WORD MISCOUNT SOMEWHERE
THEN BEGIN
CURREP _ .FIRREP;
WHILE .CURREP ISNOT NULL
DO BEGIN
IF GOERR(4) IS FALSE
THEN LEAVE JOURNALREAD;
CURREP _ .CURREP[NEXTREPORT]
END
END;
RECORDNUM _ .RECORDNUM+1 ! INCREMENT RECORD COUNT
END;
% WE LEFT THE JOURNALREAD LOOP ON INPUT FILE
EOF OR I/O ERROR. IF THERE WAS AN I/O ERROR
THE MESSAGE HAS ALREADY BEEN GIVEN. HERE WE
WE CHECK FOR UNEXPEXTED EOF, WHICH PROBABLY
MEANS SOME FORM OF INTERNAL INCONSISTENCY IN
THE JOURNAL FILE %
EOFERR: IF .WORDSREAD ISNOT 0 AND .IOCODE IS 0
THEN BEGIN
ERTEXT(37);
CURREP _ .FIRREP;
WHILE .CURREP ISNOT NULL
DO BEGIN
IF GOERR(5) IS FALSE
THEN LEAVE EOFERR;
CURREP _ .CURREP[NEXTREPORT]
END
END;
CLOFIL(.INCHNL,CLEAR); ! CLOSE INPUT FILE
CLOFIL(.OTCHNL,CLEAR); ! CLOSE THE OUTPUT FILE
INIT(NOCLEAR); ! CLEAR EVERYTHING BUT NO RESET UUO
IF SEMI() THEN ERTEXT(4) ! SCAN TO ; FOR END OF COMMAND
END;
END ELUDOM; ! END OF GO COMMAND ...