home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol021
/
nad.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1984-04-29
|
10KB
|
385 lines
(************************************************
** PROGRAM TITLE: Name and Address
** Version 3.0
**
** WRITTEN BY: Raymond E. Penley
** DATE WRITTEN: 26 June 1980
**
** ORIGINAL PROGRAM:
** A General Purpose Permuted Keyword Index Program
** Written by: Randy Reitz
** 26 Maple St
** Chatham Township, N.J. 07928
**
** Date written: June 1980
**
** WRITTEN FOR-S100 Microsystems Magazine
**
** Donated to PASCAL/Z USERS GROUP, july 1980
**
***********************************************)
Program NameAndAddress;
label 9999; { abort }
const
Program_title = 'NAME AND ADDRESS';
Sort_message = 'Sort by 1) Name, 2) Address, or 3) Zip Code? ';
default = 80 ;
dflt_str_len = default; { default length for a string }
dflt_margin = 1; { Left margin default }
fid_length = 14; {max file name length}
line_len = default;
n = 10; {Maximun # of delimeters}
name$field$width = 20; { Name line width }
address$field$width = 40; { Address line width }
Zip$field$width = 5; { ZIP Code line width}
Pdelim = '^'; { the "P" delimeter }
Sdelim = '/'; { the "S" delimeter }
space = ' ';
screen_lines = 24; {# of viewing lines on consle device }
StrMax = 255;
type
dfltstr = STRING dflt_str_len;
fid = STRING fid_length;
Indexes = array[1..n] of integer;
str0 = STRING 0 ;
str1 = STRING 1;
str255 = STRING Strmax ;
Mstring = STRING Strmax;
links = ^entry;
{}stuffing = record
name, { Name line }
address, { Address line }
Zip : dfltstr { ZIP Code line }
end;
entry = record
{} stuff: stuffing;
Rlink,
Llink: links
end;
var
bad_lines : integer; { count of # of bad lines }
bell : char;
cix : char;
error : boolean;
High,
LINE,
Low : dfltstr;
i : integer; { global index }
in_file : fid; { CP/M File Identifier <FID> }
margin, { left margin }
num : integer; { occurrences of "P"/"S" delimeters }
root : links;
Ploc, { location of "P" delimeters }
Sloc : INDEXES; { location of "S" delimeters }
sort : 0..255;
size, { size of current file }
this_line : integer; { current line counter }
termination : boolean; { Program termination flag }
wrk1 : text; { the input file <FCB> }
(*********************************************)
(*---This is how we get string functions in Pascal/Z---*)
Function length(x: str255): integer; external;
Function index(x,y: str255): integer; external;
Procedure setlength(var x: str0; y: integer); external;
Procedure KEYIN(VAR cix: char); external;
(*---Direct Keyboard onput of a single char---*)
Procedure COPY( { TO } VAR dest : dfltstr;
{ FROM } THIS : MSTRING ;
{STARTING AT} POSN : INTEGER ;
{# OF CHARS } LEN : INTEGER ) ;
{ COPY(NEW_NAME, NBUF, NAME_ADDR, NAME_LEN); }
{ COPY(A_STRING, A_STRING, 5, 5); }
{
GLOBAL default = default line length;
dfltstr = STRING default;
StrMax = 255;
MSTRING = STRING StrMax; }
LABEL 9;
VAR ix : 1..StrMax;
begin
SETLENGTH(dest,0); {length returned string=0}
If (len + posn) > default then{EXIT}goto 9;
IF ((len+posn-1) <= LENGTH(this))
and (len > 0) and (posn > 0) then
FOR ix:=1 to len do
APPEND(dest, this[posn+ix-1]);
9: {Any error returns dest with a length of ZERO.}
End{of COPY};
PROCEDURE CONCAT({New_String} VAR C : dfltstr ;
{Arg1_str } A : Mstring ;
{Arg2_str } B : Mstring );
{ CONCAT(New_string, Arg1, Arg2); }
{ An error returns length of new_string=0 }
{
GLOBAL default = default line length;
dfltstr = STRING default;
StrMax = 255;
Mstring = STRING StrMax; }
var ix : 1..StrMax;
begin
SETLENGTH(C,0);
If (LENGTH(A) + LENGTH(B)) <= default then
begin
APPEND(C,A);
APPEND(C,B);
end;
End{of CONCAT};
Function UCASE(ch: char): char;
begin
If ch IN ['a'..'z'] then
UCASE := chr(ord(ch) - 32)
Else
UCASE := ch
end;
Procedure FINDR( PAT : str1;
VAR S : dfltstr;
VAR where : INDEXES;
VAR cnt : integer );
var ix, cum : integer;
temp : dfltstr;
begin
cum := 0;
cnt := 0;
where[1] := 0;
Repeat
COPY(temp, S, cum+1, length(S)-cum);
ix := INDEX(temp, pat);
cum := cum + ix;
If (ix>0) then
begin
S[cum] := space;
cnt := cnt + 1;
where[cnt] := cum;
where[cnt+1] := 0;
end;
Until (ix=0) OR (cum=length(S));
end{of FINDR};
Procedure ENTER(newx: links);
var this, next: links;
Newkey, Thiskey: dfltstr;
begin
If (root=nil) then
root := newx
Else
begin
next := root;
Repeat
this := next;
CASE sort of
1: begin { NAME Key }
Newkey := newx^.stuff.name;
Thiskey := this^.stuff.name;
end;
2: begin { ADDRESS Key }
Newkey := newx^.stuff.address;
Thiskey := this^.stuff.address;
end;
3: begin { ZIP Code Key }
Newkey := newx^.stuff.Zip;
Thiskey := this^.stuff.Zip;
end
End{case};
If Newkey <= Thiskey then
next := this^.Llink
Else
next := this^.Rlink;
Until next=nil;
If Newkey <= Thiskey then
this^.Llink := newx
Else
this^.Rlink := newx;
end
End{of Enter};
Procedure PAUSE;
var dummy: char;
begin
this_line := 0;
write('Press return <cr> to continue');
readln(dummy);
End{of Pause};
Procedure TRAVERSE(ptr: links);
{
---Address format---
Name line 1
Address line 2
Zip Code line 3
<blank line> line 4
}
var thiskey: dfltstr;
begin
CASE sort of
1: Thiskey := ptr^.stuff.name; { Name }
2: Thiskey := ptr^.stuff.address; { Address }
3: Thiskey := ptr^.stuff.Zip { Zip Code }
End{case};
If (ptr^.Llink<>nil) AND (Thiskey>=low) then
TRAVERSE(ptr^.Llink);
If (thiskey >= low) AND (thiskey <= high) then
begin{ Write an address }
With ptr^.stuff do begin
writeln(' ':margin, name : name$field$width );
writeln(' ':margin, address : address$field$width );
writeln(' ':margin, Zip : Zip$field$width );
writeln;
end{with};
this_line := this_line + 1;
If (this_line*6)+1 > screen_lines then PAUSE;
end{ Write an address };
If (ptr^.Rlink<>nil) AND (Thiskey <= high) then
TRAVERSE(ptr^.Rlink);
End{of TRAVERSE};
Procedure CREATIT;
{
GLOBAL I : integer; <passed from main program>
}
var p: links;
temp1,
newname,
newaddress,
newZip : dfltstr;
begin
NEW(p);
CASE sort of
1: begin
COPY(newname, LINE, ploc[I]+1, sloc[ 1 ]-ploc[I] );
COPY(temp1, LINE, 1, ploc[I] );
APPEND(newname,temp1);
end;
2,3: If (LINE[1]=space) then
COPY(newname, LINE, 2, sloc[1]-1)
Else
COPY(newname, LINE, 1, sloc[1])
End{case};
COPY(newaddress, LINE, sloc[1]+1, (sloc[2]-sloc[1])-1);
If (length(newaddress) > address$field$width) then
setlength(newaddress,address$field$width);
COPY(newZip, LINE, sloc[2]+1, length(LINE)-sloc[2] );
newname[1] := Ucase(newname[1]);
newaddress[1] := Ucase(newaddress[1]);
newZip[1] := Ucase(newZip[1]);
With p^.stuff do begin
name := newname; { Name line }
address := newaddress; { Address line }
Zip := newZip { ZIP Code }
end{with};
p^.Llink := nil;
p^.Rlink := nil;
ENTER(p);
end{of CREATIT};
Procedure GETID( MESSAGE : dfltstr; VAR ID: FID );
{
GLOBAL FID_LENGTH = 14;
dfltstr = STRING dflt_str_len;
fid = STRING FID_LENGTH; }
const space = ' ';
begin
setlength(ID,0);
writeln;
write(message);
READLN(ID);
while length(ID)<FID_LENGTH do APPEND(ID,space);
End{---of GETID---};
Procedure CLEAR;
var ix :1..25;
begin
for ix:=1 to 25 do writeln
end;
Procedure Initialize;
begin
CLEAR;
writeln(' ':12,Program_title);
writeln;writeln;writeln;writeln;
root := nil;
bell := chr(7);
size := 0;
bad_lines := 0;
GETID('Enter data file name ->', in_file);
RESET(in_file,wrk1);
end{of initialize};
Begin{ of Program KeyWordInContext }
Initialize;
If EOF(wrk1) then
begin
writeln('File ', in_file, 'not found');
{EXIT}goto 9999;
end;
REPEAT
writeln;
write(Sort_messge);
KEYIN(cix);Writeln(cix);
sort := ORD(cix) - ORD('0');
UNTIL sort IN [1,2,3];
{---Read In the Data File---}
Readln(wrk1,LINE);
while not EOF(wrk1) do
begin
FINDR(Sdelim, LINE, sloc, num);
error := (num<>2);
FINDR(Pdelim, LINE, ploc, num);
error := (error OR (num=0));
If sort IN [2,3] then num := 1;
If not error then
For i:=1 to num do
begin CREATIT; size := SUCC(size) end
Else
begin
writeln(bell,'***BAD LINE***',bell);
bad_lines := bad_lines + 1;
writeln(LINE)
end;
READLN(wrk1,LINE)
end{while};
{--- Read is complete ---}
{---Announce no of records found---}
writeln('Sort complete with ', size:3, ' records entered.');
If bad_lines > 0 then
writeln('There are ', bad_lines:3, ' bad lines in the data file.');
writeln;
write('Enter left margin? ');
READLN(margin);
writeln;
writeln('Enter range for output.');
Termination := false;
REPEAT
setlength(low,0);
setlength(high,0);
writeln;
write('Low string (<ctrl-C> to quit) ->');
readln(low);
If not termination then
begin{ low string }
low[1] := UCASE(low[1]);
write('High string ->');
readln(high);
If not termination then
begin{ high string }
high[1] := UCASE(high[1]);
this_line := 0;
CLEAR;
TRAVERSE(root)
end{ high string }
end{ low string }
UNTIL Termination;
9999:{ file not found }
End{ of Program Name and Address }.