TEX: DO; $SET(PATCH=0) DECLARE /* CPM */ F$REBOOT LITERALLY '0', F$RDCON LITERALLY '1', F$WRCON LITERALLY '2', F$RDRDR LITERALLY '3', F$WRPUN LITERALLY '4', F$WRLST LITERALLY '5', F$CONIO LITERALLY '6', F$GETIO LITERALLY '7', F$SETIO LITERALLY '8', F$WRSTR LITERALLY '9', F$RDBUF LITERALLY '10', F$RDSTAT LITERALLY '11', F$VERS LITERALLY '12', F$RESET LITERALLY '13', F$SELECT LITERALLY '14', F$OPEN LITERALLY '15', F$CLOSE LITERALLY '16', F$SEARCHF LITERALLY '17', F$SEARCHN LITERALLY '18', F$DELETE LITERALLY '19', F$RDSEQ LITERALLY '20', F$WRSEQ LITERALLY '21', F$MAKE LITERALLY '22', F$RENAME LITERALLY '23', F$LOGVEC LITERALLY '24', F$CURDSK LITERALLY '25', F$SETDMA LITERALLY '26', F$ALLVEC LITERALLY '27', F$WPDISK LITERALLY '28', F$ROVEC LITERALLY '29', F$FILATT LITERALLY '30'; DECLARE /* enum OUTMODE */ SUPPRESS LITERALLY '0', LIST LITERALLY '1', CONSOLE LITERALLY '2'; DECLARE /* STATES */ SINITIAL LITERALLY '0', INWORD LITERALLY '1', INSPACE LITERALLY '2', PUNCTUATED LITERALLY '3', SKIPBLANKLINE LITERALLY '4'; /* JUMP to start code */ DECLARE EDJMP BYTE DATA(0C3H), EDADR ADDRESS DATA(.TEXSTART-3); DECLARE copyright(*) BYTE DATA(' COPYRIGHT (C) 1978 DIGITAL RESEARCH '); DECLARE BASECCP ADDRESS AT(6); DECLARE CMDLINE(128) BYTE AT(80H); DECLARE FCB1(33) BYTE AT(5CH); DECLARE FCB2(33) BYTE AT(6CH); DECLARE PAD(*) BYTE INITIAL(6, 5, 4, 3, 2, 1); DECLARE TABSTOPS(*) BYTE INITIAL(8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 255); DECLARE PATCHES(128) BYTE; DECLARE OUT$COL BYTE; DECLARE OUTFCB(33) BYTE; DECLARE (TLINE, WLINE, byte$1DE7, ELINE, SLINE, NLINE) BYTE; DECLARE LINEOUT$BUF(256) BYTE; DECLARE INPUT$BUF ADDRESS; DECLARE INPUT$BUF$SIZE ADDRESS; DECLARE INPUT$CHR$OFFSET ADDRESS; DECLARE OUTPUT$BUF ADDRESS; DECLARE OUTPUT$CHR$OFFSET ADDRESS; DECLARE CUR$LINENO ADDRESS; DECLARE PAGE$NUM ADDRESS; DECLARE LINE$LEN BYTE; DECLARE PAGE$OFFSET BYTE; DECLARE CUR$INDENT BYTE; DECLARE PP$INDENT BYTE; DECLARE PAGE$WIDTH BYTE; DECLARE PAGE$LEN BYTE; DECLARE PRINT$LEN BYTE; DECLARE TOP$MARGIN BYTE; DECLARE TOP$SPACES BYTE; DECLARE HEADING$MARGIN BYTE; DECLARE BOTTOM$MARGIN BYTE; DECLARE LINE$SPACING BYTE; DECLARE IS$INDENTED BYTE; DECLARE IS$JUSTIFIED BYTE; DECLARE HAS$TMP$INDENT BYTE; DECLARE LL$INCREASED BYTE; DECLARE SAV$LL BYTE; DECLARE unk$1F0A BYTE; DECLARE LOWER$CASE BYTE; DECLARE FORM$FEED BYTE; DECLARE PAGE$MODE BYTE; DECLARE ERR$PRINT BYTE; DECLARE IO$REDIRECT BYTE; DECLARE PO$CHANGED BYTE; DECLARE SAV$LINELENGTH BYTE; DECLARE DO$PAGENUM BYTE; DECLARE outMode BYTE; DECLARE STATE BYTE; DECLARE unk$1F15 BYTE; DECLARE SLACK BYTE; DECLARE heading(133) BYTE; DECLARE LINE$BUF(256) BYTE; DECLARE CHARS$IN$LINE$BUF BYTE; DECLARE LINE$POS BYTE; DECLARE signPrefix BYTE; DECLARE havePeeked BYTE; DECLARE peekedChar BYTE; DECLARE pad1 ADDRESS; DECLARE cpmRetVal BYTE; DECLARE MAXLEN BYTE; MON1: PROCEDURE(F,A) EXTERNAL; DECLARE F BYTE, A ADDRESS; END MON1; MON2: PROCEDURE(F,A) BYTE EXTERNAL; DECLARE F BYTE, A ADDRESS; END MON2; reboot: PROCEDURE; DECLARE VEC ADDRESS; VEC = 0; CALL VEC; END reboot; rdcon: PROCEDURE BYTE; RETURN MON2(F$RDCON, 0); END rdcon; wrcon: PROCEDURE(CH); DECLARE CH BYTE; CALL MON1(F$WRCON, CH); END wrcon; wrconCRLF: PROCEDURE; CALL wrcon(0DH); CALL wrcon(0AH); END wrconCRLF; wrlst: PROCEDURE(CH); DECLARE CH BYTE; CALL MON1(F$WRLST, CH); END wrlst; wrstr: PROCEDURE(STR); DECLARE STR ADDRESS; CALL wrconCRLF; CALL MON1(F$WRSTR, STR); END wrstr; rdbuf: PROCEDURE(BUF); DECLARE BUF ADDRESS; CALL MON1(F$RDBUF, BUF); END rdbuf; rdstat: PROCEDURE BYTE; RETURN MON2(F$RDSTAT, 0); end rdstat; reset: PROCEDURE; CALL MON1(F$RESET, 0); end reset; open: PROCEDURE(FCB); DECLARE FCB ADDRESS; cpmRetVal = MON2(F$OPEN, FCB); end open; close: PROCEDURE(FCB); DECLARE FCB ADDRESS; cpmRetVal = MON2(F$CLOSE, FCB); end close; searchf: PROCEDURE(FCB); DECLARE FCB ADDRESS; cpmRetVal = MON2(F$SEARCHF, FCB); end searchf; delete: PROCEDURE(FCB); DECLARE FCB ADDRESS; CALL MON1(F$DELETE, FCB); end delete; rdseq: PROCEDURE(FCB) BYTE; DECLARE FCB ADDRESS; return MON2(F$RDSEQ, FCB); end rdseq; wrseq: PROCEDURE(FCB) BYTE; DECLARE FCB ADDRESS; return MON2(F$WRSEQ, FCB); end wrseq; make: PROCEDURE(FCB); DECLARE FCB ADDRESS; cpmRetVal = MON2(F$MAKE, FCB); end make; setdma: PROCEDURE(BUF$P); DECLARE BUF$P ADDRESS; CALL MON1(F$SETDMA, BUF$P); end setdma; unused1: PROCEDURE; MAXLEN = 128; CALL RDBUF(.MAXLEN); end unused1; unused2: PROCEDURE; CALL MON1(F$RDSTAT, 0); end unused2; outnewline: PROCEDURE; IF ERR$PRINT THEN DO; call wrlst(0DH); call wrlst(0AH); END; ELSE call wrConCRLF; end outnewline; outchar: PROCEDURE(CH); DECLARE CH BYTE; if ERR$PRINT THEN call wrlst(CH); else call wrcon(CH); end outchar; outstr: PROCEDURE(STR); DECLARE STR ADDRESS; DECLARE c BYTE, i BYTE; DECLARE CH BASED STR(1) BYTE; i = 0ffh; if ERR$PRINT then DO; call wrlst(0DH); call wrlst(0AH); DO WHILE (c := CH(i := i + 1)) <> '$'; call wrlst(c); END; END; else call wrstr(STR); end outstr; wrapup: PROCEDURE; IF NOT IO$REDIRECT THEN DO; CALL SETDMA(80H); CALL CLOSE(.OUTFCB); END; CALL wrconCRLF; CALL wrstr(.('TEX FINISHED$')); CALL wrconCRLF; CALL reboot; END wrapup; error: PROCEDURE(ERR); DECLARE ERR ADDRESS; DECLARE n BYTE; call outstr(.('ERROR DURING $')); call outstr(ERR); call outnewline; if CHARS$IN$LINE$BUF > 0 then do; call outstr(.('INPUT CONTEXT:$')); call outnewline; n = LINE$POS - CHARS$IN$LINE$BUF; /* start offset of context chars */ do while (n := n + 1) <> LINE$POS + 1; call outchar(LINE$BUF(n)); end; call outnewline; end; end error; fatalError: PROCEDURE(ERR); DECLARE ERR ADDRESS; call error(ERR); call outstr(.('THIS ERROR TERMINATES TEX$')); call wrapup; end fatalError; FILL: PROCEDURE(BUF$P, CH, CNT); DECLARE BUF$P ADDRESS, (CH, CNT) BYTE; DECLARE BCH BASED BUF$P BYTE; do while (CNT := CNT - 1) <> 0ffh; BCH = CH; BUF$P = BUF$P + 1; end; end FILL; memcpy: PROCEDURE(SRC$P, DST$P, LEN); DECLARE (SRC$P, DST$P) ADDRESS, LEN BYTE; DECLARE SRC BASED SRC$P BYTE; DECLARE DST BASED DST$P BYTE; do while (LEN := LEN - 1) <> 0ffh; DST = SRC; SRC$P = SRC$P + 1; DST$P = DST$P + 1; end; end memcpy; READ$CHUNK: PROCEDURE; DECLARE r BYTE; DECLARE p ADDRESS; DECLARE CH BASED p BYTE; DECLARE readexit LABEL; p = INPUT$BUF; do while p < INPUT$BUF + INPUT$BUF$SIZE; call setdma(p); if (r := rdseq(.FCB1)) <> 0 then do; if r > 1 then call fatalError(.('FILE READ$')); else do; CH = 1AH; goto readexit; end; end; else do; INPUT$CHR$OFFSET = INPUT$CHR$OFFSET + 128; p = p + 128; end; end; readexit: INPUT$CHR$OFFSET = 0; end READ$CHUNK; GETCH: PROCEDURE BYTE; DECLARE c BYTE; DECLARE INB BASED INPUT$BUF(1) BYTE; if havePeeked then do; havePeeked = 0; return peekedChar; end; if INPUT$CHR$OFFSET >= INPUT$BUF$SIZE then call READ$CHUNK; c = INB(INPUT$CHR$OFFSET); INPUT$CHR$OFFSET = INPUT$CHR$OFFSET + 1; if CHARS$IN$LINE$BUF < 255 then CHARS$IN$LINE$BUF = CHARS$IN$LINE$BUF + 1; LINE$BUF(LINE$POS := LINE$POS + 1) = c; return c; end GETCH; peekChar: PROCEDURE; IF NOT havePeeked THEN DO; peekedChar = GETCH; havePeeked = 0ffh; END; end peekChar; getnonEOFchar: PROCEDURE BYTE; DECLARE CH BYTE; if (CH := GETCH) = 1AH THEN call fatalError(.('READING EOF$')); else return CH; end getnonEOFchar; FLUSH$OUTPUT: PROCEDURE; DECLARE p ADDRESS; p = OUTPUT$BUF; do while p < OUTPUT$BUF + OUTPUT$CHR$OFFSET; call setdma(p); if wrseq(.OUTFCB) <> 0 then call fatalError(.('DISK WRITE$')); else p = p + 128; end; OUTPUT$CHR$OFFSET = 0; end FLUSH$OUTPUT; PUTDEST: PROCEDURE(CH); DECLARE CH BYTE; DECLARE (i, tab) BYTE; PUTCHAR: PROCEDURE(CH); DECLARE CH BYTE; DECLARE OUTB BASED OUTPUT$BUF(1) BYTE; OUT$COL = OUT$COL + 1; if IO$REDIRECT then do; if outMode = LIST then call wrlst(CH); else if outMode = CONSOLE then call wrcon(CH); else ; if rdstat then if rdcon = 0DH then call reboot; end; else do; OUTB(OUTPUT$CHR$OFFSET) = CH; if (OUTPUT$CHR$OFFSET := OUTPUT$CHR$OFFSET + 1) >= INPUT$BUF$SIZE then call FLUSH$OUTPUT; end; end PUTCHAR; if CH = 0AH then do; call PUTCHAR(CH); OUT$COL = 1; end; else if CH = 9 then do; i = 0; do while (tab := TABSTOPS(i)) <= OUT$COL; i = i + 1; end; if tab = 255 then return; do while tab > OUT$COL; call PUTCHAR(' '); end; end; else call PUTCHAR(CH); end PUTDEST; emitPAGEOFFSET: PROCEDURE; DECLARE i BYTE; i = PAGE$OFFSET; do while (i := i - 1) <> 0ffh; call PUTDEST(' '); end; OUT$COL = 1; end emitPAGEOFFSET; emitLineText: PROCEDURE; DECLARE i BYTE; call emitPAGEOFFSET; if not HAS$TMP$INDENT then do; i = CUR$INDENT; do while (i := i - 1) <> 0ffh; call PUTDEST(' '); end; end; i = SLINE; do while i <> NLINE; call PUTDEST(LINEOUT$BUF(i)); i = i + 1; end; call PUTDEST(0DH); call PUTDEST(0AH); CUR$LINENO = CUR$LINENO + 1; end emitLineText; CENTRE: PROCEDURE; DECLARE cspc BYTE; cspc = SHR(LINE$LEN - (NLINE - SLINE), 1); do while (cspc := cspc - 1) <> 0ffh; LINEOUT$BUF(SLINE := SLINE - 1) = ' '; end; call emitLineText; SLINE = NLINE; end CENTRE; NEWLINE: PROCEDURE; CALL PUTDEST(0DH); CALL PUTDEST(0AH); CUR$LINENO = CUR$LINENO + 1; END NEWLINE; emitHeading: PROCEDURE; DECLARE (i, c) BYTE; call emitPAGEOFFSET; i = 0FFh; do while (i := i + 1) < SAV$LINELENGTH AND (c := heading(i)) <> 0; call PUTDEST(c); end; call NEWLINE; end emitHeading; EOP: PROCEDURE; DECLARE num ADDRESS; DECLARE (rem, ascLen) BYTE, ascStr(5) BYTE; DECLARE (spcCnt, i) BYTE; do while CUR$LINENO < (PRINT$LEN + TOP$MARGIN); call NEWLINE; end; if BOTTOM$MARGIN > 0 then do; spcCnt = SHR(BOTTOM$MARGIN, 1); do i = 1 to spcCnt; call NEWLINE; end; if DO$PAGENUM then do; num = PAGE$NUM; ascLen = 0FFH; do while num <> 0; rem = num - (num / 10) * 10; ascStr(ascLen := ascLen + 1) = rem + '0'; num = num / 10; end; spcCnt = SHR(SAV$LINELENGTH - ascLen, 1) + PAGE$OFFSET; do i = 1 to spcCnt; call PUTDEST(' '); end; ascLen = ascLen + 1; do while (ascLen := ascLen - 1) <> 0FFH; call PUTDEST(ascStr(ascLen)); end; call NEWLINE; end; PAGE$NUM = PAGE$NUM + 1; do while CUR$LINENO < PAGE$LEN; call NEWLINE; end; end; CUR$LINENO = 0; if FORM$FEED then call PUTDEST(0CH); if PAGE$MODE then do; if outMODE <> CONSOLE then call wrstr(.('INSERT NEW PAGE; THEN TYPE RETURN$')); do while rdcon <> 0DH; end; end; end EOP; procLine0: PROCEDURE; DECLARE i BYTE; if PO$CHANGED then do; SAV$LINELENGTH = LINE$LEN; /* patch 2 follows */ $IF PATCH if FORM$FEED then /* uses ral .. cc in asm patch !! */ call PUTDEST(0CH); /* end patch 2 */ $ENDIF PO$CHANGED = 0; end; if TOP$MARGIN <> 0 then do; if heading(0) = 0 then do i = 1 to TOP$MARGIN; call NEWLINE; end; else do; do i = 1 to TOP$SPACES; call NEWLINE; end; call emitHeading; do i = 1 to HEADING$MARGIN; call NEWLINE; end; end; end; end procLine0; SPACING: PROCEDURE(CNT); DECLARE CNT BYTE; if CUR$LINENO = 0 then call procLine0; if CUR$LINENO + CNT < PRINT$LEN + TOP$MARGIN then do while (CNT := CNT - 1) <> 0FFH; call NEWLINE; end; else call EOP; end SPACING; emitLine: PROCEDURE; DECLARE i BYTE; if CUR$LINENO = 0 then call procLine0; call emitLineText; if PRINT$LEN + TOP$MARGIN <= CUR$LINENO then call EOP; i = 0; do while (i := i + 1) < LINE$SPACING AND CUR$LINENO > 0; call NEWLINE; if PRINT$LEN + TOP$MARGIN <= CUR$LINENO then call EOP; end; end emitLine; break: PROCEDURE; if NLINE <> SLINE THEN call emitLine; SLINE, ELINE, WLINE = NLINE; end break; GET$CURLINE$LEN: PROCEDURE BYTE; DECLARE i BYTE; i = LINE$LEN; if LL$INCREASED then i = SAV$LL; if HAS$TMP$INDENT then i = i + CUR$INDENT; return i; end GET$CURLINE$LEN; JUSTIFY: PROCEDURE; DECLARE (CH, FLG) BYTE; DECLARE (LEAD$SPACECNT, NON$SPACE$CNT, POST$PUNCT$SPACE$CNT) BYTE; DECLARE loc$BD7 LABEL; DECLARE loc$D6F LABEL; DECLARE loc$BE8 LABEL; TLINE = NLINE; if WLINE = SLINE or ELINE = SLINE then do; WLINE = NLINE; call error(.('FITTING A WORD$')); return; end; else if WLINE - ELINE > 127 then do; TLINE, WLINE = NLINE; NLINE = ELINE; return; end; else NLINE = ELINE; SLACK = GET$CURLINE$LEN - (NLINE - SLINE); LEAD$SPACE$CNT = 0; NON$SPACE$CNT = 0; POST$PUNCT$SPACE$CNT = 0; do while LINEOUT$BUF(SLINE) = ' '; LEAD$SPACE$CNT = LEAD$SPACE$CNT + 1; if (SLINE := SLINE + 1) = NLINE then return; end; if unk$1F0A then do; unk$1F0A = 0; do while LINEOUT$BUF(SLINE) <> ' '; POST$PUNCT$SPACE$CNT = POST$PUNCT$SPACE$CNT + 1; if (SLINE := SLINE + 1) = NLINE then goto loc$BD7; end; if LINEOUT$BUF(SLINE-1) >= 'A' then goto loc$BD7; do while LINEOUT$BUF(SLINE) = ' '; NON$SPACE$CNT = NON$SPACE$CNT + 1; if (SLINE := SLINE + 1) = NLINE then goto loc$BD7; end; end; goto loc$BE8; loc$BD7: do; SLINE = SLINE - POST$PUNCT$SPACE$CNT - NON$SPACE$CNT; NON$SPACE$CNT = 0; POST$PUNCT$SPACE$CNT = 0; end; loc$BE8: ELINE = TLINE - 1; do while ELINE <> WLINE; LINEOUT$BUF(ELINE + SLACK) = LINEOUT$BUF(ELINE); ELINE = ELINE - 1; end; LINEOUT$BUF(ELINE + SLACK) = LINEOUT$BUF(ELINE); TLINE = TLINE + SLACK; WLINE = WLINE + SLACK; do while 1; FLG = 0ffh; if unk$1F15 then do; ELINE = NLINE + SLACK; byte$1DE7 = NLINE; NLINE = ELINE; do while byte$1DE7 <> SLINE; CH, LINEOUT$BUF(ELINE := ELINE - 1) = LINEOUT$BUF(byte$1DE7 := byte$1DE7 - 1); if CH = ' ' AND SLACK <> 0 then do; FLG = 0; LINEOUT$BUF(ELINE := ELINE - 1) = ' '; SLACK = SLACK - 1; end; end; unk$1F15 = 0; SLINE = ELINE; if SLACK = 0 then goto loc$D6F; end; else do; byte$1DE7 = SLINE - 1; SLINE = SLINE - SLACK; ELINE = SLINE - 1; do while NLINE - 1 <> byte$1DE7; CH, LINEOUT$BUF(ELINE := ELINE + 1) = LINEOUT$BUF(byte$1DE7 := byte$1DE7 + 1); if CH = ' ' AND SLACK <> 0 then do; FLG = 0; LINEOUT$BUF(ELINE := ELINE + 1) = ' '; SLACK = SLACK - 1; end; end; unk$1F15 = 0FFH; NLINE = ELINE + 1; if SLACK = 0 or FLG then goto loc$D6F; end; end; loc$D6F: SLINE = SLINE - POST$PUNCT$SPACE$CNT - NON$SPACE$CNT; do while (LEAD$SPACE$CNT := LEAD$SPACE$CNT - 1) <> 0ffH; LINEOUT$BUF(SLINE := SLINE - 1) = ' '; end; end JUSTIFY; processLine: PROCEDURE; if IS$JUSTIFIED then call JUSTIFY; else DO; TLINE = NLINE; /* Patch1 follows */ $IF PATCH if WLINE - ELINE > 127 then /* signed compare !! */ WLINE = NLINE; $ENDIF NLINE = ELINE; END; call emitLine; SLINE, ELINE = WLINE; NLINE = TLINE; /* next line offset in circular buffer */ end processLine; ADD$CHAR: PROCEDURE(CH); DECLARE CH BYTE; DECLARE I BYTE; if LL$INCREASED then if NLINE = SLINE then LL$INCREASED = 0; LINEOUT$BUF(NLINE) = CH; if (NLINE := NLINE + 1) - SLINE > GET$CURLINE$LEN then do; call processLine; HAS$TMP$INDENT = 0; LL$INCREASED = 0; i = 0; TLINE = NLINE; do while LINEOUT$BUF(TLINE := TLINE - 1) = ' ' and TLINE >= SLINE; i = i + 1; end; if NLINE - SLINE = i then NLINE = SLINE; end; end ADD$CHAR; /* put character unless leading space at start of indented line */ PUT$TEXT$CHAR: PROCEDURE(CH); DECLARE CH BYTE; if NLINE = SLINE AND IS$INDENTED THEN if CH = ' ' THEN return; call ADD$CHAR(CH); end PUT$TEXT$CHAR; CENTRELINES: PROCEDURE(CNT); DECLARE CNT BYTE; DECLARE CH BYTE; do while (CNT := CNT - 1) <> 0FFH; if PRINT$LEN + TOP$MARGIN <= CUR$LINENO then call EOP; if CUR$LINENO = 0 then call procLine0; do while (CH := getnonEOFchar) <> 0DH; call ADD$CHAR(CH); end; do while (CH := getnonEOFchar) <> 0AH; end; call CENTRE; end; end CENTRELINES; breakPage: PROCEDURE; call break; if CUR$LINENO <> 0 then call EOP; end breakPage; sub$EEF: PROCEDURE; call breakPage; call PUTDEST(1AH); if NOT IO$REDIRECT AND OUTPUT$CHR$OFFSET <> 0 then call FLUSH$OUTPUT; call wrapup; end sub$EEF; fatalCmdError: PROCEDURE; call error(.('COMMAND VERIFY$')); call sub$EEF; end fatalCmdError; DECLARE PAD$20F9 BYTE; DECLARE INPUT$CHAR BYTE; checkCRLF: PROCEDURE; if INPUT$CHAR <> 0DH then call fatalCmdError; do while GETCH <> 0AH; end; end checkCRLF; GET$NUMBER: PROCEDURE ADDRESS; DECLARE val ADDRESS; getc: PROCEDURE; INPUT$CHAR = GETCH; end getc; isdigit: PROCEDURE BYTE; return (INPUT$CHAR - '0') < 10; end isdigit; signPrefix = 0; val = 0; do while INPUT$CHAR = ' '; call getc; end; if INPUT$CHAR = 0DH then return 0; if INPUT$CHAR = '+' then do; signPrefix = 1; call getc; end; else if INPUT$CHAR = '-' then do; signPrefix = 0ffh; call getc; end; if NOT isdigit then call fatalCmdError; do while isdigit; val = val * 10 + (INPUT$CHAR - '0'); call getc; end; return val; end GET$NUMBER; GET16$NEW$VALUE: PROCEDURE(REF) ADDRESS; DECLARE REF ADDRESS; DECLARE val ADDRESS; INPUT$CHAR = ' '; val = GET$NUMBER; if signPrefix = 0 then REF = val; if signPrefix = 1 then REF = REF + val; if signPrefix = 0ffh then REF = REF - val; if ROL(HIGH(REF), 1) then /* check < 32k */ REF = 0; call checkCRLF; return REF; end GET16$NEW$VALUE; GET8$NEW$VALUE: PROCEDURE(REF) BYTE; DECLARE REF BYTE; DECLARE val ADDRESS; if HIGH(val := GET16$NEW$VALUE(DOUBLE(REF))) <> 0 then call fatalCmdError; return val; end GET8$NEW$VALUE; GET8$ABS$NUMBER: PROCEDURE BYTE; DECLARE val BYTE; val = GET8$NEW$VALUE(0); if signPrefix <> 0 then call fatalCmdError; return val; end GET8$ABS$NUMBER; GET$TEXT$CHAR: PROCEDURE BYTE; DECLARE CH BYTE; if (CH := GETCH) = 0DH then do while (CH := GETCH) = 0AH; end; return CH; end GET$TEXT$CHAR; IGNORE: PROCEDURE; DECLARE c BYTE; if (c := GET$TEXT$CHAR) = '.' or c = 1AH then return; do while 1; do while (c := getnonEOFchar) <> 0AH; end; if (c := GETCH) = '.' or c = 1AH then return; end; end IGNORE; LITERAL: PROCEDURE; DECLARE (CH, PAD) BYTE; call break; if (CH := GET$TEXT$CHAR) = '.' or CH = 1AH then return; do while 1; if CUR$LINENO = 0 then call procLine0; call emitPAGEOFFSET; call PUTDEST(CH); do while (cH := getnonEOFchar) <> 0AH; call PUTDEST(CH); end; call PUTDEST(CH); CUR$LINENO = CUR$LINENO + 1; if PRINT$LEN + TOP$MARGIN <= CUR$LINENO then call EOP; if (CH := GETCH) = '.' or CH = 1AH then return; end; end LITERAL; getCmdChar: PROCEDURE BYTE; DECLARE CH BYTE; if (CH := GETCH) < 'A' then call fatalCmdError; else if CH >= 'a' then CH = CH - ' '; if CH > 'U' then call fatalCmdError; return CH; end getCmdChar; procDotCmd: PROCEDURE; DECLARE (cmdChr1, cmdChr2) BYTE; DECLARE (i, j, k) BYTE; DECLARE n ADDRESS; procLoop: cmdChr1 = getCmdChar; cmdChr2 = getCmdChar; cmdChr1 = cmdChr1 - 'A'; do case cmdChr1; DO; /* DOTA */ if cmdChr2 = 'D' THEN do; call break; IS$INDENTED = 0ffh; IS$JUSTIFIED = 0ffh; end; else call fatalCmdError; END; DO; /* DOTB */ if cmdChr2 = 'L' then do; call break; if (i := GET8$ABS$NUMBER) = 0 then i = 1; call SPACING(i * LINE$SPACING); end; else if cmdChr2 = 'P' then do; call breakPage; if (n := GET16$NEW$VALUE(PAGE$NUM - 1)) <> 0 then do; PAGE$NUM = n; DO$PAGENUM = 0ffh; end; end; else if cmdChr2 = 'R' then call break; else call fatalCmdError; END; DO; /* DOTC */ if cmdChr2 = 'E' then do; call break; if (i := GET8$ABS$NUMBER) = 0 then i = 1; call CENTRELINES(i); end; else if cmdChr2 = 'P' then do; if CUR$LINENO + GET8$ABS$NUMBER * LINE$SPACING >= PRINT$LEN + TOP$MARGIN then call breakPage; end; else call fatalCmdError; END; DO; /* DOTD */ if cmdChr2 = 'S' then do; call break; LINE$SPACING = 2; end; else call fatalCmdError; END; call fatalCmdError; /* DOTE */ DO; /* DOTF */ if cmdChr2 = 'L' then call break; else call fatalCmdError; END; call fatalCmdError; /* DOTG */ DO; /* DOTH */ if cmdChr2 = 'E' then do; i = 0ffh; call FILL(.heading, ' ', 160); if (j := getnonEOFchar) <> ' ' then do; if j = 0DH then goto L131D; heading(0) = j; /* allow for missing space */ i = 0; end; do while (i := i + 1) < 160; if (j := getnonEOFchar) = 0DH then goto L131D; heading(i) = j; end; return; L131D: if (j := getnonEOFchar) <> 0AH then call error(.('INVALID CRLF SEQUENCE$')); heading(i) = 0; end; else if cmdChr2 = 'M' then do; HEADING$MARGIN = GET8$NEW$VALUE(HEADING$MARGIN); if HEADING$MARGIN >= TOP$MARGIN then do; call error(.('HM COMMAND$')); if TOP$MARGIN < 2 then HEADING$MARGIN = 0; else HEADING$MARGIN = TOP$MARGIN - 1; end; if TOP$MARGIN = 0 then TOP$SPACES = 0; else TOP$SPACES = TOP$MARGIN - HEADING$MARGIN - 1; end; else call fatalCmdError; END; DO; /* DOTI */ if cmdChr2 = 'G' then do; call IGNORE; goto procLoop; end; else if cmdChr2 = 'N' then do; call break; IS$INDENTED = 0FFH; CUR$INDENT = GET8$NEW$VALUE(CUR$INDENT); if PAGE$OFFSET + CUR$INDENT > 160 then CUR$INDENT = 0; LINE$LEN = PAGE$WIDTH - PAGE$OFFSET - CUR$INDENT; end; else call fatalCmdError; end; call fatalCmdError; /* DOTJ */ call fatalCmdError; /* DOTK */ do; /* DOTL */ if cmdChr2 = 'C' then LOWER$CASE = 0FFH; else if cmdChr2 = 'I' then do; CALL LITERAL; goto procLoop; end; else if cmdChr2 = 'L' then do; i = GET8$NEW$VALUE(LINE$LEN); if i < LINE$LEN then do; LL$INCREASED = 0FFH; SAV$LL = LINE$LEN; end; if i > 160 then LINE$LEN = 70; else LINE$LEN = i; PAGE$WIDTH = PAGE$OFFSET + CUR$INDENT + LINE$LEN; end; else if cmdChr2 = 'S' then do; call break; LINE$SPACING = GET8$NEW$VALUE(LINE$SPACING); end; else call fatalCmdError; end; DO; /* DOTM */ if cmdChr2 = 'B' then do; BOTTOM$MARGIN = GET8$NEW$VALUE(BOTTOM$MARGIN); if PAGE$LEN - TOP$MARGIN <= BOTTOM$MARGIN then do; call error(.('MB COMMAND$')); BOTTOM$MARGIN = 1; end; PRINT$LEN = PAGE$LEN - (TOP$MARGIN + BOTTOM$MARGIN); end; else if cmdChr2 = 'T' then do; TOP$MARGIN = GET8$NEW$VALUE(TOP$MARGIN); if PAGE$LEN - BOTTOM$MARGIN <= TOP$MARGIN then do; call error(.('MT TOO LARGE$')); TOP$MARGIN = 1; end; PRINT$LEN = PAGE$LEN - (TOP$MARGIN + BOTTOM$MARGIN); if HEADING$MARGIN < TOP$MARGIN then TOP$SPACES = TOP$MARGIN - HEADING$MARGIN - 1; else do; TOP$SPACES = 0; if TOP$MARGIN < 2 then HEADING$MARGIN = 0; else HEADING$MARGIN = TOP$MARGIN - 1; end; end; else call fatalCmdError; end; DO; /* DOTN */ if cmdChr2 = 'A' then do; call break; IS$JUSTIFIED = 0; end; else if cmdChr2 = 'E' then do; if CUR$LINENO + LINE$SPACING * GET8$ABS$NUMBER >= PRINT$LEN + TOP$MARGIN then call breakPage; end; else call fatalCmdError; END; DO; /* DOTO */ if cmdChr2 = 'P' then DO$PAGENUM = 0; else call fatalCmdError; END; DO; /* DOTP */ if cmdChr2 = 'A' then do; call break; if (i := GET8$ABS$NUMBER) = 0 then i = 1; if CUR$LINENO = 0 then i = i - 1; do j = 1 to i; call EOP; end; end; else if cmdChr2 = 'L' then do; PAGE$LEN = GET8$NEW$VALUE(PAGE$LEN); if PAGE$LEN > 128 or PAGE$LEN = 0 then PAGE$LEN = 66; PRINT$LEN = PAGE$LEN - (BOTTOM$MARGIN + TOP$MARGIN); end; else if cmdChr2 = 'N' then do; if (PAGE$NUM := GET16$NEW$VALUE(PAGE$NUM)) = 0 then PAGE$NUM = 1; DO$PAGENUM = 0FFH; end; else if cmdChr2 = 'O' then do; call break; PO$CHANGED = 0FFH; PAGE$OFFSET = GET8$NEW$VALUE(PAGE$OFFSET); PAGE$WIDTH = PAGE$OFFSET + CUR$INDENT + LINE$LEN; if PAGE$WIDTH > 160 then do; LINE$LEN = 160; PAGE$WIDTH = 160 + PAGE$OFFSET + CUR$INDENT; end; end; else if cmdChr2 = 'P' then do; call break; if CUR$LINENO = 0 then call procLine0; else call SPACING(LINE$SPACING); IS$INDENTED = 0FFH; if (i := GET8$ABS$NUMBER) <> 0 then do; if i < LINE$LEN then PP$INDENT = i; else call error(.('PP COMMAND $')); end; do j = 1 to PP$INDENT; call ADD$CHAR(' '); end; end; else call fatalCmdError; END; DO; /* DOTQ */ if cmdChr2 = 'I' then do; call break; CUR$INDENT = 0; LINE$LEN = PAGE$WIDTH - PAGE$OFFSET; end; else call fatalCmdError; END; call fatalCmdError; /* DOTR */ DO; /* DOTS */ if cmdChr2 = 'P' then do; call break; if (i := GET8$ABS$NUMBER) = 0 then i = 1; call SPACING(i * LINE$SPACING); end; else if cmdChr2 = 'S' then do; call break; LINE$SPACING = 1; end; else call fatalCmdError; END; DO; /* DOTT */ if cmdChr2 = 'B' then do; INPUT$CHAR = ' '; j = 0; do i = 0 to 18; if (k := (TABSTOPS(i) := GET$NUMBER)) = 0 then do; TABSTOPS(i) = 0FFH; i = 18; end; else if k > j then j = k; else call fatalCmdError; end; call checkCRLF; end; else if cmdChr2 = 'I' then do; call break; HAS$TMP$INDENT = 0FFH; IS$INDENTED = 0FFH; i = GET8$NEW$VALUE(CUR$INDENT); do while (i := i - 1) <> 0FFH; call ADD$CHAR(' '); end; end; else call fatalCmdError; END; DO; /* DOTU */ if cmdChr2 = 'C' then LOWER$CASE = 0; else call fatalCmdError; END; end; end procDotCmd; DECLARE (chr, AT$BOL) BYTE; sub$184C: PROCEDURE; sub$1981: PROCEDURE; if AT$BOL then do; ELINE = NLINE; call PUT$TEXT$CHAR(' '); if STATE = PUNCTUATED then call PUT$TEXT$CHAR(' '); WLINE = NLINE; STATE = INSPACE; end; end sub$1981; CHECK$PUNCTUATION: PROCEDURE BYTE; if chr = '.' or chr = '?' or chr = '!' or chr = ':' then do; call peekChar; if peekedChar = 0DH or peekedChar = 1AH or peekedChar = ' ' then return 0FFH; end; return 0; end CHECK$PUNCTUATION; AT$BOL = 0; STATE = SINITIAL; ELINE, WLINE = NLINE; do while (chr := GETCH) <> 1AH; if chr = 0DH then do; AT$BOL = 0FFH; do while (chr := GETCH) = 0AH; end; if chr = 1AH then return; end; else AT$BOL = 0; GCR: if chr = 0DH then do; if STATE <> SKIPBLANKLINE then call break; do while (chr := GETCH) = 0AH; end; call emitLine; STATE = SKIPBLANKLINE; if chr = 1AH then return; else goto GCR; end; else if chr = ' ' then do; if STATE <> INSPACE then ELINE = NLINE; call PUT$TEXT$CHAR(chr); STATE = INSPACE; end; else if CHECK$PUNCTUATION then do; if STATE <> INWORD then WLINE = NLINE; call PUT$TEXT$CHAR(chr); WLINE, ELINE = NLINE; STATE = PUNCTUATED; end; else if chr = '.' and (STATE = 0 or AT$BOL or STATE = 4) then do; call sub$1981; call procDotCmd; unk$1F15 = 0FFH; unk$1F0A = 0FFH; STATE = 0; end; else do; call sub$1981; if STATE <> INWORD then WLINE = NLINE; call PUT$TEXT$CHAR(chr); STATE = INWORD; end; end; end sub$184C; PARAM$SCAN: PROCEDURE; DECLARE (c, i, dollar) BYTE; dollar = 0; i = 0; do while (c := CMDLINE(i := i+1)) <> 0; if dollar then do; if c = 'C' then do; IO$REDIRECT = 0FFH; outMode = CONSOLE; end; else if c = 'L' then do; IO$REDIRECT = 0FFH; outMode = LIST; end; else if c = 'S' then do; IO$REDIRECT = 0FFH; outMode = SUPPRESS; end; else if c = 'E' then ERR$PRINT = 0FFH; else if c = 'F' then FORM$FEED = 0FFH; else if c = 'P' then do; PAGE$MODE = 0FFH; IO$REDIRECT = 0FFH; outMode = LISt; end; else if c <> ' ' and c <> '$' then call fatalError(.('PARAMETER SCAN$')); end; else if c = '$' then dollar = 0FFH; end; end PARAM$SCAN; prepFiles: PROCEDURE; if FCB1(1) = ' ' then call fatalError(.('OPENING SOURCE$')); if FCB1(9) = ' ' then call memcpy(.('TEX'), .FCB1(9), 3); if FCB2(1) = ' ' or FCB2(1) = '$' then do; call memcpy(.FCB1, .OUTFCB, 16); OUTFCB(0) = FCB2(0); call memcpy(.('PRN'), .OUTFCB(9), 3); end; else do; call memcpy(.FCB2, .OUTFCB, 16); if OUTFCB(9) = ' ' then call memcpy(.('PRN'), .OUTFCB(9), 3); end; FCB1(32) = 0; OUTFCB(32) = 0; call PARAM$SCAN; call open(.FCB1); if cpmRetVal = 0FFH then call fatalError(.('OPENING SOURCE$')); if not IO$REDIRECT then do; call delete(.OUTFCB); call make(.OUTFCB); if cpmRetVal = 0FFH then call fatalError(.('OPENING DESTINATION$')); end; end prepFiles; signOn: PROCEDURE; if outMode <> CONSOLE then CALL wrstr(.('TEX VERSION 1.0$')); else if FORM$FEED then DO; call wrstr(.('TEX VERSION 1.0$')); call PUTDEST(0CH); END; end signOn; INITIALISE: PROCEDURE; DECLARE INB BASED INPUT$BUF(1) BYTE; INPUT$CHR$OFFSET = INPUT$BUF$SIZE; INB(1) = 0; NLINE = 0; SLINE = 0; OUTPUT$CHR$OFFSET = 0; outMode = 0; CUR$LINENO = 0; PAGE$NUM = 1; CHARS$IN$LINE$BUF = 0; OUT$COL = 1; heading(0) = 0; heading(160) = 0; LINE$LEN = 70; PAGE$OFFSET = 8; CUR$INDENT = 0; PP$INDENT = 6; PAGE$WIDTH = 78; PAGE$LEN = 66; PRINT$LEN = 55; TOP$MARGIN = 6; TOP$SPACES = 3; HEADING$MARGIN = 2; BOTTOM$MARGIN = 5; LINE$SPACING = 1; IS$INDENTED = 0FFH; IS$JUSTIFIED = 0FFH; HAS$TMP$INDENT = 0; LL$INCREASED = 0; unk$1F0A = 0; LOWER$CASE = 0; FORM$FEED = 0; PAGE$MODE = 0; ERR$PRINT = 0; IO$REDIRECT = 0; PO$CHANGED = 0FFH; DO$PAGENUM = 0FFH; unk$1F15 = 0FFH; havePeeked = 0; end INITIALISE; TEXSTART: INPUT$BUF$SIZE = SHR((BASECCP - .MEMORY) AND 0FF00H,1); INPUT$BUF = .MEMORY; OUTPUT$BUF = INPUT$BUF + INPUT$BUF$SIZE; call INITIALISE; call prepFiles; call signON; call wrconCRLF; call sub$184C; call sub$EEF; end;