C SYNMCH-- SYNTAX MATCHER
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 THIS ROUTINE DETAILS ON BIT 4 OF PRSFLG
LOGICAL FUNCTION SYNMCH()
C THE FOLLOWING DATA STATEMENT WAS ORIGINALLY:
DFLAG=and(PRSFLG, 16).NE.0
if(dflag) write(0,*) "synflags=",sdir,sind,sstd,sflip,sdriv,svmask
IF((VVOC(J).LE.0).OR.(VVOC(J).GE.R50MIN)) GO TO 100
IF(DFLAG) PRINT 60,O1,P1,DOBJ,DFL1,DFL2
60 FORMAT('SYNMCH INPUTS TO SYNEQL- ',5I7)
60 FORMAT(' SYNMCH INPUTS TO SYNEQL- ',5I7)
IF(.NOT.SYNEQL(P1,O1,DOBJ,DFL1,DFL2)) GO TO 1000
IF(DFLAG) PRINT 60,O2,P2,IOBJ,IFL1,IFL2
IF(SYNEQL(P2,O2,IOBJ,IFL1,IFL2)) GO TO 6000
C SYNTAX MATCH FAILS, TRY NEXT ONE.
1000 IF(O1) 3000,500,3000
500 IF((QPREP.EQ.0).OR.(QPREP.EQ.SPREP)) DFORCE=J
IF((and(VFLAG,SDRIV)).NE.0) DRIVE=J
C MATCH HAS FAILED. IF DEFAULT SYNTAX EXISTS, TRY TO SNARF
C ORPHANS OR GWIMS, OR MAKE NEW ORPHANS.
IF(DFLAG) PRINT 20,DRIVE,DFORCE
20 FORMAT('SYNMCH, DRIVE=',2I6)
20 FORMAT(' SYNMCH, DRIVE=',2I6)
IF(DRIVE.EQ.0) DRIVE=DFORCE
IF(DRIVE.EQ.0) GO TO 10000
CALL UNPACK(DRIVE,DFORCE)
C TRY TO FILL DIRECT OBJECT SLOT IF THAT WAS THE PROBLEM.
IF((and(VFLAG,SDIR).EQ.0).OR.(O1.NE.0)) GO TO 4000
C FIRST TRY TO SNARF ORPHAN OBJECT.
IF(SYNEQL(P1,O1,DOBJ,DFL1,DFL2)) GO TO 4000
C ORPHAN FAILS, TRY GWIM.
3500 O1=GWIM(DOBJ,DFW1,DFW2)
30 FORMAT('SYNMCH- DO GWIM= ',I6)
30 FORMAT(' SYNMCH- DO GWIM= ',I6)
CALL ORPHAN(-1,ACT,0,and(DOBJ,VPMASK),0)
C TRY TO FILL INDIRECT OBJECT SLOT IF THAT WAS THE PROBLEM.
4000 IF((and(VFLAG,SIND).EQ.0).OR.(O2.NE.0)) GO TO 6000
40 FORMAT('SYNMCH- IO GWIM= ',I6)
40 FORMAT(' SYNMCH- IO GWIM= ',I6)
IF(O1.EQ.0) O1=and(OFLAG,OSLOT)
CALL ORPHAN(-1,ACT,O1,and(DOBJ,VPMASK),0)
C NOW TRY TO TAKE INDIVIDUAL OBJECTS AND
C IN GENERAL CLEAN UP THE PARSE VECTOR.
6000 IF(and(VFLAG,SFLIP).EQ.0) GO TO 5000
5000 PRSA=and(VFLAG,SVMASK)
IF(.NOT.TAKEIT(PRSO,DOBJ)) RETURN
IF(.NOT.TAKEIT(PRSI,IOBJ)) RETURN
IF(DFLAG) PRINT 50,SYNMCH,PRSA,PRSO,PRSI,ACT,O1,O2
50 FORMAT('SYNMCH- RESULTS ',L1,6I7)
50 FORMAT(' SYNMCH- RESULTS ',L1,6I7)
C UNPACK- UNPACK SYNTAX SPECIFICATION, ADV POINTER
SUBROUTINE UNPACK(OLDJ,J)
IF(and(VFLAG,SDIR).EQ.0) RETURN
IF(and(VFLAG,SSTD).EQ.0) GO TO 100
IF(and(DOBJ,VEBIT).EQ.0) GO TO 200
200 IF(and(VFLAG,SIND).EQ.0) RETURN
IF(and(IOBJ,VEBIT).EQ.0) RETURN
C SYNEQL- TEST FOR SYNTAX EQUALITY
LOGICAL FUNCTION SYNEQL(PREP,OBJ,SPREP,SFL1,SFL2)
SYNEQL=(PREP.EQ.and(SPREP,VPMASK)).AND.
& (or(and(SFL1,OFLAG1(OBJ)),
& and(SFL2,OFLAG2(OBJ))).NE.0)
100 SYNEQL=(PREP.EQ.0).AND.(SFL1.EQ.0).AND.(SFL2.EQ.0)
C TAKEIT- PARSER BASED TAKE OF OBJECT
LOGICAL FUNCTION TAKEIT(OBJ,SFLAG)
COMMON /STAR/ MBASE,STRBIT
IF((OBJ.EQ.0).OR.(OBJ.GT.STRBIT)) GO TO 4000
IF((X.EQ.0).OR.(and(SFLAG,VFBIT).EQ.0)) GO TO 500
IF(and(OFLAG2(X),OPENBT).NE.0) GO TO 500
500 IF(and(SFLAG,VRBIT).EQ.0) GO TO 1000
IF(and(SFLAG,VTBIT).EQ.0) GO TO 2000
C SHOULD BE IN ROOM (VRBIT NE 0) AND CAN BE TAKEN (VTBIT NE 0)
IF(SCHLST(0,0,HERE,0,0,OBJ).LE.0) GO TO 4000
C ITS IN THE ROOM AND CAN BE TAKEN.
IF((and(OFLAG1(OBJ),TAKEBT).NE.0).AND.
& (and(OFLAG2(OBJ),TRYBT).EQ.0)) GO TO 3000
C NOT TAKEABLE. IF WE CARE, FAIL.
IF(and(SFLAG,VCBIT).EQ.0) GO TO 4000
C 1000-- IT SHOULD NOT BE IN THE ROOM.
C 2000-- IT CANT BE TAKEN.
2000 IF(and(SFLAG,VCBIT).EQ.0) GO TO 4000
1000 IF(SCHLST(0,0,HERE,0,0,OBJ).LE.0) GO TO 4000
C OBJECT IS IN THE ROOM, CAN BE TAKEN BY THE PARSER,
C AND IS TAKEABLE IN GENERAL. IT IS NOT A STAR.
C TAKING IT SHOULD NOT HAVE SIDE AFFECTS.
C IF IT IS INSIDE SOMETHING, THE CONTAINER IS OPEN.
C THE FOLLOWING CODE IS LIFTED FROM SUBROUTINE TAKE.
3000 IF(OBJ.NE.AVEHIC(WINNER)) GO TO 3500
3500 IF(((X.NE.0).AND.(OADV(X).EQ.WINNER)).OR.
& ((WEIGHT(0,OBJ,WINNER)+OSIZE(OBJ)).LE.MXLOAD))
3700 CALL NEWSTA(OBJ,559,0,0,WINNER)
OFLAG2(OBJ)=or(OFLAG2(OBJ),TCHBT)
C GWIM- GET WHAT I MEAN IN AMBIGOUS SITUATIONS
INTEGER FUNCTION GWIM(SFLAG,SFW1,SFW2)
COMMON /STAR/ MBASE,STRBIT
NOCARE=and(SFLAG,VCBIT).EQ.0
C FIRST SEARCH ADVENTURER
IF(and(SFLAG,VABIT).NE.0)
& NOBJ=FWIM(SFW1,SFW2,0,0,WINNER,NOCARE)
IF(and(SFLAG,VRBIT).NE.0) GO TO 100
100 ROBJ=FWIM(SFW1,SFW2,HERE,0,0,NOCARE)
200 IF((AV.EQ.0).OR.(ROBJ.EQ.AV).OR.
& (and(OFLAG2(ROBJ),FINDBT).NE.0)) GO TO 300
IF(OCAN(ROBJ).NE.AV) GO TO 50
IF(.NOT.TAKEIT(ROBJ,SFLAG)) RETURN