(* UCSD PASCAL I.5 PASCAL I/O UNIT *) (*----------------------------------------------------------*) SEPARATE UNIT PASCALIO; INTERFACE TYPE DECMAX = INTEGER[36]; PROCEDURE FSEEK(VAR F: FIB; RECNUM: INTEGER); PROCEDURE FREADREAL(VAR F: FIB; VAR X: REAL); PROCEDURE FWRITEREAL(VAR F: FIB; X: REAL; W, D: INTEGER); PROCEDURE FREADDEC(VAR F: FIB; VAR D: TRICKARRAY; L: INTEGER); PROCEDURE FWRITEDEC(VAR F: FIB; D: DECMAX; RLENG: INTEGER); IMPLEMENTATION PROCEDURE FSEEK(*VAR F: FIB; RECNUM: INTEGER*); LABEL 1; VAR BYTE,BLOCK,N: INTEGER; BEGIN SYSCOM^.IORSLT := INOERROR; IF F.FISOPEN THEN WITH F,FHEADER DO BEGIN BLOCK := 0; BYTE := FBLKSIZE; IF (RECNUM < 0) OR NOT FSOFTBUF OR ((DFKIND = TEXTFILE) AND (FRECSIZE = 1)) THEN GOTO 1; (*NO SEEK ALLOWED*) IF FRECSIZE < FBLKSIZE THEN BEGIN N := FBLKSIZE DIV FRECSIZE; WHILE RECNUM-N >= 0 DO BEGIN RECNUM := RECNUM-N; BYTE := BYTE+N*FRECSIZE; WHILE BYTE > FBLKSIZE DO BEGIN BLOCK := BLOCK+1; BYTE := BYTE-FBLKSIZE END END END; WHILE RECNUM > 0 DO BEGIN RECNUM := RECNUM-1; BYTE := BYTE+FRECSIZE; WHILE BYTE > FBLKSIZE DO BEGIN BLOCK := BLOCK+1; BYTE := BYTE-FBLKSIZE END END; N := DLASTBLK-DFIRSTBLK; IF (BLOCK > N) OR ((BLOCK = N) AND (BYTE >= DLASTBYTE)) THEN BEGIN BLOCK := N; BYTE := DLASTBYTE END; IF BLOCK <> FNXTBLK THEN BEGIN IF FBUFCHNGD THEN BEGIN FBUFCHNGD := FALSE; FMODIFIED := TRUE; UNITWRITE(FUNIT,FBUFFER,FBLKSIZE,DFIRSTBLK+FNXTBLK-1); IF IORESULT <> ORD(INOERROR) THEN GOTO 1 END; IF (BLOCK <= FMAXBLK) AND (BYTE <> FBLKSIZE) THEN BEGIN UNITREAD(FUNIT,FBUFFER,FBLKSIZE,DFIRSTBLK+BLOCK-1); IF IORESULT <> ORD(INOERROR) THEN GOTO 1 END END; IF FNXTBLK > FMAXBLK THEN BEGIN FMAXBLK := FNXTBLK; FMAXBYTE := FNXTBYTE END ELSE IF (FNXTBLK = FMAXBLK) AND (FNXTBYTE > FMAXBYTE) THEN FMAXBYTE := FNXTBYTE; FEOF := FALSE; FEOLN := FALSE; FREPTCNT := 0; IF FSTATE <> FJANDW THEN FSTATE := FNEEDCHAR; FNXTBLK := BLOCK; FNXTBYTE := BYTE END ELSE SYSCOM^.IORSLT := INOTOPEN; 1: END (*FSEEK*) ; PROCEDURE FREADREAL(*VAR F: FIB; VAR X: REAL*); LABEL 1; VAR CH: CHAR; NEG,XVALID: BOOLEAN; IPOT: INTEGER; BEGIN WITH F DO BEGIN X := 0; NEG := FALSE; XVALID := FALSE; IF FSTATE = FNEEDCHAR THEN FGET(F); WHILE (FWINDOW^[0] = ' ') AND NOT FEOF DO FGET(F); IF FEOF THEN GOTO 1; CH := FWINDOW^[0]; IF (CH = '+') OR (CH = '-') THEN BEGIN NEG := CH = '-'; FGET(F); CH := FWINDOW^[0] END; WHILE (CH IN DIGITS) AND NOT FEOF DO BEGIN XVALID := TRUE; X := X*10 + (ORD(CH)-ORD('0')); FGET(F); CH := FWINDOW^[0] END; IF FEOF THEN GOTO 1; IPOT := -1; IF CH = '.' THEN BEGIN IPOT := 0; REPEAT FGET(F); CH := FWINDOW^[0]; IF CH IN DIGITS THEN BEGIN XVALID := TRUE; IPOT := IPOT + 1; X := X + (ORD(CH)-ORD('0'))/PWROFTEN(IPOT) END UNTIL FEOF OR NOT (CH IN DIGITS); IF FEOF THEN GOTO 1 END; IF ((CH = 'e') OR (CH = 'E')) AND (XVALID OR (IPOT < 0)) THEN BEGIN IF FSTATE = FJANDW THEN FGET(F) ELSE FSTATE := FNEEDCHAR; FREADINT(F,IPOT); IF FEOF THEN GOTO 1; IF NOT XVALID THEN X := 1; XVALID := TRUE; IF IPOT < 0 THEN X := X/PWROFTEN(ABS(IPOT)) ELSE X := X*PWROFTEN(IPOT) END; IF XVALID THEN IF NEG THEN X := -X ELSE ELSE SYSCOM^.IORSLT := IBADFORMAT END; 1: END (*FREADREAL*) ; PROCEDURE FWRITEREAL(*X:REAL; W, D: INTEGER*); VAR J, TRUNCX, EXPX: INTEGER; NORMX: REAL; S: STRING[30]; BEGIN (* Check W and D for validity *) IF (W < 0) OR (D < 0) THEN BEGIN W := 0; D := 0 END; (* Take abs(x), normalize it and calculate exponent *) IF X < 0 THEN BEGIN X := -X; S[1] := '-' END ELSE S[1] := ' '; EXPX := 0; NORMX := X; IF X >= PWROFTEN(0) THEN (* divide down to size *) WHILE NORMX >= PWROFTEN(1) DO BEGIN EXPX := EXPX+1; NORMX := X/PWROFTEN(EXPX) END ELSE IF X <> 0 THEN (* multiply up to size *) REPEAT EXPX := EXPX-1; NORMX := X*PWROFTEN(-EXPX) UNTIL NORMX >= PWROFTEN(0); (* Round number according to some very tricky rules *) IF (D=0) OR (D+EXPX+1 > 6) THEN (* scientific notation, or decimal places *) NORMX := NORMX + 5/PWROFTEN(6) (* overspecified *) ELSE IF D+EXPX+1 >= 0 THEN NORMX := NORMX + 5/PWROFTEN(D+EXPX+1); (* if D+EXPX+1 < 0, then number is effectively 0.0 *) (* If we just blew normalized stuff then fix it up *) IF NORMX >= PWROFTEN(1) THEN BEGIN EXPX := EXPX+1; NORMX := NORMX/PWROFTEN(1) END; (* Put the digits into a string *) FOR J := 3 TO 8 DO BEGIN TRUNCX := TRUNC(NORMX); S[J] := CHR(TRUNCX+ORD('0')); NORMX := (NORMX-TRUNCX)*PWROFTEN(1) END; (* Put number into proper form *) IF (D=0) OR (EXPX >= 6) THEN (* scientific notation *) BEGIN S[2] := S[3]; S[3] := '.'; J := 8; IF EXPX <> 0 THEN BEGIN J := 9; S[9] := 'E'; IF EXPX < 0 THEN BEGIN J := 10; S[10] := '-'; EXPX := -EXPX END; IF EXPX > 9 THEN BEGIN J := J+1; S[J] := CHR(EXPX DIV 10 + ORD('0')); END; J := J+1; S[J] := CHR(EXPX MOD 10 + ORD('0')) END; S[0] := CHR(J); END ELSE (* some kind of fixed point notation *) IF EXPX >= 0 THEN BEGIN MOVELEFT(S[3], S[2], EXPX+1); S[3+EXPX] := '.'; FILLCHAR(S[9], D-(5-EXPX), ' '); (* blank fill at end if precision *) S[0] := CHR(3+D+EXPX); (* was over-specified *) END ELSE BEGIN MOVERIGHT(S[3], S[3-EXPX], 6); (* make room for leading zeroes *) S[2] := '0'; S[3] := '.'; FILLCHAR(S[4], -EXPX-1, '0'); (* put in leading zeroes *) FILLCHAR(S[9-EXPX], D-6+EXPX, ' ');(* put in blanks for over-precision*) S[0] := CHR(3+D); END; IF W < LENGTH(S) THEN W := LENGTH(S); FWRITESTRING( F, S, W ); END; (*procedure write_real *) PROCEDURE FWRITEDEC(*VAR F: FIB; D: DECMAX; RLENG: INTEGER*); VAR S: STRING[38]; I: INTEGER; BEGIN STR(D,S); FWRITESTRING(F,S,RLENG) END (*FWRITEDEC*) ; PROCEDURE FREADDEC(*VAR F:FIB; VAR D: TRICKARRAY; L: INTEGER*); LABEL 1; CONST DECSIZE = 8; (*MAX SIZE OF LONG INTEGER IN WORDS*) VAR DX: RECORD CASE BOOLEAN OF FALSE:( D: DECMAX ); TRUE: ( WD: TRICKARRAY ) END; CH: CHAR; NEG,DVALID: BOOLEAN; I: INTEGER; BEGIN WITH F DO BEGIN DX.D := 0; NEG := FALSE; DVALID := FALSE; IF FSTATE = FNEEDCHAR THEN FGET(F); WHILE (FWINDOW^[0] = ' ') AND NOT FEOF DO FGET(F); IF FEOF THEN GOTO 1; CH := FWINDOW^[0]; IF (CH = '+') OR (CH = '-') THEN BEGIN NEG := CH = '-'; FGET(F); CH := FWINDOW^[0] END; WHILE (CH IN DIGITS) AND NOT FEOF DO BEGIN DVALID := TRUE; DX.D := DX.D*10 + ORD(CH) - ORD('0'); FGET(F); CH := FWINDOW^[0] END; IF DVALID OR FEOF THEN BEGIN IF NEG THEN DX.D := -DX.D; (*Transfer result into input var and check for overflow*) FOR I := L-1 DOWNTO 0 DO D[I] := DX.WD[I+DECSIZE-L]; NEG := D[0] < 0; FOR I := DECSIZE-L-1 DOWNTO 0 DO IF ((NOT NEG) AND (DX.WD[I] <> 0)) OR (NEG AND (DX.WD[I] <> -1)) THEN DVALID := FALSE END; IF NOT (DVALID OR FEOF) THEN SYSCOM^.IORSLT := IBADFORMAT END; 1: END(*FREADDEC*) ; END { PASCALIO } ; { +------------------------------------------------------------------+ | | | F I N I S | | | +------------------------------------------------------------------+ }