perm filename XREF.SAI[S,AIL]1 blob sn#000821 filedate 1972-09-29 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00009 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00002 00002	BEGIN "XREF"
 00005 00003	INTEGER PROCEDURE MIN(INTEGER X,Y)
 00007 00004	FIRST COMPUTE OPTIMAL NUMBER OF PASSES
 00008 00005	FOR NUM←1 STEP 1 UNTIL NUMS DO
 00009 00006	FOR NUMS←1 STEP 1 UNTIL PASSES DO
 00010 00007	INTEGER PROCEDURE LOOKUP(STRING A)
 00013 00008	INTEGER PROCEDURE LOOKUP(STRING A)
 00014 00009	DEFINE PGMRK= "'201004020101",WUN="'1000000",EXECBIT="'400000000000",
 00019 ENDMK
⊗;
BEGIN "XREF"
DEFINE GOODSWT = "NULL";
DEFINE SWTSIZ = "1";
DEFINE PROCESSOR = """XREF""";
DEFINE SRCEXT = "NULL";
DEFINE RELEXT = """XRF""";
DEFINE LSTEXT = """LST""";
DEFINE RELMODE = "0";
DEFINE SRCMODE = "0";
DEFINE LSTMODE = "0";

REQUIRE "SCNCMD[1,DCS]" SOURCE_FILE;
DEFINE ⊂ = " BEGIN ", ⊃ = " END ",! = " COMMENT ";
DEFINE OTPT="2",SLOUGH="1",IDSCAN="2",CMNT="3",EXSCAN= "4",
	CHKEOF= "IF SRCEOF THEN GO TO PASS2",LBLBIT= "'400000",
	L_HALF(X)= "((X LSH (-18))LAND '377777)", R_HALF(X)= "(X LAND '377777)";
DEFINE TAB="'11",SYMNO="4092",FORM="'14",BITS2="'400000400000";
INTEGER WASTHERE,CURLIN,L_PTR,K,NN,KK,L,SYMBOL,I,CURPAGE,EXECHK,III,
	NP,KP,L_SIZE;
STRING FOO,NEWNAM,LETS,DIGS;
INTEGER ARRAY LTAB[0:4095];
OUTSTR("HOW MUCH LIST SPACE?");
FOO← INCHWL;
L_SIZE← INTSCAN(FOO,NN);

BEGIN INTEGER ARRAY L_SPACE[2:L_SIZE+1];

LABEL L1,PASS2,L2,L3;
STRING ARRAY SYM[0:4095];

INTEGER PROCEDURE NODE(INTEGER A,B);
	⊂ L_PTR← L_PTR+2;
	IF L_PTR > L_SIZE THEN USERERR(0,0,"L_SPACE FULL");
	L_SPACE[L_PTR]← A LOR CURPAGE;
	L_SPACE[L_PTR+1]← B;
	RETURN(L_PTR)
	END;
Comment Generalized sort routine.

The input and output arrays must be (the same) 
power of two in length, starting at 0 or 0,0.  For
efficiency you may remove the arrays from the
calling sequence and replace references to INS
and OUTS by your own global variable names;




PROCEDURE SORT( STRING ARRAY INS; INTEGER ARRAY INDATA;
      INTEGER SIZE);

BEGIN "SORT"
   INTEGER BASE,GROUP,NUMS,NUM,I,J,K,L,PASSES;
   STRING ARRAY OUTS[0:SIZE-1]; 
   INTEGER ARRAY OUTDATA[0:SIZE-1];
   STRING S1,S2;
Comment the first phase sorts groups of SIZE/(2↑PASSES)
strings into alphameric order. Subsequent phases will then
merge these groups, forming larger groups. An odd number
of passes will result in the input array containing the final
result;

INTEGER PROCEDURE MIN(INTEGER X,Y);
 RETURN(IF X<Y THEN X ELSE Y);

BOOLEAN PROCEDURE STRINGLESS(STRING A,B);
BEGIN
   INTEGER CHA,CHB,I;
   IF LENGTH(B)=0 THEN RETURN(TRUE);
   IF LENGTH(A)=0 THEN RETURN(FALSE);
   FOR I←1 STEP 1 UNTIL MIN(LENGTH(A),LENGTH(B)) DO
   BEGIN
      CHA←A[I FOR 1];  CHB←B[I FOR 1];
      IF CHA<CHB THEN RETURN(TRUE);
      IF CHA>CHB THEN RETURN(FALSE);
   END;
   RETURN(IF LENGTH(A)≤LENGTH(B) THEN TRUE ELSE FALSE) 
END;


COMMENT FIRST COMPUTE OPTIMAL NUMBER OF PASSES;

J←SIZE;
FOR PASSES←-2 STEP 1 UNTIL 1000 DO
BEGIN
   J←J LSH -1;
   IF J=0 THEN DONE
END;
IF PASSES<1 THEN PASSES←1;


NUMS←2↑PASSES ; COMMENT NUMBER OF GROUPS;
GROUP←SIZE%NUMS ; COMMENT SIZE OF EACH GROUP;
BASE←0;
FOR NUM←1 STEP 1 UNTIL NUMS DO
BEGIN "SORT PHASE"
   INTEGER FLAG,I,J,K; LABEL BACK; STRING A;
   I←BASE+GROUP-1;
   K←0;

BACK:
   FLAG←FALSE;
   K←K+1;

   FOR J←BASE STEP 1 UNTIL I-K DO
   IF ¬STRINGLESS(S1←INS[J],S2←INS[J+1]) THEN
   BEGIN
      INS[J]←S2;
      INS[J+1]←S1;
      INDATA[J] ↔ INDATA[J+1];
      FLAG←TRUE
   END;

   IF FLAG THEN GO TO BACK;

   BASE←I+1

END "SORT PHASE";



FOR NUMS←1 STEP 1 UNTIL PASSES DO
BEGIN "MERGE PHASE"
INTEGER LIM;

LIM←SIZE%(2*GROUP);

FOR NUM←1 STEP 1 UNTIL LIM DO
BEGIN 
   I←2*(NUM-1)*GROUP;
   J←(2*NUM-1)*GROUP;
   K←2*NUM*GROUP;
   L←J;


   IF NUMS MOD 2 = 1 THEN
   FOR BASE←I STEP 1 UNTIL K-1 DO
   BEGIN
      IF I<L THEN S1←INS[I] ELSE S1←NULL;
      IF J<K THEN S2←INS[J] ELSE S2←NULL;
      IF J=K ∨ I≠L ∧  STRINGLESS(S1,S2) THEN 
      BEGIN
         OUTS[BASE]←S1;
         OUTDATA[BASE]←INDATA[I];
         I←I+1
      END ELSE

      BEGIN
         OUTS[BASE]←S2;
         OUTDATA[BASE]←INDATA[J];
         J←J+1
      END
   END

   ELSE
   FOR BASE←I STEP 1 UNTIL K-1 DO
   BEGIN
      IF I<L THEN S1←OUTS[I] ELSE S1←NULL;
      IF J<K THEN S2←OUTS[J] ELSE S2←NULL;
      IF J=K ∨ I≠L ∧  STRINGLESS(S1,S2) THEN 
      BEGIN
         INS[BASE]←S1;
         INDATA[BASE]←OUTDATA[I];
         I←I+1
      END ELSE

      BEGIN
         INS[BASE]←S2;
         INDATA[BASE]←OUTDATA[J];
         J←J+1
      END
   END;


   IF J≠K OR I≠L THEN BEGIN INTEGER X; X←CALL(0,"EXIT")END;

END;

   GROUP←GROUP*2
END "MERGE PHASE";

IF PASSES MOD 2 = 1 THEN
FOR I←0 STEP 1 UNTIL SIZE-1 DO
BEGIN
   INDATA[I]←OUTDATA[I];
   INS[I]←OUTS[I]
END  

END "SORT";
INTEGER PROCEDURE LOOKUP(STRING A);
BEGIN "LOOKUP"
 INTEGER H,Q,R;
 DEFINE SCON="10";

 H←CVASC(A) +LENGTH(A) LSH 6;
 R←SYMBOL←(H←ABS(H⊗(H LSH 2))) MOD (SYMNO+1);

 IF EQU(SYM[SYMBOL],A) THEN RETURN(-1);
 IF EQU(SYM[SYMBOL],NULL) THEN  RETURN(0); 

 Q←H%(SYMNO+1) MOD (SYMNO+1);
 IF (H←Q+SCON)≥SYMNO THEN H←H-SYMNO;

 WHILE (IF (SYMBOL←SYMBOL+H)>SYMNO
     THEN SYMBOL←SYMBOL-(SYMNO+1) ELSE SYMBOL)	≠R   DO
     BEGIN "LK1" 
	IF EQU(SYM[SYMBOL],A) THEN RETURN(-1);
	IF EQU(SYM[SYMBOL],NULL) THEN RETURN(0);
	IF (H←H+Q)>SYMNO THEN H←H-(SYMNO+1);
     END "LK1";
USERERR(0,0,"TABLE FULL");
END "LOOKUP";
DEFINE PGMRK= "'201004020101",WUN="'1000000",EXECBIT="'400000000000",
	CHKPAG= "IF CURLIN=PGMRK THEN CURPAGE← CURPAGE+WUN",
	CHKLIN= "IF SRCBRK<0 THEN ⊂ EXECHK← 0; CURLIN← -SRCBRK;
	CHKPAG; GO TO L1 ⊃";
L_PTR← 0;
CURPAGE← WUN;
WANTBIN← 1;
LETS← "ABCDEFGHIJKLMNOPQRSTUVWXYZ_" &
	"abcdefghijklmnopqrstuvwxyz";
DIGS← "0123456789";
SETBREAK(SLOUGH,LETS&"@",NULL,"IRE");
SETBREAK(IDSCAN,LETS&DIGS&"@",NULL,"XSN");
SETBREAK(CMNT,";",NULL,"ISE");
SETBREAK(EXSCAN,LETS&DIGS&"@¬#↑",NULL,"IRE");
COMMAND_SCAN;

! SPECIAL SCAN IF LOOKING FOR EXECS;
L1:	IF EXECHK=0 THEN GO TO L3;
L2:	FOO← INPUT(SRC,EXSCAN); CHKEOF;
	CHKLIN;
	IF SRCBRK= "@" THEN ⊂ FOO← INPUT(SRC,IDSCAN); GO TO L2 ⊃;
	IF (SRCBRK= "¬")∨(SRCBRK="#")∨(SRCBRK="↑") 
		THEN ⊂ EXECHK← 0; GO TO L3 ⊃;
! SKIP TO NEXT ID;
L3:	FOO← INPUT(SRC,SLOUGH);CHKEOF;
	CHKLIN;

! PICK UP ID;
	NEWNAM← INPUT(SRC,IDSCAN);CHKEOF;

! CHECK FOR RESERVED WORD;
	IF EQU(NEWNAM,"EXEC") THEN ⊂ EXECHK← EXECBIT; GO TO L1 ⊃;
	IF EQU(NEWNAM,"SCAN") THEN ⊂ EXECHK← 0; GO TO L1 ⊃;
	IF EQU(NEWNAM,"SG")
	∨(LENGTH(NEWNAM)=3 ∧ EQU(NEWNAM[1 FOR 2],"SG") ∧
	"0"≤ NEWNAM[3 FOR 1] ≤ "9")
		 THEN GO TO L1;
 	IF EQU(NEWNAM,"MUMBLE") THEN  ⊂ LABEL LL; LL: FOO←INPUT(SRC,CMNT);
	CHKEOF; IF SRCBRK<0 THEN ⊂ CURLIN← -SRCBRK; EXECHK← 0; CHKPAG;GO TO LL ⊃ ELSE
	GO TO L1 ⊃ ;

! LOOK UP ID;
	WASTHERE← LOOKUP(NEWNAM);
	IF WASTHERE=0 THEN ⊂ SYM[SYMBOL]← NEWNAM; LTAB[SYMBOL]←0 ⊃;

! PUT IN LIST OF OCCURANCES;
	IF LTAB[SYMBOL]=0 THEN ⊂ NN← NODE(0,CURLIN);
		LTAB[SYMBOL]← NN LOR (NN LSH 18) LOR (IF 
		SRCBRK=":" THEN LBLBIT ELSE 0) LOR EXECHK;
		GO TO L1 ⊃ ;

! SEE IF THIS IS THE DEFINING INSTANCE OF A LABEL;
	IF SRCBRK=":" THEN
	 ⊂ ! PUT AT HEAD OF THE LIST;
	NN← NODE(L_HALF("LTAB[SYMBOL]"),CURLIN);
	LTAB[SYMBOL]← R_HALF("LTAB[SYMBOL]") LOR (NN LSH 18) LOR LBLBIT ;
	GO TO L1 ⊃ ;

! PUT AT THE END OF THE LIST;
	KK← R_HALF("LTAB[SYMBOL]");
! SEE IF IT IS ALREADY THERE;
	IF (L_SPACE[KK+1]=CURLIN) ∧ ((L_SPACE[KK] LAND '377777000000)=
		CURPAGE) THEN GO TO L1;
	NN← NODE(0,CURLIN);
	L_SPACE[KK]← L_SPACE[KK] LOR NN;
	LTAB[SYMBOL]← (LTAB[SYMBOL] LAND '777777400000) LOR NN LOR EXECHK;
	GO TO L1;

PASS2:
! NOW SORT THE SYMBOL TABLE;
	SORT(SYM,LTAB,4096);

! PRODUCE THE LISTING;

	FOR III←0,1,2 DO ⊂
	OUT(OTPT,FORM);
	K←0;
	WHILE ¬EQU(SYM[K],NULL) DO
	⊂ LABEL NOTNOW;
	CASE III OF
		⊂ IF LTAB[K] LAND BITS2 THEN GO TO NOTNOW;
		IF (LTAB[K] LAND LBLBIT)=0 THEN GO TO NOTNOW;
		IF (LTAB[K] LAND EXECBIT)=0 THEN GO TO NOTNOW ⊃;
	OUT(OTPT,CRLF&SYM[K]&(IF LENGTH(SYM[K])<8 
		THEN TAB ELSE NULL));
	L← L_HALF("LTAB[K]");
	NP←1;
	NN←0;
	WHILE L≠0 DO
		⊂ IF NN>10 THEN ⊂ OUT(OTPT,CRLF&TAB&TAB); NN←0 ⊃;
		KP← L_HALF("L_SPACE[L]");
		IF KP≠NP THEN ⊂ OUT(OTPT,TAB&"/"&CVS(KP));
		NP← KP; NN← NN+1 ⊃;
		 IF NN>10 THEN ⊂ OUT(OTPT,CRLF&TAB&TAB); NN←0 ⊃;
		OUT(OTPT,TAB&CVSTR(L_SPACE[L+1]));
		L← R_HALF("L_SPACE[L]"); NN← NN+1 ⊃;
NOTNOW: 	K← K+1 ⊃ ⊃;
RELEASE(OTPT);

END

END "XREF";