{$linesize:130,$symtab-,$title:'FILE DUMP UTILITY'}
{$debug-}

program DUMP( input, output );

function GetNextArg(var SwitchType,Numeric:boolean;var SwitchChar:char;
			var StringArg:lstring;var NumericArg:integer):boolean;external;
			{ returns next argument from command line }
			{ returns true if there was an argument }
			{ arguments are fields separated by spaces or a slash (/) }
{			SwitchType      true if argument begins with a slash
			Numeric         true if argument is an integer
			SwitchChar      char following / for switch type args
								 (SwitchChar is folded to upper case)
			StringArg       contains the ASCII argument (not the /)
			NumericArg      contains the value of arg, if applicable

			double quotes ("...") must be used to enclose an arg 
				containing a space or slash (/). 
}



const  
	nothing = 0;
	LinesPerPage = 57;
	formfeed = chr(12);

var
	ch : char;
	i : byte;
	j : integer;
	Count : integer;
	Inp : file of byte;
	ASCIIOut : lstring(16);
	Remainder : integer;
	LineCount : integer;
	StartingByte : integer;
	PageCount : integer;

	SwitchType,Numeric : boolean;
	SwitchChar : char;
	StringArg : Lstring(80);
	NumericArg : integer;

	filestr : lstring(30);

procedure PageHeading;
begin
	if PageCount > 0 then write(formfeed);
	PageCount := PageCount + 1;
	writeln('File Dump of ',FileStr,' ':40,'Page',PageCount:3);
	writeln;
	LineCount := 4;
end;


{$subtitle:'MAIN PROGRAM'}
BEGIN															 { MAIN PROGRAM }
	PageCount := 0;
	StartingByte := 0;
	writeln;

	if not GetNextArg(SwitchType,Numeric,SwitchChar,FileStr,NumericArg)
		then { null command line } begin { get file name from operator }
	   write('Enter input file name: ');
  		readln(filestr);
	end;

	if GetNextArg(SwitchType,Numeric,SwitchCHar,StringArg,NumericArg)
		then { got an argument } begin
		if SwitchType and (SwitchChar = 'S') and Numeric 
			then { got a starting value } 
			StartingByte := (NumericArg DIV 16) * 16;
	end;

   assign(Inp,filestr);
   reset(Inp);
	Count := 0;
	LineCount := LinesPerPage;

while not eof(Inp) do begin

	if ( (Count MOD 16) = 0) and (Count >= StartingByte) then 
		{ start a new line of output } begin
		writeln;  { complete line }

		if (Count MOD 256) = 0 then { space between 256 bytes } begin
			writeln;
			LineCount := LineCount + 1;
		end;

		if LineCount >= LinesPerPage then PageHeading;
		write(Count:5,' :',Count:4:16,'  ');
		LineCount := LineCount + 1;
		ASCIIOut := NULL;
	end;

	read(Inp,i);										{ get a byte of input }
	if Count >= StartingByte then begin
		if (i < 32) or (i > 126) then ch := '.'	{ use . for non-printing }
			else ch := chr(i);
		concat(ASCIIOut,ch);		{ add ASCII value to string }
		write(' ',i:2:16);
		if (Count MOD 16) = 15 then write('  ',ASCIIOut);
	end;
	Count := Count + 1;
end;

Remainder := Count MOD 16;
if Remainder <> 0 then begin
	for j := 1 to (16 - Remainder) do write('   ');
	write('  ',ASCIIOut);
end;
writeln;writeln; writeln;
writeln('END OF FILE                    ',Count,' bytes in file');
writeln;

end.			    { main }
