1 ! ! C R O S S - R E F E R E N C E G E N E R A T O R 2! PROGRAM : CREF 5! VERSION : 6B 6! EDIT : 06 7! EDIT DATE : 14-FEB-77 8! 9! AUTHOR : MARTIN MINOW 11 ! ! C O P Y R I G H T ! Copyright (C) 1974, 1975, 1976 ! Digital Equipment Corporation, Maynard, Massachusetts ! ! ! This software is furnished under a license for use only on a ! single computer system and may be copied only with the ! inclusion of the above copyright notice. This software, or ! any other copies thereof, may not be provided or otherwise ! made available to any other person except for use on such ! system and to one who agrees to these license terms. Title to ! and ownership of the software shall at all times remain in ! DIGITAL. ! ! The information in this software is subject to change without ! notice and should not be construed as a commitment by Digital ! Equipment Corporation. ! ! DIGITAL assumes no responsibility for the use or reliability ! of its software on equipment that is not supplied by DIGITAL. ! !******************************************************************** 20 ! ! M O D I F I C A T I O N H I S T O R Y 21! VER/ED EDIT DATE REASON ! 100 ! ! G E N E R A L D E S C R I P T I O N 110! CREF GENERATES A CROSS-REFERENCE LISTING OF BASIC-PLUS I COMPILED PROGRAMS. EACH USE OF A VARIABLE IS INDICATED IN ONE OF THREE USAGE TYPES: " " REFERENCE "@" DESTRUCTIVE REFERENCE "#" DEFINITION IN A "DEF FN" OR "DIM" STATEMENT. 120! WHEN RUN, CREF REQUESTS INPUT AND OUTPUT FILES, AND THE LINE-WIDTH OF THE OUTPUT FILE. THE DEFAULT EXTENSIONS ARE: .BAC INPUT FILE .CRF OUTPUT FILE 130! IT IS BEYOND THE SCOPE OF THIS DOCUMENT TO DESCRIBE THE INTERNAL FORMAT OF BASIC-PLUS. 300 ! ! I / O C H A N N E L S 301! CHANNEL # USED FOR ! 310! 1 FILE TO CREF 2 FILE TO CREF 3 OUTPUT FILE 800 ! ! F U N C T I O N / S U B R O U T I N E D E S C . 801! FUNCTION/SUBROUTINE USE ! 810! FNB0%(A%) READ A BYTE AT ADDRESS A% FNB1%(A%) READ A BYTE AT ADDRESS A% FNC%(A%,R%) SEARCH FOR A FUNCTION REFERENCE FNF$(Q0$,Q1$,Q2$) FILE NAME INPUT ROUTINE FNI%(A%) READ WORD AT A% + PROGRAM COUNTER FNL%(I%) INSERT A LINE NUMBER REFERENCE FNP%(Q%) PRINT AND COUNT LINES FNP$(Q%,L%) PRINT-USING EMULATOR FNP1$(Q) PRINT-USING EMULATOR FNR%(A%,R%) ADD A VARIABLE-REFERENCE FNS%(A%) SEARCH FOR A% IN THE HASH-TABLE FNT%(V$,A%) ADD V$ TO THE HASH-TABLE, KEY A% FNW0%(A%) READ A WORD AT ADDRESS A% FNW1%(A%) READ A WORD AT ADDRESS A% 900 ! ! D I M E N S I O N S T A T E M E N T S 910 DIM V$(316), A%(316), H%(316), T%(316) \N%,N8%=316%+3%\ N6%=N8%/2% ! VARIABLE TABLES (TABLE SIZE + 1 MUST BE PRIME) ! N8% TABLE SIZE + 3 (WILL BECOME SIZE + 1 AND PRIME) ! N6% TABLE SIZE / 2 920 DIM L%(2800), N%(2800)\ N9%=2800% ! LINE NUMBER TABLE AND POINTER TO NEXT REFERENCE ! N9% TABLE SIZE (N9% < 4096%) 930 DIM S$(3), B%(255), T0(5), T1(5), S(2,3) ! INTERNAL TABLES 940 DIM #1%, P0%(32767)\ DIM #2%, P1%(32767) ! BASIC-PLUS COMPILED CODE ! TWO ARRAYS ARE USED TO KEEP TWO BUFFERS IN CORE 950 ! INTERNAL TABLES: ! V$ VARIABLE NAME ! A% VARIABLE LOCATION -- SEARCH KEY IN HASH LOOKUP ! H% HEAD OF REFERENCE CHAIN ! T% TAIL OF REFERENCE CHAIN ! L% VARIABLE REFERENCE LINE NUMBER ! N% (NEXT REFERENCE)*4% + TYPE ! S$ MAPS REFERENCE TYPE ! B% INSTRUCTION TYPE CODE ! T0 CLOCK (TOTAL) TIME ! T1 CPU TIME ! S% PROGRAM SIZE VALUES 960 N8% = (N8% - 2%) OR 1% \GOTO 960 IF (N8%/Q%)*Q%=N8% FOR Q%=3% TO N8%/2% STEP 2% \PRINT "%Correct prime =";N8% IF N8%<>(N%-2%) !DOUBLE CHECK THAT HASH-TABLE SIZE IS CORRECT 999 ! ! M A I N C O D I N G A R E A 1000 ! ! G E T P A R A M E T E R S A N D S E T U P 1010 ON ERROR GOTO 0\ PRINT IF POS(0%) \PRINT "CREF"; CHR$(9%); "V06B-06"; CHR$(9%); CVT$$(RIGHT(SYS(CHR$(6%)+CHR$(9%)+CHR$(0%)),3%),4%) !SIGN ON 1020 I$=FNF$(" In","??????","BAC") \OPEN I$ FOR INPUT AS FILE 1%, MODE 8192% \OPEN I$ FOR INPUT AS FILE 2%, MODE 8192% \O$=FNF$("Out",Q$,"CRF")\ OPEN O$ FOR OUTPUT AS FILE 3% \W8%,W9%,T5%,T6%,T7%,T8%,T9%,N7%,E9%=0%\ H0,H1=0.0 !GET FILE NAME AND OPEN FILES. !NOTE THAT INPUT FILES ARE OPENED READ-ONLY !INITIALIZE ALL THE COUNTERS 1030 WHILE W9%<72% OR W9%>132% \INPUT "Listing width <80>"; W9%\ W9%=80% UNLESS W9% \NEXT !LOOK MA, I'M STRUCTURED 1040 GOSUB 14100\ RESTORE\ R$="" \READ S$(Q%) FOR Q%=0% TO 3%\ READ B%(Q%) FOR Q%=0% TO 255% \A%(Q%),H%(Q%)=0% FOR Q%=0% TO N8%-1% \P$="Cross Reference Listing of "+I$+" on " +DATE$(0%)+" at "+TIME$(0%) \P%,P1%=60%\ P2%=P1%-3%\ P3%=0%\ P%=FNP%(P1%) !INITIALIZE HASH TABLE AND COUNTERS !THEN PRINT HEADING NICELY CENTERED 1060 READ A%, Q$ \IF A% THEN R$=R$+Q$+","\ STOP UNLESS FNT%(Q$,A%)\ GOTO 1060 !SETUP SPECIAL NAMES 1070 S%=FNW1%(514%)\ S0%=FNW0%(S%+28%)\ S1%,P0%=FNW0%(S%+30%) \M0%=FNB0%(S%+38%)\ M1%=4%+2%*M0%-2%\ V0%=S0%+1214% !GET SP, SPDA, SPTA, SCTH, VARTAB !M0% FLOATING POINT PRECISION !M1% FLOATING POINT OFFSET !V0% OFFSET TO VARIABLE TABLE START 3000 ! ! B U I L D S Y M B O L T A B L E 3010 FOR U%=V0% TO V0%+50% STEP 2% \Q%=FNW1%(U%)\ GOTO 3070 UNLESS Q% \W%,W1%=U%+Q% !INITIALIZE FOR VARIABLE SEARCH 3014 A0$=CHR$((U%-V0%)/2% + 65%) !GET INITIAL LETTER 3016 W1%=W1%-1%\ Q%=FNB0%(W1%) \IF (Q% AND 128%)=0% THEN A0$=A0$+CHR$(Q%) IF Q%\ GOTO 3016 !A0$ := ENTIRE VARIABLE NAME 3020 A$=A0$\ W1%=W1% AND -2%\ T%=FNB0%(W1%) \IF T% AND 8% THEN F9%=28% ELSE IF T% AND 4% THEN F9%=08% ELSE IF T% AND 2% THEN F9%=M1% ELSE F9%=04% !T% VARIABLE TYPE !F9% OFFSET TO VARIABLE VALUE 3030 A$="FN"+A$ IF T% AND 16% \A$=A$+"%" IF T% AND 1% \A$=A$+"$" IF T% AND 4% \GOTO 3040 UNLESS T% AND 8% !FINISH OFF VARIABLE NAME, DEPENDING ON TYPE 3035 A$=A$+"("+NUM1$(FNW0%(W1%-6%)) \A$=A$+","+NUM1$(FNW0%(W1%-4%)) IF FNW0%(W1%-4%)<>0% \A$=A$+")"\ Q%=FNB0%(W1%-18%) \IF Q% THEN A$=A$+"="+NUM1$(2%*FNW0%(W1%-8%)) IF T% AND 4% \A$=A$+", #"+NUM1$(Q%/2%) !GET DIMENSIONS, STRING LENGTH AND CHANNEL 3040 GOTO 4000 UNLESS FNT%(A$,W1%-F9%-S0%)>=0% !NOW, STUFF THE CAREFULLY BUILT VARIABLE !USING IT'S ADDRESS AS THE KEY 3050 Q%=FNW0%(W1%-2%)\ IF Q% THEN W1%=Q%+W1%-1%\ GOTO 3020 !ANOTHER VARIABLE WITH THIS NAME AND DIFFERENT TYPE? 3060 Q%=FNW0%(W% )\ IF Q% THEN W%,W1%=Q%+W%\ GOTO 3014 !ANOTHER VARIABLE WITH THIS FIRST LETTER? 3070 NEXT U% \GOSUB 14100 !FINISH BUILDING THE VARIABLE TABLE 4000 ! ! F I N D A L L V A R I A B L E R E F E R E N C E S 4010 T%=FNW0%(P0%)\ GOTO 5000 IF T%=0% OR E9%\ P0%=P0%+T% \T%=FNB0%(P0%+9%)\ GOTO 4010 IF T%=4% OR T%=5% \L9%=FNW0%(P0%+10%) \L0%=FNW0%(P0%+04%)\ GOTO 4010 UNLESS L0% \P8%,P9%=FNW0%(P0%+02%)+P0%\ L1%=0%\ T7%=T7%+1% !NEW LINE SETUP - NOTHING TO DO IF DATA OR REMARK ! !VARIABLE USAGE: !P0% POINTER TO LINE HEADER !P8% POINTER TO START OF CODE FOR THIS LINE !P9% "PROGRAM COUNTER" WITHIN CODE !L0% OFFSET TO END OF THIS LINE'S CODE !L2% OFFSET TO NEXT CODE BYTE ! !LINE HEADER FORMAT: ! 0 OFFSET TO NEXT LINE ! 2 OFFSET TO FIRST CODE BYTE ! 4 OFFSET PAST END OF CODE FOR THIS LINE ! 9 LINE TYPE FLAG !10 LINE NUMBER 4020 IF T%=1% THEN L2%=FNR%(W%,3%) FOR W%=2% TO L0%-3% STEP 2% \GOTO 4010 !PROCESS A DIMENSION STATEMENT 4030 P9%=P8%+L1%\ T9%=T9%+1%\ ON B%(FNB1%(P9%)) GOSUB 10100,10200,10300,10400,10500,10600,10700,10800,10900, 11000,10600,11000,11000,11400,11500,11500,11700,11800,11900 !JUMP ON STATEMENT TYPE 4040 L1%=L1%+L2%+1%\ IF L1%>=L0% THEN 4010 ELSE 4030 !STEP POINTER TO NEXT PUSH-POP CODE, OR !GOTO NEXT STATEMENT 5000 ! ! S O R T S Y M B O L T A B L E 5010 N7%=-1%\ GOSUB 14100 \FOR Q%=0% TO N8%-1% \IF H%(Q%)<>0% THEN N7%=N7%+1%\ H%(N7%)=H%(Q%)\ V$(N7%)=V$(Q%) !COMPRESS OUT EMPTY SLOTS AND NON-REFERENCED VARIABLES 5020 NEXT Q% \A%=N7%+1% !DONE COMPRESSING, SETUP FOR SHELL SORT: !A% NUMBER OF VARIABLES 5030 WHILE A%>1% \A%=A%/2%\ B%=N7%-A%\ F%=-1% !OUTER LOOP SORT V$(0) TO V$(N7%): !A% CURRENT GAP (INITIALLY HALF) !B% HOW MANY TO EXAMINE !F% "SWITCH" FLAG, INITIALLY SET 5040 WHILE F% \F%=0% \FOR I%=0% TO B% \J%=I%+A% !WITHIN THIS GAP, LOOP UNTIL NO !MORE EXCHANGES ARE NEEDED !J% WHOM TO EXCHANGE WITH 5050 IF V$(I%)>V$(J%) THEN F%=-1% \Q$=V$(I%)\ V$(I%)=V$(J%)\ V$(J%)=Q$ \Q%=H%(I%)\ H%(I%)=H%(J%)\ H%(J%)=Q% !EXCHANGE NEEDED, SET FLAG, TOO 5060 NEXT I% !END OF SCAN LOOP 5070 NEXT !LOOP UNTIL NO MORE EXCHANGES 5080 NEXT !LOOP UNTIL THE GAP IS CLOSED 6000 ! ! P R I N T C R O S S - R E F E R E N C E S 6010 GOSUB 14100\ W8%=W8%+3%\ W0%=0% !PRINT THE HEADING 6020 FOR N%=0% TO N7% \H%=H%(N%)\ P%=FNP%(P2%)\ PRINT #3%, V$(N%); TAB(W8%); \R%,W%=0%\ R%,W%=1% IF ASCII(V$(N%)) = 35% !GET THE HEAD OF THE VARIABLE REFERENCE CHAIN. !THEN, FINISH OFF THE PREVIOUS LINE AND PRINT THE !VARIABLE NAME. CLEAR R/W FLAGS, SET IF LINE NUMBER. 6030 WHILE H%<>0% \Q%=N%(H%) AND 3% \R%=1% IF Q% = 0%\ W%=1% IF Q% = 1% OR Q% = 2% \IF POS(3%)+7%>W9% THEN P%=FNP%(P1%) \PRINT #3%, TAB(W8%); !NEW REFERENCE TO PRINT, SET READ/WRITE FLAGS !AND MAYBE GET A NEW LINE 6040 PRINT #3%, FNP$(L%(H%),6%);S$(Q%); \H%=N%(H%)/4% \NEXT !PRINT ALL THE REFERENCES 6080 IF R%+W% = 2% THEN V$(N%)="" ELSE IF INSTR(1%,R$,V$(N%)+",") <> 0% THEN V$(N%)="" ELSE W0%=-1% !IF BOTH READ AND WRITTEN, WIPE IT OUT, ELSE !SET THE "WE MUST PRINT THE REFERENCES" FLAG !UNLESS IT IS A PRE-DEFINED VARIABLE 6090 NEXT N% \P%=FNP%(P2%-4%)+1%\ PRINT #3%\ GOTO 7000 UNLESS W0% \PRINT #3%, "The following variables may not "; "have been referenced properly:" !FINISH PRINTING THE VARIABLES AND CHECK FOR ONCE-ONLY 6100 FOR N%=0% TO N7% \IF V$(N%) <> "" THEN P%=FNP%(P1%) IF POS(3%)+W8% > W9% \PRINT #3%, V$(N%); SPACE$(W8%-LEN(V$(N%))); !PRINT THE ONCE-ONLY STUFF 6110 NEXT N% \P%=FNP%(P2%)\ P%=FNP%(P2%) !PRINT ALL OF THEM 7000 ! ! P R I N T S T A T I S T I C S 7010 GOSUB 14100\ P%=FNP%(P2%-1%) \T0(5%)=T0(4%)+T0(4%)-T0(0%)\ T1(5%)=T1(4%)+T1(4%)-T1(0%) \PRINT #3%, FNP$(N7%,6%); " Variables"; \PRINT #3%, FNP$(T8%,6%); " References"; \PRINT #3%, FNP$(T7%,6%); " Statements"; \PRINT #3%, FNP$(T9%,6%); " Code elements" \IF T6%>0% THEN PRINT #3%, FNP$(T6%,22%); " Missed references" !SOME STATISTICS 7020 Q%=0%\ Q0%=S0%\ GOSUB 13500\ Q%=1%\ Q0%=S1%\ GOSUB 13400 \S(0%,0%)=S(0%,0%)+512%+FNW0%(S%+26%)-S% \S(0%,2%)=S(0%,2%)+FNW0%(S%+26%) !COLLECT SIZE DATA 7030 S(2%,Q%)=S(0%,Q%)+S(1%,Q%) FOR Q%=0% TO 3% \PRINT #3%\ PRINT #3%, "K-Words Reserved Used Free" !COLLECT DATA AND TEXT SIZES 7040 FOR Q%=0% TO 2% \Q1=(S(Q%,0%)-S(Q%,1%))/2048.0 \Q2=(S(Q%,2%)-S(Q%,3%))/2048.0 \PRINT #3%, MID(" Data Code Total",Q%*6%+1%,6%); FNP1$(Q2); FNP1$(Q1); FNP1$(Q2-Q1) \NEXT Q% !PRINT STUFF 7050 REM PRINT #3% \PRINT #3%, H0; "Hash table searches"; FNP1$(H1/H0); " Probes/Search"; FNP1$((N7%*100.0)/(N8%*1.0)); " Percent full" !PRINT HASH STATISTICS 7060 REM PRINT #3%\ PRINT #3% " Cpu Total time in seconds" \FOR Q%=1% TO 5%\ READ Q0$ \PRINT #3% FNP1$((T1(Q%)-T1(Q%-1%))/10.0); FNP1$(T0(Q%)-T0(Q%-1%)); " "; Q0$ \NEXT Q% !PRINT TIMINGS 7070 CLOSE 1%,2%,3%\ GOTO 32767 !DONE FOR NOW 10000 ! ! S U B R O U T I N E S 10010 ! ! SUBROUTINES TO PROCESS EACH BASIC-PLUS ! OPERATION TYPE. NOTE THAT THE TYPE CODES ! STORED ARE THE "ACTUAL" TYPES + 2 TO QUICKEN ! THE "ON ... GOSUB" STATEMENT ! ACTUAL TYPES ARE DEFINED IN "PPCODE.MAT" ! 10100 PRINT #3%, "Bad compiled code"; FNB1%(P9%); "At line";L9% !1 BAD CODE 10200 L2%=0%\ RETURN !2 NO ARGS 10300 L2%=FNR%(1%,0%)\ RETURN !3 1 NON-DES REF 10400 L2%=FNR%(1%,2%)\ RETURN !4 1 DES REF 10500 L2%=FNL%(1%)\ RETURN !5 LINE NUMBER 10600 L2%=2%\ RETURN !6 CONSTANT IGNORED 10700 W1%=FNB1%(P9%+1%)\ L2%=FNL%(W%) FOR W%=W1% TO 2% STEP -2% \L2%=W1%+1%\ RETURN !7 ON-GOTO LINES 10800 L2%=FNR%(1%,0%)+FNR%(3%,2%)\ RETURN !8 2 REF'S 10900 L2%=FNR%(1%,0%)+FNR%(3%,0%)+FNR%(5%,2%) \RETURN !9 3 REF'S 11000 PRINT #3%, "Illegial type or ";\ GOTO 10100 !10,12,13 WEIRDO'S 11400 L2%=FNC%(1%,3%)\ W%=FNW1%(FNI%(1%)+S0%+2%)\ W1%=2% !SETUP TO GET FUNCTION FORMAL PARAMETERS 11410 IF W% AND 3% THEN W1%=W1%+2%\ W%=W%/4%\ GOTO 11410 !STUPID LOOP TO COUNT ARGUMENTS 11420 L2%=FNR%(W%,1%) FOR W%=W1% TO 4% STEP -2% \L2%=W1%+1%\ RETURN !14 FUNCTION DEF 11500 L2%=6%\ RETURN !15,16 FOR, INT. MODIF. 11700 L2%=FNR%(1%,2%)+4%\ RETURN !17 EXTERNAL NEXT 11800 L2%=3%\ RETURN !18 SKIP TO FUN EXIT 11900 L2%=FNC%(1%,0%)\ RETURN !19 FUN CALL 11999 ! ! F U N C T I O N S 12000 ! ! HASH TABLE ROUTINES: ! FNC%(A%,R%) USED INSTEAD OF FNR% TO REFERENCE FUNCTIONS. ! FNL%(I%) INSERT A LINE NUMBER IN THE HASH TABLE ! AND A REFERENCE TO L9% IN THE REFERENCE TABLE. ! FNR%(A%,R%) INSERT A REFERENCE (TYPE R%) TO L9% IN THE ! REFERENCE TABLE FOR THE VARIABLE AT FNI%(A%). ! NOTE: VARIABLE TYPE 3 (DIMENSION DEFINITION) ! WILL BE CHANGED TO TYPE 1 (FUNCTION DEFINITION) ! IF THE VARIABLE IS A VIRTUAL ARRAY. ! FNS%(A%) SEARCH FOR A%, RETURN THE TABLE ADDRESS, ! OR ZERO IF THE TABLE IS FULL. THE VALUE ! IS ALSO RETURNED IN Q%. Q0%=0% IF NOT FOUND. ! FNT%(V%,A%) INSERT VARIABLE NAME V% INTO THE HASH TABLE ! USING SEARCH ARGUMENT A%. 12100 DEF FNC%(A%,R%) \A%=FNI%(A%)+4%\ STOP IF FNS%(A%) < 0% \GOSUB 12400\ FNC%=2% !SPECIAL REFERENCE FOR FUNCTION CALLS AND DEFINITIONS 12110 FNEND 12200 DEF FNL%(R%) \R%=FNI%(R%)\ R%=FNW0%(R%+S1%+10%) IF R% \R%=FNT%("#"+FNP$(R%,5%),R% OR (32767%+1%))\ R%=0% \GOSUB 12400\ FNL%=2% !MAKE A LINE NUMBER AND ADDRESS, STUFF IT !AND DO THE REFERENCE STUFF 12210 FNEND 12300 DEF FNR%(A%,R%) \A%=FNI%(A%)\ STOP IF FNS%(A%) < 0% \R%=1% IF R%=3% AND INSTR(1%,V$(Q%),"#") <> 0% \GOSUB 12400\ FNR%=2% !GET THE VARIABLE ADDRESS, FIND IT IN THE HASH TABLE, !AND DO THE REFERENCE STUFF. (PROGRAM ERROR IF FULL) 12310 FNEND 12400 RETURN UNLESS Q0%\ T8%=T8%+1% \IF T8%>N9% THEN T6%=T6%+1% \RETURN IF T8%>N9%+1% \PRINT #3%, "More than";N9%;" References at line";L9% \P%=P%+1%\ PRINT "%Reference table full" \RETURN !STEP REFERENCE COUNTER, ERROR MESSAGE IF TROUBLE 12420 L%(T8%)=L9%\ N%(T8%)=R% \IF H%(Q%)=0% THEN H%(Q%),T%(Q%)=T8% ELSE N%(T%(Q%))=N%(T%(Q%))+(T8%*4%)\ T%(Q%)=T8% !STUFF THE REFERENCE (TYPE R%), SETUP THE CHAIN, TOO 12430 RETURN !NORMAL EXIT FROM REFERENCE STUFFER 12500 DEF FNS%(A%) \H0=H0+1.0\ Q%=(A% XOR SWAP%(A%)) AND 32767% \Q%=Q%-(Q%/N8%)*N8%\ Q1%=N6% !QUADRATIC HASH SETUP 12510 Q0%=A%(Q%)\ H1=H1+1.0 \IF Q0%=A% OR Q0%=0% THEN FNS%=Q%\ GOTO 12540 !LOOK AT THIS LOCATION 12520 Q1%=Q1%-1% \IF Q1% THEN Q%=Q%+Q1%\ Q%=Q%-N8% IF Q%>=N8%\ GOTO 12510 !NOT HERE, GET A NEW PROBE UNLESS WE'RE FULL UP. 12530 E9%=-1%\ Q%,FNS%=-1% \PRINT #3%, N8%; "Variable table is full after"; N7%; " Inserts" \P%=P%+1%\ PRINT "%Variable table full" !PRINT THE BAD NEWS 12540 FNEND 12700 DEF FNT%(V$,A%) \FNT%=FNS%(A%) \IF Q% >= 0% AND Q0%=0% THEN Q0%,A%(Q%)=A%\ V$(Q%)=V$\ N7%=N7%+1% \W8%=LEN(V$) IF LEN(V$)>W8% !STUFF THE VARIABLE IF NOT ALREADY PRESENT !MAINTAIN MAXIMUM VARIABLE LENGTH 12710 FNEND 12800 DEF FNP%(Q%) !PRINT , AND COUNT LINES, !PRINT A HEADING IF WE ARE AT LINE Q% 12810 PRINT #3%\ P%=P%+1% \IF P% > Q% THEN P3%=P3%+1% \PRINT #3%, CHR$(12%); TAB((W9%-LEN(P$)-8%)/2%);P$;TAB(W9%-7%);"Page";P3% \PRINT #3%\ P%=2% !COUNT LINES, WHEN WE REACH THE BOTTOM, SKIP TO !THE TOP AND RESET THE COUNTER 12820 FNP%=P% !RETURN THE CORRECT COUNT 12830 FNEND 13000 ! ! FUNCTIONS TO ACCESS COMPILED BASIC-PLUS FILES ! FNW0%(A%) READ THE WORD AT ADDRESS A% FROM VECTOR 0% ! FNW1%(A%) READ THE WORD AT ADDRESS A% FROM VECTOR 1% ! FNB0%(A%) READ THE BYTE AT ADDRESS A% FROM VECTOR 0% ! FNB1%(A%) READ THE BYTE AT ADDRESS A% FROM VECTOR 1% ! FNI%(A%) READ THE WORD LOCATED AT RELATIVE PC ADDRESS I% 13100 DEF FNW0%(A%)=P0%(A%/2% - 256%) 13110 DEF FNW1%(A%)=P1%(A%/2% - 256%) 13200 DEF FNB0%(A%) \F%=FNW0%(A%) \IF A% AND 1% THEN FNB0% = SWAP%(F%) AND 255% ELSE FNB0% = F% AND 255% !GET THE CORRECT BYTE 13210 FNEND 13300 DEF FNB1%(A%) \F%=FNW1%(A%) \IF A% AND 1% THEN FNB1% = SWAP%(F%) AND 255% ELSE FNB1% = F% AND 255% !GET THE CORRECT BYTE 13310 FNEND 13400 DEF FNI%(I%) = SWAP%(FNB1%(P9%+I%)) + FNB1%(P9%+I%+1%) !GET A WORD RELATIVE TO THE CURRENT PROGRAM COUNTER 13500 S(Q%,Q1%)=FNW0%(Q0%+Q1%+Q1%+6%) FOR Q1%=0% TO 3% \RETURN !GET SIZE VALUES FROM SPXA HEADER 14000 DEF FNF$(Q0$,Q1$,Q2$) ! FNF$(PROMPT, FILE, EXTENSION) ! PROMPT AND RETURN A FILE NAME ! THE FILE NAME PART IS RETURNED IN Q$ 14010 ON ERROR GOTO 14040 \PRINT Q0$; "put file <"; Q1$; "."; Q2$; "> "; \INPUT LINE Q0$\ Q0$=CVT$$(Q0$,-1%)\ Q0$=Q1$ IF Q0$ = "" \Q0$=Q0$+"."+Q2$ UNLESS INSTR(1%,Q0$,".") \Q$=LEFT(Q0$,INSTR(1%,Q0$,".")-1%) \FNF$=Q0$ 14020 ON ERROR GOTO 0 14030 FNEND 14040 IF ERR=11% THEN RESUME 32766 ELSE ON ERROR GOTO 0 14100 T0(T5%)=TIME(0)\ T1(T5%)=TIME(1)\ T5%=T5%+1%\ RETURN !SUBROUTINE TO COLLECT SOME STATISTICS 14200 DEF FNP$(Q%,L%) !RETURN Q% RIGHT-JUSTIFIED IN A L% FIELD 14210 Q$=NUM1$(Q%)\ FNP$=SPACE$(L%-LEN(Q$))+Q$ !CONVERT THE VALUE 14220 FNEND 14300 DEF FNP1$(Q) !RETURN Q IN A 10-BYTE FIELD, WITH 2 DECIMAL PLACES 14310 Q$=NUM1$(INT(Q*100.0 + .5)/100.0 + .001) \FNP1$=SPACE$(11%-LEN(Q$))+LEFT(Q$,LEN(Q$)-1%) !CONVERT IT 14320 FNEND 20000 ! ! D A T A T A B L E S 20010 DATA " ","#","@","#" 20099 ! ! PUSH-POP TYPE CODE TABLE. NOTE THAT THE VALUES ! ARE TWO GREATER THAN THE "ACTUAL" TYPES TO SIMPLIFY ! THE ON "TYPE" GOSUB ... STATEMENT ! ACTUAL TYPES ARE TAKEN FROM THE "PPCODE" PROGRAM ! 21000 DATA 02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,02 21010 DATA 02,02,06,02,02,05,07,04,03,04,03,03,04,04,04,04 21020 DATA 08,08,04,04,08,09,09,09,02,02,02,02,02,02,02,02 21030 DATA 07,05,02,19,02,02,18,02,03,02,01,01,02,01,01,02 21040 DATA 02,02,02,02,01,01,01,01,01,01,01,01,03,02,02,04 21050 DATA 04,02,02,02,02,13,02,02,11,02,02,02,02,04,04,04 21060 DATA 04,04,04,04,04,04,02,02,02,02,02,02,02,02,02,02 21070 DATA 02,02,02,02,02,02,02,02,06,02,01,01,01,01,01,01 21080 DATA 02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,02 21090 DATA 02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,02 21100 DATA 02,02,02,03,03,03,04,04,04,04,04,04,03,03,04,04 21110 DATA 04,04,04,04,04,04,04,04,04,04,04,04,04,04,02,02 21120 DATA 02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,02 21130 DATA 02,02,02,02,02,02,11,05,11,05,11,05,14,02,05,02 21140 DATA 02,02,02,02,02,02,02,02,02,02,02,15,15,15,15,15 21160 DATA 15,15,15,16,16,17,17,02,02,02,02,02,02,02,02,02 22000 ! ! RESERVED WORD TABLE. THE TABLE MUST END WITH THE ENTRY: ! DATA 0,"" ! ! NOTE THAT THE TABLE MUST BE KEPT IN SORTED ORDER 22010 DATA -24,DET, -60,ERL, -26,ERR, -58,LINE, -30,NUM, -34,NUM2, -16,PI, -54,RECOUNT, -62,STATUS, 0,"" 23000 DATA "Variable table setup", "Variable reference collection", "Variable table sort", "Cross-reference printout", "Total processing" 32766 CLOSE Q% FOR Q%=1% TO 12% 32767 END