SUBROUTINE RECALC C RECALCULATE COMMAND C RECOMPUTE ALL ELEMENTS OF SPREADSHEET WHERE VALID. C INCLUDE 'VKLUGPRM.FTN' PARAMETER CUP=1,EL=12 C PARAMETER RRW = 32 C PARAMETER RCL = 32 ! REAL ROWS, COLS C PARAMETER DRW = 8 C PARAMETER DCL = 8 ! DISPLAY MAX ROWS, COLS. C PARAMETER RRCL = 1024 C PARAMETER RRCL=RRW*RCL C NOTE: THROUGHOUT, ROWS ARE ACTUALLY DOWN, COLUMNS ACROSS ON C SCREEN. ROW 0 IN DISPLAY IS THE 27 ACCUMULATORS A-Z AND %, WITH C % BEING THE LAST-COMPUTED VALUE FROM THE CALC PROGRAM, WHICH C KNOWS HOW TO ACCESS THE DATA BUT IS JUST PASSED COMMAND STRINGS C FROM THE DISK BASED FILE HERE. LOGICAL*1 FORM,FVLD,CMDLIN(132) INTEGER*4 VNLT INTEGER*2 FORMFG,RCFGX,PZAP,RCONE COMMON/FFGG/FORMFG,RCFGX,PZAP,RCONE DIMENSION FORM(128),FVLD(RRW,RCL) COMMON/FVLDC/FVLD C FVLD FLAG 0 = NO FORMULA, -1= DISPLAY FORMULA ITSELF, NOT VALUE C 1=VALID ACTIVE FORMULA THERE TO EVALUATE. INITIALLY ALL 0'S C SO INITIALLY IGNORE. C FVLD=-2 OR -3 = DISPLAY FORMULA C FVLD=3 NUMERIC, COMPUTE ONCE THEN SET FVLD TO 2 C FVLD=2 NUMERIC CONSTANT, ALREADY COMPUTED... DO NOT RECOMPUTE. C C ROUTINE IN2AS COMPUTES ASCII CHARACTER NAMES OF SUBSCRIPTS IN1,IN2 C SO DISPLAY CAN HAVE THEM. IT MUST BE THE INVERSE OF VARSCN. INTEGER*2 PROW,PCOL,DROW,DCOL,DRWV,DCLV COMMON/DCTL/PROW,PCOL,DROW,DCOL,DRWV,DCLV DIMENSION NRDSP(DRW,DCL),NCDSP(DRW,DCL) COMMON/D2R/NRDSP,NCDSP INTEGER*2 TYPE(RRW,RCL),VLEN(9) LOGICAL*1 AVBLS(100,27),VBLS(8,RRW,RCL) INTEGER*2 KDRW,KDCL COMMON /DOT/KDRW,KDCL COMMON/V/TYPE,AVBLS,VBLS,VLEN INTEGER*2 PRS,PCS,DRS,DCS PRS=PROW PCS=PCOL DRS=DROW DCS=DCOL C THE FOLLOWING 2 LOOPS DEFINE ORDER OF CALCULATION. C HERE THIS IS: OUTER LOOP ON ROWS (ACROSS), INNER LOOP ON COLUMNS (DOWN). DO 1 N2=1,RCL DO 2 N1=1,RRW IRRX=(N2-1)*RRW+N1 IF (FVLD(N1,N2).LE.0) GOTO 2 C IF CONSTANT WAS COMPUTED ALREADY, NO NEED TO RECOMPUTE. SKIP IT. C NOTE: WE MUST ALWAYS RECOMPUTE IF R COMMAND WAS GIVEN... IF ((RCONE.EQ.0).AND.(FVLD(N1,N2).EQ.2)) GOTO 2 KDRW=N1 KDCL=N2 PROW=N1 PCOL=N2 C SEE IF THIS PHYS COL HAS A DISPLAY COL. AND IF SO SET THAT UP. DO 10 M1=1,DRW DO 20 M2=1,DCL M1X=M1 M2X=M2 IF(NRDSP(M1,M2).EQ.N1.AND.NCDSP(M1,M2).EQ.N2)GOTO 9 20 CONTINUE 10 CONTINUE 9 CONTINUE C IF NO DISPLAY ROW, LEAVE AT LOW RIGHT... C USE SAVED VALUES SO WE DON'T RELY ON DO LOOP INDEX AFTER LOOP END. DROW=M1X DCOL=M2X READ(7'IRRX)FORM C NOW HAVE THE FORMULA LINE. PASS TO DOENTRY TO HANDLE IT. LLST=110 LFST=1 FORM(111)=0 IF(FORM(118).NE.15)GOTO 2 CALL DOENTR(FORM,LFST,LLST) C IF WE JUST COMPUTED A CONSTANT, FLAG IT COMPUTED AND SKIP IT. IF(FVLD(N1,N2).EQ.3)FVLD(N1,N2)=2 2 CONTINUE 1 CONTINUE PROW=PRS PCOL=PCS DROW=DRS DCOL=DCOL C FORCE FUNCTION WORKS ONCE ONLY. RCONE=0 RETURN END SUBROUTINE DOENTR(FORM,LOW,LHIGH) C +++++++++++++++++++++++++++++++++++ INCLUDE 'VKLUGPRM.FTN' PARAMETER CUP=1,EL=12 C PARAMETER RRW = 32 C PARAMETER RCL = 32 ! REAL ROWS, COLS C PARAMETER DRW = 8 C PARAMETER DCL = 8 ! DISPLAY MAX ROWS, COLS. C PARAMETER RRCL = 1024 C PARAMETER RRCL=RRW*RCL LOGICAL*1 FORM,FVLD,CMDLIN(132) INTEGER*4 VNLT DIMENSION FORM(128),FVLD(RRW,RCL) C FVLD FLAG 0 = NO FORMULA, -1= DISPLAY FORMULA ITSELF, NOT VALUE C 1=VALID ACTIVE FORMULA THERE TO EVALUATE. INITIALLY ALL 0'S C SO INITIALLY IGNORE. INTEGER*2 PROW,PCOL,DROW,DCOL,DRWV,DCLV COMMON/DCTL/PROW,PCOL,DROW,DCOL,DRWV,DCLV DIMENSION NRDSP(DRW,DCL),NCDSP(DRW,DCL) COMMON/D2R/NRDSP,NCDSP INTEGER*2 TYPE(RRW,RCL),VLEN(9) LOGICAL*1 AVBLS(100,27),VBLS(8,RRW,RCL) COMMON/V/TYPE,AVBLS,VBLS,VLEN COMMON/FVLDC/FVLD C +++++++++++++++++++++++++++++++++++ LCURR=LOW C DO AN ENTRY. MUST SCAN FOR MULTIPLE STATEMENTS PER LINE AND ALSO C RECOGNIZE FUNCTION NAMES. 1000 CONTINUE LSL=INDEX(FORM(LCURR),'\') IF(LSL.EQ.0)LSL=LHIGH C CLAMP AT 80 CHARS LONG INPUT. IF(LSL.LE.79)GOTO 1200 C STMT HAS NO MULTIPLES. SQUASH IT TO USE ONLY 1ST PART... LSL=79 LCURR=LHIGH FORM(80)=0 1200 CONTINUE CALL DOSTMT(FORM(LCURR),LSL) IF (LCURR.GE.LHIGH)RETURN LCURR=LCURR+LSL GOTO 1000 END SUBROUTINE DOSTMT(LINE,LLAST) C HANDLE 1 STATEMENT PARSING (DOES A BIT MORE OF THE WORK WITH THE C PART OF THE LINE STRIPPED TO HAVE EXACTLY ONE COMMAND IN IT. LOGICAL*1 LINE(110) C +++++++++++++++++++++++++++++++++++ INCLUDE 'VKLUGPRM.FTN' PARAMETER CUP=1,EL=12 C PARAMETER RRW = 32 C PARAMETER RCL = 32 ! REAL ROWS, COLS C PARAMETER DRW = 8 C PARAMETER DCL = 8 ! DISPLAY MAX ROWS, COLS. C PARAMETER RRCL = 1024 C PARAMETER RRCL=RRW*RCL LOGICAL*1 FORM,FVLD,CMDLIN(132) INTEGER*4 VNLT DIMENSION FORM(128),FVLD(RRW,RCL) C FVLD FLAG 0 = NO FORMULA, -1= DISPLAY FORMULA ITSELF, NOT VALUE C 1=VALID ACTIVE FORMULA THERE TO EVALUATE. INITIALLY ALL 0'S C SO INITIALLY IGNORE. COMMON/FVLDC/FVLD INTEGER*2 PROW,PCOL,DROW,DCOL,DRWV,DCLV COMMON/DCTL/PROW,PCOL,DROW,DCOL,DRWV,DCLV DIMENSION NRDSP(DRW,DCL),NCDSP(DRW,DCL) COMMON/D2R/NRDSP,NCDSP INTEGER*2 TYPE(RRW,RCL),VLEN(9) REAL*8 XVBLS(RRW,RCL) LOGICAL*1 AVBLS(100,27),VBLS(8,RRW,RCL) INTEGER*4 JVBLS(2,RRW,RCL) EQUIVALENCE(JVBLS(1,1,1),XVBLS(1,1)) EQUIVALENCE(VBLS(1,1,1),XVBLS(1,1)) COMMON/V/TYPE,AVBLS,VBLS,VLEN REAL*8 ACX,ACY EQUIVALENCE(ACY,AVBLS(1,27)) INTEGER*2 KDRW,KDCL COMMON /DOT/KDRW,KDCL LOGICAL*1 ILINE(106) INTEGER*2 ILNFG,ILNCT COMMON/ILN/ILNFG,ILNCT,ILINE C +++++++++++++++++++++++++++++++++++ CALL FNAME(LINE,LLAST,INDEXF) C ABOVE GETS FUNCTION NAMES. C NAME INDEXF C MIN 1 C MAX 2 C AVG 3 C SUM 4 C STD 5 (STD DEVIATION) C IF 6 (IF STMT) C USE [ AND ] TO DELIMIT FUNCTION ARGS. IF(INDEXF.LT.1.OR.INDEXF.GT.6)GOTO 1000 C HERE IF A FUNCTION OR AN IF STMT (FORMAT= IF [varRELvar]stmt|else-stmt) LLB=INDEX(LINE,'[') LRB=INDEX(LINE,']') C *** ERROR WITH FORMAT -- NO [ SEEN IN TIME. JUST IGNORE IT. IF(LLB.GT.LLAST)RETURN IF(LRB.GT.LLAST)LRB=LLAST IF(INDEXF.EQ.6)GOTO 2000 C ISOLATE MATH FUNCTIONS CALL DOMFCN(LINE,LLB,LRB,INDEXF,ACX) C GET % ABOVE IF(ABS(TYPE(KDRW,KDCL)).NE.2)GOTO 1760 XVBLS(KDRW,KDCL)=ACX C LEAVE RESULT IN % TOO. ACY=ACX TYPE(1,27)=TYPE(KDRW,KDCL) RETURN 1760 JVBLS(1,KDRW,KDCL)=ACX RETURN 2000 CONTINUE C HANDLE AN "IF" STATEMENT CALL DOIF(LINE,LLB,LRB,LLAST) C PASS LLAST TO DOIF SINCE WE DON'T EXPECT ] AS LAST CHAR OF STMT. C NO DIRECT SET OF VRBL HERE... RETURN 1000 CONTINUE C HERE JUST HAVE SOMETHING TO PASS TO CALC. DO SO. ILNFG=1 LMX=LLAST-1 DO 1001 N1=1,LMX 1001 ILINE(N1)=LINE(N1) ILNCT=LMX C PROTECT CALC FROM ANY PART OF A LINE LONGER THAN 80 CHARS (ITS MAX) IF(ILNCT.GT.80)ILNCT=80 CALL CALC C STORE EXPRESSION RESULT. XVBLS(KDRW,KDCL)=ACY RETURN END SUBROUTINE FNAME(LINE,LLAST,INDEXF) C RETURN FUNCTION NAME IF ANY LOGICAL*1 LINE(110) INTEGER*4 FNAM(6) LOGICAL*1 FCHNM(4,6) EQUIVALENCE(FNAM(1),FCHNM(1,1)) DATA FNAM/'MIN ','MAX ','AVG ','SUM ','STD ','IF '/ INDEXF=0 DO 1 N1=1,6 DO 2 N2=1,3 IF(LINE(N2).NE.FCHNM(N2,N1))GOTO 1 2 CONTINUE C IF WE FALL THROUGH, WE HAVE A VALID FCN NAME INDEX IN INDEXF INDEXF=N1 GOTO 3 1 CONTINUE 3 CONTINUE RETURN END SUBROUTINE TEST(LOGTYP,FLAG,V1,V2) INTEGER*2 FLAG,V1,V2 FLAG=0 IF(LOGTYP.EQ.1.AND.V1.GT.V2)FLAG=1 IF(LOGTYP.EQ.2.AND.V1.LT.V2)FLAG=1 IF(LOGTYP.EQ.3.AND.V1.EQ.V2)FLAG=1 IF(LOGTYP.EQ.4.AND.V1.NE.V2)FLAG=1 IF(LOGTYP.EQ.5.AND.V1.GE.V2)FLAG=1 IF(LOGTYP.EQ.6.AND.V1.LE.V2)FLAG=1 C TEST LOGICAL RELATIONS FOR IF STATEMENT, FLAG=1 IF TRUE, 0 ELSE. RETURN END SUBROUTINE MTHINI(INDEXF,AC,SS,CTR,ACX) REAL*8 AC,SS,CTR,ACX SS=0. CTR=0. ACX=0. AC=0. IF(INDEXF.EQ.1)AC=1.E20 IF(INDEXF.EQ.2)AC=-1.E20 RETURN END SUBROUTINE DOMATH(INDEXF,VAR,AC,SS,CTR,ACX) REAL*8 AC,SS,CTR,ACX REAL*8 VAR IF(INDEXF.NE.1)GOTO 100 IF(VAR.LT.AC)AC=VAR ACX=AC 100 IF(INDEXF.NE.2)GOTO 200 IF(VAR.GT.AC)AC=VAR ACX=AC 200 IF(INDEXF.NE.3)GOTO 300 AC=AC+VAR CTR=CTR+1. ACX=AC/CTR 300 IF(INDEXF.NE.4)GOTO 400 AC=AC+VAR ACX=AC 400 IF(INDEXF.NE.5)GOTO 500 AC=AC+VAR SS=SS+(VAR*VAR) CTR=CTR+1. ACX=(SS-((AC*AC)/CTR))/CTR 500 CONTINUE RETURN END SUBROUTINE DOMFCN(LINE,LLB,LRB,INDEXF,ACX) C LLB = LOC OF [ C LRB = LOC OF ] C INDEXF IS AS ABOVE. GUARANTEED IN RANGE 1-5. LOGICAL*1 LINE(110) C +++++++++++++++++++++++++++++++++++ INCLUDE 'VKLUGPRM.FTN' PARAMETER CUP=1,EL=12 C PARAMETER RRW = 32 C PARAMETER RCL = 32 ! REAL ROWS, COLS C PARAMETER DRW = 8 C PARAMETER DCL = 8 ! DISPLAY MAX ROWS, COLS. C PARAMETER RRCL = 1024 C PARAMETER RRCL=RRW*RCL LOGICAL*1 FORM,FVLD,CMDLIN(132) INTEGER*4 VNLT DIMENSION FORM(128),FVLD(RRW,RCL) C FVLD FLAG 0 = NO FORMULA, -1= DISPLAY FORMULA ITSELF, NOT VALUE C 1=VALID ACTIVE FORMULA THERE TO EVALUATE. INITIALLY ALL 0'S C SO INITIALLY IGNORE. INTEGER*2 PROW,PCOL,DROW,DCOL,DRWV,DCLV COMMON/DCTL/PROW,PCOL,DROW,DCOL,DRWV,DCLV DIMENSION NRDSP(DRW,DCL),NCDSP(DRW,DCL) COMMON/D2R/NRDSP,NCDSP INTEGER*2 TYPE(RRW,RCL),VLEN(9) REAL*8 XVBLS(RRW,RCL) LOGICAL*1 AVBLS(100,27),VBLS(8,RRW,RCL) INTEGER*4 JVBLS(2,RRW,RCL) EQUIVALENCE(JVBLS(1,1,1),XVBLS(1,1)) REAL*8 XXX EQUIVALENCE(VBLS(1,1,1),XVBLS(1,1)) COMMON/V/TYPE,AVBLS,VBLS,VLEN REAL*8 ACX,ACY REAL*8 AC,SS,CTR EQUIVALENCE(ACY,AVBLS(1,27)) INTEGER*2 KDRW,KDCL COMMON /DOT/KDRW,KDCL LOGICAL*1 ILINE(106) INTEGER*2 ILNFG,ILNCT COMMON/ILN/ILNFG,ILNCT,ILINE COMMON/FVLDC/FVLD C +++++++++++++++++++++++++++++++++++ C C FIRST GET A VARIABLE NAME. ALL MATH FUNCTIONS REQUIRE VARIABLE C NAMES SINCE THEIR VARIABLES ARE THEIR ONLY VALID ARGS. CALL MTHINI(INDEXF,AC,SS,CTR,ACX) C SET UP PROPER INITS C KV2=1 IF A 2ND VBL EXISTS LCR=LLB+1 100 CONTINUE KV2=0 LB=LCR LE=LRB-1 IF(LB.GE.LE)RETURN CALL VARSCN(LINE,LB,LE,LASST,ID1,ID2,IVALID) IF(IVALID.EQ.0)RETURN IF(LINE(LASST).NE.':')GOTO 110 LB=LASST+1 LE=LRB-1 CALL VARSCN(LINE,LB,LE,LASST,ID1B,ID2B,IVALID) IF(IVALID.NE.0)KV2=1 110 CONTINUE XXX=XVBLS(ID1,ID2) IF(ABS(TYPE(ID1,ID2)).NE.2)XXX=JVBLS(1,ID1,ID2) CALL DOMATH(INDEXF,XXX,AC,SS,CTR,ACX) IF(KV2.EQ.0)GOTO 200 IF(ID1.NE.ID1B) GOTO 120 IF(ID2.GT.ID2B)GOTO 200 M=ID2+1 DO 121 MM=M,ID2B XXX=XVBLS(ID1,MM) IF(ABS(TYPE(ID1,MM)).NE.2)XXX=JVBLS(1,ID1,MM) CALL DOMATH(INDEXF,XXX,AC,SS,CTR,ACX) 121 CONTINUE GOTO 200 120 CONTINUE IF(ID2.NE.ID2B)GOTO 130 IF(ID1.GT.ID1B)GOTO 200 M=ID1+1 DO 131 MM=M,ID1B XXX=XVBLS(MM,ID2) IF(ABS(TYPE(MM,ID2)).NE.2)XXX=JVBLS(1,MM,ID2) CALL DOMATH(INDEXF,XVBLS(MM,ID2),AC,SS,CTR,ACX) 131 CONTINUE 130 CONTINUE 200 CONTINUE C IF NEXT CHAR IS A COMMA, SKIP IT AND KEEP UP SCAN UNLESS DONE IF(LINE(LASST).EQ.',')GOTO 300 RETURN 300 LCR=LASST+1 GOTO 100 END SUBROUTINE DOIF(LINE,LLB,LRB,LLAST) INCLUDE 'VKLUGPRM.FTN' PARAMETER CUP=1,EL=12 LOGICAL*1 LINE(110) REAL*8 V1,V2 V1=0. V2=0. LS=LRB-LLB+1 CALL GETLOG(LINE(LLB),LS,LOGTYP,LASST) LOV1=LLB LHIV1=LASST+LLB-1 IF(LOV1.GE.LHIV1)GOTO 100 C USE SUM FUNCTION HERE AS TYPE OF FCN LT=4 CALL DOMFCN(LINE,LOV1,LHIV1,LT,V1) 100 CONTINUE IF(LOGTYP.EQ.0)GOTO 1000 LOV2=LASST+2+LLB LHIV2=LRB IF(LOV2.GE.LHIV2)GOTO 200 LT=4 CALL DOMFCN(LINE,LOV2,LHIV2,LT,V2) 200 CONTINUE CALL TEST(LOGTYP,LFLAG,V1,V2) D CALL UVT100(CUP,17,1) D WRITE(6,542)LOGTYP,LFLAG,LOV1,LHIV1,LOV2,LHIV2,V1,V2 D542 FORMAT('LTP,LFG,L,H.V1;L,H.V2,V1,2:',6I3,2F8.2) D CALL UVT100(CUP,18,1) IF(LFLAG.EQ.0)GOTO 700 C HERE HAVE "TRUE" ALTERNATIVE OF IF STMT LBAR=INDEX(LINE,'|') LBAR=MIN0(LBAR,LLAST) LSTM=LRB+1 C LSTM TO LBAR IS NOW THE STMT TO EVALUATE. SINCE WE ALREADY HAVE A C ROUTINE TO EVALUATE A STMT, DO SO. NOTE PARTIAL RECURSION, SO C NO NESTED IFS ALLOWED, AND CALL MUST PERMIT RECURSION ON YOUR C MACHINE OR FORGET IT. (OK ON PDP11, VAX). LSZ=LBAR-LSTM IF(LSZ.LT.1)GOTO 1000 CALL DOSTMT(LINE(LSTM),LSZ) GOTO 1000 700 CONTINUE C HERE HAVE "FALSE" ALTERNATIVE OF IF STMT LBAR=INDEX(LINE,'|')+1 LBAR=MIN0(LBAR,LLAST) LSZ=LLAST-LBAR IF(LSZ.LT.1)GOTO 1000 CALL DOSTMT(LINE(LBAR),LSZ) 1000 CONTINUE C THAT'S ALL. RETURN END SUBROUTINE GETLOG(LINE,LMX,LOGTYP,LASST) LOGICAL*1 LINE(110) LOGICAL*1 LFN(4,6) INTEGER*4 LF(6) EQUIVALENCE(LF(1),LFN(1,1)) DATA LF/'.GT.','.LT.','.EQ.','.NE.','.GE.','.LE.'/ C LOGTYP RELATIONSHIP TO RELATIONSHIPS OF 2 VARIABLES C IS DEFINED IN ABOVE DATA STMT. C IF LINE CONTAINS STRING IN NAME, RETURN TYPE AND END LOC. LMX4=LMX-3 DO 100 LL=1,6 LOGTYP=LL DO 1 N1=1,LMX4 IF(LINE(N1 ).NE.LFN(1,LL))GOTO 2 IF(LINE(N1+1).NE.LFN(2,LL))GOTO 2 IF(LINE(N1+2).NE.LFN(3,LL))GOTO 2 IF(LINE(N1+3).NE.LFN(4,LL))GOTO 2 C HERE HAVE A MATCH LASST=N1 C RETURN LOC OF NEXT CHAR AFTER RELATION. GOTO 200 2 CONTINUE 1 CONTINUE 100 CONTINUE LOGTYP=0 200 CONTINUE RETURN END