C RDLINE-	READ INPUT LINE
C
C COPYRIGHT 1980, INFOCOM COMPUTERS AND COMMUNICATIONS, CAMBRIDGE MA. 02142
C ALL RIGHTS RESERVED, COMMERCIAL USAGE STRICTLY PROHIBITED
C WRITTEN BY R. M. SUPNIK
C
C DECLARATIONS
C
	SUBROUTINE RDLINE(BUFFER,LENGTH,WHO)
	IMPLICIT INTEGER(A-Z)
	CHARACTER BUFFER(78)
#ifndef PDP
	character*78 sysbuf
#endif
#include "parser.h"
#include "io.h"

#ifdef PDP
5	if (WHO .eq. 1) call prompt
C	read a line of input
90	call rdlin(BUFFER,LENGTH)
#else
5	GO TO (90,10),WHO+1
C						!SEE WHO TO PROMPT FOR.
10	WRITE(OUTCH,50)
C						!PROMPT FOR GAME.
#ifdef NOCC
50	FORMAT('>',$)
#else NOCC
50	FORMAT(' >',$)
#endif NOCC

90	READ(INPCH,100, END=210) BUFFER
100	FORMAT(78A1)

	DO 200 LENGTH=78,1,-1
	  IF(BUFFER(LENGTH).NE.' ') GO TO 250
200	CONTINUE
	GO TO 5
C						!END OF FILE
210	STOP
C						!TRY AGAIN.

C
C	check for shell escape here before things are
C	converted to upper case
C
250	if (buffer(1) .ne. '!') go to 300
	do 275 j=2,length
	  sysbuf(j-1:j-1) = buffer(j)
275	continue
	sysbuf(length:length) = char(0)
	call system(sysbuf)
	go to 5

C CONVERT TO UPPER CASE
300	DO 400 I=1,LENGTH
 	  IF(and((BUFFER(I).GE.'a'),(BUFFER(I).LE.'z')))
&		BUFFER(I)=char(ichar(BUFFER(I))-32)
400	CONTINUE
#endif PDP

	if(LENGTH.EQ.0) GO TO 5
	PRSCON=1
C						!RESTART LEX SCAN.
	RETURN
	END
C PARSE-	TOP LEVEL PARSE ROUTINE
C
C DECLARATIONS
C
C THIS ROUTINE DETAILS ON BIT 0 OF PRSFLG
C
	LOGICAL FUNCTION PARSE(INBUF,INLNT,VBFLAG)
	IMPLICIT INTEGER(A-Z)
	CHARACTER INBUF(78)
	LOGICAL LEX,SYNMCH,VBFLAG
	INTEGER OUTBUF(40)
#include "debug.h"
#include "parser.h"
#include "xsrch.h"
C
#ifdef debug
	DFLAG=and(PRSFLG,1).NE.0
#endif
	PARSE=.FALSE.
C						!ASSUME FAILS.
	PRSA=0
C						!ZERO OUTPUTS.
	PRSI=0
	PRSO=0
C
#ifdef PDP
C	LEX recoded in C for pdp version (see lex.c)
	if(.not. lex(INBUF,INLNT,OUTBUF,OUTLNT,VBFLAG,PRSCON)) goto 100
#else
	IF(.NOT.LEX(INBUF,INLNT,OUTBUF,OUTLNT,VBFLAG)) GO TO 100
#endif
	IF(SPARSE(OUTBUF,OUTLNT,VBFLAG)) 100,200,300
C						!DO SYN SCAN.
C
C PARSE REQUIRES VALIDATION
C
200	IF(.NOT.VBFLAG) GO TO 350
C						!ECHO MODE, FORCE FAIL.
	IF(.NOT.SYNMCH(X)) GO TO 100
C						!DO SYN MATCH.
	IF(and((PRSO.GT.0),(PRSO.LT.XMIN))) LASTIT=PRSO
C
C SUCCESSFUL PARSE OR SUCCESSFUL VALIDATION
C
300	PARSE=.TRUE.
350	CALL ORPHAN(0,0,0,0,0)
C						!CLEAR ORPHANS.
#ifdef debug
	if(dflag) write(0,*) "parse good"
	IF(DFLAG) PRINT 10,PARSE,PRSA,PRSO,PRSI
#ifdef NOCC
10	FORMAT('PARSE RESULTS- ',L7,3I7)
#else NOCC
10	FORMAT(' PARSE RESULTS- ',L7,3I7)
#endif NOCC
#endif
	RETURN
C
C PARSE FAILS, DISALLOW CONTINUATION
C
100	PRSCON=1
#ifdef debug
	if(dflag) write(0,*) "parse failed"
	IF(DFLAG) PRINT 10,PARSE,PRSA,PRSO,PRSI
#endif
	RETURN
C
	END
C ORPHAN- SET UP NEW ORPHANS
C
C DECLARATIONS
C
	SUBROUTINE ORPHAN(O1,O2,O3,O4,O5)
	IMPLICIT INTEGER(A-Z)
	COMMON /ORPHS/ A,B,C,D,E
C
	A=O1
C						!SET UP NEW ORPHANS.
	B=O2
	C=O3
	D=O4
	E=O5
	RETURN
	END
#ifndef PDP
C LEX-	LEXICAL ANALYZER
C
C
C THIS ROUTINE DETAILS ON BIT 1 OF PRSFLAG
C
	LOGICAL FUNCTION LEX(INBUF,INLNT,OUTBUF,OP,VBFLAG)
	IMPLICIT INTEGER(A-Z)
	CHARACTER INBUF(78),J,DLIMIT(9)
	INTEGER OUTBUF(40),ZLIMIT(9)
	LOGICAL VBFLAG
#include "parser.h"
C
#include "debug.h"
C
c the System V compiler doesn't like octal initialization of character
c arrays, so the following is done for its benefit
c
c	DATA DLIMIT/'A','Z',o'100','1','9',o'22','-','-',o'22'/
c
	DATA ZLIMIT/o'101',o'132',o'100',o'61',o'71',o'22',o'55',o'55',o'22'/
c
	do 99 i=1,9
	  dlimit(i) = char(zlimit(i))
c					! copy integers to chars
99	continue
C
	DO 100 I=1,40
C						!CLEAR OUTPUT BUF.
	  OUTBUF(I)=0
100	CONTINUE
C
#ifdef debug
	DFLAG=and(PRSFLG,2).NE.0
#endif debug
	LEX=.FALSE.
C						!ASSUME LEX FAILS.
	OP=-1
C						!OUTPUT PTR.
50	OP=OP+2
C						!ADV OUTPUT PTR.
	CP=0
C						!CHAR PTR=0.
C
200	IF(PRSCON.GT.INLNT) GO TO 1000
C						!END OF INPUT?
	J=INBUF(PRSCON)
C						!NO, GET CHARACTER,
	PRSCON=PRSCON+1
C						!ADVANCE PTR.
	IF(J.EQ.'.') GO TO 1000
C						!END OF COMMAND?
	IF(J.EQ.',') GO TO 1000
C						!END OF COMMAND?
	IF(J.EQ.' ') GO TO 6000
C						!SPACE?
	DO 500 I=1,9,3
C						!SCH FOR CHAR.
	  IF(and((J.GE.DLIMIT(I)),(J.LE.DLIMIT(I+1))))
&		GO TO 4000
500	CONTINUE
C
	IF(VBFLAG) CALL RSPEAK(601)
C						!GREEK TO ME, FAIL.
	RETURN
C
C END OF INPUT, SEE IF PARTIAL WORD AVAILABLE.
C
1000	IF(PRSCON.GT.INLNT) PRSCON=1
C						!FORCE PARSE RESTART.
	IF(and((CP.EQ.0),(OP.EQ.1))) RETURN
	IF(CP.EQ.0) OP=OP-2
C						!ANY LAST WORD?
	LEX=.TRUE.
#ifdef debug
	IF(DFLAG) PRINT 10,CP,OP,PRSCON,(OUTBUF(I),I=1,OP+1)
#ifdef NOCC
10	FORMAT('LEX RESULTS- ',3I7/1X,10O7)
#else NOCC
10	FORMAT(' LEX RESULTS- ',3I7/1X,10O7)
#endif NOCC
#endif debug
	RETURN
C
C LEGITIMATE CHARACTERS: LETTER, DIGIT, OR HYPHEN.
C
4000	J1=ichar(J)-ichar(DLIMIT(I+2))
#ifdef debug
	IF(DFLAG) PRINT 20,J,J1,CP
#ifdef NOCC
20	FORMAT('LEX- CHAR= ',3I7)
#else NOCC
20	FORMAT(' LEX- CHAR= ',3I7)
#endif NOCC
#endif debug
	IF(CP.GE.6) GO TO 200
C						!IGNORE IF TOO MANY CHAR.
	K=OP+(CP/3)
C						!COMPUTE WORD INDEX.
	GO TO (4100,4200,4300),(MOD(CP,3)+1)
C						!BRANCH ON CHAR.
4100	J2=J1*780
C						!CHAR 1... *780
	OUTBUF(K)=OUTBUF(K)+J2+J2
C						!*1560 (40 ADDED BELOW).
4200	OUTBUF(K)=OUTBUF(K)+(J1*39)
C						!*39 (1 ADDED BELOW).
4300	OUTBUF(K)=OUTBUF(K)+J1
C						!*1.
	CP=CP+1
	GO TO 200
C						!GET NEXT CHAR.
C
C SPACE
C
6000	IF(CP.EQ.0) GO TO 200
C						!ANY WORD YET?
	GO TO 50
C						!YES, ADV OP.
C
	END
#endif PDP
