(* ********************************************************* * * * PISTOL-Portably Implemented Stack Oriented Language * * Version 1.3 * * (C) 1982 by Ernest E. Bergmann * * Physics, Building #16 * * Lehigh Univerisity * * Bethlehem, Pa. 18015 * * * * Permission is hereby granted for all reproduction and * * distribution of this material provided this notice is * * is included. * * * ********************************************************* *) PROGRAM PISTOL(INPUT:/); (*DECEMBER 22, 1981 --FOR BEST PERFORMANCE IN PASCAL, THIS PROGRAM SHOULD BE EDITED TO MAKE FULL USE OF THE OPTIONS, USER=0,W=1,S=1,CSTEP=1,L=1,R=1 AND STRINGSMIN=-1 *) LABEL 99; CONST VERSION=13;(*10* THE VERSION NUMBER,READABLE BY USER*) USER=0;(*DISPLACEMENT FOR USER'S RAM AREA; IT SHOULD BE CHANGED TO SIMPLIFY ADDRESS CALCULATION IN ASSEMBLY CODE IMPLEMENTATIONS*) W=1;(*RAM ADDRESS INCREMENT SIZE; TYPICALLY WOULD BE 2 OR 4 FOR 8-BIT MICROS AND OTHER BYTE ADDRESSABLE MACHINES*) R=1;(*INCREMENT SIZE FOR RSTACK,HIDDEN FROM USER*) S=1;(*INCREMENT SIZE FOR (PARAMETER) STACK,HIDDEN*) STACKMIN=0;(*WHATEVER IS CONVENIENT,HIDDEN FROM USER*) MSTACKMIN=-3;(*STACKMIN-S*3*) PSTACKMAX=203;(*STACKMAX+S*3*) STACKMAX=200;(*STACKMIN+SSIZE*S*) LSTACKMIN=0;(*WHATEVER IS CONVENIENT,HIDDEN FROM USER*) L=1;(*LSTACK INCREMENT,HIDDEN FROM USER*) LSTACKMAX=30;(*LSTACKMIN+LSIZE*L*) CSTACKMIN=0;(*WHATEVER IS CONVENIENT*) CSTEP=1;(*CSTACK INCREMENT*) CSTACKMAX=30;(*CSTACKMIN+CSIZE*CSTEP*) NUMINSTR=75; RAMMIN=-57(*USER-W*57,OR LOWER,READABLE*); MAXORD=127;(*7 BIT FOR DEC-20,READABLE*) RAMMAX=8000;(*=RAMMIN+W*4000 AT LEAST,READABLE BY USER*) COMPBUF=7000;(*=RAMMAX-W*200,OR LOWER,READABLE BY USER*) SSIZE=200;(*READABLE BY USER*) RSIZE=30;(*READABLE BY USER*) RSTACKMIN=0;(*ARBITRARY,HIDDEN*) RSTACKMAX=30;(*RSTACKMIN+R*RSIZE*) LSIZE=30;(*READABLE BY USER*) CSIZE=30;(*READABLE BY USER*) (*VOCABULARY STACK IS LOCATED IN RAM*) VSIZE=8;(*VOCAB STACK,READABLE BY USER*) VBASE=1;(*=USER +W,READABLE BY USER*) STRINGSMIN=7000(*READABLE BY USER*); SYNTAXBASE=7001(*STRINGSMIN+1*); STRINGSMAX=12000;(*STRINGSMIN+ 3000..5000 INTENDED FOR EDIT AREA *) MAXLINNO=300;(*MAX # OF LINES POSSIBLE IN EDIT BUFFER, READABLE BY USER*) LINEBUF=9800;(*STRINGSMIN+2800,READABLE BY USER*) CHKLMT=20(*SIZE OF CHECK STACK,READABLE BY USER*); FALS=0; TRU=-1; (* OPCODES WHOSE VALUES ARE NOT CRITICAL; THEY MUST BE UNIQUE AND RECOGNIZEABLE BY KERNQ, AND SEPERABLE INTO PINT1 AND PINT2 *) PSEMICOLON=0; WSTORE=1; TIMES=2; PLUS=3; SUBTRACT=4; DIVMOD=5; PIF=6; WAT=7; ABRT=8; SP=9; LOAD=10; PELSE=11; WRD=12; RP=13; DROPOP=14; PUSER=15; EXEC=16; EXITOP=17; LIT=18; STRLIT=19; RPOP=20; SWP=21; TYI=22; TYO=23; RPSH=24; SEMICF=25; RAT=26; COMPME=27; COMPHERE=28; DOLLARC=29; COLON=30; SEMICOLON=31; IFOP=32; ELSEOP=33; THENOP=34; DOOP=35; LOOPOP=36; BEGINOP=37; ENDOP=38; REPET=39; PERCENT=40; PDOLLAR=41; PCOLON=42; CASAT=43; PDOOP=44; PPLOOP=45; PLLOOP=46; CAT=47; CSTORE=48; PLOOP=49; GT=50; SEMIDOL=51; KRNQ=52; (* OPCODES 53,54 NOT USED AT MOMENT *) SAT=55; FINDOP=56; LISTFIL=57; (* OPCODE 58 MOMENTARILY UNUSED *) LAT=59; OFCAS=60; CCOLON=61; SEMICC=62; NDCAS=63; POFCAS=64; PCCOL=65; PSEMICC=66; GTLIN=67; WORD=68; OPENR=69; OPENW=70; READL=71; WRITL=72; CORDMP=73; RESTOR=74; (* END OF OPCODE DECLARATIONS *) TYPE DALFA = PACKED ARRAY[1..20] OF CHAR; IMAGE= RECORD STRINGS:PACKED ARRAY[STRINGSMIN..STRINGSMAX] OF CHAR; RAM:ARRAY[RAMMIN..RAMMAX] OF INTEGER; END(*RECORD*); IMFILE=FILE OF IMAGE; VAR IMAGENAME,NAMEIN,NAMOUT,INFIL1,LISTNAME,NULLNAME:DALFA; IP:INTEGER;(*INSTRUCTION POINTER*) INSTR:INTEGER;(*INSTRUCTION CURRENTLY EXECUTED BY INTERPRET*) SAVINSTR:INTEGER(*SAVES INSTR DURING TRACING*); SAVLEVEL:INTEGER(*SAVES LEVEL DURING TRACING*); TEMP: INTEGER; EDIN,EDOUT,LDFIL1,LIST,OUTPUT:TEXT; SAVEFILE:IMFILE; NOPEN,FEOF,UNDFLO,OVFLO,SYNT,ID,REDEF,ADDR,VAL,I,DIVBY0:INTEGER; CONVERTED:BOOLEAN; C:CHAR; (* RAM[RAMMIN...]: RAM[USER-W*57]=MAXLINNO RAM[USER-W*56]=CHKLMT RAM[USER-W*55]=RAMMIN RAM[USER-W*54]=STRINGSMIN RAM[USER-W*53]=**TO BE RECYCLED** RAM[USER-W*52]=ABORT PATCH RAM[USER-W*51]=USER CONVERSION PATCH RAM[USER-W*50]=PROMPT PATCH RAM[USER-W*49]=STRINGSMAX RAM[USER-W*48]=VBASE RAM[USER-W*47]=VSIZE RAM[USER-W*46]=CSIZE RAM[USER-W*45]=LSIZE RAM[USER-W*44]=RSIZE RAM[USER-W*43]=SSIZE RAM[USER-W*42]=LINEBUF RAM[USER-W*41]=COMPBUF RAM[USER-W*40]=RAMMAX RAM[USER-W*39]=MAXORD =127 FOR 7 BIT CHARACTER REP. RAM[USER-W*38]=MAXINT RAM[USER-W*37]=**TO BE RECYCLED** RAM[USER-W*36]=VERSION =11 (1.1) RAM[USER-W*35]=SESSION DONE BOOLEAN RAM[USER-W*34]=^PISTOL< RAM[USER-W*33]=0(FOR PISTOL) RAM[USER-W*32]=^VSTACK(CONTEXT) FILE STATUS: NEGATIVE VALUE MEANS EOF FOR INPUT OR FILE OPENED FOR WRITE; MAGNETUDE OF VALUE=LINES OF TEXT TRANSFERED SINCE FILE WAS OPENED. RAM[USER-W*31]=STATUS FOR EDOUT RAM[USER-W*30]=STATUS FOR EDIN RAM[USER-W*29]=STATUS FOR LDFIL1 RAM[USER-W*28]=#GETLINE ADDRESS RAM[USER-W*27]=TAB SIZE, NORMALLY 8 RAM[USER-W*26]=TRACE PATCH ADDRESS RAM[USER-W*25]=ENDCASE PATCH ADDRESS RAM[USER-W*24]=COLUMN RAM[USER-W*23]=TERMINAL WIDTH RAM[USER-W*22]=# OF LINES OUTPUT TO CONSOLE RAM[USER-W*21]=TERMINAL PAGE,MAX # OF LINES RAM[USER-W*20]=COMPILE-END-PATCH USED TO SHOW CONTENTS OF COMPILE BUFFER RAM[USER-W*19]=TRACE BOOLEAN AND LEVEL RAM[USER-W*18]=HEAD OF TOKEN IN LINE RAM[USER-W*17]=RAISE LC-->UC BOOLEAN RAM[USER-W*16]=LINELENGTH RAM[USER-W*15]=NEXTCH POINTER RAM[USER-W*14]=CONSOLE OUT BOOLEAN RAM[USER-W*13]=ECHO BOOLEAN RAM[USER-W*12]=LIST BOOLEAN RAM[USER-W*11]=INPUT FILE RAM[USER-W*10..-7]=SYS TEMPS RAM[USER-W*6]=CURRENT (POINTER) RAM[USER-W*5]=OLD END OF STRINGS RAM[USER-W*4]=CURRENT END OF STRINGS RAM[USER-W*3]=.D RAM[USER-W*2]=.C RAM[USER-W*1]=RADIX RAM[VBASE..VBASE+VSIZE]=VOCABULARY STACK RAM[VBASE+VSIZE..NUMINSTR]=NOT USED HERE *) MEMORY:IMAGE; STKPTR:INTEGER; RPTR:INTEGER; LPTR:INTEGER; CPTR:INTEGER; (* STRINGS[STRINGSMIN] RADIX INDICATOR STRINGS[SYNTAXBASE] DEPTH OF NESTING & CHECKSTACK POINTER *) RSTACK:ARRAY[RSTACKMIN..RSTACKMAX] OF INTEGER; STACK:ARRAY[MSTACKMIN..PSTACKMAX] OF INTEGER; LSTACK:ARRAY[LSTACKMIN..LSTACKMAX] OF INTEGER; CSTACK:ARRAY[CSTACKMIN..CSTACKMAX] OF INTEGER; (* VSTACK LOCATED IN LOW RAM *) PROCEDURE ABORT; FORWARD;(*RECURSION NEEDED HERE ONLY FOR CARRET,BELOW:*) PROCEDURE CARRET(*OUTPUTS A CR-LF SEQUENCE*); BEGIN WITH MEMORY DO BEGIN IF RAM[USER-W*14]<>FALS THEN BEGIN RAM[USER-W*22]:=RAM[USER-W*22]+1; IF RAM[USER-W*22]=RAM[USER-W*21] THEN BEGIN READLN(INPUT); READ(INPUT,C); RAM[USER-W*22]:=0; IF (C='Q') OR (C='q') THEN ABORT; END; RAM[USER-W*24]:=0; WRITELN(OUTPUT); END; IF RAM[USER-W*12]<>FALS THEN WRITELN(LIST); END(*WITH MEMORY*); END(*CARRET*); PROCEDURE SPACES(NUM:INTEGER); FORWARD; (* NEEDED BY TAB, BELOW: *) PROCEDURE TAB; BEGIN WITH MEMORY DO BEGIN IF RAM[USER-W*27]>0 THEN SPACES(RAM[USER-W*27]-(RAM[USER-W*24] MOD RAM[USER-W*27])); END(*WITH MEMORY*); END(*TAB*); PROCEDURE CHOUT(CH:CHAR); (* OUTPUTS A CHARACTER*) BEGIN WITH MEMORY DO BEGIN IF CH=CHR(13) THEN CARRET ELSE IF CH=CHR(9) THEN TAB ELSE BEGIN IF RAM[USER-W*24]=RAM[USER-W*23] THEN CARRET; RAM[USER-W*24]:=RAM[USER-W*24]+1; IF RAM[USER-W*14]<>FALS THEN WRITE(OUTPUT,CH); IF RAM[USER-W*12]<>FALS THEN WRITE(LIST,CH); END END(*WITH MEMORY*); END(*CHOUT*); PROCEDURE SPACES; BEGIN WHILE NUM>0 DO BEGIN CHOUT(' '); NUM:=NUM-1; END(*WHILE*) END(*SPACES*); PROCEDURE MESSAGE(ST:INTEGER); BEGIN WITH MEMORY DO BEGIN IF ORD(STRINGS[ST])>0 THEN BEGIN RAM[USER-W*10]:=ST+ORD(STRINGS[ST]);(*LAST*) REPEAT ST:=ST+1; CHOUT(STRINGS[ST]); UNTIL ST=RAM[USER-W*10]; END(*IF*) END(*WITH MEMORY*); END(*MESSAGE*); PROCEDURE INTERPRET(I:INTEGER); FORWARD;(*NEEDED IN ABORT,PROMPT FOR USER SUPPLIED PATCHES*) PROCEDURE ABORT; (* RESETS STACKS RETURNS I/O TO TTY: PRODUCES SIGNON MSG *) BEGIN WITH MEMORY DO BEGIN IP:=COMPBUF;(*SO RAM[IP] IS NOT OUT OF RANGE*) RAM[USER-W*35]:=FALS;(*SESSION NOT DONE*) RAM[USER-W*32]:=VBASE; RAM[VBASE]:=USER-W*34; RAM[USER-W*6]:=USER-W*34; STKPTR := STACKMIN; RPTR := RSTACKMIN-R; CPTR := CSTACKMIN; LPTR := LSTACKMIN; STRINGS[SYNTAXBASE] := CHR(0); RAM[USER-W*11]:=FALS;(*RETURN TO CONSOLE INPUT*) RAM[USER-W*14]:=TRU;(*TURN ON CONSOLE OUTPUT*) IF LISTNAME=NULLNAME THEN RAM[USER-W*12]:=FALS; (*TURN OFF LISTING IF NO LISTFILE IS OPEN*) MESSAGE(ID); (* IFCR *) IF RAM[USER-W*24]>0 THEN CARRET; RAM[USER-W*19]:=FALS;(*TURN TRACE OFF, IF NECESSARY*) IF RAM[USER-W*52]<>FALS THEN INTERPRET(RAM[USER-W*52]);(*USER SUPPLIED SUPPLEMENT TO ABORT*) GOTO 99; END(*WITH MEMORY*); END(*ABORT*); PROCEDURE MERR(M:INTEGER);(*MESSAGE-ERROR*) BEGIN MEMORY.RAM[USER-W*14]:=TRU;(*TURN ON CONSOLE*) (* IFCR *) IF MEMORY.RAM[USER-W*24]>0 THEN CARRET; MESSAGE(M); ABORT; END(*MERR*); PROCEDURE SYNTERR; BEGIN WITH MEMORY DO BEGIN RAM[USER-W*14]:=TRU; (*TURN ON CONSOLE*) (* IFCR *) IF RAM[USER-W*24]>0 THEN CARRET; IF (RAM[USER-W*11]<>FALS) AND (RAM[USER-W*13]=FALS) THEN MESSAGE(LINEBUF); MERR(SYNT); END(*WITH MEMORY*); END(*SYNTERR*); PROCEDURE PUSH(ITEM:INTEGER); (*PARAMETER STACK*) BEGIN STKPTR:=STKPTR+S; IF STKPTR>=STACKMAX THEN MERR(OVFLO); STACK[STKPTR]:=ITEM; END(*PUSH*); PROCEDURE RPRAISE;(*RAISE RETURN STACK POINTER*) BEGIN RPTR:=RPTR+R; IF RPTR>=RSTACKMAX THEN MERR(OVFLO) END(*RPRAISE*); (*RSTACK USED FOR RETURN ADDRESSES ONLY; NOT FOR CASE OR LOOP STRUCTURES*) PROCEDURE RPUSH(ITEM:INTEGER); (*ON RETURN STACK*) BEGIN RPRAISE; RSTACK[RPTR]:=ITEM; END(*RPUSH*); PROCEDURE LPUSH(ITEM:INTEGER); BEGIN LPTR:=LPTR+L; IF LPTR>=LSTACKMAX THEN MERR(OVFLO); LSTACK[LPTR]:=ITEM; END(*LPUSH*); PROCEDURE CPUSH(ITEM:INTEGER);(*FOR CASE STACK*) BEGIN CPTR:=CPTR+CSTEP; IF CPTR>=CSTACKMAX THEN MERR(OVFLO); CSTACK[CPTR]:=ITEM; END(*CPUSH*); PROCEDURE PUSHCK(CHKCH:CHAR); (*PLACE ON CHARACTER CHECK STACK*) BEGIN WITH MEMORY DO BEGIN STRINGS[SYNTAXBASE]:= CHR(ORD(STRINGS[SYNTAXBASE])+1); IF ORD(STRINGS[SYNTAXBASE])=COMPBUF THEN MERR(OVFLO); END(*WITH MEMORY*); END(*APPEND*); PROCEDURE ALOOP;(*USED BY (LOOP) AND BY (+LOOP) *) BEGIN IF LSTACK[LPTR]0 THEN STRINGS[SYNTAXBASE] := CHR(ORD(STRINGS[SYNTAXBASE])-1) ELSE SYNTERR END(*WITH MEMORY*); END(*DROPCK*); FUNCTION VFIND(PTOKEN:INTEGER; LOC:INTEGER;V:INTEGER):INTEGER; (*PTOKEN POINTS TO THE LOCATION IN STRINGS THAT THE START OF THE TOKEN IS; THIS TOKEN IS LOOKED UP IN VOCABULARY INDIRECTLY POINTED BY V AND THE ADDRESS IS RETURNED BY VFIND *) (*RETURNS POINTER TO PF IF MATCHED OTHERWISE LOC:=0*) (* RAM[USER-W*10]=STRING CURSOR RAM[USER-W*9]=LENGTH RAM[USER-W*8]=MATCH:BOOLEAN RAM[USER-W*7]=TEMPORARY *) BEGIN WITH MEMORY DO BEGIN RAM[USER-W*9]:=ORD(STRINGS[PTOKEN]); LOC:=RAM[RAM[V]]; IF LOC<>FALS THEN REPEAT RAM[USER-W*8]:=TRU; IF STRINGS[RAM[LOC-W*2]]=CHR(RAM[USER-W*9]) THEN BEGIN RAM[USER-W*7]:=0; REPEAT RAM[USER-W*7]:=RAM[USER-W*7]+1; UNTIL (STRINGS[RAM[LOC-W*2]+RAM[USER-W*7]]) <>(STRINGS[PTOKEN+RAM[USER-W*7]]); IF RAM[USER-W*7]<(RAM[USER-W*9]+1) THEN RAM[USER-W*8]:=FALS; END(*THEN*) ELSE RAM[USER-W*8]:=FALS; IF RAM[USER-W*8]=FALS THEN LOC:=RAM[LOC-W*3] UNTIL (RAM[USER-W*8]<>FALS) OR (LOC=FALS); VFIND:=LOC; END(*WITH MEMORY*); END(*VFIND*); FUNCTION FIND(PTOKEN:INTEGER; LOC:INTEGER):INTEGER; VAR V:INTEGER; BEGIN V:=MEMORY.RAM[USER-W*32]; REPEAT LOC:=VFIND(PTOKEN,LOC,V); V:=V-W; UNTIL (VFALS); FIND:=LOC; END(*FIND*); (* HEADER: ENDA:CODE END,NORMALLY POINTS TO RET NFA:STRINGS COMPA:CF EXECA:PF *) PROCEDURE ENTER(*CREATES AN ENTRY FOR TOKEN POINTED TO BY TOP OF PARAMETER STACK*); BEGIN WITH MEMORY DO BEGIN DROP; TEMP:=FIND(STACK[STKPTR+S],TEMP); IF TEMP<>FALS THEN BEGIN MESSAGE(REDEF); SPACES(3); MESSAGE(STACK[STKPTR+S]); CARRET END(*IF*); APPEND(0);(*FOR ENDA*) APPEND(RAM[RAM[USER-W*6]]); APPEND(STACK[STKPTR+S]); APPEND(COMPHERE);(* (:) *) RAM[RAM[USER-W*6]]:=RAM[USER-W*3];(*CURRENT:=EXECA*) END(*WITH MEMORY*); END(*ENTER*); PROCEDURE FENTER(I:INTEGER);(*FINISH MOST RECENT ENTRY FILLING IN ENDA WITH I *) BEGIN WITH MEMORY DO BEGIN RAM[RAM[RAM[USER-W*6]]-W*4] := I END(*WITH MEMORY*) END(*FENTER*); PROCEDURE GEOLN; (* ADVANCES TO EOLN*) BEGIN WITH MEMORY DO WHILE STRINGS[RAM[USER-W*15]]<>CHR(13) DO RAM[USER-W*15]:=RAM[USER-W*15]+1; END(*GEOLN*); PROCEDURE GETLINE; (*BUFFERS INPUT LINE INTO STRINGS[LINEBUF]*) VAR CH:CHAR; BEGIN(*GETLINE*) WITH MEMORY DO BEGIN RAM[USER-W*16]:=0;(*LINELENGTH*) RAM[USER-W*15]:=LINEBUF; IF RAM[USER-W*11]=FALS THEN BEGIN READLN(INPUT); WHILE NOT EOLN(INPUT) DO BEGIN READ(INPUT,CH); IF RAM[USER-W*12]<>FALS THEN WRITE(LIST,CH); RAM[USER-W*16]:=RAM[USER-W*16]+1; RAM[USER-W*15]:=RAM[USER-W*15]+1; STRINGS[RAM[USER-W*15]]:=CH; END(*WHILE*); IF RAM[USER-W*12]<>FALS THEN WRITELN(LIST); END(*THEN*); IF RAM[USER-W*11]<>FALS (* CANNOT BE USED TO LOAD FROM EDITBUF*) THEN BEGIN IF EOF(LDFIL1) THEN MERR(FEOF); WHILE NOT EOLN(LDFIL1) DO BEGIN READ(LDFIL1,CH); RAM[USER-W*16]:=RAM[USER-W*16]+1; RAM[USER-W*15]:=RAM[USER-W*15]+1; STRINGS[RAM[USER-W*15]]:=CH; END(*WHILE*); READLN(LDFIL1); IF EOF(LDFIL1) THEN RAM[USER-W*29]:=-RAM[USER-W*29] ELSE RAM[USER-W*29]:=RAM[USER-W*29]+1; END(*THEN*); STRINGS[LINEBUF]:=CHR(RAM[USER-W*16]+1); STRINGS[RAM[USER-W*15]+1]:=CHR(13); RAM[USER-W*15]:=LINEBUF+1; (**ECHO:**) IF (RAM[USER-W*13]<>FALS) AND (RAM[USER-W*11]<>FALS) THEN MESSAGE(LINEBUF); END(*WITH MEMORY*); END(*GETLINE*); PROCEDURE MOVE(AS:INTEGER; AD:INTEGER; NOWD:INTEGER); (* AS:ADDRESS OF SOURCE BLOCK AD:ADDRESS OF DESTINATION NOWD:NUMBER OF WORDS*W TO BE MOVED *) VAR ENDADDR:INTEGER; BEGIN(*MOVE*) ENDADDR:=AS+NOWD; REPEAT MEMORY.RAM[AD]:=MEMORY.RAM[AS]; AD:=AD+W; AS:=AS+W; UNTIL AS>ENDADDR END(*MOVE*); PROCEDURE SLIT(VAR START:INTEGER); (* EMPLACES THE TOKEN POINTED TO BY RAM[USER-W*4] INTO STRINGS AND POINTS TO ITS START*) VAR LENGTH, I:INTEGER; BEGIN WITH MEMORY DO BEGIN START:=RAM[USER-W*4]; LENGTH:=ORD(STRINGS[START])-1; FOR I:= 1 TO LENGTH DO STRINGS[START+I]:=STRINGS[START+I+1]; STRINGS[START]:=CHR(LENGTH); RAM[USER-W*4]:=RAM[USER-W*4]+LENGTH+1 END(*WITH MEMORY*); END(*SLIT*); PROCEDURE SWAP;(*TOP TWO ITEMS ON PARAMETER STACK*) BEGIN STACK[STKPTR+S]:=STACK[STKPTR]; STACK[STKPTR]:=STACK[STKPTR-S]; STACK[STKPTR-S]:=STACK[STKPTR+S] END(*SWAP*); PROCEDURE NEXTCH; (*ADVANCES POINTER, RAM[USER-W*15] TO NEXT CHARACTER IN BUFFERED INPUT LINE; WILL NOT ADVANCE BEYOND A CARRIAGE RETURN *) BEGIN WITH MEMORY DO BEGIN IF STRINGS[RAM[USER-W*15]] <> CHR(13) THEN RAM[USER-W*15]:=RAM[USER-W*15]+1; END(*WITH MEMORY*); END(*NEXTCH*); PROCEDURE PROMPT; BEGIN WITH MEMORY DO BEGIN IF RAM[USER-W*50]<>FALS THEN INTERPRET(RAM[USER-W*50])(*SPECIAL USER PROMPT*) ELSE BEGIN(*PRIMITIVE PROMPT*) (* IFCR *) IF RAM[USER-W*24]>0 THEN CARRET; IF RAM[USER-W*14]<>FALS THEN WRITE(OUTPUT,STRINGS[STRINGSMIN]); IF RAM[USER-W*12]<>FALS THEN WRITE(LIST,STRINGS[STRINGSMIN]); MESSAGE(SYNTAXBASE); IF RAM[USER-W*14]<>FALS THEN WRITE(OUTPUT,'> '); IF RAM[USER-W*12]<>FALS THEN WRITE(LIST,'> '); END(*STANDARD PROMPT*) END(*WITH MEMORY*); END(*PROMPT*); PROCEDURE IGNRBLNKS; (*ADVANCES RAM[USER-W*15] TO POINT TO NEXT NON-BLANK, ETC. CHARACTER IN BUFFERED INPUT LINE; WILL NOT ADVANCE BEYOND A CARRIAGE RETURN*) BEGIN WITH MEMORY DO WHILE ORD(STRINGS[RAM[USER-W*15]]) IN [0,9,10,32] DO NEXTCH END(*IGNRBLNKS*); PROCEDURE LONGSTRING(VAR START:INTEGER); (*EMPLACES "STRING" POINTED TO BY RAM[USER-W*18] INTO STRINGS AND POINTS TO ITS START*) VAR LENGTH:INTEGER; BEGIN(*LONGSTRING*) WITH MEMORY DO BEGIN IF STRINGS[RAM[USER-W*18]]<>'"' THEN ABORT; START:=RAM[USER-W*4]; LENGTH:=0; RAM[USER-W*15]:=RAM[USER-W*18]+1; (*RESET NEXTCH POINTER*) WHILE NOT(ORD(STRINGS[RAM[USER-W*15]]) IN [13,34]) DO BEGIN LENGTH := LENGTH+1; STRINGS[START+LENGTH]:=STRINGS[RAM[USER-W*15]]; NEXTCH; END(*WHILE NOT*); NEXTCH; STRINGS[START]:=CHR(LENGTH); RAM[USER-W*4]:=START+LENGTH+1; END(*WITH MEMORY*); END(*LONGSTRING*); PROCEDURE INTOKEN; (* PLACES STRING AT END OF STRINGS SO THAT RAM[USER-W*4] POINTS TO IT *) BEGIN WITH MEMORY DO BEGIN RAM[USER-W*9]:=0; REPEAT RAM[USER-W*9]:=RAM[USER-W*9]+1; IF (STRINGS[RAM[USER-W*15]]>='a') AND (STRINGS[RAM[USER-W*15]]<='z') AND (RAM[USER-W*17]<>FALS) THEN(*RAISE TO UPPERCASE*) STRINGS[RAM[USER-W*9]+RAM[USER-W*4]]:= CHR(ORD(STRINGS[RAM[USER-W*15]])-32) ELSE(*NO NEED TO RAISE*) STRINGS[RAM[USER-W*9]+RAM[USER-W*4]]:= STRINGS[RAM[USER-W*15]]; NEXTCH UNTIL ORD(STRINGS[RAM[USER-W*15]]) IN [0,9,10,13,32]; STRINGS[RAM[USER-W*4]]:=CHR(RAM[USER-W*9]); END(*WITH MEMORY*); END(*INTOKEN*); FUNCTION DIGIT(D:INTEGER):INTEGER; (*CONVERTS ORD(ASCII) INTO NUMERICAL EQUIVALENT*) (*ERROR CONDITION FOR ARGUMENT PRODUCES NEGATIVE RESULT*) BEGIN IF D<=ORD('9') THEN DIGIT:=D-ORD('0') ELSE IF D=RAMMAX THEN MERR(OVFLO) ; END(*WITH MEMORY*); END(*COMPILE*); PROCEDURE FWDREF;(*COMPILES 0 TO PROVIDE SPACE FOR TOUCHUP TO USE*) BEGIN PUSH(MEMORY.RAM[USER-W*2]); COMPILE(0);(*TO BE OVERWRITTEN*) END(*FWDREF*); PROCEDURE CONVERT(PTKN:INTEGER;BASE:INTEGER;VAR OK:BOOLEAN; VAR VALUE:INTEGER); (*INPUT NUMBER CONVERSION ROUTINE*) VAR TEND:INTEGER(*TOKEN END*); (* RAM[USER-W*10]=SIGN RAM[USER-W*9]=STRING CURSOR *) BEGIN WITH MEMORY DO BEGIN VALUE:=0; RAM[USER-W*10]:=+1; TEND:=ORD(STRINGS[PTKN])+PTKN+1; IF STRINGS[PTKN+1]='+'THEN RAM[USER-W*9]:=PTKN+2 ELSE IF STRINGS[PTKN+1]='-' THEN BEGIN RAM[USER-W*10]:=-1; RAM[USER-W*9]:=PTKN+2 END ELSE RAM[USER-W*9]:=PTKN+1; WHILE(DIGIT(ORD(STRINGS[RAM[USER-W*9]]))-1) AND (RAM[USER-W*9]0 THEN BEGIN STACK[STKPTR+S]:=STACK[STKPTR-S] DIV STACK[STKPTR]; STACK[STKPTR]:=STACK[STKPTR-S] MOD STACK[STKPTR]; STACK[STKPTR-S]:=STACK[STKPTR+S]; END ELSE MERR(DIVBY0); PIF: (* 0BRANCH OR (IF) *) BEGIN DROP; IF STACK[STKPTR+S]=0 THEN (*BRANCH*) IP:=IP+RAM[IP] ELSE (*SKIP*) IP:=IP+W END; WAT: (* W@ *) STACK[STKPTR]:=RAM[STACK[STKPTR]]; ABRT: ABORT; SP: (* SP *) PUSH(STKPTR); LOAD: (* LOAD *) BEGIN DROP; RAM[USER-W*11]:=STACK[STKPTR+S]; IF RAM[USER-W*11]>MAXLINNO THEN BEGIN FOR I:= 1 TO 20 DO INFIL1[I]:=CHR(0); RAM[USER-W*10]:=ORD(STRINGS[RAM[USER-W*11]]); FOR I := 1 TO RAM[USER-W*10] DO INFIL1[I]:=STRINGS[RAM[USER-W*11]+I]; RESET(LDFIL1,INFIL1); RAM[USER-W*29]:=0; END(*IF*) END(*LOAD:*); PELSE: (* BRANCH OR (ELSE) *) IP:=IP+RAM[IP]; WRD: (* W *) PUSH(W); RP: (* RP *) PUSH((RPTR-RSTACKMIN) DIV R); DROPOP: DROP; PUSER: (* USER *) PUSH(USER); EXEC: (* EXEC *) BEGIN DROP; IF (*KERNEL?*) (STACK[STKPTR+S]) *) (*POP THE TOP OF RSTACK ONTO STACK*) BEGIN PUSH(RSTACK[RPTR]); RPTR:=RPTR-R END(*RPOP:*); SWP: SWAP; TYI: (* TYI *) BEGIN IF EOLN(INPUT) THEN READLN(INPUT); READ(INPUT,C); PUSH(ORD(C)) END; TYO: (* TYO *) BEGIN DROP; CHOUT(CHR(STACK[STKPTR+S])); END(* TYO *); RPSH: (* , ABOVE , RPOP: *) BEGIN RPUSH(STACK[STKPTR]); DROP; END(*RPSH:*); SEMICF: (* ;F *) BEGIN (* IFCR *) IF RAM[USER-W*24]>0 THEN CARRET; IF(RAM[USER-W*11]0) THEN BEGIN RAM[USER-W*11]:=RAM[USER-W*11]-1; WRITELN(OUTPUT); WRITELN(OUTPUT,' THROUGH LINE ', RAM[USER-W*11]:3,'(DECIMAL) LOADED'); IF RAM[USER-W*12]<>FALS THEN BEGIN WRITELN(LIST); WRITELN(LIST,' THROUGH LINE ', RAM[USER-W*11]:3,'(DECIMAL) LOADED'); END(*IF RAM[USER-W*12]<>FALS*) END(*=MAXLINNO) THEN BEGIN WRITELN(OUTPUT,INFIL1,' LOADED'); IF RAM[USER-W*12]<>FALS THEN WRITELN(LIST,INFIL1,' LOADED'); END(* >=MAXLINNO *); RAM[USER-W*11]:=0; END(*SEMICF:*); RAT: (* R@ *) BEGIN DROP; IF((RPTR-R*STACK[STKPTR+S])STACK[STKPTR+S*2] THEN PUSH(TRU) ELSE PUSH(FALS); END(*GT:*); SEMIDOL: (* ;$ *) (*VERY SIMILAR TO SEMICOLON:*) IF STRINGS[ORD(STRINGS[SYNTAXBASE])+SYNTAXBASE]='$' THEN BEGIN DROPCK; COMPILE(PSEMICOLON); TOUCHUP; END ELSE SYNTERR; KRNQ: (* KERNEL? *) BEGIN DROP; IF (*KERNEL?*) (STACK[STKPTR+S])NULLNAME THEN WRITELN(OUTPUT,' CHANGING LISTFILE NAME FROM:', LISTNAME); LISTNAME:=NULLNAME; FOR I:=1 TO ORD(STRINGS[STACK[STKPTR+1]]) DO LISTNAME[I]:=STRINGS[STACK[STKPTR+1]+I]; REWRITE(LIST,LISTNAME); END(*WITH MEMORY*) END(*LISTFIL:*); (* 58: MAY BE RECYCLED *) LAT: (* L@ *)(*SIMILAR TO S@, BUT FOR LOOP STACK*) (* 'I : 0 L@ ; *) BEGIN DROP; IF LPTRFALS THEN MESSAGE(LINEBUF); END(*READL:*); WRITL: (* WRITELINE *) BEGIN DROP; IF RAM[USER-W*31]>0 THEN MERR(NOPEN); RAM[USER-W*9]:=STACK[STKPTR+S]; RAM[USER-W*10]:=RAM[USER-W*9]+ORD(STRINGS[RAM[USER-W*9]])-1; WHILE RAM[USER-W*9] < RAM[USER-W*10] DO BEGIN RAM[USER-W*9]:=RAM[USER-W*9]+1; WRITE(EDOUT,STRINGS[RAM[USER-W*9]]); END(*WHILE*); WRITELN(EDOUT); RAM[USER-W*31]:=RAM[USER-W*31]-1;(*INCREASE NEGATIVE*) END(*WRITL*); CORDMP: (* COREDUMP *) BEGIN WITH MEMORY DO BEGIN DROP; FOR I:=1 TO 20 DO IMAGENAME[I]:=CHR(0); FOR I:=1 TO ORD(STRINGS[STACK[STKPTR+S]]) DO IMAGENAME[I]:=STRINGS[STACK[STKPTR+S]+I]; REWRITE(SAVEFILE,IMAGENAME); WRITE(SAVEFILE,MEMORY); END(*WITH MEMORY*); END(*CORDMP*); RESTOR: (* RESTORE *) BEGIN WITH MEMORY DO BEGIN DROP; FOR I:=1 TO 20 DO IMAGENAME[I]:=CHR(0); FOR I:=1 TO ORD(STRINGS[STACK[STKPTR+S]]) DO IMAGENAME[I]:=STRINGS[STACK[STKPTR+S]+I]; RESET(SAVEFILE,IMAGENAME); READ(SAVEFILE,MEMORY); ABORT; END(*WITH MEMORY*); END(*RESTOR:*); END(*CASE*); END(*WITH MEMORY*); END(*PINT1*); PROCEDURE PINT; BEGIN IF INST>40 THEN PINT1(INST) ELSE PINT0(INST) END(*PINT*); PROCEDURE INTERPRET;(*ORIGINAL ENTRY PLACED BEFORE ABORT*) BEGIN WITH MEMORY DO BEGIN INSTR:=I; REPEAT IP:=IP+W; IF (*KERNEL?*) INSTRFALS) THEN PROMPT; IF (RAM[USER-W*11]>0) AND (RAM[USER-W*11] CHR(13) DO BEGIN RAM[USER-W*18] := RAM[USER-W*15]; (* NOTE TOKEN START*) INTOKEN; ADDR:=FIND(RAM[USER-W*4],ADDR); IF ADDR<>FALS THEN(*FOUND*) INTERPRET(ADDR-W) (* THE CPA *) ELSE BEGIN(*NOT DEFINED DURING EXECUTION*) CONVERT(RAM[USER-W*4],RAM[USER-W*1],CONVERTED,VAL); IF CONVERTED THEN BEGIN COMPILE(LIT); COMPILE(VAL) END ELSE IF STRINGS[RAM[USER-W*4]+1]='''' THEN BEGIN SLIT(VAL); COMPILE(STRLIT); COMPILE(VAL); END(*IF SINGLE-QUOTED STRING*) ELSE IF STRINGS[RAM[USER-W*4]+1]='"' THEN BEGIN LONGSTRING(VAL); COMPILE(STRLIT); COMPILE(VAL); END(*DOUBLE QUOTED STRING*) ELSE IF RAM[USER-W*51]<>FALS THEN INTERPRET(RAM[USER-W*51]) (*USER SUPPLIED CONVERSION*) ELSE BEGIN (*TOKEN NOT DECHIPHERABLE*) RAM[USER-W*14]:=TRU(*TURN ON CONSOLE*); (*SHOW BAD LINE IF NOT ON CONSOLE*) IF (RAM[USER-W*11]<>FALS) AND (RAM[USER-W*13]=FALS) THEN BEGIN (* IFCR *) IF RAM[USER-W*24]>0 THEN CARRET; MESSAGE(LINEBUF); END(*IF*); MESSAGE(RAM[USER-W*4]); WRITELN(OUTPUT,' ?'); IF RAM[USER-W*12]<>FALS THEN WRITELN(LIST,' ?'); ABORT; END END(*NOT DEFINED DURING EXECUTION*); IGNRBLNKS; END(*WHILE*); END(*WITH MEMORY*); END(*PROCEDURE COMPLINE*); PROCEDURE ADDSTRING(LENGTH:INTEGER; STRING:DALFA;VAR START:INTEGER); (*CONVENIENCE DURING INITIALIZATION OF PISTOL*) VAR I:INTEGER; BEGIN(*ADDSTRING*) WITH MEMORY DO BEGIN START:=RAM[USER-W*4]; RAM[USER-W*4]:=RAM[USER-W*4]+1; FOR I:= 1 TO LENGTH DO BEGIN STRINGS[RAM[USER-W*4]]:=STRING[I]; RAM[USER-W*4]:=RAM[USER-W*4]+1; END(*FOR*); STRINGS[START]:=CHR(I-1); (* STRING HAS NOW BEEN PLACED IN STRINGS,RAM[USER-W*4] HAS BEEN UPDATED*) PERMSTRINGS; END(*WITH MEMORY*); END(*ADDSTRING*); PROCEDURE PENTER(LENGTH:INTEGER;NAME:DALFA;OPCODE:INTEGER); (* THIS PROCEDURE IS USED ONLY TO SIMPLIFY BRINGING UP PISTOL; THE PRIMITIVE,"BUILT-IN" FUNCTIONS ARE ENTERED INTO THE DICTIONARY BY THIS PROCEDURE. IF OPCODE IS POSITIVE, IT IS 'NOTIMMEDIATE', HENCE THE COMPILE-TIME OPCODE SHOULD BE 27, ELSE IF OPCODE IS NEGATIVE, IT IS IMMEDIATE*) VAR START:INTEGER; BEGIN(*PENTER*) WITH MEMORY DO BEGIN ADDSTRING(LENGTH,NAME,START); APPEND(0);(*SPACE FOR ENDA*) APPEND(RAM[RAM[USER-W*6]]); (*LINK FIELD*) APPEND(START); (*NAME FIELD*) (*COMPILE-TIME FIELD: *) IF OPCODE<0 THEN BEGIN APPEND(-OPCODE) (*IMMEDIATE WORD*); APPEND(PSEMICOLON) (*FOR SYMMETRY*) END ELSE BEGIN APPEND(COMPME); (*PRIMITIVE NOTIMMEDIATE*) APPEND(OPCODE); END(*ELSE*); RAM[RAM[USER-W*6]]:=RAM[USER-W*3]-W; (*UPDATE CURRENT*) FENTER(RAM[USER-W*3]);(* ENDA:=.D *) END(*WITH MEMORY*); END(*PENTER*); (******************************************) BEGIN(*PISTOL MAIN*) WITH MEMORY DO BEGIN FOR TEMP:=RAMMIN TO RAMMAX DO RAM[TEMP]:=10000; REWRITE(OUTPUT,'TTY: '); FOR I:=1 TO 20 DO NULLNAME[I]:=CHR(0); LISTNAME:=NULLNAME; RAM[USER-W*57]:=MAXLINNO; RAM[USER-W*56]:=CHKLMT;(*SIZE OF SYNTAX CHECKSTACK*) RAM[USER-W*55]:=RAMMIN; RAM[USER-W*54]:=STRINGSMIN; RAM[USER-W*52]:=FALS;(*ABORT PATCH*) RAM[USER-W*51]:=FALS;(*CONVERSION PATCH*) RAM[USER-W*50]:=FALS;(*STANDARD PROMPT*) RAM[USER-W*49]:=STRINGSMAX; RAM[USER-W*48]:=VBASE; RAM[USER-W*47]:=VSIZE; RAM[USER-W*46]:=CSIZE; RAM[USER-W*45]:=LSIZE; RAM[USER-W*44]:=RSIZE; RAM[USER-W*43]:=SSIZE; RAM[USER-W*42]:=LINEBUF; RAM[USER-W*41]:=COMPBUF; RAM[USER-W*40]:=RAMMAX; RAM[USER-W*39]:=MAXORD; RAM[USER-W*38]:=MAXINT; RAM[USER-W*36]:=VERSION; RAM[USER-W*34]:=0; RAM[USER-W*33]:=FALS;(* PISTOL< LINK IS NIL; IT'S AT THE END OF BRANCH LIST*) (*INITIALIZE FILE STATUS*) RAM[USER-W*31]:=+1;(*EDOUT*) RAM[USER-W*30]:=-1;(*EDIN*) RAM[USER-W*29]:=-1;(*LDFIL1*) RAM[USER-W*27]:=8; (*INITIALIZE TABSIZE*) RAM[USER-W*25]:=67; (*INITIALIZE ENDCASE TO ABORT*) RAM[USER-W*23]:=64 (* INITIALIZE TERMINAL WIDTH*); RAM[USER-W*21]:=20 (* INITIALIZE TERMINAL PAGE LENGTH*); RAM[USER-W*20]:=FALS;(*COMPILE-END-PATCH*) RAM[USER-W*19]:=FALS;(*INITALIZE TRACE OFF*) RAM[USER-W*17]:=TRU (*RAISE ON*); RAM[USER-W*13]:=FALS (*ECHO OFF*); RAM[USER-W*12]:=FALS;(*LIST OFF*) RAM[USER-W*6]:=USER-W*34; IF USER>NUMINSTR THEN RAM[USER-W*3]:=USER+W*VSIZE+W ELSE RAM[USER-W*3]:=NUMINSTR+1;(* SET BASE OF DICTIONARY*) RAM[USER-W*5]:=SYNTAXBASE+CHKLMT+1; RAM[USER-W*4]:=RAM[USER-W*5]; ADDSTRING(20,'*** EOF ENCOUNTERED*',FEOF); ADDSTRING(20,'*** FILE NOT OPENED*',NOPEN); ADDSTRING(18,'*** PISTOL 1.3 *** ',ID); ADDSTRING(20,'*** SYNTAX ERROR ***',SYNT); ADDSTRING(19,'** STACK OVERFLOW **',OVFLO); ADDSTRING(19,'* STACK UNDERFLOW * ',UNDFLO); ADDSTRING(16,'---REDEFINING--- ',REDEF); ADDSTRING(16,'DIVISION BY ZERO ',DIVBY0); PENTER(2,'W! ',WSTORE); PENTER(1,'* ',TIMES); PENTER(1,'+ ',PLUS); PENTER(1,'- ',SUBTRACT); PENTER(4,'/MOD ',DIVMOD); PENTER(2,'W@ ',WAT); PENTER(5,'ABORT ',ABRT); PENTER(2,'SP ',SP); PENTER(4,'LOAD ',LOAD); PENTER(1,'W ',WRD); PENTER(2,'RP ',RP); PENTER(4,'DROP ',DROPOP); PENTER(4,'USER ',PUSER); PENTER(4,'EXEC ',EXEC); PENTER(4,'EXIT ',EXITOP); PENTER(2,'R> ',RPOP); PENTER(4,'SWAP ',SWP); PENTER(3,'TYI ',TYI); PENTER(3,'TYO ',TYO); PENTER(2,'FALS THEN INTERPRET(RAM[USER-W*20]); IF (RAM[USER-W*14]<>FALS) AND ((RAM[USER-W*11]=FALS) OR (RAM[USER-W*13]<>FALS)) THEN BEGIN RAM[USER-W*24]:=FALS (*RESET COLUMN POSTION VARIABLE*); RAM[USER-W*22]:=FALS (*RESET TERMINAL LINE COUNT*); END; INTERPRET(COMPBUF); 99: RAM[USER-W*4]:=RAM[USER-W*5]; UNTIL RAM[USER-W*35]<>FALS(*SESSION DONE*); WRITELN(OUTPUT,'PISTOL NORMAL EXIT'); IF RAM[USER-W*12]<>FALS THEN WRITELN(LIST,'PISTOL NORMAL EXIT'); (*FLUSH AND CLOSE FILES IF OPERATING SYSTEM DOESN'T DO IT*) END(*WITH MEMORY*); END. .