home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
RBBS in a Box Volume 1 #3.1
/
RBBSIABOX31.cdr
/
pool
/
plist2b.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1990-09-29
|
17KB
|
484 lines
program PLIST;
(*
Written by: Rick Schaeffer
E. 13611 26th Av.
Spokane, Wa. 99216
modifications (7/8/84 by Len Whitten, CIS: [73545,1006])
1) added error handling if file not found
2) added default extension of .PAS to main & include files
3) added "WhenCreated" procedure to extract file
creation date & time from TURBO FIB
4) added demarcation of where include file ends
5) added upper char. conversion to include file
6) increased left margin to 5 spaces (80 char. line just fits @ 10cpi)
7) added listing control: {.L-} turns it off, {.L+} turns it back on,
must be in column 1
further modifications (7/12/84 by Rick Schaeffer)
1) cleaned up the command line parsing routines and put them in
separate procedures. Now permits any number of command line
arguments, each argument separated with at least one space.
2) added support for an optional second command line parameter
which specifies whether include files will be listed or not.
The command is invoked by placing "/i" on the command line
at least one space after the file name to be listed. For
instance, to list MYPROG.PAS as well as any "included" files,
the command line would be: PLIST MYPROG /I
further modification (8/28/84) by Jay Kadashaw)
1) Restored filedate and filetime after listing an included
file.
2) Added comment counter and begin/end counter.
3) Output can be routed to either the printer or console.
4) After listing first file the user is prompted for next
file if any.
*)
(* Supported pseudo operations:
1) Listing control: {.L-} turns it off, {.L+} turns it back on,
must be in column 1
2. Page ejection: {.PAGE}, must be in column 1.
*)
{ When program is first run will check for a file
name passed by DOS, and will try to open that file. If no name is
passed, will ask operator for a file name to open. Proc will tell
operator if file doesn't exist and will allow multiple retrys.
Included files will be expanded only if the program is invoked as
follows:
pretty filename /i
The default is not to expand included files.
On 2nd and later executions, proc will not check for DOS passed file
name. In all cases, proc will assume a file type of .PAS if file
type is not specified.
PROGRAM EXIT from this proc when a null string is encountered in
response to a file name request. }
const monthmask = $000F;
daymask = $001F;
minutemask = $003F;
secondmask = $001F;
First : boolean = true; {true when prog is run}
{ to customize code for your printer - adjust the next item }
maxline = 58;
cr = #13;
lf = #10;
ff = #12;
type
two_letters = string[2];
dtstr = string[8];
fnmtype = string[14];
instring = string[135];
regpack = record
ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
end;
Var
Buff1 : instring; {input line buffer}
listfil : text; {FIB for LST: or CON: output}
infile : text; {FIB for input file}
fnam : fnmtype; {in file name}
bcount : integer; {begin/end counter}
kcount : integer; {comment counter}
linect : integer; {output file line counter}
pageno : integer;
offset : integer;
print : boolean; (* {.L-} don't print *)
(* {.L+} print *)
print_head : boolean;
c : char;
month, day, year,
hour, minute, second : two_letters;
sysdate, systime,
filedate, filetime : dtstr;
expand_includes : boolean;
holdarg : instring;
allregs : regpack;
{.page}
procedure getchar(var char_value : char);
begin
allregs.ax := $0000;
intr($16, allregs);
char_value := chr(ord(lo(allregs.ax)));
end; {getchar}
procedure fill_blanks (var line: dtstr);
var
i : integer;
begin
for i:= 1 to 8 do if line[i] = ' ' then line[i]:= '0';
end; {fill_blanks}
procedure getdate(var date : dtstr);
begin
allregs.ax := $2A * 256;
MsDos(allregs);
str((allregs.dx div 256):2,month);
str((allregs.dx mod 256):2,day);
str((allregs.cx - 1900):2,year);
date := month + '/' + day + '/' + year;
fill_blanks (date);
end; {getdate}
procedure gettime(var time : dtstr);
begin
allregs.ax := $2C * 256;
MsDos(allregs);
str((allregs.cx div 256):2,hour);
str((allregs.cx mod 256):2,minute);
str((allregs.dx div 256):2,second);
time := hour + ':' + minute + ':' + second;
fill_blanks (time);
end; {gettime}
procedure WhenCreated (var date, time: dtstr; var infile: text);
var fulltime,fulldate: integer;
begin
{fulldate gets the area of the FIB which corresponds to bytes 20-21
of the FCB. Format is: bits 0 - 4: day of month
5 - 8: month of year
9 -15: year - 1980 }
fulldate:= memw [seg(infile):ofs(infile)+31];
str(((fulldate shr 9) + 80):2,year);
str(((fulldate shr 5) and monthmask):2,month);
str((fulldate and daymask):2,day);
date:= month + '/' + day + '/' + year;
fill_blanks(date);
{fulltime gets the area of the FIB which corresponds to bytes 22-23
of the FCB. Format is: bits 0 - 4: seconds/2
5 -10: minutes
11-15: hours }
fulltime:= memw [seg(infile):ofs(infile)+33];
str((fulltime shr 11):2,hour);
str(((fulltime shr 5) and minutemask):2,minute);
str(((fulltime and secondmask) * 2):2,second);
time:= hour + ':' + minute + ':' + second;
fill_blanks (time);
end; {WhenCreated}
procedure print_heading(filename : fnmtype);
var offset_inc: integer;
begin
if print then
begin
pageno := pageno + 1;
write(listfil, ff); {top of form}
writeln(listfil);
write(listfil,' TURBO Pascal Program Lister');
writeln(listfil,' ':8,'Printed: ',sysdate,' ',
systime,' Page ',pageno:4);
if filename <> fnam then begin
offset_inc:= 14 - length (filename);
write(listfil,' Include File: ',filename,' ':offset_inc,
'Created: ',filedate,' ',filetime);
end
else write(listfil,' Main File: ',fnam,' ':offset,
'Created: ',filedate,' ',filetime);
writeln(listfil); writeln(listfil);
writeln(listfil, ' C B');
writeln(listfil);
linect := 6;
end; {check for print}
end; {print_heading}
procedure printline(iptline : instring; filename : fnmtype);
begin
if print then
begin
if linect < 56 then
begin
writeln(listfil,' ',iptline);
linect := linect + 1;
end
else
begin
print_heading(filename);
end;
end; {check for print}
end; {printline}
{.page}
function chkinc(var iptline : instring; var incflname : fnmtype) : boolean;
var
done : boolean;
i, j : integer;
begin
i := 4; j := 1; incflname := '';
if copy(iptline, 1, 3) = '{$I' then begin
i := 4; j := 1; incflname := '';
while (iptline[i] = ' ') and (i <= length(iptline)) do i := i + 1;
done := false;
while not done do begin
if i <= length(iptline) then begin
if not (iptline[i] in [' ','}','+','-']) then begin
incflname[j] := iptline[i];
i := i + 1; j := j + 1;
end else done := true;
end else done := true;
if j > 14 then done := true;
end;
incflname[0] := chr(j - 1);
end;
if incflname <> '' then chkinc := true else chkinc := false;
end; {chkinc}
function parse_cmd(argno : integer) : instring;
var
i,j : integer;
wkstr : instring;
done : boolean;
cmdline : ^instring;
begin
cmdline := ptr(CSEG,$0080);
wkstr := '';
done := false; i := 1; j := 0;
if length(cmdline^) < i then done := true;
repeat
while ((cmdline^[i] = ' ') and (not done)) do begin
i := i + 1;
if i > length(cmdline^) then done := true;
end;
if not done then j := j + 1;
while ((cmdline^[i] <> ' ') and (not done)) do begin
wkstr := wkstr + cmdline^[i];
i := i + 1;
if i > length(cmdline^) then done := true;
end;
if (j <> argno) then wkstr := '';
until (done or (j = argno));
for i := 1 to length(wkstr) do
wkstr[i] := upcase(wkstr[i]); {all arguments forced to upper case}
parse_cmd := wkstr;
end;
PROCEDURE GET_IN_FILE; {GETS INPUT FILE NAME }
var
existing : boolean;
begin
repeat {until file exists}
holdarg := parse_cmd(1); {get command line argument # 1}
if (length(holdarg) in [1..14]) and first then
fnam := holdarg {move possible file name to fnam}
else
begin
writeln;
write(' ENTER FILE NAME TO LIST or <cr> to EXIT ');
readln(fnam);
end;
if fnam = '' then HALT; {***** EXIT *****}
if pos('.',fnam) = 0 then {file type given?}
fnam := concat(fnam,'.PAS'); {file default to .PAS type}
{get optional command line argument # 2}
if (length(holdarg) in [1..14]) and first then
begin
holdarg := parse_cmd(2);
if holdarg = '/I' then expand_includes := true
else expand_includes := false;
end;
first := false; {get passed file name only once}
assign( infile, fnam);
{$I-}
reset( infile ); {check for existence of file}
{$I+}
existing := (ioresult = 0); {true if file found}
if not existing then
begin
writeln;
writeln(' FILE DOESN''T EXIST'); {tell operator the sad news}
end;
until existing; {until file exists}
end; {GET_IN_FILE}
{ GET_OUT_FILE procedure asks operator to select output to console
device or list device, and then assigns and resets a file control
block to the appropriate device. 'C' or 'P' is only correct
response, and multiple retrys are allowed. }
Procedure Get_Out_File;
var
c : char;
begin
repeat {until good selection}
writeln; write(' OUTPUT LISTING TO (C)ONSOLE OR (P)RINTER ? ');
getchar(c);
c := upcase(c); write(c);
until c in ['C', 'P'];
writeln;
if c = 'C' then
assign (listfil, 'CON:')
else
assign (listfil, 'LST:');
reset(listfil);
end; {GET_OUT_FILE}
Procedure ListIt(filename : fnmtype); forward;
{.page}
{ SCAN_LINE procedure scans one line of Turbo Pascal source code
looking for BEGIN/END pairs, CASE/END pairs, LITERAL fields
and COMMENT fields. BCOUNT is begin/end and case/end counter.
KCOUNT is comment counter. Begin/case/ends are only valid
outside of comment fields and literal constant fields (KCOUNT = 0
and NOT LITERAL).
Some of the code in the SCAN_LINE procedure appears at first glance
to be repitive and/or redundant, but was added to speed up the
process of scanning each line of source code.}
Procedure SCAN_LINE;
var
literal : boolean; { true if in literal field}
tmp : string[7]; { tmp work area }
i : integer; {loop variable index}
buff2 : instring; {working line buffer}
incflname : fnmtype; {in file name}
filedate_save : dtstr;
filetime_save : dtstr;
begin
literal := false;
buff2[0] := buff1[0]; {copy input buffer to working buffer}
for i := 1 to length(buff1) do
buff2[i] := upcase(buff1[i]); {and translate to upper case}
if chkinc(buff2, incflname) and expand_includes then
begin
for i := 1 to length(incflname) do
incflname[i] := upcase(incflname[i]);
if pos('.',incflname) = 0 then incflname := incflname + '.PAS';
printline('*************************************',incflname);
printline(' Including "'+incflname+'"', incflname);
printline('*************************************',incflname);
filedate_save := filedate; {save filedate & filetime for}
filetime_save := filetime; {main file }
listit(incflname);
filedate := filedate_save; {restore}
filetime := filetime_save;
printline('*************************************',incflname);
printline(' End of "'+incflname+'"', incflname);
printline('*************************************',incflname);
end; {include file check}
if copy(buff2,1,5) = '{.L-}' then print := false;
if copy(buff2,1,5) = '{.L+}' then print := true;
if copy(buff2,1,7) = '{.PAGE}' then print_head := true;
buff2 := concat(' ', buff2, ' '); {add on some working space}
for i := 1 to length(buff2) - 6 do
begin
tmp := copy(buff2, i, 7);
if not literal then {possible to find comment delim}
begin
{determine if comment area delim}
if tmp[1] in ['{', '}', '(', '*'] then
begin
if (tmp[1] = '{') or (copy(tmp,1,2)='(*') then
kcount := succ(kcount); {count comment opens}
if (tmp[1] = '}') or (copy(tmp,1,2)='*)') then
kcount := pred(kcount); {un-count comment closes}
end;
end;
if kcount = 0 then {we aren't in a comment area}
begin
if tmp[1] = chr(39) then
literal := not literal; {toggle literal flag}
if not literal and (tmp[2] in ['B','C','E']) then
begin
if (tmp = ' BEGIN ') or (copy(tmp,1,6) = ' CASE ') then
begin
bcount := succ(bcount); {count BEGIN}
i := i + 5; {skip rest of begin}
end;
if (copy(tmp,1,4) = ' END') and
(tmp[5] in ['.', ' ', ';']) and
(bcount > 0) then
begin
bcount := pred(bcount); {un-count for END}
i := i + 4;
end;
end; {if not literal}
end; { if kcount = 0 }
end; { for i := }
end; {SCAN_LINE}
{.page}
Procedure ListIt;
var
infile : text;
begin
assign(infile, filename);
{$I-} reset(infile) {$I+} ;
if IOresult <> 0 then begin
writeln ('File ',filename,' not found.');
halt;
end;
WhenCreated (filedate,filetime,infile);
print_heading(filename);
while not eof(infile) do
begin
readln(infile, buff1);
scan_line;
if print_head then
print_heading(filename);
if print and (not print_head) then
begin
writeln(listfil,kcount : 2, bcount : 3, ' ', buff1);
linect := succ(linect);
if linect > maxline then
begin
print_heading(filename);
end;
end;
print_head := false;
end; {while not eof}
end; {ListIt}
{.page}
begin {main procedure}
getdate(sysdate);
gettime(systime);
expand_includes := false; {default settings}
print := true;
repeat {forever}
ClrScr;
GotoXY(2, 2);
writeln('TURBO Pascal Formatted Listing');
GotoXY(2, 4);
get_in_file; {file to list}
offset := 24 - length(fnam);
get_out_file; {where to list it}
pageno := 0;
linect := 1; {output line counter}
kcount := 0;
bcount := 0;
print_head := false;
listit(fnam);
write(cr, lf, 'HIT ANY KEY TO CONTINUE '); {allow op to see end
of listing}
getchar(c);
until false {repeat forever - exit is in GET_IN_FILE PROCEDURE}
end. {main procedure}
cedure}