1
0
mirror of https://github.com/retro-software/B5500-software.git synced 2026-01-13 23:25:24 +00:00
2014-04-05 20:58:25 +00:00

1568 lines
73 KiB
Plaintext

?COMPILE 0XBASIC/UTILITY WITH XALGOL
?XALGOL STACK = 5000
?DATA CARD
$ CARD LIST SINGLE XREF
BEGIN
COMMENT:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::: XBASIC -- A CONVERSATIONAL BASIC INTERPRETER :::::
::::: :::::
::::: MK XV 1.04: 1 DECEMBER 1975 :::::
::::: :::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
XBASIC IS A BASIC INTERPRETER DEVELOPED FOR THE BURROUGHS RANGE
OF COMPUTERS BY STAFF AT PAISLEY COLLEGE OF TECHNOLOGY. ITS PURPOSE
IS TO PROVIDE FAST RESPONSE TO SIMPLE BASIC PROGRAMS UNDER TIME-
SHARING. ACTUAL RUNNING OF PROGRAMS IS MUCH SLOWER FOR XBASIC, BUT
EXPERIENCE SHOWS THAT MOST CLASS TIME IS SPENT ON INPUT AND COMPILE.
XBASIC IS AN IMPLEMENTATION OF STANDARD BASIC, AND DIFFERS
FROM BURROUGHS BASIC IN CERTAIN MATTERS OF DETAIL. THE COMMANDS
ALLOWED IN XBASIC FORM A SUBSET OF THE COMMANDS AVAILABLE UNDER CANDE.
FILES ARE EDITABLE UNDER CANDE. TRACE AND UNTRACE STATEMENTS
CAN BE MADE AVAILABLE - SEE LINES 83300-83400 AND 107300-108700.
XBASIC OUTPUT MAY BE DIVERTED FROM REMOTE TO PRINTER ("SEND").
VIDEO TERMINALS ARE SUPPORTED FOR EASY CORRECTION OF SOURCE PROGRAM.
PROGRAMS ARE MONITORED FOR EXCESS LOOPING.
TO USE XBASIC FROM THE BATCH TERMINAL, THE FOLLOWING
CARDS SHOULD BE SUPPLIED:
? EXECUTE 0XBASIC/UTILITY
? COMMON=2
? DATA CRD
(INSERT DECK HERE: USE TERMINAL FORMAT)
? END
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
COMMENT
THE BLOCK STRUCTURE FOR THE PROGRAM IS AS FOLLOWS:
------------- /------|
1 SOURCEIN: 1 / DOES |
START-->--1 & EXECUTE 1--RUN->----< OBJECT >--YES--->---|
1 1 COMMANDS 1 | EXIST? / 1
A ------------- |------| V
1 1 1 1
1 1 (YES) V (NO) 1
1 /------| 1 1
1 / ANY | ------------- 1
1 < SYNTAX >------<----1 COMPILE: 1 1
1 | ERRORS?/ 1 1 1
1 |------/ ------------- 1
1 1 1
1 V (NO) 1
1 1 1
1 ------------- 1
|---<---1 EXECUTE: 1------------------<--------------/
-------------
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
INTEGER IU; % (COMMON) INPUT UNIT=0 VDU,1 TTY,2 CRD
INTEGER ARRAY PROG[0:200,2:11], % SOURCE STRINGS
SSEQ[0:200], % SEQUENCE NUMBERS
STYP, % STATEMENT TYPES
SPOB[1:200], % POINTERS TO OBJECTPROGRAM
SUB[1:26], % INFO ON USER FUNCTIONS
ARR[1:26,0:2], % ARRAYS
STRAR[1:26,0:1], % STRING ARRAYS
IOB[1:240],IOF[1:10], % I/O PSEUDOBUFFERS
IOBE[1:14], % " "
KEY[1:38], % COMPILE KEYWORDS
FNM[1:3,1:2]; % FILENAMES FOR EXECUTE
REAL ARRAY OBJ[0:999], % PSEUDO-OBJECTPROGRAM
FORX[1:10,1:4], % INFO ON FOR STATEMENTS
CONST[1:1000], % SOURCE PROGRAM CONSTANTS
ANSA[0:9], % FOR DISK SEARCH
IO[0:3]; % FILENAMES
INTEGER MS, % NUMBER OF LINES OF PROGRAM
ACS, % FIRST EXECUTABLE STATEMENT
CS, % CURRENT STATEMENT NUMBER
CHA, % CURRENT SOURCE CHARACTER
CP, % POSITION OF CHA IN SOURCE
LP, % SEE LOOK
CO, % POSITION IN OBJ
OU, % OUTPUT UNIT (0 REMOTE, 1 PRINTER)
MSTO, % CURRENT TOP OF ARRAYS
MSTR, % CURRENT TOP OF STRING ARRAYS
NCON, % NUMBER OF CONSTANTS
DELIM, % SEE NCH
TIM, % MAX EXECUTION TIME (2 MIN USUALLY)
LL, % CURRENT LINE NUMBER IN INPUT PAGE
AREASIZE, % FOR EXECUTE OUTPUT FILE IF ANY
BEG, % LIST COMMAND INITIAL LINE
EN, % FINAL LINE
NDEP, % ARITH STACK COUNTER
ADDR, % CURRENT VARIABLE ADDRESS
FORE,FORC, % HELP COMPILE FOR NESTS
NF, % NUMBER OF EXECUTE FILES
A,B,C,D,K; % HASH
REAL R,S,T; % HASH
BOOLEAN OBJECT, % "THERE IS AN ORJECTPROGRAM"
STRIN, % "EXPRESSION IS A STRING"
HDDR, % "PRINTER HEADER PRINTED"
INFILTOG, % "PROGRAM NEEDS INPUT FILE"
OUTFILTOG, % "PROGRAM NEEDS OUTPUT FILE"
FIRSTOFF, % "HELLO"
DANGER, % "NEW MATERIAL IN WORKFILE"
VAR, % "EXPRESSION IS A VARIABLE"
SY, % "PROGRAM CONTAINS SYNTAX ERRORS"
EQOK, % "EXPRESSION MAY CONTAIN ="
AA; % "SUCCESSIVE EXPNS TO PRINT"
POINTER PINB, % START OF LINE IN IOB[*]
PIOB, % CURRENT CHARACTER "
PIBE, % LAST CHARACTER IN IOBE[1]
POB, % FIRST CHARCTER IN OBJ[*]
APR,BPR,CPR; % HASH
FORMAT WHT ("ERR- ",A6," IS NOT A COMMAND IN XBASIC"),
STP (/"END ",A6),
SPC (/),
WRN ("MORE THAN 100 GOTOS. IS YOUR PROGRAM ALL RIGHT?"),
REP (A3),
SYER ("SYNTAX ERRORS: CLEAR SCREEN AND TRANSMIT A SPACE"),
SYR ("SYNTAX ERRORS:"),
WT ("WAIT-"),
MESS ("EXECUTING"),
INTR ("ILLEGAL NUMBER"),
LNGPRG("PROGRAM TOO LONG AT LINE ",I6),
INVIT ("VDU ASSUMED - ELSE SAY TTY"),
DVO ("OUTPUT IS BEING DIVERTED TO PRINTER"),
BK ("EXECUTION STOPPED - EXCESS TIME."/
"FOR LONG PROGRAMS USE MAIN SYSTEM"),
SNUM (X72,I8),
F1 ("USE RENAME XXXXXX OR SAVE XXXXXX COMMAND"),
F2 ("ERR? THIS WILL DELETE THE WORKFILE"),
F3 ("OK- ",I3," RECORDS",A6,"D, LAST RECORD =",I7),
F4 ("FILE ",A6," - ",A6,A1," BY XBASIC"),
F5 ("YOUR WORKFILE IS AS AT LAST RUN COMMAND"),
F6 (I6,X3,"DIM OR FILES STATEMENT OUT OF SEQUENCE"/
"ERR RUN"),
F7 ("WORKFILE NOW EMPTY"),
HD1 ("FURTHER OUTPUT WILL BE PRINTED WHEN YOU SIGN OFF"),
HD3 (X40,"XBASIC MK XV",X8,"RUN ",A6,"DAY ",
A2,"/",A2,"/",A2,/X54,"USER NO. ",A3,A4,/X52,20("*")//),
F9 ("XBASIC IS RUNNING-"),
F10 ("UNNAMED WORKFILE HAS",I4," RECORDS, LAST RECORD =",I6),
F11 (A6," (WORKFILE) HAS",I4," RECORDS, LAST RECORD =",I6),
F12 ("ERR- ILLEGAL PARAMETER"),
F13 ("ARE PRESENT CONTENTS OF FILE ",A6," TO BE DESTROYED?");
SWITCH FORMAT NUM:=(U10),(U6),(X20,U10);
SWITCH FORMAT MNP:=("NOT ENOUGH INPUT AT LINE",I6,X5,"TRY AGAIN"),
("BLANK INPUT AT LINE",I6,X5,"IGNORED");
FILE TTY 19(2,10);FILE IN CRD 2(2,10); FILE IN VDU 19(1,240);
FILE OUT LIN 1(2,14);SWITCH FILE FN:=TTY,CRD;SWITCH FILE FL:=TTY,LIN;
MONITOR INTOVR,EXPOVR,INDEX,FLAG,ZERO;
LABEL SOURCEIN,COMPILE,EXECUTE,STOP,FINSH,ERR,INCST,PER,INER,
TOOLONG;
LABEL EXS,EQL,LET,CAR,ONX,RON,IFF,FEQ,GOT,GOS,RET,FOX,NEX,
DEF,REA,RREA,INP,RAN,RES,PRI,RPRI,XPRI,DIM,ENX,REM,RFIL,
INTVR,QUOTE,RDUM,DAT,RDAT,RDIM,PAG,MAT,IOMT,FLAGR,FIL,CGO;
SWITCH OPN:=LET,GOT,GOS,RET,INP,REA,PRI,FOX,NEX,MAT,
DEF,DAT,RAN,PAG,RES,REM,ENX,ENX,IFF,ONX;
DEFINE ON(ON1)=IF CHA=ON1 THEN #;
COMMENT::::::::::::::::GLOBAL PROCEDURES:::::::::::::::::::::::::::
--- CHCONV CONVERTS CHA TO LETTER CODE 1-26 ;
INTEGER PROCEDURE CHCONV(A);VALUE A; INTEGER A;
BEGIN CHCONV:=0;IF A GTR 16 AND A LSS 26 THEN CHCONV:=A-16 ELSE
IF A GTR 32 AND A LSS 42 THEN CHCONV:=A-23 ELSE
IF A GTR 49 AND A LSS 58 THEN CHCONV:=A-31 END;
COMMENT
--- NCH PICKS NEXT CHARACTER FROM SOURCE STRING
AND STORE IT IN CHA. BLANKS ARE SKIPPED.
IF LAST CHAR- RETURN "%" AT DELIM.
CP IS UPDATED. IOBE[*] IS USED AS HASH.;
INTEGER PROCEDURE NCH;
BEGIN INTEGER A;LABEL RPT; POINTER CPR;
IOBE[1]:=0;A:=CP;
RPT: IF A GEQ DELIM THEN CHA:=NCH:="%" ELSE BEGIN
CPR:=POINTER(PROG[CS,2])+A;
REPLACE PIBE BY CPR:CPR FOR 1;A:=A+1;
IF IOBE[1]=48 THEN GO TO RPT;CHA:=NCH:=IOBE[1];CP:=A
END END;
COMMENT
--- NMBR PICKS UP STATEMENT NUMBER ;
INTEGER PROCEDURE NMBR(N);VALUE N;INTEGER N;
BEGIN LABEL DONE,RNB,BLK,NST,SKB;
DEFINE RD(RD1)=REPLACE BPR BY APR:APR FOR 1;
IF DELTA(PINB,APR) GEQ RD1 THEN GO BLK;IF IOBE[1]#;
CHA:=NMBR:=IOBE[1]:=0;
NST: RD(N)=48 THEN GO NST;IF (CHA:=IOBE[1]) GEQ 10 THEN GO DONE;
RNB: RD(72) LSS 10 THEN BEGIN CHA:=CHA|10+IOBE[1];GO RNB END;
NMBR:=CHA;CHA:=IOBE[1];IF CHA NEQ 48 THEN GO DONE;
SKB: RD(72)=48 THEN GO SKB;CHA:=IOBE[1];GO DONE;
BLK: CHA:="%";
DONE: END;
COMMENT
--- FILECONTROL DEALS WITH SOURCE FILE OPERATIONS
A=0 "MAKE"/"RENAME",
1 "SAVE", 2 "LOAD"/"COPY",
3 "REMOVE", 4 SAVE WORKFILE(AT "RUN")
5 LOAD WORKFILE(AT XBASIC ENTRY),
6 EXPLICIT REMOVE (AT "BYE",ETC)
7 EXPLICIT SAVE, 8 EXPLICIT LOAD;
PROCEDURE FILECONTROL(A,C,D,L);VALUE A,C,D;INTEGER A;REAL C,D;LABEL L;
% C AND D CARRY LABEL EQUATE FOR EXPLICIT OPERATIONS
BEGIN INTEGER B,X,Y;
PROCEDURE FILERR(E);VALUE E;INTEGER E;
BEGIN SWITCH FORMAT ERR:=("ERR- ",A3,A4,"/",A3,A4,"- NOT ON DISK"),
("ERR- ",A3,A4,"/",A3,A4," - INVALID USER"),
("ERR- ",A3,A4,"/",A3,A4," - NON-STANDARD"),
("ERR- ",A3,A4,"/",A3,A4," - ILLEGAL NAME"),
("ERR- ",A3,A4,"/",A3,A4," - DUPLICATE NAME"),
("ERR- NO FILENAME"),
("ERR- WORKFILE"),
("ERR- WORKFILE IS EMPTY");
IF E>4 THEN WRITE(TTY,ERR[E]) ELSE WRITE(TTY,ERR[E],
FOR X:=B,2 DO [IO[X].[41:18],IO[X].[23:24]]);
IF B=0 THEN IO[0]:=0;IF A=1 AND E=3 THEN WRITE(TTY,F1);
GO SOURCEIN END;
LABEL SKIP,MK,SV,LD,RM,EF,SW,LW,EW;
SWITCH OP:=MK,SV,LD,RM,SW,LW,RM,SV,LD;
FILE DSK DISK "XBWKFL "(2,10,300,SAVE 7);% NB LABEL EQN ABOVE SKIP
IF DANGER AND (C="CREATE" OR A=2 OR A=6) THEN BEGIN DANGER:=FALSE;
WRITE(TTY,F2);GO SOURCEIN END;
B:=IF A=0 THEN 0 ELSE 1;IF A>3 THEN BEGIN
FILL DSK WITH C,D;IO[1]:=C;IO[2]:=D;GO SKIP END;
IO[B]:=" "; % FILENAME
SCAN APR:APR FOR 5 UNTIL NEQ " ";IF DELTA(PINB,APR)<12 THEN
REPLACE POINTER(IO[B])+1 BY APR:APR FOR IF A<2 THEN 6 ELSE 7
WHILE IN ALPHA;
IF IO[B]=" " THEN BEGIN % ON SAVE SAVE WKFILE IF NO NAME
IF A=1 AND IO[0] NEQ 0 THEN IO[1]:=IO[0] ELSE FILERR(5) END;
IO[2]:=0;IF A GTR 1 THEN BEGIN % PROCESS "/USERCODE" IF PRESENT
SCAN CPR:CPR:=APR FOR 10 WHILE NEQ "/";IF DELTA(PINB,CPR) LSS 15 THEN
BEGIN IO[2]:=" ";
REPLACE POINTER(IO[2])+1 BY APR:CPR+1 FOR 7 WHILE IN ALPHA END END;
IF IO[2]=0 THEN IO[2]:=TIME(-1);
IF IO[B]="XBWKFL " OR IO[B].[41:36] LSS "A00000" THEN FILERR(3);
FILL DSK WITH IO[B],IO[2];DSK.SAVE:=7;
SKIP: IF NOT FIRSTOFF THEN BEGIN X:=CHA;Y:=NMBR(72);
IF Y NEQ 0 OR CHA NEQ "%" THEN GO PER;CHA:=X END;
SEARCH(DSK,ANSA[*]);IF (A=5 OR A=6) AND ANSA[0]=-1 THEN GO L;
IF A=0 AND ANSA[0] NEQ -1 THEN FILERR(4);
IF A=1 AND IO[1] NEQ IO[0] AND ANSA[0] NEQ -1 THEN FILERR(4);
IF A>1 AND A NEQ 4 THEN BEGIN IF ANSA[0] LEQ 0 THEN FILERR(ANSA[0]+1);
IF ANSA[3] NEQ 10 OR ANSA[4] NEQ 300 THEN FILERR(2) END;
IF CHA="MAKE00" THEN BEGIN MS:=0;OBJECT:=FALSE END;
GO OP[A+1];
SV: IF IO[0]=0 THEN IO[0]:=IO[B]; % NAME WORKFILE
IF MS=0 THEN FILERR(7);IF ANSA[0] NEQ -1 AND ANSA[0] NEQ 7 THEN
FILERR(1);DSK.AREAS:=20;DSK.AREASIZE:=10;
FOR CS:=1 STEP 1 UNTIL MS DO BEGIN % SAVE IT IN CANDE FORMAT
REPLACE POINTER(IOBE[10]) BY SSEQ[CS] FOR 8 DIGITS;
REPLACE POINTER(IOBE[*]) BY POINTER(PROG[CS,2]) FOR 9 WORDS;
WRITE(DSK,10,IOBE[*]) END;LOCK(DSK);DANGER:=FALSE;GO MK;
LD: FOR MS:=1 STEP 1 UNTIL 200 DO BEGIN % LOAD FROM
READ(DSK,10,IOBE[*])[EF];READ(IOBE[*],SNUM,SSEQ[MS]); % CANDE FORMAT
WRITE(PROG[MS,*],9,IOBE[*]);PROG[MS,11]:=SSEQ[MS] END;
EF: MS:=MS-1;OBJECT:=FALSE;LOCK(DSK);
WRITE(TTY,F3,MS,C,SSEQ[MS]);
ON("LOAD00") IO[0]:=IF IO[2]=TIME(-1) THEN IO[1] ELSE 0;GO MK;
RM: IF IO[B]=IO[0] AND A=3 THEN BEGIN IF MS=0 THEN
IO[0]:=0 ELSE FILERR(6) END;IF ANSA[0] NEQ 7 THEN FILERR(1);
WRITE(DSK,*,0);CLOSE(DSK,PURGE);GO MK;
SW: DSK.AREAS:=20;DSK.AREASIZE:=11;
IF MS=0 THEN FILERR(7);
WRITE(DSK,*,IO[0]);FOR CS:=1 STEP 1 UNTIL MS DO
WRITE(DSK,10,PROG[CS,*]);LOCK(DSK);DANGER:=FALSE;GO MK;
LW: READ(DSK,*,IO[0]);FOR MS:=1 STEP 1 UNTIL 200 DO
BEGIN READ(DSK,10,PROG[MS,*])[EW];SSEQ[MS]:=PROG[MS,11] END;
EW: LOCK(DSK);MS:=MS-1;OBJECT:=FALSE;GO MK;
MK: IF A<4 AND CHA NEQ "COPY00" THEN
WRITE(TTY,F4,IO[B].[41:36],C,D);
IF A=5 THEN WRITE(TTY,F5);
IF CHA="COPY00" THEN WRITE(TTY,STP,"COPY ");
GO L END;
COMMENT
--- SYNT DEALS WITH SYNTAX ERRORS ;
PROCEDURE SYNT(A);VALUE A;REAL A;
BEGIN IF SY THEN BEGIN IF IU=0 THEN BEGIN WRITE(TTY,SYER);
READ(TTY[STOP]) END ELSE WRITE(TTY,SYR);SY:=FALSE END;
REPLACE APR:=POINTER(IOBE[*]) BY " " FOR 72;
WRITE(IOBE[*],NUM[0],SSEQ[CS]);SCAN APR:APR WHILE NEQ 48;
IF IU=0 THEN BEGIN REPLACE APR:APR BY POINTER(PROG[CS,*]) FOR 72;
APR:=POINTER(IOBE[*])+72;
REPLACE APR:APR BY "!" FOR 1 END ELSE APR:=APR+3;
REPLACE POB BY A FOR 8;REPLACE APR BY POB+1 FOR 7;
OBJ[1]:=0;REPLACE POB+7 BY POINTER(IOBE[*])+79 FOR 1;
IF IU GTR 0 THEN WRITE(TTY,9,IOBE[*]) ELSE IF OBJ[1]=48 THEN
WRITE(TTY,10,IOBE[*]) ELSE WRITE(TTY[NO],10,IOBE[*]);GO TO ERR END;
COMMENT
--- NWC MODIFIES NCH FOR COMPILE ;
INTEGER PROCEDURE NWC;
BEGIN ON("%") SYNT("MISG OP");NWC:=NCH END;
COMMENT
--- PUT STORES CHARACTER IN OBJ ;
PROCEDURE PUT(A);VALUE A;INTEGER A;
BEGIN IF A>63 THEN SYNT("STR >63");
IOBE[1]:=A;REPLACE POB+CO BY PIBE FOR 1;CO:=CO+1;
IF CO GEQ 8000 THEN GO TO TOOLONG;IF CO MOD 8=0 THEN CO:=CO+1 END;
COMMENT
--- RED MOVES BACK ONE SPACE IN OBJ;
DEFINE RED=CO:=IF CO.[2:3]=1 THEN CO-2 ELSE CO-1#;
COMMENT
--- LOOK LOOKS AT A STRING IN SOURCE PROG ;
INTEGER PROCEDURE LOOK(A);VALUE A;INTEGER A;
BEGIN INTEGER B,C,D,E;E:=C:=CHA;B:=CP;
FOR D:=1 STEP 1 UNTIL A-1 DO IF CHA NEQ "%" THEN C:=C|64+NWC;
LOOK:=C;LP:=CP;CP:=B;CHA:=E END;
COMMENT
--- NUMB PICKS UP DIM AND MAT SIZES ;
INTEGER PROCEDURE NUMB;
BEGIN LABEL RP;INTEGER A;
A:=0;
RP: IF NWC LSS 10 THEN BEGIN A:=A|10+CHA;GO TO RP END;
IF A=0 THEN SYNT("IL STMT");
NUMB:=A END;
COMMENT
--- ARITH(1) CONVERTS EXPNS TO REVERSE POLISH ;
PROCEDURE ARITH(TT);VALUE TT;INTEGER TT;
BEGIN INTEGER I,A,B,C,J,K,OP,STCK;BOOLEAN INMOK,VOK,STROK;
LABEL S,SS,RPT,EXPON,DONE,FINEV,FORM1,FORM2,FORM3,FIN,RP;
INTEGER ARRAY OPK[1:20];
COMMENT AN EXPRESSION CONSISTS OF A NUMBER OF PRIMARIES
SEPARATED BY OPERATORS, POSSIBLY PRECEDED BY INITIAL - .
PRIMARIES: OPERATORS:
NUMBER +
VARIABLE -
ARRAY WITH SUBSCRIPT(S) *
FUNCTION WITH PARAMETER(S) /
STRING **
STRING VARIABLE =
STRING ARRAY WITH SUBSCRIPT
EXPRESSION IN BRACKETS
EXPRESSION HAS TYPE REAL UNLESS STRING PRIMARY
OCCURS: IF SO IT HAS TYPE STRING. A VARIABLE PRIMARY IS
A PRIMARY OTHER THAN NUMBER, FUNCTION, OR STRING.
IN OBJ AN EXPRESSION HAS FORM
A OPS A OPS ... A OPS 0
WHERE A IS A CHARACTER BETWEEN 1 AND 16 GIVING THE PRIMARY
OR OPERATOR TYPE. OPS IS 0-2 CHARACTERS GIVING MORE INFORMATION
DEPENDING ON A. ;
STRIN:=FALSE;NDEP:=NDEP+1;IF NDEP=10 THEN SYNT("SIMPLFY");
STCK:=OP:=0;INMOK:=VOK:=TRUE;STROK:=TT=0;
COMMENT PRIMARIES: ;
SS: CHA:=NWC;
COMMENT BRACKETED EXPRESSION;
S: ON(29) BEGIN ARITH(1);IF CHA NEQ 45 THEN SYNT("NO ) ,A");
RED;GO TO FORM1 END;
COMMENT 1 NUMBER ;
IF CHA LSS 10 OR CHA = 26 THEN BEGIN R:=I:=0;
RPT: ON(26) BEGIN I:=1;CHA:=NWC END;
IF CHA GEQ 10 THEN GO TO EXPON;IF I>0 THEN BEGIN R:=R+CHA|10*(-I);
I:=I+1 END ELSE R:=R|10+CHA;CHA:=NWC; GO TO RPT;
EXPON: IF CHA NEQ 21 THEN GO TO DONE;I:=1;CHA:=NWC;J:=0;
ON(44) BEGIN I:=-1;CHA:=NWC END ELSE ON(16) CHA:=NWC;J:=CHA;
IF CHA GEQ 10 THEN SYNT("NO EXPN");CHA:=NWC;
IF CHA LSS 10 THEN BEGIN J:=J|10+CHA;CHA:=NWC END;R:=R|10*(I|J);
DONE: PUT(1);NCON:=NCON+1;CONST[NCON]:=R;
PUT(NCON.[11:6]);PUT(NCON.[5:6]);GO FORM2 END;
COMMENT 8 INITIAL - ;
ON(44) BEGIN IF NOT INMOK THEN SYNT ("MISPL -");PUT(8);
GO TO FORM2 END;
COMMENT 16 STRING ;
ON(63) BEGIN IF NOT STROK THEN SYNT("ILL STR");PUT(16);
SCAN CPR:APR:=POINTER(PROG[CS,2])+CP WHILE NEQ 63;A:=DELTA(APR,CPR);
STRIN:=TRUE;IF A>14 THEN SYNT("LONGSTR");PUT(A);PUT(CP);
CP:=CP+A+1;CHA:=NWC;VAR:=FALSE;GO TO FORM3 END;
IF CHCONV(CHA)=0 THEN SYNT("ILL NUM");
B:=CHA;A:=LOOK(2) MOD 64;IF CHCONV(A) NEQ 0 THEN BEGIN
A:=LOOK(3) MOD 4096;CHA:=B;
IF A NEQ "ST" AND A NEQ "TH" AND A NEQ"TO" AND A NEQ "GO" THEN
BEGIN LABEL EQL,FNQ,RDUM;
COMMENT 5 STANDARD FNS;
INTEGER B,AS,AP;
B:=LOOK(3);CP:=LP;
FOR A:=21 STEP 1 UNTIL 32 DO IF B=KEY[A] THEN GO TO EQL;
GO TO FNQ;
EQL: IF NWC NEQ 29 THEN SYNT("NO PARM");ARITH(1);RED;
PUT(5);PUT(A-2);
IF CHA NEQ 45 THEN SYNT("NO ) A");GO TO FORM1;
COMMENT 4 USER FNS ;
FNQ: K:=B DIV 64; IF K NEQ "FN" THEN SYNT("UNRC FN");
B:=CHCONV(B MOD 64);IF SUB[B]=0 THEN SYNT("UNDC FN");
IF NWC NEQ 29 THEN SYNT("NO PARM");A:=0;
RDUM: A:=A+1;ARITH(1);RED;ON(58) GO TO RDUM;
IF CHA NEQ 45 OR A NEQ SUB[B] THEN SYNT("PARAMTR");
CHA:=NWC;PUT(4);PUT(B);GO TO FORM2 END END;
B:=CHCONV(B);IF B=0 THEN SYNT("INV VAR");CHA:=NWC;
COMMENT 3 ARRAY ;
ON(29) BEGIN IF ARR[B,1]=0 THEN SYNT("UNDC AR");
ARITH(1);RED;ON(58) BEGIN IF ARR[B,2]=0 THEN SYNT("SUBSCPT");
ARITH(1);RED END;IF CHA NEQ 45 THEN SYNT("SUBSCPT");STROK:=FALSE;
PUT(3);PUT(B);CHA:=NWC END
ELSE ON("$") BEGIN IF NOT STROK THEN SYNT("ILL STR");
COMMENT 15 STRING ARRAY;
CHA:=NWC;ON(29)BEGIN IF STRAR[B,1]=0 THEN SYNT("UNDSTAR");ARITH(1);
RED;
IF CHA NEQ 45 THEN SYNT("NO ) ,5");PUT(15);CHA:=NWC END ELSE
PUT(14);PUT(B);STRIN:=TRUE;VAR:=VOK;GO TO FORM3 END
ELSE BEGIN PUT(2);PUT(B);IF CHA LSS 10 THEN BEGIN PUT(C:=CHA+1);
COMMENT 14 STRING VBLE
2 VARIABLE ;
CHA:=NCH END ELSE PUT(C:=0);IF STCK=0 THEN ADDR:=11|(B-1)+C;
STROK:=FALSE END;VAR:=VOK;GO TO FORM3;
FORM1: CHA:=NWC;
FORM2: STROK:=VAR:=FALSE;IF STRIN THEN SYNT("ILL STR");
COMMENT 7-13 OPERATORS:
DANGER: REVERSE POLISH SECTION ;
FORM3: BEGIN LABEL RPT,TEST,BOP,XOP;
STCK:=STCK+1;INMOK:=FALSE;
RPT: I:=0;ON(16) I:=3 ELSE ON(44) I:=4 ELSE
ON(43) BEGIN IF NWC=43 THEN I:=7 ELSE BEGIN CP:=CP-1;I:=5 END;
END ELSE ON(49) I:=6 ELSE IF CHA=61 AND EQOK THEN BEGIN INMOK:=TRUE;
IF NOT VAR THEN SYNT("ILL ASN");I:=1 END;VOK:=I LEQ 1;
IF NOT VOK THEN BEGIN STROK:=FALSE;IF STRIN THEN SYNT("ILL STR") END;
TEST: IF OP=0 THEN GO TO BOP; IF OP LSS 0
THEN SYNT(" ARITH");
J:=OPK[OP];IF I|J NEQ 1 AND (I+1) DIV 2 LEQ (J+1) DIV 2 THEN BEGIN
OP:=OP-1;GO TO XOP END;
BOP: IF I=0 THEN GO TO FIN;OP:=OP+1;OPK[OP]:=1;GO TO SS;
XOP: VAR:=FALSE;STCK:=STCK-1;
PUT(J+6);IF STCK LEQ 0 THEN SYNT(" ARITH");
GO TO TEST END;
COMMENT 6 END EXPN ;
FIN: NDEP:=NDEP-1;IF STCK NEQ 1 THEN SYNT(" ARITH");
PUT(0) END;
COMMENT
--- SKIP SKIPS GIVEN STRING IF FOUND ;
PROCEDURE SKIP(A,B);VALUE A,B;INTEGER A,B;
BEGIN INTEGER C,D,E;E:=CP;C:=NWC;
FOR D:=1 STEP 1 UNTIL A-1 DO IF CHA NEQ "%" THEN C:=C|64+NWC;
IF C NEQ B THEN BEGIN CP:=E;CHA:=0 END END;
COMMENT
--- CHMAT CHECK USED IN MAT STATEMENT ;
INTEGER PROCEDURE CHMAT(A);VALUE A;INTEGER A;
BEGIN A:=CHCONV(A);IF A=0 THEN SYNT("ILL ARR");
IF ARR[A,1]=0 THEN SYNT("UNDC AR");IF ARR[A,2]=0 THEN
SYNT(" TYPE");CHMAT:=A END;
COMMENT ---- CFN FOR FILE INPUT ANO OUTPUT;
PROCEDURE CFN;
BEGIN LABEL L,M;
CHA:=NWC;IF LOOK(4)="FILE" THEN BEGIN CP:=LP;D:=IF A=15 THEN 5 ELSE A;
FOR C:=1 STEP 1 UNTIL NF DO BEGIN CHA:=NWC;B:=LOOK(FNM[2,C]);
IF B=FNM[1,C] THEN BEGIN IF FNM[3,C]=0 THEN FNM[3,C]:=D ELSE IF D NEQ
FNM[3,C] THEN SYNT("IN+OUT?");CP:=LP;PUT(A);IF D=5 THEN
INFILTOG:=TRUE;IF A=7 THEN OUTFILTOG:=TRUE;
IF NWC=":" THEN BEGIN A:=NUMB;FOR B:=ACS STEP 1 UNTIL MS DO
IF A=SSEQ[B] THEN BEGIN PUT(B.[11:6]);PUT(B.[5:6]);GO ON(58) L ELSE M
END;SYNT("UNDF GO") END;PUT(0);PUT(0);ON(58) GO L;
GO TO M END ELSE BEGIN CP:=CP-1;CHA:=0 END END;SYNT("UNDC FL") END;
PUT(0);ON("%") GO TO M;CP:=CP-1;CHA:=0;GO TO L;
M: IF A=5 THEN SYNT("NOINPUT");PUT(0);GO TO INCST;
L: END;
COMMENT-------------------------------------------------------
----------- XBASIC STARTS HERE -----------------
-------------------------------------------------------------;
FIRSTOFF:=IU NEQ 2;IF IU=2 THEN TTY.TYPE:=1;
PIBE:=POINTER(IOBE[1])+7; PINB:=POINTER(IOB[1]);
DELIM:=72;TIM:=10800;LL:=-1;
OBJECT:=HDDR:=FALSE;OU:=0;
FILL KEY[*] WITH "LET","GOT","GOS","RET","INP",
"REA","PRI","FOR","NFX","MAT","DEF","DAT",
"RAN","PAG","RES","REM","STO","END","IF ","ON ","SIN","COS",
"TAN","ATN","EXP","LOG","ABS","INT","SQR","FIX","SGN","RND",
"EQ","LT","LE","GT","GE","NE";
COMMENT------------------------------------------------------
------------SOURCEIN: FOR INPUT OF SOURCE PROGRAM -------
------------ AND EXECUTION OF COMMANDS -------
-----------------------------------------------------------------;
COMMENT: COMMANDS ALLOWED IN XBASIC
HELLO SAME AS BYE
BYE TERMINATES XBASIC. PRINTER OUTPUT IS SCHEDULED
RUN EXECUTES PROGRAM IF FREE OF SYNTAX ERRORS
SCR DELETES WORKFILE
DELETE SAME AS SCR
LIST LISTS ENTIRE WORKFILE
LIST E WHERE E IS A NUMBER OF ELEMENTS OF FORM
N OR M-N (M,N STATEMENT NUMBERS)
SEPARATED BY COMMAS. LISTS PART OF PROGRAM
MAKE NNNNNN INITIALISES AND NAMES WORKFILE
SAVE SAVES WORKFILE IF NAMED
SAVE NNNNNN SAVES WORKFILE IN NNNNNN. NAMES WORKFILE
IF NOT ALREADY NAMED
LOAD NNNNNN LOADS WORKFILE AND NAMES IT
LOAD NNNNNN/UUUUUUU COPIES WORKFILE FROM NNNNNN/UUUUUUU
WORKFILE BECOMES UNNAMED
COPY NNNNNN COPIES NNNNNN INTO WORKFILE
COPY NNNNNN/UUUUUUU SAME FOR NNNNNN/UUUUUUU
REMOVE NNNNNN REMOVES FILE NNNNNN/USER NO.
RENAME NNNNNN RENAMES WORKFILE
PLOP RESETS WORKFILE TO LAST RUN STATUS
WHATS OBTAINS WORKFILE STATUS
TTY INPUT UNIT IS TTY
VDU INPUT UNIT IS VDU
SEND DIVERTS OUTPUT TO PRINTER
NOSEND TERMINATES DIVERSION OF OUTPUT
TIME N RESETS MAX EXECUTION TIME TO N MINUTES
-------------------------------------------------------------;
SOURCEIN: BEGIN LABEL SOURCEIN,EF,COPY,NEWL,SOURCE,RMOB,
FST;
INTOVR:=INER;
IF FIRSTOFF THEN BEGIN FILECONTROL(5,"XBWKFL ",TIME(-1),FST);
FST: IF IU=0 THEN WRITE(TTY,INVIT);FIRSTOFF:=FALSE END;
IF LL=-1 THEN GO TO SOURCE;
SOURCEIN: IF IU GTR 0 THEN GO TO SOURCE;PINB:=PINB+80;
LL:=LL+1;IF LL LSS 24 THEN GO TO NEWL;
SOURCE: LL:=0;IF IU GTR 0 THEN READ(FN[IU-1][STOP],10,IOB[*])
ELSE READ(VDU[STOP],240,IOB[*]);
IF IU=2 THEN WRITE(TTY,10,IOB[*]);
PINB:=POINTER(IOB[*]);IOBE[1]:=0;
NEWL: C:=IF MS>0 THEN SSEQ[MS] ELSE 0;APR:=PINB;BPR:=PIBE;
A:=NMBR(6);IF A=0 THEN BEGIN IF CHA="%" THEN GO TO SOURCEIN;
COMMENT NONVOID INPUT WITH ZERO STATEMENT NO. MUST BE COMMAND;
IOBE[1]:=0;REPLACE BPR-5 BY APR:CPR:=APR-1 FOR 1;
REPLACE BPR-4 BY APR:APR FOR 5 WHILE IN ALPHA;CHA:=IOBE[1];
ON("RUN000") BEGIN IF OBJECT THEN BEGIN IF NMBR(72) NEQ 0 OR
CHA NEQ "%" THEN GO PER;GO EXECUTE END
ELSE IF IU=2 THEN GO COMPILE
ELSE BEGIN WRITE(TTY,WT);
FILECONTROL(4,"XBWKFL ",TIME(-1),COMPILE) END END;
ON("DELETE" OR CHA="SCR000") BEGIN C:=NMBR(72);
IF C NEQ 0 OR CHA NEQ "%" THEN GO PER;WRITE(TTY,F7);
CS:=MS:=IO[0]:=0;DANGER:=OBJECT:=FALSE;GO SOURCEIN END;
ON("LIST00") BEGIN
COMMENT PROCESS LIST COMMAND;
LABEL NEX,LEX;
IF OU=1 THEN WRITE(TTY,DVO);
WRITE(FL[OU],SPC);
NEX: BEG:=NMBR(72);IF CHCONV(CHA) NEQ 0 THEN GO PER;
EN:=ON("%" AND BEG=0) 1000000 ELSE ON(44) NMBR(72) ELSE BEG;
IF CHCONV(CHA) NEQ 0 THEN GO PER;
FOR A:=1 STEP 1 UNTIL MS DO IF SSEQ[A] LEQ EN
AND SSEQ[A] GEQ BEG THEN BEGIN
REPLACE POINTER(IOBE[1]) BY " " FOR 112;
WRITE(IOBE[*],NUM[2|OU],SSEQ[A]);
SCAN CPR:POINTER(IOBE[1])+20|OU FOR 20 WHILE NEQ 48;
REPLACE CPR BY POINTER(PROG[A,2]) FOR 72;WRITE(FL[OU],14,IOBE[*])
END;ON(58) GO TO NEX;WRITE(TTY,STP,"LIST ");GO TO SOURCEIN END;
ON("RENAME") FILECONTROL(0," NAMED"," ",SOURCEIN);
ON("MAKE00") FILECONTROL(0,"CREATE","D",SOURCEIN);
ON("SAVE00") FILECONTROL(1," SAVED"," ",SOURCEIN);
ON("LOAD00") FILECONTROL(2," LOADE","D",SOURCEIN);
ON("REMOVE") FILECONTROL(3,"REMOVE","D",SOURCEIN);
ON("COPY00") FILECONTROL(2," COPIE",0,SOURCEIN);
ON("BYE000" OR CHA="HELL00") BEGIN IF IU=2 THEN GO FINSH;
FILECONTROL(6,"XBWKFL ",TIME(-1),FINSH) END;
ON("SEND00") BEGIN OU:=1;IF NOT HDDR THEN BEGIN
WRITE(LIN,HD3,TIME(6),TIME(5).[23:12],TIME(5).[35:12],TIME(5).[11:12],
TIME(-1).[41:18],TIME(-1).[23:24]);
HDDR:=TRUE END;WRITE(TTY,HD1);GO SOURCEIN END;
ON("NOSEND") BEGIN OU:=0;WRITE(TTY,STP,"NOSEND");GO TO SOURCEIN END;
ON("TTY000") BEGIN IU:=1;WRITE(TTY,STP,"SETTTY");GO TO SOURCE END;
ON("VDU000") BEGIN IU:=0;WRITE(TTY,STP,"SETVDU");GO TO SOURCEIN END;
ON("TIME00") BEGIN TIM:=3600|NMBR(10);WRITE(TTY,STP,"SETTIM");
GO TO SOURCEIN END;
ON("PLOP00") FILECONTROL(5,0,0,SOURCEIN);
ON("WHATSO") BEGIN WRITE(TTY,F9);IF IO[0]=0 THEN
WRITE(TTY,F10,MS,SSEQ[MS]) ELSE
WRITE(TTY,F11,IO[0].[41:36],MS,SSEQ[MS]);
GO SOURCEIN END;
% ILLEGAL COMMAND
WRITE(TTY,WHT," "&CHA[35:35:6|DELTA(CPR,APR)]);GO SOURCEIN END;
COMMENT PROCESS SOURCE STATEMENT;
OBJECT:=FALSE;DANGER:=TRUE;
COMMENT DELETE STATEMENT;
ON("%") BEGIN CHA:=A;FOR A:=1 STEP 1 UNTIL MS DO
ON(SSEQ[A]) BEGIN MS:=MS-1;FOR B:=A STEP 1 UNTIL MS DO
BEGIN SSEQ[B]:=SSEQ[B+1];WRITE(PROG[B,*],10,PROG[B+1,*]) END END;
GO TO SOURCEIN END;
CHA:=A;APR:=APR-1;
COMMENT ADD NEW LAST STATEMENT;
IF CHA GTR C THEN BEGIN CS:=MS;MS:=A:=MS+1;
IF MS GTR 200 THEN GO TOOLONG;
GO TO COPY END;
COMMENT REPLACE EARLIER STATEMENT;
FOR A:=1 STEP 1 UNTIL MS DO ON(SSEQ[A]) GO TO COPY
ELSE IF CHA LSS SSEQ[A] THEN BEGIN MS:=MS+1;
COMMENT INSERT STATEMENT;
IF MS GTR 200 THEN GO TO TOOLONG;
FOR B:=MS STEP -1 UNTIL A+1 DO
BEGIN SSEQ[B]:=SSEQ[B-1];WRITE(PROG[B,*],10,PROG[B-1,*]) END;
GO TO COPY END;
COPY: PROG[A,11]:=SSEQ[A]:=CHA;
REPLACE BPR:CPR:=POINTER(PROG[A,2]) BY " " FOR 1;
B:=DELTA(APR,PINB+80);IF B>71 THEN B:=71;
REPLACE BPR:BPR BY APR FOR B WHILE NEQ "!";
REPLACE BPR BY " " FOR 72-DELTA(CPR,BPR);GO SOURCEIN END SOURCEIN;
INER: WRITE(TTY,INTR);GO TO SOURCEIN;
TOOLONG: WRITE(TTY,LNGPRG,SSEQ[CS]);GO TO SOURCEIN;
PER: WRITE(TTY,F12);GO SOURCEIN;
COMMENT----------------------------------------------------------
-------------------- END SOURCEIN ---------------------------
------------------------------------------------------------------
----------- COMPILE: SEARCH FOR SYNTAX ERRORS ---------
----------- AND MAKE PSEUDO-OBJECT CODE ---------
--------------------------------------------------------------------;
COMMENT
SYNTAX ERROR MESSAGES: OUTPUT AFTER "RUN"
WITH NEW FAULTY PROGRAM
ARITH MISSING OPERATOR OR OPERAND IN ARITHMETIC
EXPRESSION (SHOULD NOT OCCUR)
FILES PROGRAM CAN HAVE ONLY ONE INPUT AND ONE OUTPUT
FILE
IL GOSB THIS STATEMENT HAS BEEN ILLEGALLY REFERENCED
BY A GOSUB STATEMENT (IT IS IN A FOR LOOP)
IL RELN AN ILLEGAL RELATION OF FORM X?? HAS BEEN
FOUND IN AN IF STATEMENT
ILL ARR ARRAY NAME EXPECTED BUT CHARACTER IS NOT
A LETTER
ILL ASN AN ASSIGNMENT IS ATTEMPTED BUT LEFT HAND SIDE
IS NOT A VARIABLE
ILL FN THE NAME OF A DEFINED FUNCTION MUST BE OF FORM
FN LETTER. PARAMETER(S) MUST BE SUPPLIED.
ILL FOR A FOR STATENENT IS ALREADY IN OPERATION
FOR THIS VARIABLE
ILL NEX NEXT MUST REFER TO AN UNSUBSCRIPTED REAL VBLE
ILL NUM A PRIMARY IS MISSING OR ILLEGAL
ILL STR A STRING PRIMARY HAS BEEN ENCOUNTERED IN
A REAL EXPRESSION
IL STMT ILLEGAL STATEMENT
INV IF STRINGS CAN ONLY BE COMPARED FOR EQUALITY
OR INEQUALITY
INV PAR A FORMAL PARAMETER IN A DEF STATEMENT
MUST BE A VARIABLE
INV VAR A PRIMARY IS MISSING OR ILLEGAL. IN A READ
STATEMENT EVERY EXPRESSION MUST CONSIST OF
A SINGLE VARIABLE PRIMARY.
IN+OUT? A FILE IS BEING USED FOR INPUT AND OUTPUT
LONGSTR A STRING CONTAINS MORE THAN 14 CHARACTERS
IN A STATEMENT OTHER THAN PRINT.
MISG OP AN OPERAND ESSENTIAL TO THIS STATEMENT HAS
BEEN OMITTED (END OF STATEMENT ERROR).
MISP = MISPLACED OR MISSING = IN DEF STATEMENT
MISPL - A - SIGN HAS BEEN PLACED ILLEGALLY IN AN
EXPRESSION (E.G. A*-B).
NAME PROBABLY CAUSED BY ILLEGAL FILENAME
NESTING INCORRECTLY NESTED FOR AND NEXT STATEMENTS
NO ) X MISSING PARENTHESES: X=A IN ARITH EXPRESSION
NO ( X P IN FUNCTION PARAMETER
S IN SUBSCRIPT
F IN FILE DECLARATION
NO EXPN E HAS BEEN FOUND IN A NUMBER BUT NO EXPONENT
FOLLOWS
NO FOR A NEXT STATEMENT HAS NO CORRESPONDING FOR
NOINPUT INPUT STATEMENT MUST HAVE LIST OF VARIABLES
NO NEXT A FOR STATEMENT EARLIER IN PROGRAM HAS NO NEXT
NO PARM EVERY FUNCTION MUST HAVE PARAMETER(S) IN
BRACKETS
NO PROG THERE IS NO PROGRAM TO RUN
NO RELN NO RELATION HAS BEEN FOUND IN AN IF STATEMENT
NO SEPR CONSECUTIVE ARITH EXPRESSIONS IN PRINT
STATEMENT MUST BE SEPARATED BY , OR SEMICOLON
NO TO A FOR STATEMENT MUST HAVE A FINAL VALUE
(FOR X=1 TO 10 ETC.)
NOT END THE LAST STATEMENT MUST BE AN END STATEMENT
NOTLAST THE END STATEMENT MUST BE THE LAST STATEMENT
OVERFLW A NUMBER IS TOO LARGE
QUOTES MISMATCHED STRING QUOTES
REDC AR ARRAY TWICE DIMENSIONED
REDC FN A FUNCTION HAS BEEN DEFINED MORE THAN ONCE
SAMEFIL A FILE HAS BEEN DECLARED MORE THAN ONCE
PARAMTR WRONG NUMBER OF PARAMETERS IN A FUNCTION CALL
SIMPLFY AN EXPRESSION IS NESTED TO A DEPTH OF 10 OR
MORE AND SHOULD RE BROKEN UP
SIZE AN ARRAY DIMENSION IS GREATER THAN 64 OR
(IN MAT STATEMENT) IS GREATER THAN THE DECLARED
DIMENSION OF THE ARRAY
STORAGE ARRAY STORAGE HAS BEEN EXCEEDED (700 WORDS OF
TYPE REAL, 70 OF TYPE ALPHA)
STR >63 ILLEGAL OBJECT CHARACTER (E.G. PRINT STRING
HAS >63 CHARS OR STARTS LATER THAN COL 63)
STR=STR A STRING CAN ONLY BE COMPARED WITH ANOTHER
SUBSCPT AN ARRAY REFERENCE HAS THE WRONG NUMBER OF
SUBSCRIPTS
TOO MCH PROCESSING OF THE SOURCE STATEMENT HAS NOT
USED UP ALL THE INFORMATION IN IT. (CAN BE
CAUSED BY OMISSION OF AN OPERATOR IN AN
EXPRESSION)
TYPE AN ATTEMPT HAS BEEN MADE TO USE A MAT STATEMENT
FOR A 1-DIMENSIONAL ARRAY
UNDC AR AN ARRAY HAS BEEN REFERENCED BUT NOT DECLARED
UNDC FL A FILE HAS BEEN REFERENCED BUT NOT DECLARED
UNDC FN A FUNCTION OF TYPE FN* HAS BEEN REFERENCED BUT
NOT DECLARED
UNDF GO THERE IS NO STATEMENT IN THE PROGRAM WITH THE
SEQUENCE NUMBER REFERENCED BY THIS STATEMENT
UNDSTAR A STRING ARRAY HAS BEEN REFERENCED BUT NOT
DECLARED
UNRC FN A FUNCTION NAME OR KEYWORD HAS BEEN MISSPELLED
OR MISPLACED
3 FILES NOT MORE THAN TWO FILES MAY BE DECLARED
11 FORS FOR STATEMENTS NESTED TOO DEEP
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
COMPILE:
COMMENT IN THE FOLLOWING COMMENTS,
<E> IS ANY EXPRESSION (POSSIBLY WITH =)
<L> IS ANY LETTER
<V> IS ANY VARIABLE PRIMARY
<N> IS ANY UNSIGNED INTEGER
<S> IS A STATEMENT NUMBER
<F> IS A FILENAME
ALLOWED VARIANTS ARE LISTED BELOW. THREE LETTER
ABBREVIATIONS OF INITIAL KEYWORDS ARE ALLOWED WHERE UNAMBIGUOUS.
SPACES ARE IGNORED EXCEPT INSIDE STRING QUOTES;
INTOVR:=INTVR;INDEX:=QUOTE;FLAG:=FLAGR;
MSTO:=287;MSTR:=27;INFILTOG:=OUTFILTOG:=FALSE;
FOR A:=1 STEP 1 UNTIL 26 DO STRAR[A,1]:=ARR[A,1]:=ARR[A,2]:=SUB[A]:=0;
IO[1]:=IO[2]:=FNM[2,1]:=FNM[2,2]:=FNM[3,1]:=FNM[3,2]:=AREASIZE:=0;
NDEP:=CO:=1;POB:=POINTER(OBJ[*]);
CS:=0;SY:=EQOK:=TRUE;
IF MS =0 THEN SYNT("NO PROG");
FORE:=FORC:=NCON:=0;FOR A:=1 STEP 1 UNTIL 200 DO STYP[A]:=0;
COMMENT FILES
<N> FILES <D>,..
WHERE <D> IS <F> (EXISTING FILE)
OR <F>(<N>) (FILE TO BE CREATED: N=MAX NO OF RECS)
WHERE <F> IS A CANDE FILENAME
THERE CAN ONLY BE ONE FILES STATEMENT. IT MUST BE THE FIRST STATEMENT.
THERE CAN BE AT MOST ONE INPUT FILE AND ONE OUTPUT FILE;
FIL: ACS:=CS:=CS+1;CP:=CHA:=0;CHA:=NWC;B:=LOOK(3);
IF B="REM" THEN GO FIL;IF B="FIL" THEN BEGIN CP:=LP;SKIP(2,"ES");A:=0;
RFIL: A:=A+1;IF A>3 THEN SYNT("3 FILES");
CHA:=NWC;IO[A]:=" ";BPR:=POINTER(PROG[CS,2])+CP-1;
SCAN APR:BPR FOR 6 WHILE IN ALPHA;FNM[2,A]:=B:=DELTA(BPR,APR);
REPLACE POINTER(IO[A])+1 BY BPR FOR B;FNM[1,A]:=LOOK(B);CP:=LP;
NF:=A;CHA:=NWC;ON("(") BEGIN AREASIZE:=NUMB/20+1;FNM[3,A]:=7;
IF CHA NEQ ")" THEN SYNT("NO ) ,F");CHA:=NWC END;ON(",") GO TO RFIL;
IF A=2 AND IO[1]=IO[2] THEN SYNT("SAMEFIL");IF CHA NEQ "%" THEN
SYNT("TOO MCH") END ELSE CS:=0;
IF ACS>MS THEN SYNT("NO PROG");
COMMENT DIM
<N> DIM <M>(<S>),...
<N> DIMENSION <M>(<T>),...
WHERE <M> IS <L> OR <L>$
<T> IS <N> OR <N>,<N>
DIM STATEMENTS MUST PRECEDE ALL EXECUTABLE STATEMENTS
STRING ARRAY MUST BE ONE-DIMENSIONAL.
ALL DIMENSIONS MUST BE <64.
713 WORDS REAL AND 73 STRINGS ARE AVAILABLE FOR ARRAYS ;
DIM: ACS:=CS:=CS+1;CP:=CHA:=0;CHA:=NWC;
B:=LOOK(3);IF B="REM" THEN GO DIM;
IF B="DIM" THEN BEGIN CP:=LP;SKIP(6,"ENSION");
RDIM: K:=CHCONV(NWC);IF K=0 THEN SYNT("ILL ARR");
IF NWC="$" THEN BEGIN STRAR[K,0]:=MSTR;IF NWC NEQ "(" THEN
SYNT("NO ( ,S");A:=STRAR[K,1]:=NUMB;MSTR:=MSTR+A;
IF CHA NEQ ")" THEN SYNT("NO ) ,S");IF NWC="," THEN GO TO RDIM;
GO TO DIM END; ARR[K,0]:=MSTO;IF CHA NEQ "(" THEN SYNT("NO ( ,S");
IF ARR[K,1] NEQ 0 THEN SYNT("REDC AR");
B:=ARR[K,1]:=NUMB;IF B>64 THEN SYNT(" SIZE ");
ON(",") BEGIN A:=ARR[K,2]:=NUMB;B:=B|A END;
MSTO:=MSTO+B;IF MSTO GTR 1000 THEN SYNT("STORAGE");
IF CHA NEQ ")" THEN SYNT("NO ) ,S");IF NWC="," THEN GO TO RDIM;
GO TO DIM END;IF ACS>MS THEN SYNT("NO PROG");
COMMENT PROGRAM COMPILATION BEGINS HERE ;
FOR CS:=ACS STEP 1 UNTIL MS DO BEGIN
COMMENT IF GOSUB ENTRY THEN FIX FOR LEVEL ;
EXS: IF STYP[CS] NEQ 0 THEN BEGIN IF FORC NEQ FORE THEN
SYNT("IL GOSB");FORE:=FORC:=STYP[CS] END;
COMMENT IDENTITY STATEMENT TYPE ;
NDEP:=CP:=CHA:=0;CHA:=NWC;B:=LOOK(3);EQOK:=TRUE;
FOR A:=1 STEP 1 UNTIL 18 DO IF B=KEY[A] THEN GO TO EQL;
IF B="DIM" OR B="FIL" THEN BEGIN WRITE(TTY,F6,SSEQ[CS]);
GO SOURCEIN END;
%IF B="TRA" THEN BEGIN STYP[CS]:=20;GO REM END;
%IF B="UNT" THEN BEGIN STYP[CS]:=21;GO REM END;
B:=B DIV 64;
IF B="IF" THEN BEGIN LP:=LP-1;A:=19;GO TO EQL END;
IF B="ON" THEN BEGIN LP:=LP-1;A:=20;GO TO EQL END;
LP:=0;A:=1;
EQL: CP:=LP;STYP[CS]:=A;SPOB[CS]:=CO;
IF CS=MS AND A NEQ 18 THEN SYNT("NOT END");GO TO OPN[A];
COMMENT 1 LET
<N> LET <E>
<N> <E>
WHERE E MAY BE A STRING ASSIGNMENT ;
LET: ARITH(0);GO TO INCST;
CAR: ARITH(1); GO TO INCST;
COMMENT 20 ON
<N> ON <E> GO TO <S>,... ;
ONX: ARITH(1);SKIP(3,"OTO");
RON: A:=NUMB;FOR B:=ACS STEP 1 UNTIL MS DO IF A=SSEQ[B]
THEN BEGIN PUT(B.[11:6]);PUT(B.[5:6]);
IF STYP[CS]=3 AND STYP[B]<FORC THEN STYP[B]:=FORC ELSE
COMMENT SEE FOR STATEMENT FOR THIS TRICK;
IF STYP[CS]=20 THEN BEGIN ON(58) GO RON ELSE BEGIN PUT(0);PUT(0)
END END;GO INCST END;SYNT("UNDF GO");
COMMENT 19 IF
<N> IF <X><R><E> THEN <S>
<N> IF <X><R><E> GO TO <S>
<X> IS AN EXPRESSION WITHOUT =
<R> IS ONE OF THE FOLLOWING
|EQ |GT |LT |GE |LE |NE
= > < >= <= <>
STRINGS CAN BE COMPARED ONLY FOR EQUALITY OR INEQUALITY;
IFF: EQOK:=FALSE;ARITH(0);EQOK:=TRUE;
C:=IF STRIN THEN 0 ELSE 1;
B:=0;IF CHA=30 THEN BEGIN B:=B+2;CHA:=NWC END;
IF CHA=14 THEN BEGIN B:=B+4;CHA:=NWC END;IF CHA=61 THEN B:=B+1
ELSE CP:=CP-1;IF B=0 THEN CHA:=NWC ELSE GO TO FEQ;
IF CHA NEQ "|" THEN SYNT("NO RELN");CHA:=NWC;
A:=CHA|64+NWC;FOR B:=1 STEP 1 UNTIL 6 DO IF A=KEY[B+32]
THEN GO TO FEQ;SYNT("IL RELN");
FEQ: PUT(B);ARITH(C);IF C=0 AND NOT STRIN THEN SYNT("STR=STR");
IF STRIN AND B NEQ 1 AND B NEQ 6 THEN SYNT("INV IF ");
SKIP(3,"OTO");SKIP(3,"HEN");GO TO RON;
COMMENT 2 GO TO
<N> GO TO <S> ;
GOT: SKIP(1,"0");GO TO RON;
COMMENT 3 GOSUB
<N> GOSUB <S> ;
GOS: SKIP(2,"UB");GO TO RON;
COMMENT 4 RETURN
<N> RETURN ;
RET: SKIP(3,"URN");CHA:=NWC;GO TO INCST;
COMMENT 8 FOR
<N> FOR <E> TO <E> STEP <E>
<N> FOR <E> TO <E> ;
COMMENT DURING COMPILE, FOR INFO IS STORED IN FORX AS FOLLOWS:
2 3 4
OBJPOINTER TO STORE NEXTLINE FORLINE ADDR
EACH FOR IS ASSIGNED A LEVEL (=FORC), WHICH 1S USED TO CHECK
NESTING AND DURING EXECUTION. IN SUBROUTINES FORC IS INITIALISED
TO MAX FORC OF CALLING (GOSUB) STATEMENT: THIS LEVEL 1S STORED
TEMPORARILY IN STYP. OBJECT FORM OF FOR STATEMENT IS AS FOLLOWS:
LEVEL ASSIGN FINAL INCREMENT NEXTLINE ;
FOX: FORC:=FORC+1;PUT(FORC);IF FORC>10 THEN SYNT("11 FORS");
ARITH(1);FORX[FORC,4]:=ADDR+1;IF CHA NEQ "T" THEN SYNT(" NO TO");
SKIP(1,"0");FOR A:=1 STEP 1 UNTIL FORC-1 DO IF FORX[A,4]=ADDR THEN
SYNT("ILL FOR");ARITH(1);IF CHA="S" THEN BEGIN SKIP(3,"TEP");ARITH(1)
END ELSE PUT(0);FORX[FORC,2]:=CO;PUT(0);PUT(0);FORX[FORC,3]:=CS;
GO INCST;
COMMENT 9 NEXT
<N> NEXT <V>
WHERE <V> IS A VARIABLE NAME ;
NEX: SKIP(1,"T");B:=CHCONV(NWC)-1;IF B=-1 THEN SYNT("ILL NEX");
IF NWC LSS 10 THEN BEGIN B:=11|B+CHA+1;CHA:=NWC END ELSE B:=11|B;
IF FORC=FORE THEN SYNT("NO FOR ");
IF B+1 NEQ FORX[FORC,4] THEN SYNT("NESTING");
A:=CO;CO:=FORX[FORC,2];PUT(CS.[11:6]);PUT(CS.[5:6]);
CO:=A;SPOB[CS]:=FORC+16|FORX[FORC,3];FORX[FORC,4]:=0;FORC:=FORC-1;
GO INCST;
COMMENT 11 DEF
<N> DEF FN<L>(<L>....)=<E>
FORMAL PARAMETERS MUST BE SINGLE LETTERS ;
DEF: SKIP(3,"INE");SKIP(2,"FN");K:=CHCONV(NWC);
IF K=0 OR NWC NEQ 29 THEN SYNT(" ILL FN");A:=0;PUT(K);
IF SUB[K] NEQ 0 THEN SYNT("REDC FN");
RDUM: A:=A+1;B:=11|CHCONV(NWC)-11;IF B=-11 THEN SYNT("INV PAR");
CONST[NCON+A]:=B;IF NWC=58 THEN GO RDUM;IF CHA NEQ 45 THEN SYNT
(" NO ) P");SUB[K]:=A;FOR B:=A STEP -1 UNTIL 1 DO BEGIN
PUT((C:=CONST[NCON+B]).[11:6]);PUT(C.[5:6]) END;
IF NWC NEQ "=" THEN SYNT("MISP = ");ARITH(1);SUB[K]:=A;GO TO INCST;
COMMENT 6 READ
<N> READ <V>,... ;
REA: SKIP(1,"D");
RREA: ARITH(0);IF NOT VAR THEN SYNT("INV VAR");
ON(58) GO TO RREA;PUT(0);GO TO INCST;
COMMENT 5 INPUT
<N> INPUT <V>,...
<N> INPUT FILE <F>,<V>,...
WHERE <F> IS THE FILENAME;
INP: SKIP(2,"UT");CFN;GO TO RREA;
COMMENT 13 RANDOMISE
<N> RANDOMISE
<N> RANDOMIZE ;
RAN: SKIP(6,"DOMISE");SKIP(6,"DOMIZE");CHA:=NWC;GO TO INCST;
COMMENT 15 RESTORE
<N> RESTORE
<N> RESTORE FILE <F>
WHERE <F> IS THE INPUT FILE ;
RES: SKIP(4,"TORE");CFN; GO TO INCST;
COMMENT 7 PRINT
<N> PRINT <P>
<N> PRINT FILE <F>,<Q>,...
WHERE <F> IS A FILENAME
WHERE <P> IS A NUMBER OF ELEMENTS OF FORM
"<Z>" 4
<E>, 2 OR 6, 1
<E>; COMMENT 2 OR 6
, 1 (1,5 IF TRAILS)
; COMMENT 5 IF TRAILS
TAB(<E>) 3
WHERE <Z> IS ANY STRING
WHERE <Q> IS "<Z>" OR <E> ;
PRI: SKIP(2,"NT");CFN;CHA:=NWC;AA:=FALSE;
RPRI: ON("%") BEGIN PUT(0);GO TO INCST END;
ON(58) BEGIN PUT(1);AA:=FALSE;
IF NWC="%" THEN BEGIN PUT(5); GO TO INCST END
ELSE GO TO RPRI END;
ON(";" OR CHA=":") BEGIN AA:=FALSE;IF NWC="%" THEN BEGIN PUT(5);
GO INCST END;GO TO RPRI END;
ON(63) BEGIN AA:=FALSE;PUT(4);PUT(CP);CPR:=POINTER(PROG[CS,2])+CP;
SCAN APR:CPR UNTIL=63;B:=DELTA(CPR,APR);PUT(B);
CP:=CP+B+1;CHA:=NWC;GO TO RPRI END;
IF LOOK(4)="TAB(" THEN BEGIN AA:=FALSE;PUT(3);CP:=LP;ARITH(1);
IF CHA NEQ 45 THEN SYNT("NO ) P");CHA:=NWC;GO TO RPRI END;
CP:=CP-1;IF AA THEN SYNT("NO SEPR");AA:=TRUE;
B:=CO;PUT(2);ARITH(0);IF STRIN THEN
REPLACE POB+B BY "6" FOR 1;GO TO RPRI;
COMMENT 14 PAGE
<N> PAGE ;
PAG: SKIP(1,"E");CHA:=NWC;GO TO INCST;
COMMENT 10 MAT
<N> MAT READ <L> 1
<N> MAT READ <L>(<N>,<N>) 1
<N> MAT PRINT <L> 2
<N> MAT PRINT <L>(<N>,<N>) 2
<N> MAT LET <L>=(<E>)*<L> 4
<N> MAT <L>=(<E>)*<L> 4
<N> MAT LET <L>=<M> 3
<N> MAT <L>=<M> 3
WHERE <M> IS AS DESCRIBED IN EXECUTE(PROCEDURE MATOP) ;
MAT: CHA:=NWC;A:=LOOK(4);IF A="READ" THEN BEGIN PUT(1);CP:=LP;
GO TO IOMT END;IF A="PRIN" THEN BEGIN PUT(2);CP:=LP;SKIP(1,"T");
GO TO IOMT END;CP:=CP-1;SKIP(3,"LET");A:=CP;B:=CHMAT(NWC);CHA:=NWC;
IF NWC=29 THEN BEGIN PUT(4);PUT(B);ARITH(1);CHA:=NWC;PUT(CHMAT(NWC));
END ELSE BEGIN PUT(3);PUT(A) END;GO TO REM;
IOMT: K:=CHMAT(NWC);PUT(K);IF NWC=29 THEN BEGIN
FOR B:=1,2 DO BEGIN A:=NUMB;IF A LSS 0 OR A GTR ARR[K,B] THEN
SYNT(" SIZE");PUT(A) END;CHA:=NWC;
END ELSE BEGIN PUT(ARR[K,1]);PUT(ARR[K,2]) END;
PUT(ON(";") 1 ELSE 0);ON(";") CHA:=NWC;GO TO INCST;
COMMENT 12 DATA
<N> DATA <E>,... ;
DAT: SKIP(1,"A");
RDAT: ARITH(0);ON(58) GO TO RDAT;PUT(0);GO INCST;
COMMENT 17 STOP
<N> STOP
18 END
<N> END ;
ENX: IF CS NEQ MS AND A=18 THEN SYNT("NOTLAST");CHA:=NWC;
IF A=17 THEN CHA:=NWC;
INCST: IF CHA NEQ "%" THEN SYNT("TOO MCH");
COMMENT 16 REM
<N> REM <Z>
WHERE <Z> IS ANYTHING ;
REM:ERR: END;
% SORT OUT FILES IF 2 TO BE USED
CS:=MS;IF NF=2 AND FNM[3,1]=FNM[3,2] THEN SYNT(" FILES ");
IF FNM[3,1]=7 THEN BEGIN IO[3]:=IO[1];IO[1]:=IO[2];
IO[2]:=IO[3] END;
IF NOT SY THEN BEGIN WRITE(TTY,STP,"ERRORS");GO TO SOURCEIN END;
OBJECT:=TRUE;GO TO EXECUTE;
INTVR: SYNT("OVERFLW"); QUOTE: SYNT(" QUOTES");
FLAGR: SYNT("NAME ");
COMMENT----------------------------------------------------------------
-------------- END COMPILE ------------------------
------------------------------------------------------------------------
-------------- EXECUTE: EXECUTION OF --------------------
-------------- USERS PROGRAM --------------------
-----------------------------------------------------------------------;
EXECUTE: BEGIN
FILE IN FIL1 DISK " "(2,10,300);
FILE OUT FIL2 DISK[20:AREASIZE] " "(2,10,300,SAVE 7);
INTEGER ARRAY SVE[1:10], % HOLDS GOSUB CALLS
FUNC[1:26], % DEFINES
STRGS[-1:100,0:2], % STRINGS
IOB[1:14], % I/O PSEUDOBUFFER
IOF[1:10], % "
ADR[0:20]; % ADDRESS STCK FOR EVAL
ARRAY STORE[0:1000], % HOLDS VARIABLE VALUES ETC
STK[0:20]; % VALUE STACK FOR EVAL
INTEGER XRND, % PSEUDO-RANDOM NUMBER INDEX
CO, % CURRENT POSITION IN OBJ[*]
RDAT, % DATA STATEMENT
NGOT, % GO COUNTER
SLVE, % GOSUB COUNTER
RDTP, % POSITION IN DATA STATEMENT
MSTO, % TOP OF STORE[*]
MSTR, % TOP OF STRGS[*, ]
IR, % INPUT FILE SEQUENCE NO
NR, % OUTPUT FILE COUNTER
RT, % RUN TERMINATION TIME
MF, % FILE (0=TTY,OTHERWISE DISK)
STCK, % STACK POINTER FOR EVAL
A,B,C,D,I,J,K,L,U,V,W,X,Y,Z,AS;
REAL R,S,T; % HASH
POINTER PIOB, % CURRENT POSITION IN IOB[*]
POUB, % INITIAL
PBR,IPR;
LABEL INCST;
% TRACE PACKAGE
%FORMAT T1(I6,X2,A3,X5,"VALUE ASSIGNED= "U),T2(I6,X2,A3,X5," TO STMT "
% ,I6),T3(I6,X2,A3);
BOOLEAN TRACEON,TLIN;%POINTER ITR;
%PROCEDURE DSTR(A);VALUE A;INTEGER A;
%BEGIN WRITE(IOF[*],T3,SSEQ[CS],IF TLIN THEN KEY[STYP[CS]] ELSE " ");
%REPLACE ITR:POINTER(IOF[*])+14 BY "STRING ASSIGNED=";REPLACE ITR:ITR
%BY """ FOR 1;REPLACE ITR:ITR BY POINTER(STRGS[A,1]) FOR STRGS[A,0];
%REPLACE ITR BY """ FOR 1;WRITE(FL[OU],9,IOF[*]);TLIN:=FALSE END;
DEFINE TR0(TR01,TR02)=#,%IF TR01 THEN BEGIN WRITE(FL[OU],TR02,SSEQ[CS],
% IF TLIN THEN KEY[STYP[CS]] ELSE " "#,
TR1(TR11)=#, %=TR0(TRACEON,T1),TR11);TLIN:=FALSE END#,
TR2(TR21)=#, %=TR0(TRACEON,T2),SSEQ[TR21]);TLIN:=FALSE END#,
TR3 =#, %=TR0(TLIN,T3));TLIN:=FALSE END#,
TR4(TR41)=#; %=IF TRACEON THEN DSTR(TR41)#;
% PROCEDURES FOR EXECUTE:
COMMENT
--- GET GETS NEXT CHARACTER FROM OBJ ;
DEFINE GET=0&OBJ[CO.[46:44]][5:47-CO.[2:3]|6:6];CO:=CO+1;
IF CO.[2:3]=0 THEN CO:=CO+1#;
COMMENT
--- ERROR DEALS WITH EXECUTION TIME ERRORS;
PROCEDURE ERROR(A);VALUE A;INTEGER A;
BEGIN SWITCH FORMAT ERR:=("ERR0",I6), % SHOULD NOT OCCUR.. %0
("SUBSCRIPT OUT OF BOUNDS AT LINE ",I6), %1
("LOG OF NEGATIVE OR ZERO NUMBER AT LINE ",I6), %2
("SQR OF NEGATIVE NUMBER AT LINE ",I6), %3
("UNDEFINED FUNCTION AT LINE ",I6), %4
("INPUT STATEMENT ATTEMPTED IN BATCH MODE AT LINE",I6),
("GO TO UNDEFINED STATEMENT NUMBER AT LINE ",I6), %6
("RETURN WITHOUT GOSUB AT LINE ",I6), %7
("ARGUMENT FOR SIN,COS,TAN OR EXP EXCEEDS 158 AT LINE",I6), %8
("INCREMENT UNDEFINED OR ZERO AT LINE ",I6), %9
("NEXT WITHOUT FOR AT LINE ",I6), %10
("STORAGE EXCEEDED AT LINE ",I6), %11
("INTEGER OVERFLOW AT LINE ",I6), %12
("INVALID ADDRESS AT LINE ",I6), %13
("DIVIDE BY ZERO AT LINE ",I6), %14
("ILLEGAL EXPONENTIATION AT LINE ",I6), %15
("FLOATING-POINT OVERFLOW AT LINE ",I6), %16
("GOSUBS NESTED TOO DEEP (MORE THAN 10) AT LINE ",I6), %17
("ILLEGAL EXPONENT ON INPUT AT LINE ",I6), %18
("MISPLACED STRING IN INPUT AT LINE ",I6), %19
("INPUT STRING TOO LONG AT LINE ",I6), %20
("OUT OF DATA AT LINE ",I6),("ERR22",I6), % ERR22 SHOULDNT OCCUR 21,22
("ILLEGAL MATRIX OPERATION AT LINE ",I6), %23
("INVERSE OF ILL-CONDITIONED MATRIX AT LINE ",I6), %24
("INSUFFICIENT SPARE STORAGE FOR MAT OP AT LINE ",I6), %25
("ILLEGAL FILE OPERATION AT LINE ",I6), %26
("INPUT FILE NOT ON DISK AT LINE",I6), %27
("INPUT FILE - INVALID USER AT LINE",I6), %28
("INPUT FILE IS NON-STANDARD AT LINE",I6), %29
("OUTPUT FILE - DUPLICATE NAME AT LINE",I6); %30
COMMENT LAST MESSAGE HERE IS NO. 30 ;
FORMAT DUR("THE FOLLOWING LINE WAS AWAITING OUTPUT:"),
FILAT(A6," FILE SEQUENCE NO.",I8);
WRITE(TTY,ERR[A],SSEQ[CS]);
IF INFILTOG THEN WRITE(TTY,FILAT," INPUT",IR);
IF OUTFILTOG THEN WRITE(TTY,FILAT,"OUTPUT",NR);
IF DELTA(POUB,PIOB) GTR 0 THEN BEGIN WRITE(TTY,DUR);
WRITE(TTY,9,IOB[*]) END;
LOCK(FIL1);LOCK(FIL2);GO TO STOP END;
COMMENT --- EVAL EVALUATES ARITHMETIC EXPRESSION
(REVERSE POLISH DECODER) ;
REAL PROCEDURE EVAL;
BEGIN
LABEL EQ,DONE,EXPON,RPT,SS,S,NUM,VR,AR,SF,UF,AD,SU,MU,DI,EX,FIN,
INM,STRGA,STRGC,STRGV;
SWITCH TYP:=FIN,NUM,VR,AR,UF,SF,FIN,EQ,INM,AD,SU,MU,DI,EX,STRGV,
STRGA,STRGC;
DEFINE TOP=STK[STCK];STCK:=STCK-1#;
DEFINE STACK(STACK1)=STCK:=STCK+1;STK[STCK]:=STACK1;GO TO SS#;
COMMENT ADDR RETURNS RESULT ADDRESS (IN STORE IF REAL, STRGS
IF STRING). INTERMEDIATE RESULTS AND ADDRESSES ARE STACKED
IN STK AND ADR RESECTIVELY. ;
STRIN:=FALSE;STCK:=0;
SS: ADR[STCK]:=ADDR;CHA:=GET;GO TO TYP[CHA+1];
NUM: A:=GET;A:=A|64+GET;STACK(CONST[A]);
STRGV: ADDR:=GET;STRIN:=TRUE;STACK(0);
STRGA: K:=GET;A:=TOP;IF A LEQ 0 OR A GTR STRAR[K,1]
THEN ERROR(1);ADDR:=STRAR[K,0]+A;STRIN:=TRUE;STACK(0);
STRGC: A:=GET;K:=GET;REPLACE POINTER(STRGS[0,1])BY POINTER
(PROG[CS,2])+K FOR A;STRGS[0,0]:=A;STRIN:=TRUE;ADDR:=0;STACK(0);
INM: STACK(0);
VR: K:=GET;K:=K-1;ADDR:=11|K+GET;STACK(STORE[ADDR]);
AR: K:=GET;A:=B:=TOP;IF ARR[K,2] NEQ 0 THEN BEGIN
A:=TOP;IF B LEQ 0 OR B GTR ARR[K,2] THEN ERROR(1) END;
IF A LEQ 0 OR A GTR ARR[K,1] THEN ERROR(1);
ADDR:=ARR[K,0]+(A-1)|ARR[K,2]+B-1;STACK(STORE[ADDR]);
SF:
BEGIN LABEL SQR,SIF,COF,TAF,ATF,EXF,LOF,ABF,ENF,FNQ,DC,
FIX,SGN,RND;
SWITCH SFUN:=SIF,COF,TAF,ATF,EXF,LOF,ABF,ENF,SQR,FIX,SGN,RND;
DEFINE TEST=IF ABS(R)>158 THEN ERROR(8)#;
A:=GET;R:=TOP;GO TO SFUN[A-18];
SIF: TEST;R:=SIN(R);GO TO DC;
COF: TEST;R:=COS(R); GO TO DC;
TAF: TEST;R:=SIN(R)/COS(R); GO TO DC;
ATF: R:=ARCTAN(R); GO TO DC;
EXF: TEST;R:=EXP(R); GO TO DC;
LOF: IF R LEQ 0 THEN ERROR(2);R:=LN(R); GO TO DC;
ABF: R:=ABS(R); GO TO DC;
SQR: IF R LSS 0 THEN ERROR(3);R:=R*.5; GO TO DC;
ENF: R:=ENTIER(R);GO TO DC;
FIX: R:=ENTIER(R);IF R LSS 0 THEN R:=R+1;GO TO DC;
SGN: R:=IF R LSS 0 THEN -1 ELSE IF R GTR 0 THEN 1 ELSE 0;
GO TO DC;
RND: XRND:=XRND|2899;XRND:=XRND.[23:23];
R:=XRND|2*(-23);GO TO DC;
DC: STACK(R) END;
COMMENT USER FUNCTIONS SECTION ;
UF: BEGIN INTEGER AS,SVSK,SVADDR;
ARRAY DUM[1:20,1:4],SVSTK,SVADR[0:20];
K:=GET;AS:=CS;CS:=FUNC[K];IF CS=0 THEN BEGIN CS:=AS;ERROR(4) END;
B:=CO;CO:=SPOB[CS];C:=GET;FOR A:=1 STEP 1 UNTIL SUB[K] DO BEGIN
COMMENT SAVE VALUES OF FORMAL PARAMETERS AND STORE ACTUALS;
R:=TOP;C:=GET;C:=64|C+GET;DUM[A,1]:=C;DUM[A,2]:=STORE[C];STORE[C]:=R
END;SVADDR:=ADDR;SVSK:=STCK;
FOR A:=0 STEP 1 UNTIL 20 DO BEGIN SVSTK[A]:=STK[A];SVADR[A]:=ADR[A]
END;
COMMENT NOW EVALUATE FUNCTION ANO RESTORE FORMAL PARAMETERS;
R:=EVAL;FOR A:=1 STEP 1 UNTIL SUB[K] DO STORE[DUM[A,1]]:=DUM[A,2];
FOR A:=0 STEP 1 UNTIL 20 DO BEGIN STK[A]:=SVSTK[A];ADR[A]:=SVADR[A]
END;ADDR:=SVADDR;STCK:=SVSK;
CS:=AS;CO:=B;STACK(R) END;
EQ: IF STRIN THEN BEGIN ADDR:=A:=ADR[STCK];STCK:=STCK-1;
B:=ADR[STCK];REPLACE POINTER(STRGS[B,*]) BY POINTER(STRGS[A,*])
FOR 3 WORDS;TR4(B);GO TO SS END;R:=TOP;ADDR:=ADR[STCK];
STORE[ADDR]:=STK[STCK]:=R;TR1(R);GO TO SS;
AD: R:=TOP;R:=R+TOP;STACK(R);
SU: R:=TOP;R:=-R+TOP;STACK(R);
MU: R:=TOP;R:=R|TOP;STACK(R);
DI: R:=TOP;R:=1/R|TOP;STACK(R);
EX: T:=TOP;R:=TOP;IF T NEQ ENTIER(T) AND R LSS 0
THEN ERROR(15);STACK(R*T);
FIN: EVAL:=STK[1] END;
COMMENT
--- OUTP OUTPUTS CONTENTS OF PSEUDO-BUFFER ;
PROCEDURE OUTP;
BEGIN IF MF>0 THEN ERROR(26);TR3;
WRITE(FL[OU],14,IOB[*]);REPLACE PIOB:=POUB:=POINTER(IOB[*]) BY
" " FOR 112;IF OU=1 THEN PIOB:=POUB:=POUB+20 END;
COMMENT
--- MORE FALSE IF END OF STATEMENT ;
BOOLEAN PROCEDURE MORE;
BEGIN INTEGER A,B;A:=CO;B:=GET;MORE:=B NEQ 0;CO:=A END;
COMMENT
--- OUTNUM PLACES NUMBER IN PSEUDO-BUFFER ;
PROCEDURE OUTNUM(A,F);VALUE A,F;REAL A;INTEGER F;
BEGIN CHA:=0;CP:=CP-1;WRITE(IOBE[*],NUM[F],A); % CARE:
SCAN APR:CPR FOR 16 UNTIL ="@";
IF DELTA(CPR,APR) NEQ 16 THEN REPLACE APR BY "E" FOR 1;
IF DELTA(POUB,PIOB) GTR 60+F|4 THEN OUTP;
REPLACE PIOB:PIOB BY POINTER(IOBE[1]) FOR 14 UNTIL=48;
REPLACE PIOB:PIOB BY " " FOR 1 END;
COMMENT
--- QUO PLACES " IN OUTPUT BUFFER ;
DEFINE QUO=IF MF>0 THEN REPLACE PIOB:PIOB BY """#;
COMMENT
--- MATOP PROCESSES MOST MAT STATEMENTS ;
PROCEDURE MATOP;
BEGIN INTEGER U,V,W,X,Y,Z,I,J;
COMMENT MAT STATEMENTS CONCERNED HAVE FORMAT
<N> MAT LET <L>=<M>
<N> MAT <L>=<M>
THE SECOND CHARACTER IN <M> IS USED TO IDENTIFY ACTION TAKEN
THIS CAN BE * + - E O D R N %
(RECALL % IS END-STATEMENT CHARACTER) ;
LABEL DONE,ADSU,EQM,CONS,EX,EY;REAL PIVOT,AI;
INTEGER ARRAY IR[1:72];REAL ARRAY TEM[1:72];
DEFINE AA(AA1,AA2)=STORE[ARR[K,0]+(AA1-1)|U+AA2-1]#;
CP:=GET;CHA:=0;K:=CHCONV(NCH);IF K=0 THEN ERROR(23);
IF NCH NEQ 61 THEN ERROR(23);A:=CHCONV(NCH);CHA:=NCH;
COMMENT SWITCH OCCURS HERE
* MATRIX MULTIPLICATION
<M> IS <L>*<L>
HASH STORAGE IS USED TO AVOID TROUBLE WITH A=A*B ETC ;
ON("*") BEGIN B:=CHCONV(NCH);
U:=ARR[K,1]-1;V:=ARR[K,2]-1;W:=ARR[A,1]-1;X:=ARR[A,2]-1;
Y:=ARR[B,1]-1;Z:=ARR[B,2]-1;IF U NEQ W OR V NEQ Z OR X NEQ Y
THEN ERROR(23);IF MSTO+(U+1)|(V+1) GTR 1000 THEN ERROR(25);
FOR W:=0 STEP 1 UNTIL U DO FOR Z:=0 STEP 1 UNTIL V DO BEGIN R:=0;
FOR Y:=0 STEP 1 UNTIL X DO R:=R+STORE[ARR[A,0]+X|W+W+Y]|
STORE[ARR[B,0]+Y|V+Y+Z];STORE[MSTO+W|V+W+Z]:=R END;
FOR W:=0 STEP 1 UNTIL U DO FOR Z:=0 STEP 1 UNTIL V DO
STORE[ARR[K,0]+W|V+W+Z]:=STORE[MSTO+W|V+W+Z];
GO TO DONE END;
COMMENT + MATRIX ADDITION
<M> IS <L>+<L> ;
ON("+") BEGIN Z:=1;GO TO ADSU END;
COMMENT - MATRIX SUBTRACTION
<M> IS <L>-<L> ;
ON("-") BEGIN Z:=-1;GO TO ADSU END;
COMMENT O ALL ONES
<M> IS CON ;
ON("O") BEGIN Z:=Y:=1;GO TO CONS END;
COMMENT D IDENTITY MATRIX
<M> IS IDN ;
ON("D") BEGIN IF ARR[K,1] NEQ ARR[K,2] THEN ERROR(23);Z:=1;Y:=0;
COMMENT E ZERO MATRIX
<M> IS ZER ;
GO TO CONS END; ON("E") BEGIN Z:=Y:=0;GO TO CONS END;
COMMENT R TRANSPOSITION
<M> IS TRN(<L>)
HASH STORAGE USED TO AVOID TROUBLE WITH A=TRN(A) ;
ON("R") BEGIN CHA:=NCH;CHA:=NCH;A:=CHCONV(NCH);IF A=0 THEN ERROR(23);
U:=ARR[K,1]-1;V:=ARR[K,2]-1;W:=ARR[A,1]-1;X:=ARR[A,2]-1;
IF U NEQ X OR V NEQ W THEN ERROR(23);
IF MSTO+(U+1)|(V+1) GTR 1000 THEN ERROR(25);
FOR U:=0 STEP 1 UNTIL X DO FOR V:=0 STEP 1 UNTIL W DO
STORE[MSTO+U|W+U+V]:=STORE[ARR[A,0]+V|X+V+U];
FOR U:=0 STEP 1 UNTIL X DO FOR V:=0 STEP 1 UNTIL W DO
STORE[ARR[K,0]+U|W+U+V]:=STORE[MSTO+U|W+U+V];
GO TO DONE END;
COMMENT N INVERSION
<M> IS INV(<L>) ;
ON("N") BEGIN CHA:=NCH;CHA:=NCH;A:=CHCONV(NCH);
U:=ARR[K,1];IF U NEQ ARR[K,2] OR U NEQ ARR[A,1] OR U NEQ ARR[A,2]
THEN ERROR(23);FOR I:=0 STEP 1 UNTIL U-1 DO FOR J:=0 STEP 1 UNTIL U-1
DO AA(I+1,J+1):=STORE[ARR[A,0]+I|U+J];
FOR V:=1 STEP 1 UNTIL U DO BEGIN PIVOT:=0;
FOR I:=1 STEP 1 UNTIL U DO BEGIN IF V NEQ 1 THEN BEGIN
FOR X:=1 STEP 1 UNTIL V-1 DO IF I=IR[X] THEN GO TO EX END;
IF ABS(AA(I,V))GTR ABS(PIVOT) THEN BEGIN PIVOT:=AA(I,V);Y:=IR[V]:=I
END;
EX: END;IF ABS(PIVOT) LSS .0001 THEN ERROR(24);
FOR J:=1 STEP 1 UNTIL U DO AA(Y,J):=AA(Y,J)/PIVOT;AA(Y,V):=1/PIVOT;
FOR I:=1 STEP 1 UNTIL U DO IF I NEQ Y THEN BEGIN AI:=AA(I,V);
AA(I,V):=-AI/PIVOT;FOR J:=1 STEP 1 UNTIL U DO IF J NEQ V THEN
AA(I,J):=AA(I,J)-AI|AA(Y,J) END END;
FOR I:=1 STEP 1 UNTIL U DO
BEGIN FOR J:=1 STEP 1 UNTIL U DO TEM[J]:=AA(I,J);
FOR J:=1 STEP 1 UNTIL U DO AA(I,IR[J]):=TEM[J] END;
FOR J:=1 STEP 1 UNTIL U DO BEGIN FOR I:=1 STEP 1 UNTIL U DO
TEM[I]:=AA(IR[I],J);FOR I:=1 STEP 1 UNTIL U DO AA(I,J):=TEM[I]
END;GO TO DONE END;
% EQUALITY
COMMENT <M> IS <L> ;
ON("%") BEGIN B:=A;Z:=0; GO TO EQM END;
ERROR(23);
ADSU: B:=CHCONV(NCH);IF B=0 THEN ERROR(23);
IF ARR[A,1] NEQ ARR[B,1] OR ARR[A,2] NEQ ARR[A,2] THEN ERROR(23);
EQM: U:=ARR[K,1];V:=ARR[K,2];IF U NEQ ARR[A,1]
OR V NEQ ARR[A,2] THEN ERROR(23);
FOR I:=0 STEP 1 UNTIL U-1 DO FOR J:=0 STEP 1 UNTIL V-1 DO
AA(I+1,J+1):=STORE[ARR[A,0]+I|U+J]+Z|STORE[ARR[B,0]+I|U+J];
GO TO DONE;
CONS: U:=ARR[K,I];FOR I:=1 STEP 1 UNTIL ARR[K,1] DO
FOR J:=1 STEP 1 UNTIL ARR[K,2] DO AA(I,J):=IF I=J THEN Z ELSE Y;
DONE: GO TO INCST END;
LABEL RPT,REM,DAT,EXS,LET,RLET,ONX,
INP,PRI,RPRI,XPRI,MAT,ENX,RREA,XREA,QDAT,FREA,RES,NDAT,
STRV,FOL,INTVR,INDEXR,DZER,EXPVR,
NM,TAB,COM,STR,EPRI,OUD,OUF,
IFF,GOT,GOX,GOS,RET,FOX,NEX,FD,DEF,REA,EREA,RAN,PAG;
SWITCH OPN:=LET,GOT,GOS,RET,INP,REA,EPRI,FOX,NEX,MAT,
DEF,DAT,RAN,PAG,RES,REM,ENX,ENX,IFF,ONX;
SWITCH TYP:=XPRI,COM,NM,TAB,STR,INCST,STRV;
COMMENT----------------------------------------------------------------
----------------- EXECUTE BEGINS HERE --------------------
-----------------------------------------------------------------------;
INTOVR:=INTVR;EXPOVR:=EXPVR;ZERO:=DZER;INDEX:=INDEXR;
WRITE(TTY,MESS);RT:=TIME(2)+TIM;IF OU=1 THEN WRITE(TTY,DVO);
WRITE(FL[OU],SPC);NR:=IR:=RDAT:=RDTP:=NGOT:=0;TRACEON:=TLIN:=FALSE;
FORC:=SLVE:=0;XRND:=101;CS:=ACS-1;
POUB:=PIOB:=POINTER(IOB[*])+20|OU;
REPLACE POINTER(IOB[*]) BY " " FOR 112;
% GET FILES IF NEEDED:
IF INFILTOG THEN BEGIN FILL FIL1 WITH IO[1],TIME(-1);
SEARCH(FIL1,ANSA[*]);IF ANSA[0] LEQ 0 THEN ERROR(28+ANSA[0]);
IF ANSA[3] NEQ 10 OR ANSA[4] NEQ 300 THEN ERROR(29) END;
IF OUTFILTOG THEN BEGIN FILL FIL2 WITH IO[2],TIME(-1);
SEARCH(FIL2,ANSA[*]);IF ANSA[0] NEQ -1 THEN BEGIN
WRITE(TTY,F13,IO[2].[41:36]);
IF IU=2 THEN U:=0 ELSE
READ(TTY,REP,U);IF U NEQ "YES" THEN ERROR(30) END END;
COMMENT RETURN TO HERE AFTER EACH STATEMENT;
REM:DAT:INCST: TR3;CS:=CS+1;
EXS: MF:=0; % FIRST SEE IF EXCESS TIME
IF TIME(2) GTR RT THEN BEGIN WRITE(TTY,BK);GO TO ENX END;
IF STYP[CS]>19 THEN BEGIN TRACEON:=STYP[CS]=20;GO INCST END;
IF TRACEON THEN TLIN:=TRUE;
U:=STYP[CS];CO:=SPOB[CS];GO TO OPN[U]; % NOW GO TO APPROPRIATE PLACE
% LET STATEMENT
LET: R:=EVAL;GO TO INCST;
% ON STATEMENT
ONX: U:=EVAL;
FOR V:=1 STEP 1 UNTIL 2|U-2 DO BEGIN S:=GET END;GO GOT; %(STET)
% IF STATEMENT
IFF: R:=EVAL;IF STRIN THEN BEGIN
COMMENT STRING IF ;
U:=GET;
REPLACE IPR:=POINTER(STRGS[-1,*]) BY POINTER(STRGS[ADDR,*]) FOR 24;
R:=EVAL;GO IF IPR=POINTER(STRGS[ADDR,*])
FOR STRGS[-1,0]+8 EQV U=1 THEN GOT ELSE INCST END;
COMMENT REAL IF ;
U:=GET;R:=R-EVAL;
IF R GTR 0 AND U.[2:1]=1 THEN GO TO GOT ELSE
IF R LSS 0 AND U.[1:1]=1 THEN GO TO GOT ELSE
IF R = 0 AND U.[0:1]=1 THEN GO TO GOT;GO TO INCST;
% GOTO STATEMENT
GOT: U:=GET;U:=64|U+GET;IF U=0 THEN ERROR(6);
GOX: NGOT:=NGOT+1;TR2(U);
COMMENT MONITOR FOR EXCESS LOOPING;
IF NGOT=100 AND IU NEQ 2 THEN BEGIN WRITE(TTY,WRN);READ(TTY,REP,W);
IF W NEQ "YES" THEN GO TO STOP END;
CS:=U;GO EXS;
% GOSUB STATEMENT
GOS: SLVE:=SLVE+1;IF SLVE GTR 10 THEN ERROR(17);
SVE[SLVE]:=CS;GO GOT;
% RETURN STATEMENT
RET: IF SLVE=0 THEN ERROR(7);
CS:=SVE[SLVE];SLVE:=SLVE-1;GO TO INCST;
% FOR STATEMENT
FOX: FORC:=GET;R:=EVAL;
COMMENT FORX CONTROL INFO IS STORED AS FOLLOWS:
1 2 3 4
ADDR STEP FINAL FORLINE
A FOR LOOP IS EXECUTED ZERO TIMES IN THE RIGHT CIRCUMSTANCES;
V:=FORX[FORC,1]:=ADDR;S:=FORX[FORC,3]:=EVAL;
T:=FORX[FORC,2]:=IF MORE THEN EVAL ELSE 1;
W:=FORX[FORC,4]:=CS;IF T=0 THEN ERROR(9);
IF T|R LEQ T|S THEN GO INCST; % ELSE SKIP LOOP
U:=GET;U:=GET;CS:=64|U+GET;GO TO INCST;
% NEXT STATEMENT
% SPOB STORES (NEXTS LEVEL IN FORX)+16|FORLINE
NEX: U:=SPOB[CS].[3:4];V:=SPOB[CS].[41:38];
IF V NEQ FORX[U,4] THEN ERROR(10);L:=FORX[U,1];
T:=FORX[U,2];R:=STORE[L]+T;
IF T|R LEQ T|FORX[U,3] THEN BEGIN STORE[L]:=R;TR1(R);T:=FORX[U,4];
TR2(T+1);CS:=T END ELSE FORX[U,4]:=0;
GO TO INCST;
% DEFINE STATEMENT
DEF: U:=GET;FUNC[U]:=CS;GO TO INCST;
% READ STATEMENT
REA: U:=0;
COMMENT THIS SECTION IS COMPLICATED BECAUSE OF SWITCHING
OF ATTENTION FROM READ STATEMENT TO DATA STATEMENT AND BACK ETC;
RREA: R:=EVAL;L:=ADDR;U:=CS;V:=CO;
IF RDTP=0 THEN GO TO QDAT;CO:=RDTP;CS:=RDAT;
XREA: IF STRIN THEN BEGIN R:=EVAL;CS:=U;IF NOT STRIN THEN
ERROR(20);REPLACE POINTER(STRGS[L,*])BY POINTER(STRGS[ADDR,*])
FOR 3 WORDS;TR4(L) END ELSE BEGIN R:=EVAL;IF STRIN THEN ERROR(20);
STORE[L]:=R;CS:=U;TR1(R) END;RDTP:=IF MORE THEN CO ELSE 0;CO:=V;
IF MORE THEN GO TO RREA ELSE GO TO INCST;
COMMENT FIND ANOTHER DATA STATEMENT;
QDAT: FOR CS:=RDAT+1 STEP 1 UNTIL MS DO BEGIN
IF STYP[CS]=12 THEN GO TO FREA END;
CS:=U;ERROR(21);
FREA: RDAT:=CS;CO:=SPOB[CS];GO TO XREA;
% INPUT STATEMENT
% "STOP" AT START OF INPUT STREAM STOPS A RUN
INP: BEGIN LABEL RINP,EVINP,RPT,EXPON,DONE,FINP;
MF:=GET;IF MF=0 THEN BEGIN IF IU=2 THEN ERROR(5);
IF DELTA(POUB,PIOB) GTR 0 THEN BEGIN
REPLACE POINTER(IOBE[*]) BY POUB FOR 72;WRITE(TTY[STOP],9,IOBE[*]);
REPLACE PIOB:=POUB:=POINTER(IOB[*]) BY " " FOR 112;IF OU=1 THEN
PIOB:=POUB:=PIOB+20 END;READ(TTY,9,IOBE[*]);
READ(IOBE[*],REP,V);IF V="STO" THEN GO TO STOP END
ELSE BEGIN Z:=GET;Z:=64|Z+GET;READ(FIL1,10,IOBE[*])[OUD];
READ(IOBE[*],SNUM,IR) END;
REPLACE POINTER(PROG[0,2]) BY POINTER(IOBE[1]) FOR 72;X:=0;
RINP: R:=EVAL;L:=ADDR;U:=CS;CS:=0;CP:=X;CHA:=0;
IF NCH="%" THEN BEGIN IF MF=0 THEN BEGIN WRITE(TTY,MNP[IF X=0 THEN 1
ELSE 0],PROG[U,1]);CS:=U;GO TO EXS END ELSE BEGIN
READ(FIL1,9,IOBE[*])[OUD];
REPLACE POINTER(PROG[0,2]) BY POINTER(IOBE[*]) FOR 72;CP:=1 END END;
COMMENT INPUT STRING MAY OR MAY NOT HAVE "" ;
EVINP: CP:=CP-1;CHA:=NCH;IF STRIN THEN BEGIN
ON(63) SCAN APR:APR:=CPR:=POINTER(PROG[0,2])+CP FOR 15 WHILE NEQ 63
ELSE BEGIN CP:=CP-2;SCAN APR:APR:=CPR:=POINTER(PROG[0,2])+CP+1 FOR 15
WHILE IN ALPHA END;
V:=DELTA(CPR,APR);IF V>14 THEN BEGIN CS:=U;ERROR(20) END;
STRGS[L,0]:=V;REPLACE POINTER(STRGS[L,1]) BY CPR FOR V;
CP:=CP+V+1;CHA:=NCH;CS:=U;TR4(L);GO FINP END;
T:=R:=Y:=0;
COMMENT INPUT NUMBER ;
ON(44) BEGIN T:=1;CHA:=NCH END;
RPT: ON(26) BEGIN Y:=1;CHA:=NCH END;
IF CHA GEQ 10 THEN GO TO EXPON;IF Y GTR 0 THEN
BEGIN R:=R+CHA|10*(-Y);
Y:=Y+1 END ELSE R:=R|10 +CHA;CHA:=NCH; GO TO RPT;
EXPON: IF CHA NEQ 21 THEN GO TO DONE;Y:=1;CHA:=NCH;Z:=0;
ON(44)BEGIN Y:=-1;CHA:=NCH END ELSE ON(16) CHA:=NCH;
IF CHA GEQ 10 THEN BEGIN CS:=U;ERROR(18) END;Z:=CHA;CHA:=NCH;
IF CHA LSS 10 THEN BEGIN Z:=Z|10+CHA;CHA:=NCH END;
R:=R|10*(Y|Z);
DONE: IF T=1 THEN R:=-R;DELIM:=72;STORE[L]:=R;CS:=U;TR1(R);
FINP: X:=CP;IF CHA NEQ 58 AND CHA NEQ "%" THEN ERROR(19);
IF MORE THEN GO TO RINP ELSE GO TO INCST END;
% RANDOMISE STATEMENT
RAN: XRND:=(2|TIME(1)+1).[23:23];GO TO INCST;
% RESTORE STATEMENT
RES: MF:=GET;IF MF=0 THEN RDTP:=RDAT:=0 ELSE REWIND(FIL1);
GO INCST;
% PRINT STATEMENT
EPRI: MF:=GET;IF MF>0 THEN BEGIN PBR:=PIOB;
TR3;Z:=GET;Z:=64|Z+GET;
POUB:=POINTER(IOF[*]);REPLACE PIOB:=POINTER(IOF[*]) BY " " FOR 72 END;
PRI: CHA:=GET;IF MF>0 AND CHA=5 THEN ERROR(26);
GO TO TYP[CHA+1];
Z:=GET;Z:=64|X+GET;
COMMENT , IN PRINT MOVES TO NEXT 14-SPACE COLUMN.
(SEMICOLON IN MIDDLE OF PRINT IS JUST DELIMITER);
COM: IF MF>0 THEN REPLACE PIOB:PIOB BY "," ELSE BEGIN
V:=DELTA(POUB,PIOB);IF V GTR 56 THEN BEGIN
OUTP;V:=0 END ELSE V:=14-(V MOD 14);
FOR U:=1 STEP 1 UNTIL V DO REPLACE PIOB:PIOB BY " " END;
GO TO PRI;
COMMENT PLACE STRING IN PSEUDO-BUFFER ;
STR: CP:=GET;
CPR:=POINTER(PROG[CS,2])+CP;
V:=72-DELTA(POUB,PIOB);W:=GET;
IF W GTR V THEN BEGIN REPLACE PIOB:PIOB BY CPR:CPR FOR V;
OUTP;W:=W-V END;
QUO;REPLACE PIOB:PIOB BY CPR:CPR FOR W;QUO;
GO TO PRI;
COMMENT TAB OVERWRITES ON TELETYPE AND LINE-PRINTER
BUT REPLACES ON VIDEO UNIT. ;
TAB: IF MF>0 THEN ERROR(26);U:=EVAL-1;U:=U MOD 72;
IF IU+OU NEQ 0 THEN BEGIN TR3;WRITE(FL[OU][NO],9,IOB[*]);
REPLACE POUB BY " " FOR 72 END;PIOB:=POUB+U; GO TO PRI;
STRV: R:=EVAL;QUO;REPLACE PIOB:PIOB BY POINTER(STRGS[ADDR,1])
FOR STRGS[ADDR,0];QUO;GO TO PRI;
NM: OUTNUM(EVAL,0);GO TO PRI;
XPRI: IF MF>0 THEN BEGIN REPLACE PIOB BY ",";
NR:=NR+10;REPLACE POINTER(IOF[10]) BY NR FOR 8 DIGITS;
WRITE(FIL2,10,IOF[*])[OUF];PIOB:=PBR;POUB:=POINTER(IOB[*])+20|OU END
ELSE OUTP;GO TO INCST;
% PAGE STATEMENT
PAG: IF OU=1 THEN WRITE(LIN[PAGE]);GO TO INCST;
% MAT STATEMENT
% MAT 1=READ, 2=PRINT, 3=MATOP, 4=SCALAR MULTIPLE
MAT: BEGIN INTEGER E,F,G;LABEL QDAT,FREA,XREA,RREA;
L:=GET;IF L=1 THEN BEGIN E:=CS;L:=GET;U:=GET;V:=GET;
FOR W:=0 STEP 1 UNTIL U-1 DO FOR X:=0 STEP 1 UNTIL V-1 DO BEGIN
IF RDTP = 0 THEN GO TO QDAT;CO:=RDTP;CS:=RDAT;
XREA: STORE[ARR[L,0]+W|ARR[L,2]+X]:=EVAL;
RDTP:=IF MORE THEN CO ELSE 0;GO TO RREA;
QDAT: FOR CS:=RDAT + 1 STEP 1 UNTIL MS DO BEGIN IF STYP[CS]
=12 THEN GO TO FREA END;CS:=E;ERROR(21);
FREA: RDAT:=CS;CO:=SPOB[CS];GO TO XREA;
RREA: END;CS:=E;GO TO INCST END;
IF L=2 THEN BEGIN
IF DELTA(POUB,PIOB) GTR 0 THEN OUTP;
L:=GET;U:=GET;V:=GET;E:=GET;G:=14-E|7;FOR W:=0 STEP 1 UNTIL U-1 DO
BEGIN FOR X:=0 STEP 1 UNTIL V-1 DO BEGIN OUTNUM(STORE[ARR[L,0]+
W|ARR[L,2]+X],E);PIOB:=POUB+G|((DELTA(POUB,PIOB)-1) DIV G +1)
END;OUTP END;GO TO INCST END;
IF L=3 THEN MATOP;
L:=GET;R:=EVAL;W:=GET;
IF ARR[L,1] NEQ ARR[W,1] OR ARR[L,2] NEQ ARR[W,2] THEN ERROR(23);
FOR U:=0 STEP 1 UNTIL ARR[L,1]-1 DO FOR V:=0 STEP 1 UNTIL ARR[L,2]-1
DO STORE[ARR[L,0]+U|ARR[L,2]+V]:=R|STORE[ARR[W,0]+U|ARR[L,2]+V];
GO TO INCST END;
% STOP OR END STATEMENT
ENX: TR3;IF DELTA(POUB,PIOB)>0 THEN OUTP;
LOCK(FIL1);LOCK(FIL2);GO TO STOP;
OUD: IF Z=0 THEN ERROR(21);TR2(Z);CS:=Z;GO EXS;
OUF: IF Z=0 THEN ERROR(26);TR2(Z);CS:=Z;GO EXS;
INTVR: ERROR(12);INDEXR: ERROR(13);
DZER: ERROR(14);EXPVR: ERROR(16) END;
STOP: WRITE(TTY,STP,"RUN ");GO TO SOURCEIN;
COMMENT
PROGRAM WRITTEN BY MALCOLM CROWE
LANGUAGE DETAILS DECIDED BY IAN MILLER AND JOHN FURLONG
MATRIX INVERSION CORRECTED BY ARTHUR MACDIVITT ;
FINSH: END.
?END