Category : Pascal Source Code
Archive   : INLIN219.ZIP
Filename : UNPARS.INC

 
Output of file : UNPARS.INC contained in archive : INLIN219.ZIP

{UnPars.inc}
(********* Source code Copyright 1986, by L. David Baldwin *********)

Type
Symb = (Nul,Ident4,Ident2,Identunk,Bytesy,Wordsy,Lparn,Rparn);
Var
Sy : Symb;

{-------------DefaultExtension}
PROCEDURE DefaultExtension(Extension:Filestring;Var Infile,Name :Filestring);
{Given a filename, infile, add a default extension if none exists. Return
also the name without any extension.}
Var
I,J : Integer;
Temp : Filestring;
begin
I:=Pos('..',Infile);
if I=0 then
Temp:=Infile
else
begin {a pathname starting with ..}
Temp:=Copy(Infile,I+2,64);
I:=I+1;
end;
J:=Pos('.',Temp);
if J=0 then
begin
Name := Infile;
Infile:=Infile+'.'+Extension;
end
else Name:=Copy(Infile,1,I+J-1);
end;

{-------------GetCh}
PROCEDURE GetCh;
{Return next char in Uch and lch with Uch in upper case. Ignore comments}
Var Comment : Boolean;
PROCEDURE GetchBasic; {read a character and a character pair}
begin
if Chi<=Ord(St[0]) then
begin {NOTE: pair has the same address as lch}
Move(St[Chi], Pair, 2);
if LCh=Chr(Tab) then LCh:=' ';
UCh := UpCase(LCh);
Chi := Chi+1;
end
else
if not EOF(Inf) then
begin
ReadLn(Inf,St);
St:=St+' '; {EOL is equivalent to space}
Chi:=1;
GetCh;
end
else
begin
EofInf:=True;
if Comment then
begin
WriteLn('Open Comment at End of Input File');
Halt(1);
end;
end;
end;

begin {Getch}
if UCh<>' ' then
Symname:=Symname+UCh; {build up a phrase with old character}
repeat
if EofInf then
begin WriteLn('Unexpected End of Input File'); Halt(1) end;
Comment:=False;
GetchBasic;
if (UCh='{') or (Pair='(*') then
begin
Comment:=True;
if UCh='{' then repeat GetchBasic; until UCh='}'
else
begin
repeat GetchBasic; until Pair='*)';
GetchBasic; {pass by the '*'}
end;
end;
until not Comment;
end;

{-------------SkipSpaces}
PROCEDURE SkipSpaces;
begin
while (UCh=' ') or (UCh=Chr(Tab)) do
GetCh;
end;

{-------------GetDec}
FUNCTION GetDec(Var V :Integer): Boolean ;
Const
Ssize = 8;
Var
S : String[Ssize];
Getd : Boolean;
Code : Integer;
begin
Getd := False;
S := '';
while (UCh>='0') and (UCh<='9') do
begin
Getd := True;
if Ord(S[0]) then S := S+UCh;
GetCh;
end;
if Getd then
begin
Val(S,V,Code);
if Code<>0
then Error(Chi,'Bad Number Format');
end;
GetDec := Getd;
end;

{-------------GetHex}
FUNCTION GetHex(Var H :Integer): Boolean;
Var
Digit : Integer; {check for '$' before the call}
begin
H := 0;
GetHex := False;
while (UCh in ['A'..'F','0'..'9']) do
begin
GetHex := True;
if (UCh>='A')
then Digit := Ord(UCh)-Ord('A')+10
else Digit := Ord(UCh)-Ord('0');
if H>=$1000
then Error(Chi,'Overflow');
H := (H Shl 4)+Digit;
GetCh;
end;
end;

{-------------GetNumber}
FUNCTION GetNumber(Var N :Integer): Boolean;
{get a number and return it in n}
begin
SkipSpaces;
N := 0;
if UCh='$'
then
begin {a hex number}
GetCh;
if not GetHex(N)
then Error(Chi, 'Hex Number Exp');
GetNumber := True;
end
else
begin {maybe a decimal number}
GetNumber := GetDec(N);
end;
end;

{-------------GetExpr}
FUNCTION GetExpr(Var Rslt :Integer): Boolean;
Var
Rs1,Rs2 : Integer;
Pos,Neg,GE : Boolean;
begin
GE := False;
SkipSpaces;
Neg := UCh='-';
Pos := UCh='+';
if Pos or Neg
then GetCh;
if GetNumber(Rs1)
then
begin
GE := True;
if Neg
then Rs1 := -Rs1;
SkipSpaces;
if (UCh='+') or (UCh='-') then
if GetExpr(Rs2) then
Rs1 := Rs1+Rs2 {GetExpr will take care of sign}
else GE:=False;
Rslt := Rs1;
end;
SkipSpaces;
GetExpr:=GE and ((UCh='/') or (UCh=')')); {must terminate in '/' or ')'}
end;

{-------------GetToken}
PROCEDURE GetToken;
Const
Tokenchars : set of Char = ['A'..'Z','0'..'9','_'];
Startchars : set of Char = ['A'..'Z','_'];
begin
while not (UCh in Startchars) and not EofInf do GetCh;
Token[0] := #0;
if not EofInf then
while UCh in Tokenchars do
begin
if Ord(Token[0]) then Token := Token+UCh;
GetCh;
end;
end;

{-------------Next}
PROCEDURE Next;
Var C : Char;

FUNCTION GetExprX(Var N : Word; Var C : Char): Boolean;
begin
C:=UCh;
if (UCh='>') or (UCh='<') then GetCh;
GetExprX:=GetExpr(Integer(N));
end;

begin
Sy := Nul;
repeat
SkipSpaces;
Symname[0]:=#0; {build up a phrase which may be needed later}
if BytePending then
begin
NValue:=PendingByte;
BytePending:=False;
Sy:=Bytesy;
end
else if UCh='(' then begin Sy:=Lparn; GetCh; end
else if UCh=')' then begin Sy:=Rparn; GetCh; end
else if UCh='/' then Error(Chi+2, 'Syntax')
else if GetExprX(NValue,C) then
begin
if C='<' then Sy:=Bytesy
else if C='>' then Sy:=Wordsy
else if NValue and $FF00 = 0 then Sy := Bytesy
else Sy:=Wordsy;
if UCh='/' then GetCh;
end
else
begin {it's a symbolic phrase}
while (UCh<>'/') and (UCh<>')') do GetCh; {finish reading the phrase}
if UCh='/' then
begin
GetCh; {pass the '/' by}
Symname[0]:=Pred(Symname[0]); {but remove it from phrase}
end;
if (Pos('>',Symname)>0) or (Pos('*',Symname)>0) then
Sy:=Ident4
else if Pos('<',Symname)>0 then Sy:=Ident2
else Sy:=Identunk; {unknown size}
end;
if Sy=Nul then GetCh;
until Sy<>Nul;
end;

{-------------GetByte}
FUNCTION GetByte(Var P :Packet; PhraseOk : Boolean): Boolean;
Var Result : Boolean;
begin
Result:=True;
with P do
begin
Dispsize:=Bytesize; Phrase:=False;
if (Sy=Ident2) or (Sy=Identunk) then
begin
if not PhraseOk then Result:=False
else
begin
Phrase:=True;
if Sy=Identunk then Insert('<',Symname,1);
S:=Symname; {the phrase}
end;
end
else if Sy=Bytesy then Value:=Lo(NValue)
else if Sy=Wordsy then
begin
Value:=Lo(NValue);
BytePending:=True;
PendingByte:=Hi(NValue);
end
else Result:=False;
if Result then
begin
PC:=PC+1;
Next;
end;
GetByte:=Result;
end;
end;

{-------------GetWord}
PROCEDURE GetWord(Var P :Packet);
Var H,L : Packet;
PROCEDURE WordErr;
begin Error(Chi,'Word or two bytes exp'); PC:=PC+2; Next; end;
begin
with P do
begin
Dispsize:=Wordsize; Phrase:=False;
if (Sy=Ident4) or (Sy=Identunk) then
begin
if Sy=Identunk then Insert('>',Symname,1);
Phrase:=True; S:=Symname;
PC:=PC+2; Next;
end
else if Sy=Ident2 then WordErr
else if Sy=Wordsy then
begin Value:=NValue; PC:=PC+2; Next; end
else if GetByte(L,not PhraseOk) then
begin
if not GetByte(H, not PhraseOk) then NumbyteErr;
Value:=H.Value Shl 8 +L.Value;
end
else WordErr;
end;
end;