home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG049.ARK
/
RATFOR.RAT
< prev
next >
Wrap
Text File
|
1984-04-29
|
25KB
|
953 lines
#symbolic constants greater than 10000 have been changed to
#negative numbers which fit in bytes. If they are enclosed in
#parentheses in relational expressions, they should be accepted by all FORTRAN.
define(alpha,-100)
define(amper,38) #ampersand
define(arb,100)
define(atsign,64)
define(backslash,92)
define(backspace,8)
define(bang,33)#exclamation point
define(bar,124)#synonym for .or.
define(biga,65)
define(bigb,66)
define(bigc,67)
define(bigd,68)
define(bige,69)
define(bigf,70)
define(bigg,71)
define(bigh,72)
define(bigi,73)
define(bigj,74)
define(bigk,75)
define(bigl,76)
define(bigm,77)
define(bign,78)
define(bigo,79)
define(bigp,80)
define(bigq,81)
define(bigr,82)
define(bigs,83)
define(bigt,84)
define(bigu,85)
define(bigv,86)
define(bigw,87)
define(bigx,88)
define(bigy,89)
define(bigz,90)
define(blank,32)
define(bufsize,300)#pushback buffer for ngetch, putbak
define(caret,94)#alternate not, converted to !
define(colon,58)
define(comma,44)
define(deftype,-10)
define(dig0,48)
define(dig1,49)
define(dig2,50)
define(dig3,51)
define(dig4,52)
define(dig5,53)
define(dig6,54)
define(dig7,55)
define(dig8,56)
define(dig9,57)
define(digit,2)
define(dollar,36)
define(dquote,34)
define(eof,-3)
define(eos,-2)
define(equals,61)
#define(err,-1) not used, conflicts with err=
define(kons,3)
define(errout,kons)#error message to console
define(greater,62)
define(kb,3)
define(lbrace,123)
define(lbrack,91)
define(less,60)
define(leta,97)
define(letb,98)
define(letc,99)
define(letd,100)
define(lete,101)
define(letf,102)
define(letg,103)
define(leth,104)
define(leti,105)
define(letj,106)
define(letk,107)
define(letl,108)
define(letm,109)
define(letn,110)
define(leto,111)
define(letp,112)
define(letq,113)
define(letr,114)
define(lets,115)
define(lett,116)
define(letter,1)
define(letu,117)
define(letv,118)
define(letw,119)
define(letx,120)
define(lety,121)
define(letz,122)
define(lexbreak,-64)
define(lexdigits,-60)
define(lexdo,-66)
define(lexelse,-62)
define(lexfor,-68)
define(lexif,-61)
define(lexnext,-65)
define(lexother,-67)
define(lexrepeat,-69)
define(lexuntil,-70)
define(lexwhile,-63)
define(lparen,40)
define(maxcard,80)#input record size
define(maxchars,10)#chars in ascii integer incl - and eos
define(maxdef,200)#max chars in defn
define(maxforstk,200)#space for reinit clauses
define(maxline,81)#maxcard+1
define(maxname,30)#include file name length
define(maxptr,200)#number of defines
define(maxstack,100)#parser stack depth
define(maxtbl,1500)#size of definition table
define(maxtok,200)#token size
define(minus,45)
#define(nchars,33)
define(newline,10)#lf
define(nfiles,5)#max open files
define(no,.false.)
define(not,bang)#use !
define(percent,37)
define(period,46)
define(plus,43)
define(qmark,63)
define(rbrace,125)
define(rbrack,93)
#define(readonly,0)#not used by Microsoft
define(rparen,41)
define(semicol,59)
define(sharp,35)
define(slash,47)
define(squote,39)
define(star,42)
define(stdin,7)#input unit
define(stdout,6)
define(tab,9)
define(tilde,126)
define(underline,95)
define(yes,.true.)
define(character,byte)
define(abs,iabs)
program ratfor#main program
character name(8),namer(11),namef(11)
data namer(9),namer(10),namer(11)/'R','A','T'/
data namef(9),namef(10),namef(11)/'F','O','R'/
9 format('Addison-Wesley Ratfor adapted for FORTRAN-80 August',
'1979 by Tim Prince, 1 EastLakeView Apt 17, Cincinnati 45237')
write(kons,1,err=3)
1 format(1x,'Input file name ?')
3 read(kb,2,err=4)name
2 format(8a1)
4 do i=1,8
{namer(i)=name(i);namef(i)=name(i)}
call open(stdin,namer,0)
call open(stdout,namef,0)
call parse
endfile stdout
stop
end
block data initl
include RATCOMNS
data outp/0/#output character pointer
#file control
data level/1/,linect(1)/1/,infile(1)/stdin/
data bp/0/#pushback buffer pointer
data fordep/0/#for stack depth
#table lookup pointers
data lastp/0/,lastt/0/
#keywords:
data sdo/letd,leto,eos/,vdo/lexdo,eos/
data sif/leti,letf,eos/,vif/lexif,eos/
data selse/lete,letl,lets,lete,eos/
data velse/lexelse,eos/
data swhile/letw,leth,leti,letl,lete,eos/
data vwhile/lexwhile,eos/
data sbreak/letb,letr,lete,leta,letk,eos/
data vbreak/lexbreak,eos/
data snext/letn,lete,letx,lett,eos/
data vnext/lexnext,eos/
data sfor/letf,leto,letr,eos/,vfor/lexfor,eos/
data srept/letr,lete,letp,lete,leta,lett,eos/
data vrept/lexrepeat,eos/
data suntil/letu,letn,lett,leti,letl,eos/
data vuntil/lexuntil,eos/
#if a transliteration table is required, insert it here
end
logical function alldig(str)#yes if str is all digits
#called by lex
character type,str(arb)
alldig=no
if(str(1)==eos)return
for(i=1;str(i)!=eos;i=i+1)if(type(str(i))!=digit)return
alldig=yes
return
end
subroutine balpar #copy balanced paren string
#called by ifgo
character gettok,t,token(maxtok)
integer*1 nlpar
if(gettok(token,maxtok)!=lparen)
{call synerr("missing left paren.")
return}
call outstr(token)
nlpar=1
repeat{
t=gettok(token,maxtok)
if(t==semicol | t==lbrace | t==rbrace | t==eof)
{call pbstr(token)
break}
if(t==newline)token(1)=eos # delete lf
else if (t==lparen)nlpar=nlpar+1
else if (t==rparen)nlpar=nlpar-1
call outstr(token)
}until(nlpar<=0)
if(nlpar!=0)call synerr("missing parenthesis in condition.")
return
end
subroutine brknxt(sp,lextyp,labval,token)#break & next
#called by parse
integer i,labval(maxstack),sp
character lextyp(maxstack),token
for(i=sp;i>0;i=i-1)
if(lextyp(i)==lexwhile | lextyp(i)==lexdo
| lextyp(i)==lexfor | lextyp(i)==lexrepeat)
{labout=labval(i)
if(token==lexbreak)labout=labout+1
call outgo(labout)
return}
if(token==lexbreak)call synerr("illegal break.")
else call synerr("illegal next.")
return
end
subroutine closei(fd)#file close
#called by gettok
integer fd
endfile fd
return
end
character function deftok(token,toksiz,fd)
#called by gettok
integer fd,toksiz
character gtok,defn(maxdef),t,token(toksiz)
logical lookup
for(t=gtok(token,toksiz,fd);t!=eof;t=gtok(token,toksiz,fd))
{if(t!=alpha)break #non-alpha
if(! lookup(token,defn))break #undefined
if(defn(1)==deftype) #get definition
{call getdef(token,toksiz,defn,maxdef,fd)
call instal(token,defn)}
else call pbstr(defn)} #push replacement onto input
deftok=t
if(deftok==alpha) call fold(token) #convert to lower case
return
end
subroutine fold(token)
#called by deftok
character token(arb)
# internal numeric equivalence of letters must be sequential
# within each case.
integer*1 lwrmup
lwrmup=leta-biga
for(i=1;token(i)!=eos;i=i+1)
if(token(i)>=biga & token(i)<=bigz)
token(i)=token(i)+lwrmup
return
end
subroutine docode(lab) #generate do
#called by parse
character dostr(4)
data dostr/letd,leto,blank,eos/
call outtab
call outstr(dostr)
lab=labgen(2)
call outnum(lab)
call eatup
call outdon
return
end
subroutine dostat(lab) #generate end do
#called by unstak
call outcon(lab)
call outcon(lab+1)
return
end
subroutine eatup #proc rest of statement incl continuations
#called by docode,forcod,otherc
character gettok,ptoken(maxtok),t,token(maxtok)
integer*1 nlpar
nlpar=0
repeat{
t=gettok(token,maxtok)
if(t==semicol | t==newline)break
if(t==rbrace){call pbstr(token);break}
if(t==lbrace | t==eof){
call synerr("unexpected brace or eof.")
call pbstr(token)
break}
if(t==comma | t==underline){
if(gettok(ptoken,maxtok)!=newline)call pbstr(ptoken)
if(t==underline)token(1)=eos}
else if(t==lparen)nlpar=nlpar+1
else if(t==rparen)nlpar=nlpar-1
call outstr(token)
}until(nlpar<0)
if(nlpar!=0)call synerr("unbalanced parentheses.")
return
end
subroutine elseif(lab) #generate else code
#called by parse
call outgo(lab+1)
call outcon(lab)
return
end
logical function equal(str1,str2) #? strings equal
#called by gettok,lex
character str1(arb),str2(arb)
for(i=1;str1(i)==str2(i);i=i+1)
if(str1(i)==eos){equal=yes;return}
equal=no
return
end
subroutine error(buf)#fatal error msg; die
#called by getdef,parse,putbak
character buf(arb)
call remark(buf)
endfile stdout
stop
end
subroutine forcod(lab)#begin for
#called by parse
character gettok,t,token(maxtok),ifnot(9)
integer*1 i,nlpar
include RATCOMNS
data ifnot/leti,letf,lparen,period,letn,leto,lett,period,eos/
lab=labgen(3)
call outcon(0)
if(gettok(token,maxtok)!=lparen){
call synerr("missing left paren.")
return}
if(gettok(token,maxtok)!=semicol)#real init clause
{call pbstr(token)
call outtab
call eatup
call outdon}
if(gettok(token,maxtok)==semicol)#empty condition
call outcon(lab)
else{ #non-empty condition
call pbstr(token)
call outnum(lab)
call outtab
call outstr(ifnot)
call outch(lparen)
nlpar=0
while(nlpar>=0){
t=gettok(token,maxtok)
if(t==semicol)break
if(t==lparen)nlpar=nlpar+1
else if(t==rparen)nlpar=nlpar-1
if(t!=newline & t!=underline)call outstr(token)}
call outch(rparen)
call outch(rparen)
call outgo(lab+2)
if(nlpar<0)call synerr("invalid for clause.")}
fordep=fordep+1 #stack reinit clause
j=1
for(i=1;i<fordep;i=i+1)#find end
j=j+length(forstk(j))+1
forstk(j)=eos #null, in case no reinit
nlpar=0
while(nlpar>=0){
t=gettok(token,maxtok)
if(t==lparen)nlpar=nlpar+1
else if(t==rparen)nlpar=nlpar-1
if(nlpar>=0 & t!=newline & t!=underline){
call scopy(token,1,forstk,j)
j=j+length(token)}}
lab=lab+1 #label for NEXTs
return
end
subroutine fors(lab)#process end of for
#called by unstak
integer*1 i
include RATCOMNS
call outnum(lab)
j=1
for(i=1;i<fordep;i=i+1)
j=j+length(forstk(j))+1
if(length(forstk(j))>0){
call outtab
call outstr(forstk(j))
call outdon}
call outgo(lab-1)
call outcon(lab+1)
fordep=fordep-1
return
end
character function getch(c,f)#get character from file
#called by ngetch
character buf(maxline),c
integer f
data lastc/maxline/,buf(maxline)/newline/
#note: maxline=maxcard+1
if(buf(lastc)==newline | lastc>=maxline){
read(f,1,err=5,end=10)(buf(i),i=1,maxcard)
1 format(maxcard a1)#use r1 format if available
#now transliterate into ascii and shift right if needed
for(i=maxcard;i>0;i=i-1)
if(buf(i)!=blank)break
buf(i+1)=newline
go to 7
5 buf(1)=qmark
buf(2)=newline
7 if(buf(1)==newline)lastc=1
else lastc=0
}#Microsoft leaves newline in front; skip it
lastc=lastc+1
c=buf(lastc)
getch=c
return
10 c=eof
getch=eof
return
end
subroutine getdef(token,toksiz,defn,defsiz,fd)
#called by deftok
integer defsiz,fd,toksiz
character gtok,ngetch,c,defn(defsiz),token(toksiz)
integer*1 nlpar
if(ngetch(c,fd)!=lparen)call remark("missing left paren.")
if(gtok(token,toksiz,fd)!=alpha)
call remark("non-alphanumeric name.")
else if(ngetch(c,fd)!=comma)
call remark("missing comma in define.")
nlpar=0
for(i=1;nlpar>=0;i=i+1)
if(i>defsiz)call error("definition too long.")
else if(ngetch(defn(i),fd)==eof)
call error("missing right paren.")
else if(defn(i)==lparen)nlpar=nlpar+1
else if(defn(i)==rparen)nlpar=nlpar-1
defn(i-1)=eos
return
end
character function gettok(token,toksiz)
#called by balpar,eatup,forcod,lex
logical equal
integer openi,toksiz
character junk
character deftok,name(maxname),token(toksiz),incl(8)
include RATCOMNS
data incl/leti,letn,letc,letl,letu,letd,lete,eos/
for(;level>0;level=level-1){
for(gettok=deftok(token,toksiz,infile(level));gettok!=eof;
gettok=deftok(token,toksiz,infile(level))){
if(! equal(token,incl))return
junk=deftok(name,maxname,infile(level))
if(level>=nfiles)
call synerr("includes nested too deeply.")
else{
infile(level+1)=openi(name,level+1)
linect(level+1)=1
#open error not flagged by FORT-80;must change name anyway
# if(infile(level+1)==err)
# call synerr("can't open include.")
# else
level=level+1}}
if(level>1)call closei(infile(level))}
gettok=eof
return
end
character function gtok(lexstr,toksiz,fd)
#called by deftok,getdef
integer toksiz,fd
character ngetch,type,c,lexstr(toksiz)
include RATCOMNS
while(ngetch(c,fd)!=eof)if(c!=blank&c!=tab)break
call putbak(c)
for(i=1;i<toksiz-1;i=i+1){
gtok=type(ngetch(lexstr(i),fd))
if(gtok!=letter>ok!=digit)break}
if(i>=toksiz-1)call synerr("token too long.")
if(i>1){ #some alpha seen
call putbak(lexstr(i))#insert eos before lexstr(i)
lexstr(i)=eos
gtok=alpha}
else if(lexstr(1)==dollar){#process $( & $)
if(ngetch(lexstr(2),fd)==lparen){
lexstr(1)=lbrace
gtok=lbrace}
else if(lexstr(2)==rparen){
lexstr(1)=rbrace
gtok=rbrace}
else call putbak(lexstr(2))}
else if(lexstr(1)==squote | lexstr(1)==dquote){
for(i=2;ngetch(lexstr(i),fd)!=lexstr(1);i=i+1)
if(lexstr(i)==newline | i>=toksiz-1){
call synerr("missing quote.")
lexstr(i)=lexstr(1)
call putbak(newline)
break}}
else if(lexstr(1)==sharp){ #strip comment
while(ngetch(lexstr(1),fd)!=newline);
gtok=newline}
else{
if(lexstr(1)==tilde | lexstr(1)==caret)lexstr(1)=not
if(lexstr(1)==greater|lexstr(1)==less|lexstr(1)==not
|lexstr(1)==equals|lexstr(1)==amper|lexstr(1)==bar)
call relate(lexstr,i,fd)}
lexstr(i+1)=eos
if(lexstr(1)==newline)linect(level)=linect(level)+1
return
end
subroutine ifcode(lab)#initial if code
#called by parse
lab=labgen(2)
call ifgo(lab)
return
end
subroutine ifgo(lab)
#called by ifcode,unstak,whilec
character ifnot(9)
data ifnot/leti,letf,lparen,period,letn,leto,lett,period,eos/
call outtab #get to column 7
call outstr(ifnot)
call balpar #collect & output condition
call outch(rparen)
call outgo(lab) #"goto lab"
return
end
subroutine initkw #install "define" in definition table
#called by parse
#note "define"must be all lower case unless further provided.
character defnam(7),deftyp(2)
data defnam/letd,lete,letf,leti,letn,lete,eos/
data deftyp/deftype,eos/
call instal(defnam,deftyp)
return
end
subroutine instal(name,defn)#add to definition table
#called by deftok,initkw
character defn(maxtok),name(maxdef)
integer dlen
include RATCOMNS
nlen=length(name)+1
dlen=length(defn)+1
if(lastt+nlen+dlen>maxtbl | lastp>=maxptr){
call putlin(name,errout)
call remark(": too many definitions.")}
lastp=lastp+1
namptr(lastp)=lastt+1
call scopy(name,1,table,lastt+1)
call scopy(defn,1,table,lastt+nlen+1)
lastt=lastt+nlen+dlen
return
end
function itoc(int,str,size)#convert int to str
#called by outnum,synerr
integer size
character k,str(size)
intval=abs(int)
str(1)=eos
i=1
repeat{
i=i+1
str(i)=mod(intval,10)+dig0
intval=intval/10
}until(intval==0 | i>=size)
if(int<0 & i<size){ #check sign
i=i+1
str(i)=minus}
itoc=i-1
for(j=1;j<i;j=j+1) #reverse
{k=str(i)
str(i)=str(j)
str(j)=k
i=i-1}
return
end
subroutine labelc(lexstr)#output label
#called by parse
character lexstr(arb)
if(length(lexstr)==5) #warn about 23xxx labels
if(lexstr(1)==dig2 & lexstr(2)==dig3)
call synerr("warning: possible label conflict.")
call outstr(lexstr)
call outtab
return
end
function labgen(n)#generate n labels, return first one
#called by docode,forcod,ifcode,repcod,whilec
data label/23000/
labgen=label
label=label+n
return
end
function length(str)
#called by fors,labelc,pbstr
character str(arb)
for(length=0;str(length+1)!=eos;length=length+1);
return
end
character function lex(lexstr)
#called by parse,unstak
character gettok,lexstr(maxtok)
logical alldig,equal
include RATCOMNS
while(gettok(lexstr,maxtok)==newline);
lex=lexstr(1)
if(lex==eof | lex==semicol | lex==lbrace | lex==rbrace)return
if(alldig(lexstr))lex=lexdigits
else if(equal(lexstr,sif))lex=vif(1)
else if(equal(lexstr,selse))lex=velse(1)
else if(equal(lexstr,swhile))lex=vwhile(1)
else if(equal(lexstr,sdo))lex=vdo(1)
else if(equal(lexstr,sbreak))lex=vbreak(1)
else if(equal(lexstr,snext))lex=vnext(1)
else if(equal(lexstr,sfor))lex=vfor(1)
else if(equal(lexstr,srept))lex=vrept(1)
else if(equal(lexstr,suntil))lex=vuntil(1)
else lex=lexother
return
end
logical function lookup(name,defn)
#called by deftok
character defn(maxdef),name(maxtok)
include RATCOMNS
for(i=lastp;i>0;i=i-1) #note last defn checked first
{j=namptr(i)
for(k=1;name(k)==table(j)&name(k)!=eos;k=k+1)
j=j+1
if(name(k)==table(j)){ #found defn
call scopy(table,j+1,defn,1)
lookup=yes
return}}
lookup=no
return
end
character function ngetch(c,fd)#get char (possibly pushed back)
#called by getdef,gtok,type,relate
character getch,c
integer fd
include RATCOMNS
if(bp>0)c=buf(bp)
else{bp=1;buf(1)=getch(c,fd)}
bp=bp-1
ngetch=c
return
end
integer function openi(name,level)
#called by gettok
character name(maxname),namer(11)
data namer(9),namer(10),namer(11)/'R','A','T'/
openi=level+6#use units 8,9,10 according to include level
for(i=1;i<=8&name(i)!=eos;i=i+1)
{if(name(i)>underline)name(i)=name(i)-blank
namer(i)=name(i)} #strip lc bit
if(name(i)!=eos)i=i+1 #don't blank unless eos
while(i<=8){namer(i)=blank;i=i+1}
call open(openi,namer,0)#current disk
return
end
subroutine otherc(lexstr)#put out ordinary FORTRAN
#called by parse
character lexstr(arb)
call outtab
call outstr(lexstr)
call eatup
call outdon
return
end
subroutine outch(c)#output by characters
#called by forcod,ifgo,outnum,outstr,outtab
character c
include RATCOMNS
if(outp>=72){#make continuation card
call outdon
do i=1,5
outbuf(i)=blank
outbuf(6)=amper#ampersand in col 6 (may want *)
outp=6}
outp=outp+1
outbuf(outp)=c
return
end
subroutine outcon(n)#put out "n continue"
#called by dostat,elseif,forcod,fors,repcod,unstak,whilec,whiles
character contin(9)
data contin/letc,leto,letn,lett,leti,letn,letu,lete,eos/
if(n>0)call outnum(n)
call outtab
call outstr(contin)
call outdon
return
end
subroutine outdon #terminate output line
#called by docode,forcod,fors,otherc,outch,outcon,outgo
include RATCOMNS
outbuf(outp+1)=newline
outbuf(outp+2)=eos
call putlin(outbuf,stdout)
outp=0
return
end
subroutine outgo(n)#put out "goto n"
#called by brknxt,elseif,forcod,fors,ifgo,unstak,whiles
character goto(6)
data goto/letg,leto,lett,leto,blank,eos/
call outtab
call outstr(goto)
call outnum(n)
call outdon
return
end
subroutine outnum(n)#put out decimal number
#called by docode,forcod,fors,outcon,outgo,outstr,whilec
character chars(maxchars)
len=itoc(n,chars,maxchars)
do i=1,len
call outch(chars(i))
return
end
subroutine outstr(str)#put out string
#called by balpar,docode,eatup,forcod,fors,ifgo,labelc,otherc,
#outcon,outgo
character c,str(arb)
for(i=1;str(i)!=eos;i=i+1){
c=str(i)
if(c!=squote & c!=dquote)call outch(c)
else{
i=i+1
for(j=i;str(j)!=c;j=j+1);#count Hollerith string
call outnum(j-i)
call outch(leth)
for(;i<j;i=i+1)call outch(str(i))}}
return
end
subroutine outtab#tab to column 7
#called by docode,forcod,fors,ifgo,labelc,otherc,outcon,outgo
include RATCOMNS
while(outp<6)call outch(blank)
return
end
subroutine parse#parse ratfor source
#called by ratfor
character lexstr(maxtok),lex,lextyp(maxstack),token
integer labval(maxstack),sp
call initkw #install initial definitions
sp=1
lextyp(1)=eof
for(token=lex(lexstr);token!=eof;token=lex(lexstr)){
if(token==lexif)call ifcode(lab)
else if(token==lexdo)call docode(lab)
else if(token==lexwhile)call whilec(lab)
else if(token==lexfor)call forcod(lab)
else if(token==lexrepeat)call repcod(lab)
else if(token==lexdigits)call labelc(lexstr)
else if(token==lexelse){
if(lextyp(sp)==lexif)call elseif(labval(sp))
else call synerr("illegal else.")}
if(token==lexif | token==lexelse | token==lexwhile
| token==lexfor | token==lexrepeat
| token==lexdo | token==lexdigits | token==lbrace){
sp=sp+1 #begin statement
if(sp>maxstack)call error("stack overflow in parser.")
lextyp(sp)=token #stack type and value
labval(sp)=lab}
else{ #end of statement - prepare to unstack
if(token==rbrace){
if(lextyp(sp)==lbrace)sp=sp-1
else call synerr("illegal right brace.")}
else if(token==lexother)call otherc(lexstr)
else if(token==lexbreak | token==lexnext)
call brknxt(sp,lextyp,labval,token)
token=lex(lexstr) #peek at next token
call pbstr(lexstr)
call unstak(sp,lextyp,labval,token)}}
if(sp!=1)call synerr("unexpected eof.")
return
end
subroutine pbstr(in)#push string back on input
#called by balpar,deftok,eatup,forcod,parse
character in(arb)
for(i=length(in);i>0;i=i-1)call putbak(in(i))
return
end
subroutine putbak(c)#push character back on input
#called by gtok,pbstr,relate
character c
include RATCOMNS
bp=bp+1
if(bp>bufsize)call error("too many characters pushed back.")
buf(bp)=c
return
end
subroutine putch(c,f)
#called by putlin,synerr
character buf(maxline),c,c1,q1
integer f
data c1/'C'/,q1/'?'/
data lastc/0/
if(lastc>=maxline | c==newline){
if(lastc>0){
write(f,1,err=5)(buf(i),i=1,lastc)
goto 4
5 write(errout,1)c1,q1
4 continue
1 format(1x,maxcard a1)}# r1 where appropriate
lastc=0}
if(c!=newline){lastc=lastc+1
c=c&127 #strip sign
if(c<27)c=c+33 #map bomb chars into visible zone
buf(lastc)=c}
return
end
subroutine putlin(b,f)#put out line via putch
#called by instal,outdon,synerr
character b(arb)
integer f
for(i=1;b(i)!=eos;i=i+1)call putch(b(i),f)
return
end
subroutine relate(token,last,fd)
#called by gtok
#called by error,getdef,instal,synerr
character ngetch,token(arb),dotge(5),dotgt(5),dotle(5),
dotne(5),dotnot(6),doteq(5),dotand(6),dotor(5),dotlt(5)
integer fd
data dotge/period,letg,lete,period,eos/,
dotgt/period,letg,lett,period,eos/,
dotle/period,letl,lete,period,eos/,
dotlt/period,letl,lett,period,eos/,
dotne/period,letn,lete,period,eos/,
doteq/period,lete,letq,period,eos/,
dotor/period,leto,letr,period,eos/,
dotand/period,leta,letn,letd,period,eos/,
dotnot/period,letn,leto,lett,period,eos/
if(ngetch(token(2),fd)!=equals)call putbak(token(2))
if(token(1)==greater){
if(token(2)==equals)call scopy(dotge,1,token,1)
else call scopy(dotgt,1,token,1)}
else if(token(1)==less){
if(token(2)==equals)call scopy(dotle,1,token,1)
else call scopy(dotlt,1,token,1)}
else if(token(1)==not){
if(token(2)==equals)call scopy(dotne,1,token,1)
else call scopy(dotnot,1,token,1)}
else if(token(1)==equals){
if(token(2)==equals)call scopy(doteq,1,token,1)
else token(2)=eos}
else if(token(1)==amper)call scopy(dotand,1,token,1)
else if(token(1)==bar)call scopy(dotor,1,token,1)
else token(2)=eos#not recognized
last=length(token)
return
end
subroutine remark(buf)#warning message
#called by error,getdef,instal,synerr
character buf(arb),pct
data pct/'%'/
for(j=1;j<63&buf(j)!=period;j=j+1){
buf(j)=buf(j)&127
if(buf(j)<27)buf(j)=buf(j)+33}
write(errout,10,err=5)(buf(i),i=1,j)
10 format(1x,63a1)
return
5 write(errout,10)pct
return
end
subroutine repcod(lab)#begin repeat
#called by parse
call outcon(0)#in case there was a label
lab=labgen(3)
call outcon(lab)
lab=lab+1 #label for NEXTs
return
end
subroutine scopy(from,i,to,j)
#called by forcod,instal,lookup,relate
character from(arb),to(arb)
k2=j
for(k1=i;from(k1)!=eos;k1=k1+1){
to(k2)=from(k1)
k2=k2+1}
to(k2)=eos
return
end
subroutine synerr(msg)#report syntax error
#called by balpar,brknxt,eatup,forcod,gettok,gtok,labelc,parse
character lc(maxline),msg(maxline)
include RATCOMNS
call remark("error at line.")
do i=1,level
{call putch(blank,errout)
junk=itoc(linect(i),lc,maxline)
call putlin(lc,errout)}
call putch(colon,errout)
call putch(newline,errout)
call remark(msg)
return
end
character function type(c)#based on ascii
#called by alldig,gtok
character c
if(c>=dig0 & c<=dig9)type=digit
else if((c>=leta & c<=letz)|(c>=biga&c<=bigz))type=letter
else type=c
return
end
subroutine unstak(sp,lextyp,labval,token)#at statement end
#called by parse
integer labval(maxstack),sp
character lextyp(maxstack),token
for(;sp>1;sp=sp-1){
if(lextyp(sp)==lbrace|(lextyp(sp)==lexif&token==lexelse))
break
if(lextyp(sp)==lexif)call outcon(labval(sp))
else if(lextyp(sp)==lexelse){
if(sp>2)sp=sp-1
call outcon(labval(sp)+1)}
else if(lextyp(sp)==lexdo)call dostat(labval(sp))
else if(lextyp(sp)==lexwhile)call whiles(labval(sp))
else if(lextyp(sp)==lexfor)call fors(labval(sp))
else if(lextyp(sp)==lexrepeat)call untils(labval(sp),token)}
return
end
subroutine untils(lab,token)#generate end of repeat
#called by unstak
character ptoken(maxtok),token,junk,lex
call outnum(lab)
if(token==lexuntil){
junk=lex(ptoken)
call ifgo(lab-1)}
else call outgo(lab-1)
call outcon(lab+1)
return
end
subroutine whilec(lab)#begin while
#called by parse
call outcon(0) #in case there was a label
lab=labgen(2)
call outnum(lab)
call ifgo(lab+1)
return
end
subroutine whiles(lab)#end of while
#called by unstak
call outgo(lab)
call outcon(lab+1)
return
end