
{ WINFORMAT1.TEXT - Configuration file handler }

PROCEDURE ReadFile;
VAR
  Cursor:INTEGER;
  Found:BOOLEAN;
  S,SU:STRING;
  Result:STRING;
  FileName:STRING;
  F:FILE OF CHAR;
  Winch:Conf_Winch;

FUNCTION GetInput:BOOLEAN;
VAR
  Dummy:BOOLEAN;
  Done:BOOLEAN;
BEGIN
  Done:=FALSE;
  REPEAT
    Dummy:=SIO_ByDlim(Cursor,S,' ');
    IF Cursor > LENGTH(S) THEN
      BEGIN
	S:='';
	IF NOT EOF(F) THEN
	  BEGIN
	    {$I-}
	    READLN(F,S);
	    {$I+}
	    IF IORESULT <> 0 THEN
	      BEGIN
		Exception(TRUE);
		WRITELN('Error reading ',FileName);
		EXIT(ReadFile);
	      END;
	    Cursor:=1;
	    SU:=S;
	    SIO_Upper(SU);
	  END
	ELSE
	  Done:=TRUE;
      END
    ELSE
      Done:=TRUE;
  UNTIL Done;
  GetInput:=(Cursor <= LENGTH(S) );
END;

PROCEDURE SyntaxError(Num:INTEGER);
VAR
  MSG:STRING;
BEGIN
  Exception(TRUE);
  WRITE('Command syntax error - ');
  MSG:='';
  CASE Num OF
    1:MSG:='Number expected';
    2:MSG:='Head expected';
    3:MSG:='Name expected';
    4:MSG:='Illegal system name';
    5:MSG:='Track expected';
    6:MSG:='Blocks expected';
    7:MSG:='Illegal command';
    8:MSG:='Bad Track Map must preceed Device Map';
  END;
  WRITELN(MSG);
  WRITELN(' ',S);
  WRITELN(' ':Cursor,'^');
  EXIT(ReadFile);
END;

PROCEDURE Illegal;
BEGIN
  Exception(TRUE);
  WRITELN('Illegal value');
  WRITELN(' ',S);
  WRITELN(' ':Cursor,'^');
  EXIT(ReadFile);
END;

PROCEDURE IntRead(VAR Value:INTEGER);
BEGIN
  IF GetInput THEN
    BEGIN
      IF NOT SIO_IntRd(Cursor,S,Value) THEN SyntaxError(1);
    END
  ELSE
    SyntaxError(1);
END;

FUNCTION CheckString(Target:STRING):BOOLEAN;
VAR
  OldCursor:INTEGER;
  Index:INTEGER;
  Searching:BOOLEAN;
BEGIN
  CheckString:=FALSE;
  IF GetInput THEN
    BEGIN
      OldCursor:=Cursor;
      Index:=1;
      Searching:=TRUE;
      WHILE (Index <= LENGTH(Target)) AND (Cursor <= LENGTH(SU)) AND
	     Searching DO
	BEGIN
	  IF Target[Index] <> SU[Cursor] THEN Searching:=FALSE
	  ELSE
	    BEGIN
	      Index:=Index+1;
	      Cursor:=Cursor+1;
	    END;
	END;
      IF Index > LENGTH(Target) THEN CheckString:=TRUE
      ELSE
	Cursor:=OldCursor;
    END;
END;

PROCEDURE CheckHeads;
VAR
  NumHeads:INTEGER;
  Found:BOOLEAN;
  Dummy:BOOLEAN;
  Cursor:INTEGER;
  S:STRING;
BEGIN
  IF NOT HeadSet[Drive] THEN
    BEGIN
      Found:=FALSE;
      REPEAT
	MNU_ClrScreen;
	WRITE('Enter number of heads on drive ',Drive,': ');
	READLN(S);
	IF LENGTH(S) = 0 THEN EXIT(ReadFile);
	Cursor:=1;
	IF SIO_IntRd(Cursor,S,NumHeads) THEN
	  BEGIN
	    IF (NumHeads < 1) OR (NumHeads > 16) THEN
	      BEGIN
		WRITE(CHR(7),'Head range is 1 to 16, ');
		Dummy:=SC_Space_Wait(TRUE);
	      END
	    ELSE
	      BEGIN
		Found:=TRUE;
		HeadSet[Drive]:=TRUE;
		HeadsOnDrive[Drive]:=NumHeads;
		Winch.Heads:=NumHeads;
	      END;
	  END
	ELSE
	  WRITE(CHR(7));
      UNTIL Found;
    END;
END;

{ Drive specification }
PROCEDURE Level2;
VAR
  Dummy:BOOLEAN;
  NumHeads:INTEGER;
BEGIN
  Dummy:=CheckString('=');
  IntRead(Drive);
  IF (Drive < 0) OR (Drive > 3) THEN Illegal;
  FILLCHAR(DiskImage[Drive],SIZEOF(Win_DiskImage),0);
  Conf_Assign(17,9,Drive*16);
  Conf_RD_Winch(17,Winch);
  Conf_Restore;
  Dummy:=CheckString(',');
  IF CheckString('HEADS') THEN
    BEGIN
      Dummy:=CheckString('=');
      IntRead(NumHeads);
      IF (NumHeads < 1) OR (NumHeads > 16) THEN Illegal;
      Winch.Heads:=NumHeads;
      HeadSet[Drive]:=TRUE;
      HeadsOnDrive[Drive]:=NumHeads;
    END;
  CheckHeads;
  WITH DiskImage[Drive].DevMap[0],Winch DO
    BEGIN
      BaseTrack:=0;
      IF Cylinders > 0 THEN TopTrack:=(Cylinders * Heads)-1
      ELSE
	TopTrack:=0;
    END;
  ValidConfig[Drive]:=TRUE;
END;

FUNCTION GetTrack(VAR Track:INTEGER):BOOLEAN;
VAR
  Cyl,Head:INTEGER;
  Dummy:BOOLEAN;
BEGIN
  IF CheckString('CYLINDER') THEN
    BEGIN
      Dummy:=CheckString('=');
      IntRead(Cyl);
      Dummy:=CheckString(',');
      IF NOT CheckString('HEAD') THEN SyntaxError(2);
      Dummy:=CheckString('=');
      IntRead(Head);
      IF Cyl >= Winch.Cylinders THEN Illegal;
      IF Head >= Winch.Heads THEN Illegal;
      Track:=(Cyl*Winch.Heads)+Head;
      GetTrack:=TRUE;
    END
  ELSE
    IF CheckString('TRACK') THEN
      BEGIN
	Dummy:=CheckString('=');
	IntRead(Track);
	IF Track >= (Winch.Cylinders*Winch.Heads) THEN Illegal;
	GetTrack:=TRUE;
      END
    ELSE
      GetTrack:=FALSE;
END;

PROCEDURE Level3;
VAR
  Bad:INTEGER;
  Index:INTEGER;
  I,Scan:INTEGER;
  Dum:BOOLEAN;
BEGIN
  CheckHeads;
  ValidConfig[Drive]:=TRUE;
  Index:=0;
  WITH DiskImage[Drive] DO
    WHILE GetTrack(Bad) DO
      BEGIN
	IF Bad = 0 THEN
	  BEGIN
	    WRITELN('Cannot have first track bad');
	    EXIT(ReadFile);
	  END;
	IF Index >= Win_BadMax THEN
	  BEGIN
	    WRITELN('More than ',Win_BadMax+1,' bad track entries for drive ',
		     Drive);
	    EXIT(ReadFile);
	  END;
	Scan:=0;
	WHILE (BadTracks[Scan] < Bad) AND (Scan < Index) DO Scan:=Scan+1;
	IF Scan < Index THEN
	  FOR I := Index DOWNTO Scan+1 DO  BadTracks[I]:=BadTracks[I-1];
	BadTracks[Scan]:=Bad;
	Index:=Index+1;
	Dum:=CheckString(',');
      END;
END;

PROCEDURE Level4;
TYPE
  BlockType = INTEGER[10];
VAR
  Start,Ending:INTEGER;
  Partition:INTEGER;
  Dummy:BOOLEAN;
  Blocks:BlockType;
  Accum:BlockType;
  BlocksPerTrack:INTEGER;
  MaxTrack,MaxUser:INTEGER;
  TotalBad:INTEGER;
  Scan:INTEGER;

PROCEDURE Parameters;
VAR
  Found:BOOLEAN;
  Dummy:BOOLEAN;
  I:INTEGER;
  Result:STRING;
  TempName:Win_NameType;
BEGIN
  REPEAT
    Found:=FALSE;
    IF CheckString('NAME') THEN
      BEGIN
	Found:=TRUE;
	Dummy:=CheckString('=');
	IF NOT GetInput THEN SyntaxError(3);
	IF NOT SIO_AlNuRd(Cursor,SU,Result) THEN SyntaxError(3);
	WITH DiskImage[Drive].DevData[Partition] DO
	  FOR I:= 0 TO 7 DO
	    IF I < LENGTH(Result) THEN Name[I]:=Result[I+1]
	    ELSE
	      Name[I]:=CHR(0);
      END
    ELSE
    IF CheckString('SYSTEM') THEN
      BEGIN
	Found:=TRUE;
	Dummy:=CheckString('=');
	IF CheckString('UCSD') THEN I:=1
	ELSE
	IF CheckString('CPM') THEN I:=2
	ELSE
	IF CheckString('MODULA') THEN I:=3
	ELSE
	IF CheckString('HYFORTH') THEN I:=4
	ELSE
	IF CheckString('PDOS') THEN I:=5
	ELSE
	IF CheckString('MIRAGE') THEN I:=6
	ELSE
	IF CheckString('BOS') THEN I:=7
	ELSE
	IF CheckString('IDRIS') THEN I:=8
	ELSE
	  SyntaxError(4);
	DiskImage[Drive].DevData[Partition].System:=I;
      END;
  UNTIL NOT Found;
END;

FUNCTION GetBlocks(VAR Blocks:BlockType):BOOLEAN;
VAR
  Dummy:BOOLEAN;
  Blk:INTEGER;
BEGIN
  GetBlocks:=FALSE;
  IF CheckString('BLOCKS') THEN
    BEGIN
      Dummy:=CheckString('=');
      IntRead(Blk);
      Blocks:=Blk;
      GetBlocks:=TRUE;
    END;
END;

BEGIN { Level 4}
  CheckHeads;
  ValidConfig[Drive]:=TRUE;
  Start:=1;
  MaxTrack:=(Winch.Heads*Winch.Cylinders)-1;
  TotalBad:=0;
  Scan:=0;
  WHILE (Scan < Win_BadMax) DO
    BEGIN
      IF DiskImage[Drive].BadTracks[Scan] <> 0 THEN TotalBad:=TotalBad+1;
      Scan:=Scan+1;
    END;
  MaxUser:=MaxTrack-TotalBad;
  BlocksPerTrack:=(Winch.BytesPerSector*Winch.SectorsPerTrack) DIV 512;
  WHILE CheckString('PARTITION') DO
    BEGIN
      Dummy:=CheckString('=');
      IntRead(Partition);
      IF (Partition < 0) OR (Partition > 15) THEN Illegal;
      IF Partition = 0 THEN Start:=0;
      Dummy:=CheckString(':');
      IF GetTrack(Start) THEN
	BEGIN
	  IF (Partition = 0) AND (Start <> 0) THEN Illegal;
	  IF CheckString('TO') THEN
	    BEGIN
	      IF NOT GetTrack(Ending) THEN SyntaxError(5);
	      IF Start > Ending THEN Illegal;
	      IF Partition = 0 THEN
		BEGIN
		  IF Ending <> MaxTrack THEN Illegal;
		END
	      ELSE
		BEGIN
		  IF Ending > MaxUser THEN Illegal;
		END;
	    END
	  ELSE
	    BEGIN
	      Dummy:=CheckString(',');
	      IF NOT GetBlocks(Blocks) THEN SyntaxError(6);
	      Ending:=Start + TRUNC((Blocks-1) DIV BlocksPerTrack);
	      IF Partition = 0 THEN
		BEGIN
		  IF Ending <> MaxTrack THEN Illegal;
		END
	      ELSE
		BEGIN
		  IF Ending > MaxUser THEN Illegal;
		END;
	    END;
	END
      ELSE
	BEGIN
	  IF NOT GetBlocks(Blocks) THEN SyntaxError(6);
	  Ending:=Start + TRUNC((Blocks-1) DIV BlocksPerTrack);
	  IF Partition = 0 THEN
	    BEGIN
	      IF Ending <> MaxTrack THEN Illegal;
	    END
	  ELSE
	    BEGIN
	      IF Ending > MaxUser THEN Illegal;
	    END;
	END;
      WITH DiskImage[Drive].DevMap[Partition] DO
	BEGIN
	  BaseTrack:=Start;
	  TopTrack:=Ending;
	END;
      Start:=Ending+1;
      IF Partition = 0 THEN Start:=1;
      Parameters;
    END;
END;

PROCEDURE Level1;
VAR
  Devmap:BOOLEAN;
  
BEGIN
  Devmap:=FALSE;
  WHILE GetInput DO
    BEGIN
      IF CheckString('DRIVE') THEN
	BEGIN
	  Devmap:=FALSE;
	  Level2;
	END
      ELSE
	IF CheckString('BAD TRACK MAP') THEN
	  BEGIN
	    IF Devmap THEN SyntaxError(8);
	    Level3;
	  END
	ELSE
	  IF CheckString('DEVICE MAP') THEN
	    BEGIN
	      Devmap:=TRUE;
	      Level4;
	    END
	  ELSE
	    SyntaxError(7);
    END;
  GoodRead:=TRUE;
END;

BEGIN { ReadFile }
  GoodRead:=FALSE;
  Found:=FALSE;
  REPEAT
    WRITELN;
    WRITE('File with Bad Track and Device Maps: ');
    READLN(FileName);
    WRITELN;
    IF LENGTH(FileName)=0 THEN
      BEGIN
	GoodRead:=TRUE;
	EXIT(ReadFile);
      END;
    SIO_Suffix('.TEXT',FileName);
    {$I-}
    RESET(F,FileName);
    {$I+}
    IF IORESULT<>0 THEN
      BEGIN
	Exception(TRUE);
	WRITELN('Could not open file ',FileName);
      END
    ELSE
      Found:=TRUE;
  UNTIL Found;
  S:=' ';
  Cursor:=1;
  { Default to drive 0 }
  Drive:=0;
  Conf_Assign(17,9,0);
  Conf_RD_Winch(17,Winch);
  Conf_Restore;
  Level1;
END;



                                                                                                                                                                                                                                                                                                                           