perm filename RECIN.SAI[NEW,AIL] blob sn#408311 filedate 1979-01-08 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00006 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY RREAD
C00005 00003	SIMPROC SETFLD(INTEGER TYPPOINTER FLDINTEGER VAL)
C00007 00004	STRING SIMPROC CVASTR(INTEGER WD)
C00009 00005	PROCEDURE ARRRD(POINTER FIXUPINTEGER CHN)
C00011 00006	INTERNAL RPTR(ANY_CLASS) PROCEDURE RREAD(INTEGER CHNBOOLEAN PROCEDURE PRED)
C00015 ENDMK
C⊗;
ENTRY RREAD;

BEGIN "RECIN"

REQUIRE "PROLOG.HDR[SYS,PDQ]" SOURCE_FILE;
REQUIRE "LIB.HDR[SYS,PDQ]" SOURCE_FILE;

DEFINE RING=⊂INTEGER⊃;

EXTERNAL RECORD_CLASS $CLASS(RPTR($CLASS) RECRNGS;PROCEDURE HNDLER;INTEGER RECSIZ;
				INTEGER ARRAY TYPARR;STRING ARRAY TXTARR);

EXTERNAL RPTR(ANY_CLASS) PROCEDURE $REC$(INTEGER OP;RPTR($CLASS) R);

INTEGER DISKLOC;
EXTERNAL POINTER RECCHN;
POINTER RECARR;
DEFINE BSIZ=128;

PROCEDURE DSKPOS(INTEGER CHN,ADR);
BEGIN	INTEGER_ARRAY FOO[1:BSIZ];
	INTEGER N,S;
	IF (N←ADR-DISKLOC)<4*BSIZ THEN 
	 WHILE N>0 DO 
		⊂ S←BSIZ MIN N;N←N-S;ARRYIN(CHN,FOO[1],S)⊃
	 ELSE ⊂ USETI(CHN,ADR DIV BSIZ+1);
		ARRYIN(CHN,FOO[1],ADR MOD BSIZ);⊃;
	DISKLOC←ADR;
END;
	 
SIMPROC FIXUP(RPTR(ANY_CLASS) REC;REFERENCE RPTR(ANY_CLASS) L);
 START_CODE
	LABEL AGAIN,XIT;
	DEFINE A=1,B=2,R=3;
	MOVE A,L;MOVE R,REC;HRRZM R,L;
	JUMPE A,XIT;
 AGAIN:	MOVE B,(A);MOVEM R,(A);MOVE A,B;JUMPN A,AGAIN;
 XIT:
 END;


DEFINE MEMLOC(X)=⊂MEMORY[LOCATION(X)]⊃;

DEFINE RINGHD(X)=⊂(LOCATION(X)+2)⊃;

RPTR(ANY_CLASS) SIMPLE PROCEDURE RINGRT(REFERENCE POINTER R;POINTER HD);
START_CODE LABEL XIT;
	SKIPN 1,R;
	JRST XIT;		! NULL RECORD -- RETURN(NIL);
	HRRZ 2,HD;
	HRRZ 1,-1(1);		! RING POINTER;
	CAIN 1,(2);		! POINTER TO HEAD;
	MOVEI 1,0;
XIT:	MOVEM 1,R;
END;

RPTR($CLASS) PROCEDURE FINDREC(STRING S);
 BEGIN
   POINTER CLSHD,CLSPT;
   RPTR($CLASS) CLS;
   CLSPT←CLSHD←RINGHD($CLASS);
   WHILE (CLS←RINGRT(CLSPT,CLSHD))≠NIL DO
	IF EQU($CLASS:TXTARR[CLS][0],S) THEN RETURN(CLS);
   STRIN("CAN'T FIND RECORD="&S&CRLF);
   RETURN(NIL);
 END;

SIMPROC SETFLD(INTEGER TYP;POINTER FLD;INTEGER VAL);
 START_CODE
	DEFINE SP='16,A=1,B=2,T=3,R=4,V=5,S=6;
	LABEL FX,F0,ST1,F2S,ARR,FS,STRNG;
	MOVE V,VAL;
	MOVE R,FLD;
	SKIPN S,(R);		! DON'T CLOBBER DEFINED FIELDS;
	MOVEM V,(R);		! THIS WORKS FOR SIMPLE CASES;
	JUMPE V,FX;		! NULL FIELDS NEED NO MORE WORK;
	HLRZ T,TYP;
	LSH T,-5;
	TRNE T,'20;		! ARRAY?;
	JRST ARR;		! YES, ARRAY;
	CAIN T,3;		! STRING?;
	JRST STRNG;
	CAIE T,'15;		! RECORD?;
	JRST FX;		! NO, MUST BE SIMPLE TYPE ... DONE;
	MOVE A,RECARR;		! RECORD ARRAY BASE;
	ADD A,V;		! PLUS RECORD NUMBER;
	SKIPG B,(A);	
	HRROM R,(A);		! CHAIN THE UNDEFINED RECORD POINTER;
	MOVEM B,(R);		! POINT TO DEFINED RECORD OR FIXUP CHAIN;
	JRST FX;
	
STRNG:	MOVEM V,(S);		! FIXUP INFO PLACED IN STRING DESCR;
ARR:	HRL R,T;		! PUT ARRAY (OR STRING) TYPE IN LEFT HALF;
	PUSH SP,R;		! REMEMBER LOCATION TO FIXUP (WHICH CONTAINS IOWD);
    FX:
  END;


STRING SIMPROC CVASTR(INTEGER WD);
IF WD=0 THEN RETURN(NULL)
ELSE 
BEGIN	STRING S;
	S←CVSTR(WD);
	WHILE S[∞ FOR 1]=0 DO S←S[1:∞-1];
	RETURN(S);
END;

SIMPROC STRRD(POINTER F;INTEGER CHN);
BEGIN	INTEGER I,N,FIX;
	STRING S;
	FIX←MEMORY[F];
	IF RTHALF(FIX)≠DISKLOC THEN OUTSTR("DISK ORDERING ERROR");
	START_CODE HLRE 1,FIX;MOVNM 1,N;END;
	S←NULL;
	FOR I←1 STEP 1 UNTIL N-1 DO
	 S←S&CVSTR(WORDIN(CHN));
	S←S&CVASTR(WORDIN(CHN));	! SUPPRESS TRAILING NULLS AT END OF LAST WORD;
	MEMORY[F-1]←MEMORY[LOCATION(S)-1];
	MEMORY[F]←MEMORY[LOCATION(S)];
	! COPY STRING DESCR;
	DISKLOC←DISKLOC+N;
END;

SIMPROC STARRRD(INTEGER CHN;POINTER ARR);
 BEGIN	INTEGER I,WD,XOPT,N,PT,C,SIZ;
	STRING S;
	START_CODE MOVE 1,ARR;HRRZ 1,-2(1);MOVEM 1,SIZ;END;
	XOPT←POINT(7,WD,-1);
	N←0;
	FOR I←1 STEP 2 UNTIL SIZ DO
	 BEGIN
	  S←NULL;
	  WHILE TRUE DO
	    BEGIN
		IF N=0 THEN 
		  BEGIN WD←WORDIN(CHN);N←5;PT←XOPT;DISKLOC←DISKLOC+1;END;
		C←ILDB(PT);N←N-1;
		IF C=NULL THEN DONE;
		S←S&C;
	    END;
	  MEMORY[ARR+I-2]←MEMORY[LOCATION(S)-1];
	  MEMORY[ARR+I-1]←MEMORY[LOCATION(S)];
	 END;
 END;		

PROCEDURE ARRRD(POINTER FIXUP;INTEGER CHN);
BEGIN	INTEGER I,LOC,T,N,DIM,CHNL,SIZ;
	EXTERNAL PROCEDURE ARMAK;
	POINTER ARR;
	DIM←WORDIN(CHNL←CHN);
	START_CODE 
		HLRE 1,DIM;MOVMM 1,I;HRR 1,I;MOVEM 1,N;
	END;
	
	I←2*I;
	
	DISKLOC←DISKLOC+I+1;
	START_CODE
	 DEFINE P='17;
	 LABEL AGAIN;
AGAIN:	 PUSH P,CHNL;PUSHJ P,WORDIN;PUSH P,1;	! BOUNDS;
	 SOSLE I;JRST AGAIN;
	 PUSH P,N;				! N NEGATIVE FOR STRING ARRAY;
	 PUSHJ P,ARMAK;
	 MOVEM 1,ARR;				! ALLOCATE THE ARRAY;
	 HRRZ 1,-1(1);
	 MOVEM 1,SIZ;				! NO GOOD FOR STRING ARRAYS;
	END;
	MEMORY[FIXUP]←ARR;
	T←LTHALF(FIXUP);
	IF T='41 THEN 				! RECORD ARRAY;
	 FOR I←1 STEP 1 UNTIL SIZ DO
	  	MEMORY[ARR+I-1]←MEMORY[RECARR+WORDIN(CHNL)]
	ELSE IF T='27 THEN			! STRING ARRAY;
		STARRRD(CHN,ARR)
	ELSE START_CODE 			! SIMPLE TYPE ARRAY;
		DEFINE P='17;
		PUSH P,CHNL;PUSH P,ARR;PUSH P,SIZ;PUSHJ P,ARRYIN;
	     END;
	IF T≠'27 THEN DISKLOC←DISKLOC+SIZ;
END;
	
INTERNAL RPTR(ANY_CLASS) PROCEDURE RREAD(INTEGER CHN;BOOLEAN PROCEDURE PRED);
BEGIN
	INTEGER RECNUM;
	RPTR(ANY_CLASS) HANDLE;
	INTEGER SPSAV,SPTOP;
	
	START_CODE MOVEM '16,SPSAV;END;		! REMEMBER INITIAL STRING STACK;
	
	RECNUM←WORDIN(CHN);
	DISKLOC←1;
	 BEGIN
		INTEGER I,J,NAM,SIZ,SPNUM;
		RPTR($CLASS) CLS;
		RPTR(ANY_CLASS) ARRAY RECS[0:RECNUM];
		RPTR(ANY_CLASS) REC;

		START_CODE MOVE 1,RECS;MOVEM 1,RECARR;END;
		
		FOR I←1 STEP 1 UNTIL RECNUM DO
		 BEGIN
			NAM←WORDIN(CHN);		! SIXBIT RECORD CLASS NAME;
			CLS←FINDREC(CV6STR(NAM));	! FIND RECORD CLASS;
			REC←$REC$(1,CLS);		! ALLOCATE RECORD;
			SIZ←$CLASS:RECSIZ[CLS];
			DISKLOC←DISKLOC+SIZ+1;
			
			FOR J←1 STEP 1 UNTIL SIZ DO	! READ ALL FIELDS;
			   SETFLD($CLASS:TYPARR[CLS][J],MEMLOC(REC)+J,WORDIN(CHN));

			FIXUP(REC,RECS[I]);		! FIXUP ALL FORWARD REFERENCES;
		 END;

		HANDLE←RECS[1];
				! WE NOW HAVE ALL RECORDS;
				! STRING STACK CONTAINS FIXUP INFO FOR ARRAYS AND STRINGS;
		START_CODE
		 MOVE 1,'16;SUB 1,SPSAV;HRRZM 1,SPNUM;
		END;		! DETERMINE NUMBER OF FIXUPS;

		IF SPNUM>0 THEN
		BEGIN "FIXES"
		 INTEGER_ARRAY FIXUP[1:SPNUM];
		 INTEGER L,F,I,TOTSIZ,VIRTLOC,TYP;
		 FOR I←SPNUM STEP -1 UNTIL 1 DO
		  BEGIN 
			START_CODE POP '16,F;END;	! WIND DOWN STRING STACK;
			FIXUP[I]←F;			! STORE FIXUPS;
		  END;
		 VIRTLOC←DISKLOC;
		 FOR I←1 STEP 1 UNTIL SPNUM DO
		  BEGIN	F←FIXUP[I];
			L←MEMORY[F];			! PROCESS FIXUPS;
			TYP←LTHALF(F);
			TOTSIZ←-(MEMORY[F] ASH -18);
			IF PRED(TOTSIZ,TYP) THEN
			 ⊂ MEMORY[F]←0;VIRTLOC←VIRTLOC+TOTSIZ;⊃
			ELSE 
			 BEGIN	IF VIRTLOC>DISKLOC THEN DSKPOS(CHN,VIRTLOC);
				IF TYP=3 THEN STRRD(L,CHN)
				 ELSE ARRRD(F,CHN);
				VIRTLOC←DISKLOC;
			 END;
		  END;
		END "FIXES";
	 END;
	RETURN(HANDLE);
END "RREAD";


INTERNAL RPTR(ANY_CLASS) PROCEDURE RECIN(STRING FILE;BOOLEAN PROCEDURE PRED);
 BEGIN	INTEGER CHN;
	RPTR(ANY_CLASS) REC;
	RPTR(IO) INP;
	CHN←MKIODEV(FILE);
	INP←IOCHANS[CHN];
	IO:MODE[INP]←'14;
	FILEOP("L",CHN);
	REC←RREAD(CHN,PRED);
	FILEOP("R",CHN);
	RETURN(REC);
 END;
	
END "RECIN";