home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
167
/
P4MAT202.ZIP
/
PFORMAT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-08-30
|
37KB
|
1,239 lines
PROGRAM pformat (INPUT, OUTPUT);
{----------------------------------------------------------------------------}
{ Compiler Directives Follow }
{$X+} {Array Optimization ON ... This PGM is Very-Much-So Array Driven}
{$U-} {Non-User-Interruptible}
{$K-} {NO Stack Checking}
{$C-} {KeyBoard CTRL-<char> Interp OFF}
{$R-} {NO Index Range Checking}
{$V-} {Var Parameter Type Checking OFF}
{----------------------------------------------------------------------------}
{ ========================================================================
pFORMAT version 2.0.2
~~~~~~~~~~~~~~~~~~~~~
AUTHOR: andy j s decepida 26-AUG-85
416 Perth Avenue, Toronto, Ontario, CANADA M6P 3Y6
DESCRIPTION: Reads in a .PAS text file and, depending on the user's
choice/s, generates a copy with alterations in the case of
the contained text.
Modifications
(2.0.0) : File Attributes routine has been changed;
prior algorithm worked only for Turbo Pascal
compiler release 2.xx; the current one accomodates
both 2.xx & 3.xx;
(2.0.0) : Reserved Words Table has been expanded to accomodate
new ones in Turbo Pascal 3.0;
(2.0.1) : Disabled Routing to Printer which was primitive (no
Pagination) anyway;
(2.0.1) : Added handling of hexadecimal literals
(preceded by '$' and composed of '0'..'9', 'A'..'F')
--- these literals will be made uppercase (only letters
'A'..'F' of course)
(2.0.1) : Added handling of CommandLine Parameters
When present, the 1st Parm is the InputFile
the 2nd Parm is the OutputFile
(2.0.2) : Prior versions would mishandle a line that has
more than one comment in it ... the comment/s subsequent
to the first is/are treated as executable; this has
been corrected.
(2.0.2) : Corrected an incipient bug in keypress-to-signal-run-abort
option (scenario: when option is active and the user,
intentionally or not, presses key "Y" the abort-confirm
hesitation query would already have been answered);
Correction implemented by changing function getc to
use the DOS call $0C to clear KBD buffer then let the
same chain to DOS call $07 (stdin w/o input)
As distributed, the source for pFORMAT.PAS has been submitted to pformat
itself. All ISO-PASCAL words are in caps and the Turbo-Extensions are
in mixed-case while user-defined words are in lower-case.
I am also providing this source indented following the laudable indenting
guidelines suggested by Robert E. Heckert in his article "A Pascal
Indentation Philosophy" published in Computer Language magazine of
Sept 1985 (v2,#9).
======================================================================= }
CONST
{$I tblsize.inc}
alphabet : SET OF CHAR = ['a'..'z', 'A'..'Z'];
nullstr = '';
space = ' ';
apostrophe = '''';
period = '.';
stdextns = '.PAS';
TYPE
charset = SET OF CHAR;
cursorsize = (full, half, normal, invisible);
s255 = STRING[255];
casetype = (upper, lower, asis);
VAR
iobuf, linebuf, legend, mask,
srcharg, tempstr, infnam,
outfnam : s255;
inf,
outf : TEXT[$1000];
token : ARRAY [1..tbl_size] OF STRING[20];
case4reserved,
case4nonreserved: casetype;
strt, endd, posn, indx,
parmcnt,
len, cnt : INTEGER;
reservedcount,
linecount, charcount,
commentcount: REAL;
resp, prior,
next : CHAR;
mixedcase, abortable,
commentactive, tokenfound,
ok : BOOLEAN;
{-----------------------------------------------------------------------------}
PROCEDURE initarray;
{-----------------------------------------------------------------------------}
{
initialize the reserved word array
}
BEGIN
{$I TOKEN.INC}
END; {initarray}
{-----------------------------------------------------------------------------}
PROCEDURE makecursor (size : cursorsize);
{-----------------------------------------------------------------------------}
{
crsr is set according to the passed Size ... IBM-PC specific!
}
TYPE
regpack = RECORD
ax, bx, cx, dx, bp, si, di, es, flags : INTEGER;
END; {of RegPack}
VAR
reg : regpack;
BEGIN
reg.ax := $0100; {set crsr type service code ... cf A-47 of
Hardware Technical Reference Manual}
CASE size OF
full : reg.cx := $000D;
half : reg.cx := $070C;
normal : reg.cx := $0B0C;
invisible: reg.cx := $2000
END; {CASE Size OF}
Intr ($10, reg) {call video I/O ROM call}
END;
{-----------------------------------------------------------------------------}
FUNCTION isdelimited (ch : CHAR) : BOOLEAN;
{-----------------------------------------------------------------------------}
{
TRUE if Ch is a valid delimiter for a substring pattern that matches that
of a reserved word
}
BEGIN
isdelimited := (ORD(ch) IN [32, 39..47, 58..62, 91, 93, 123, 125])
END;
{-----------------------------------------------------------------------------}
FUNCTION lowcase (ch : CHAR) : CHAR;
{-----------------------------------------------------------------------------}
{
returns lower case of an alpha char
}
BEGIN
IF (ch IN ['A'..'Z'])
THEN
ch := CHR (ORD(ch) - ORD('A') + ORD('a'));
lowcase := ch
END;
{-----------------------------------------------------------------------------}
FUNCTION upstrg (strg : s255) : s255;
{-----------------------------------------------------------------------------}
{
returns a string with alpha chars in capitals
}
VAR
slot : INTEGER;
BEGIN
FOR slot := 1 TO Length(strg)
DO
strg[slot] := UpCase(strg[slot]);
upstrg := strg
END;
{-----------------------------------------------------------------------------}
FUNCTION lowstrg (strg : s255) : s255;
{-----------------------------------------------------------------------------}
{
returns a string with alpha chars in lower-case
}
VAR
slot : INTEGER;
BEGIN
FOR slot := 1 TO Length(strg)
DO
strg[slot] := lowcase(strg[slot]);
lowstrg := strg;
END;
{-----------------------------------------------------------------------------}
PROCEDURE alarm;
{-----------------------------------------------------------------------------}
{
! sounds an alarm
}
BEGIN
Sound (100);
Delay (60);
NoSound;
Sound (50);
Delay (3);
NoSound
END;
{-----------------------------------------------------------------------------}
FUNCTION getc (legalchar : charset) : CHAR;
{-----------------------------------------------------------------------------}
{
waits for a CHAR input belonging in set legalchar, we are using
a DOS service call because we need a workaround to the bug
described in the prologue comment regarding keypress-to-signal-run-abort
feature
}
TYPE
regpack = RECORD
ax, bx, cx, dx, bp, si, di, es, flags : INTEGER;
END; {of RegPack}
CONST
bks = 8;
VAR
inchr : CHAR;
reg : regpack;
BEGIN
WRITE ('[ ]');
WRITE (CHR(bks), CHR(bks), space,CHR(bks));
REPEAT
makecursor (full);
reg.ax := $0C07; {Clear keyboard buffer & invoke DOS stdin w/o echo}
MsDos (reg);
inchr := CHR(Lo(reg.ax));
inchr := UpCase (inchr);
IF NOT (inchr IN legalchar)
THEN
alarm;
UNTIL (inchr IN legalchar);
makecursor (normal);
getc := inchr
END;
{-----------------------------------------------------------------------------}
FUNCTION yes : BOOLEAN;
{-----------------------------------------------------------------------------}
{
waits for a y/Y or n/N CHAR input
}
VAR
reply : CHAR;
BEGIN
WRITE (' [y/n] ■ ');
LowVideo;
yes := (getc(['Y','N']) = 'Y')
END;
{-----------------------------------------------------------------------------}
PROCEDURE trim (VAR tempstr : s255);
{-----------------------------------------------------------------------------}
{
strip leading spaces from a string
}
BEGIN
WHILE Pos(space, tempstr) = 1
DO
Delete (tempstr, 1, 1)
END;
{-----------------------------------------------------------------------------}
PROCEDURE userquits;
{-----------------------------------------------------------------------------}
{
when the pgm gets here, the user has indicated his/her intentions
}
BEGIN
Window (1,1,80,25);
GoToXY (1, 1);
LowVideo;
makecursor (normal);
ClrScr;
{$I-}
Close (inf);
Close (outf);
{$I+}
HALT
END;
{-----------------------------------------------------------------------------}
PROCEDURE confirm (confirmation : s255; reserved : BOOLEAN);
{-----------------------------------------------------------------------------}
{
evaluate / confirm user's pick
}
PROCEDURE setto (userchoice : casetype);
{-----------------------------------------------------------------------------}
{
"setto" is nested in confirm !!!
change case4reserved & case4nonreserved settings as per userchoice
}
BEGIN
IF reserved
THEN
case4reserved := userchoice
ELSE
case4nonreserved := userchoice
END;
BEGIN {confirm}
WRITELN;
WRITE (' You chose ');
TextColor (Black);
TextBackGround (White);
CASE resp OF
'U' : BEGIN
WRITE ('Upper-case');
setto (upper)
END;
'L' : BEGIN
WRITE ('Lower-case');
setto (lower)
END;
'A' : BEGIN
WRITE ('As-Is');
setto (asis)
END;
'Q' : userquits
END; {CASE}
LowVideo;
WRITELN (space,confirmation);
WRITE (' Is this correct? ')
END; {confirm}
{-----------------------------------------------------------------------------}
PROCEDURE altersettings;
{-----------------------------------------------------------------------------}
BEGIN {altersettings}
WRITELN;
REPEAT
WRITELN; WRITELN;
WRITELN (' ■ PASCAL reserved words.');
WRITE (' Options are : U(pper-case, L(ower-case, A(s-Is, Q(uit');
resp := getc (['U','L','A','Q']);
confirm ('for the RESERVED words.', TRUE)
UNTIL yes;
WRITELN; WRITELN; WRITELN;
WRITELN (' ■ Turbo Pascal Extensions.');
WRITELN (' Would you like to have the Borland extensions written ');
WRITELN (' in "Mixed Case" (e.g., "GotoXY" instead of "GOTOXY"');
WRITE (' or "gotoxy"?');
mixedcase := yes;
WRITELN;
REPEAT
WRITELN; WRITELN;
WRITELN (' ■ Non-Reserved Words.');
WRITE (' Options are : U(pper-case, L(ower-case, A(s-is, Q(uit');
resp := getc (['U','L','A','Q']);
confirm (' for the user defined identifiers.',FALSE);
UNTIL yes
END; {altersettings}
{-----------------------------------------------------------------------------}
PROCEDURE makemixedcase (VAR extension : s255);
{-----------------------------------------------------------------------------}
{
when user selects the option for mixed-case formatting of reserved words,
this proc will be invoked;
}
BEGIN {makemixedcase}
CASE indx OF
{$I EXTNS.INC}
END; {CASE Indx OF}
END; {makemixedcase}
{-----------------------------------------------------------------------------}
PROCEDURE findmatch;
{-----------------------------------------------------------------------------}
VAR
place : INTEGER;
{-----------------------------------------------------------------------------}
FUNCTION isreserved : BOOLEAN;
{-----------------------------------------------------------------------------}
{
returns true if token is properly delimited
}
BEGIN
IF (place + Length(token[indx])) < len
THEN { there is at least 1 }
next := Copy(linebuf, { more character beyond }
(place + (Length(token[indx]))), 1) { the pattern match }
ELSE
next := period; {the pattern match is end of the line ...so}
{force Next to be a valid delimiter }
IF place > 1
THEN { the pattern is not at the start of the line }
BEGIN
prior := Copy(linebuf, place - 1, 1);
isreserved := ((isdelimited(prior)) AND (isdelimited(next)))
END
ELSE
IF place = 1
THEN { the pattern is at the start of the line }
isreserved := (isdelimited(next))
END;
{-----------------------------------------------------------------------------}
PROCEDURE doreserved;
{-----------------------------------------------------------------------------}
BEGIN
reservedcount := reservedcount + 1;
srcharg := token[indx];
CASE case4reserved OF
lower : BEGIN
Delete (iobuf, place, Length(token[indx]));
srcharg := lowstrg (srcharg);
IF mixedcase
THEN
makemixedcase (srcharg);
Insert (srcharg, iobuf, place)
END;
upper : BEGIN
Delete (iobuf, place, Length(token[indx]));
IF mixedcase
THEN
makemixedcase (srcharg);
Insert (srcharg, iobuf, place)
END;
asis : IF mixedcase
THEN
BEGIN
Delete (iobuf, place, Length(token[indx]));
makemixedcase (srcharg);
Insert (srcharg, iobuf, place)
END
END {CASE case4reserved OF}
END;
{-----------------------------------------------------------------------------}
PROCEDURE searchtable (arg : s255; VAR key : INTEGER; VAR found : BOOLEAN);
{-----------------------------------------------------------------------------}
{
this is your basic binary table search algorithm ... no magic here
}
VAR
lohalf,
uphalf,
centre : INTEGER;
BEGIN {searchtable}
lohalf := 1;
uphalf := tbl_size;
found := FALSE;
WHILE (uphalf >= lohalf) AND (NOT found)
DO
BEGIN
centre := (lohalf + uphalf) DIV 2;
IF arg = token[centre]
THEN
BEGIN
found := TRUE;
key := centre
END
ELSE
IF arg > token[centre]
THEN
lohalf := centre + 1
ELSE
uphalf := centre - 1
END {WHILE}
END; {searchtable}
{-----------------------------------------------------------------------------}
PROCEDURE buildarg;
{-----------------------------------------------------------------------------}
{
step thru the string until a non-alphabetic char is encountered
}
VAR
done : BOOLEAN;
BEGIN {buildarg}
REPEAT
IF linebuf[posn] IN alphabet
THEN
srcharg := srcharg + linebuf[posn];
done := ((NOT (linebuf[posn] IN alphabet)) OR (posn = len));
IF NOT done
THEN
posn := SUCC(posn);
UNTIL done
END; {buildarg}
{-------------------------------------------}
BEGIN {findmatch}
posn := 1;
REPEAT {till the string is exhausted}
srcharg := nullstr;
place := posn;
buildarg;
IF Length(srcharg) > 1
THEN
BEGIN
searchtable (srcharg, indx, tokenfound);
IF tokenfound AND (isreserved)
THEN
doreserved
END
ELSE
posn := SUCC(posn)
UNTIL posn > len;
IF abortable
THEN {check for interrupt from keyboard}
IF KeyPressed
THEN
BEGIN
TextColor (Yellow);
TextBackGround (Black);
GoToXY (15, 11);
WRITE ('Abort pFORMAT of file ',infnam,'?');
IF yes
THEN
userquits
ELSE
BEGIN
DelLine;
makecursor (invisible)
END
END;
LowVideo
END; {findmatch}
{-----------------------------------------------------------------------------}
PROCEDURE mask_comments_strings;
{-----------------------------------------------------------------------------}
{
find then mask out comments & strings so as-is chars can be restored from
tempstr onto iobuf
}
{-----------------------------------------------------------------------------}
PROCEDURE maskmatch (commentlen : INTEGER);
{-----------------------------------------------------------------------------}
VAR
slot : INTEGER;
BEGIN {maskmatch}
tempstr := Copy (linebuf, strt, commentlen);
FOR slot := 1 TO Length(tempstr)
DO
tempstr[slot] := space;
Delete (linebuf, strt, commentlen);
Insert (tempstr, linebuf, strt)
END; {maskmatch}
BEGIN {mask_comments_strings}
REPEAT {do strings}
strt := Pos(apostrophe, linebuf);
IF strt <> 0
THEN
linebuf[strt] := space;
endd := Pos (apostrophe, linebuf);
IF endd <> 0
THEN
linebuf[endd] := space;
IF ((endd <> 0) AND (strt <> 0))
THEN
maskmatch (endd - strt + 1)
UNTIL ((endd = 0) OR (strt = 0));
REPEAT
strt := Pos('{', linebuf);
IF strt = 0 {check again for alternative delimiter}
THEN
strt := Pos ('(*', linebuf);
endd := Pos('}', linebuf);
IF endd = 0 {check again for alternate delimiter}
THEN
endd := Pos('*)', linebuf);
IF strt <> 0
THEN
BEGIN
commentactive := TRUE;
commentcount := commentcount + 1
END;
IF endd <> 0
THEN
commentactive := FALSE;
IF strt = 0
THEN
IF endd = 0 {no end-comment nor begin-comment}
THEN
IF commentactive {continued multiline comment}
THEN
BEGIN
strt := 1;
maskmatch (len - strt + 1)
END
ELSE {no active comment}
BEGIN {do nothing}
END
ELSE {end-comment found but no begin-comment}
BEGIN {multiline comment being terminated on current line}
strt := 1;
maskmatch (endd - strt + 1)
END
ELSE {begin-comment found}
IF endd <> 0
THEN {line has begin-comment & end-comment}
maskmatch (endd - strt + 1) {regular single line comment}
ELSE {line has begin-comment but no end-comment}
maskmatch (len - strt + 1) {start of a multiline comment}
UNTIL ((endd = 0) OR (strt = 0));
END; {mask_comments_strings}
{-----------------------------------------------------------------------------}
PROCEDURE parse;
{-----------------------------------------------------------------------------}
VAR
slot : INTEGER;
{-----------------------------------------------------------------------------}
PROCEDURE fixhex (VAR subject : s255);
{-----------------------------------------------------------------------------}
{
Ensure that the HexaDecimal Literals ( ::= (prefixed by a $) |0..9|
A..F ) stand out better by having the occurrences of A..F xlat to
uppercase unconditionally --- if you don't want this feature see
main block of parse which calls this PROC
}
CONST
hexset : SET OF CHAR = ['0'..'9', 'A'..'F'];
hexprefix = '$';
VAR
from,
num,
len,
step,
place : INTEGER;
hold,
tmp,
newstrg: s255;
done : BOOLEAN;
{-----------------------------------------------------------------------------}
PROCEDURE fixhexinit;
{-----------------------------------------------------------------------------}
BEGIN
hold := subject;
from := 1;
len := Length(hold);
newstrg := nullstr;
tmp := nullstr;
END;
{-----------------------------------------------------------------------------}
FUNCTION ishexstr : BOOLEAN;
{-----------------------------------------------------------------------------}
BEGIN
place := Pos (hexprefix, hold);
ishexstr := place <> 0;
END;
{-----------------------------------------------------------------------------}
PROCEDURE fixhex1;
{-----------------------------------------------------------------------------}
BEGIN
num := place - from + 1;
step := place + 1;
tmp := newstrg;
newstrg := Copy (hold, from, num);
newstrg := tmp + newstrg;
hold [place] := space;
END;
BEGIN {fixhex}
fixhexinit;
IF NOT ishexstr
THEN
Exit;
WHILE ishexstr
DO
BEGIN
fixhex1;
done := FALSE;
WHILE NOT done
DO
BEGIN
IF UpCase(hold[step]) IN hexset
THEN
BEGIN
IF step <= len {concat}
THEN
BEGIN
newstrg := newstrg + UpCase(hold[step]);
step := SUCC(step)
END
ELSE {a stray $ is at end of string ... concat done}
done := TRUE;
END
ELSE
done := TRUE
END; {WHILE NOT done}
from := step;
END; {WHILE ishexstr}
IF Length (newstrg) < len
THEN {copy rest of the string}
BEGIN
from := step;
hold := Copy (subject, from, len - from+1);
subject := newstrg+hold
END
ELSE
subject := newstrg;
END;
BEGIN {parse}
linebuf := iobuf;
len := Length (iobuf);
charcount := charcount + len;
mask_comments_strings;
linebuf := upstrg (linebuf);
tempstr := iobuf;
IF case4nonreserved = upper
THEN
iobuf := upstrg (iobuf)
ELSE
IF case4nonreserved = lower
THEN
iobuf := lowstrg (iobuf);
FOR slot := 1 TO Length(iobuf)
DO
IF linebuf[slot] = space
THEN
iobuf[slot] := tempstr[slot];
fixhex (iobuf); {--- comment this out if you don't want hex literals in caps}
findmatch
END; {parse}
{-----------------------------------------------------------------------------}
PROCEDURE banner;
{-----------------------------------------------------------------------------}
CONST
title = 'pFormat [v2.0.2] (C) Andy Decepida 1985-Aug-26';
BEGIN
Window (1, 1, 80, 25);
GoToXY (1, 1);
ClrScr;
NormVideo;
FOR cnt := 1 TO 80
DO
WRITE ('═');
LowVideo;
WRITELN (title:((80 + Length(title)) DIV 2));
NormVideo;
FOR cnt := 1 TO 80
DO
WRITE ('═');
LowVideo;
Window (1, 5, 80, 25);
GoToXY (1, 1);
WRITELN;
END;
{-----------------------------------------------------------------------------}
PROCEDURE checksettings;
{-----------------------------------------------------------------------------}
BEGIN
WRITELN; WRITELN;
ClrScr; banner;
TextColor (Brown);
WRITELN ('Output File ',outfnam,apostrophe,'s default attributes are :');
LowVideo;
WRITELN (' ■ TurboPASCAL key/reserved words are in UPPER-case letters and');
WRITELN (' ■ Other alphabetic characters are written as is.');
WRITELN;
WRITE ('Care to change these defaults ? ');
IF yes
THEN
altersettings
ELSE
BEGIN
case4reserved := upper;
case4nonreserved := asis;
END;
NormVideo;
WRITELN;
WRITELN;
WRITE ('Would you like to be able to abort this run with a keypress ?');
abortable := yes;
LowVideo
END;
{-----------------------------------------------------------------------------}
PROCEDURE get_attr (fd : s255);
{-----------------------------------------------------------------------------}
{
Get the File Attributes for displaying to user ... for confirmation
purposes ... IBM-PC specific
}
TYPE
filelist = RECORD
name : STRING[13];
attrib : Byte;
size : REAL;
date,
time : s255;
END;
regpack = RECORD
ax,bx,cx,dx,bp,si,di,ds,es,flags: INTEGER
END;
wrkstr = STRING[80];
VAR
list: filelist;
sizestr,
filemask: wrkstr;
x,total: Byte;
recpack: regpack;
hidden,system,readonly,normal,archive,dircty: BOOLEAN;
{-----------------------------------------------------------------------------}
PROCEDURE directory(filemask: wrkstr; VAR list: filelist; VAR total: Byte);
{-----------------------------------------------------------------------------}
VAR
dta: STRING[44];
{-----------------------------------------------------------------------------}
FUNCTION filesiz: REAL; { decipher the File's Size in Bytes }
{-----------------------------------------------------------------------------}
VAR size: REAL;
byte1,byte2,byte3,byte4: Byte;
BEGIN
byte1 := ORD(Copy(dta,28,1));
byte2 := ORD(Copy(dta,27,1));
byte3 := ORD(Copy(dta,29,1));
byte4 := ORD(Copy(dta,30,1));
size := byte1 ShL 8+byte2;
IF size< 0
THEN
size := size+65536.0; { adjust for negative values }
size := (byte3 ShL 8+byte4)*256.0+size;
filesiz := size;
END; { filesiz }
{-----------------------------------------------------------------------------}
FUNCTION filedate: wrkstr; { decipher the File's Date Stamp }
{-----------------------------------------------------------------------------}
VAR day,month,year: wrkstr;
mon : STRING[3];
temp: INTEGER;
byte1,byte2: Byte;
BEGIN
byte1 := ORD(Copy(dta,25,1));
byte2 := ORD(Copy(dta,26,1));
Str(byte1 AND 31:2,day);
temp := (byte1 ShR 5) AND 7+(byte2 AND 1) ShL 3;
CASE temp OF
01 : mon := 'Jan'; 02 : mon := 'Feb'; 03 : mon := 'Mar';
04 : mon := 'Apr'; 05 : mon := 'May'; 06 : mon := 'Jun';
07 : mon := 'Jul'; 08 : mon := 'Aug'; 09 : mon := 'Sep';
10 : mon := 'Oct'; 11 : mon := 'Nov'; 12 : mon := 'Dec'
END;
Str((byte2 ShR 1)+80: 2,year);
IF day[1]= space
THEN
day[1] := '0';
IF year[1]= space
THEN
year[1] := '0';
filedate := day+'-'+mon+'-'+year
END; { filedate }
{-----------------------------------------------------------------------------}
FUNCTION filetime: wrkstr; { decipher the File's Time Stamp }
{-----------------------------------------------------------------------------}
VAR hour,min,ampm: wrkstr;
temp: INTEGER;
byte1,byte2: Byte;
BEGIN
byte1 := ORD(Copy(dta,23,1));
byte2 := ORD(Copy(dta,24,1));
temp := (byte1 ShR 5) AND 7+(byte2 AND 7) ShL 3;
Str(temp:2,min);
temp := byte2 ShR 3;
IF temp<13
THEN
ampm := 'am'
ELSE
BEGIN
temp := temp-12;
ampm := 'pm'
END;
Str(temp:2,hour);
WHILE (Pos(space, hour) <> 0)
DO
Delete (hour,1,1);
IF min[1]= space
THEN
min[1] := '0';
filetime := hour+':'+min+ampm
END; { filetime }
{-----------------------------------------------------------------------------}
PROCEDURE fillrecord(recno: Byte); { fill List.[RecNo] with file info }
{-----------------------------------------------------------------------------}
BEGIN
WITH list
DO
BEGIN
name := Copy(dta,31,13);
attrib := ORD(Copy(dta,22,1));
size := filesiz;
date := filedate;
time := filetime;
IF (name[1]<>period) AND (Pos(period,name)<>0)
THEN
BEGIN { line up the file ext.}
WHILE Pos(period,name)<9
DO
Insert(space,name,Pos(period,name));
name[Pos(period,name)] := space;
END;
END;
END; { fillrecord }
{-----------------------------------------------------------------------------}
PROCEDURE filldirlist;
{-----------------------------------------------------------------------------}
BEGIN
total := 1;
fillrecord(total);
REPEAT
recpack.ax := $4F ShL 8;
MsDos(recpack);
IF (recpack.ax<>18) AND (recpack.ax<>2)
THEN
BEGIN
total := total+1;
fillrecord(total)
END { repeat filling until no more }
UNTIL (recpack.flags AND 1)<>0;{ files are found }
END; { filldirlist }
BEGIN { Directory }
total := 0;
dta := ' ';
filemask := filemask+#0;
WITH recpack
DO
BEGIN { First, Set aside the DTA }
ax := $1A ShL 8; { or Data Transfer Area, }
ds := Seg(dta);
dx := Ofs(dta)+1; { call $1A then call $4E to }
MsDos(recpack); { find the First Match. Set }
ax := $4E ShL 8; { set Cx to 23 to include all }
ds := Seg(filemask);
dx := Ofs(filemask)+1; { hidden files. Then up above }
cx := 23; { call $4F to find subsequent }
MsDos(recpack); { matches, filling List. }
IF (flags AND 1)=0
THEN
filldirlist
END
END; { directory }
BEGIN
directory(fd,list,total); { if available }
WRITELN;
WITH list
DO
BEGIN
Str(size:15:0, sizestr);
WHILE (Pos(space,sizestr) <> 0)
DO
Delete (sizestr,1,1);
WRITE ('The ', sizestr, '-byte file ');
HighVideo;
WRITE (fd);
LowVideo;
WRITE (' was saved on ', date);
WRITE (' at ', time);
END;
WRITELN;
END;
{-----------------------------------------------------------------------------}
PROCEDURE checkinput;
{-----------------------------------------------------------------------------}
BEGIN
IF Length (infnam) < 1
THEN
userquits;
IF (Pos (period, infnam) = 0)
AND (Pos (stdextns, infnam) = 0)
THEN
infnam := infnam+stdextns;
Assign (inf, infnam);
{$I-}
RESET (inf)
{$I+};
ok := (IOResult = 0);
IF ok
THEN
BEGIN {open of an existing file is successful}
get_attr (infnam);
WRITELN;
NormVideo;
WRITE ('Is this the file you really want to submit? ');
IF NOT yes
THEN
ok := FALSE;
LowVideo
END
ELSE
BEGIN
alarm; alarm; alarm;
WRITELN; WRITELN;
WRITE (' ... Cannot find file ');
NormVideo;
WRITE (infnam);
LowVideo;
WRITELN(' ... PRESS ',CHR(17),'┘');
WRITELN;
makecursor (invisible);
READLN (KBD);
END
END;
{-----------------------------------------------------------------------------}
PROCEDURE getinfnam;
{-----------------------------------------------------------------------------}
BEGIN {getinfnam}
ok := FALSE;
WHILE NOT ok
DO
BEGIN
WRITELN;
LowVideo;
WRITE ('Name of TurboPASCAL source text file : ');
makecursor (full);
READLN (infnam);
makecursor(invisible);
trim (infnam);
infnam := upstrg (infnam);
checkinput;
END; {WHILE}
makecursor (normal)
END; {getinfnam}
{-----------------------------------------------------------------------------}
PROCEDURE checkoutput;
{-----------------------------------------------------------------------------}
BEGIN
outfnam := upstrg (outfnam);
IF Length (outfnam) < 1
THEN
userquits;
IF (Pos (period, outfnam) = 0) {concat (.PAS) only if }
AND (Pos (stdextns, outfnam) = 0) {there is no supplied extns}
THEN
outfnam := outfnam+stdextns;
IF outfnam = infnam
THEN
BEGIN
TextColor (Yellow);
makecursor (invisible);
WRITELN;
alarm; alarm; alarm;
WRITELN ('You have PERILOUSLY designated the same file_name for both your');
WRITELN (' input and your output file !!! ');
WRITELN;
WRITELN(' PRESS ',CHR(17),'┘ ... ');
WRITELN;
WRITELN(' And then give an output file name that is different from the input.');
alarm;
READLN (KBD);
LowVideo;
ok := FALSE;
Exit;
END;
Assign (outf, outfnam);
{$I-}
RESET (outf); {check & see if destination file}
{$I+} { already exists}
ok := (IOResult = 0);
IF ok
THEN
BEGIN
WRITELN; WRITELN;
TextColor (Black);
TextBackGround (White);
WRITELN (' ■ ',outfnam,' already exists ...');
LowVideo;
alarm; alarm; alarm;
get_attr(outfnam);
alarm;
WRITELN;
TextColor (Yellow);
WRITE (' ■ Do you want to go ahead and write over it ');
IF yes
THEN
Close (outf)
ELSE
BEGIN
ok := FALSE;
Exit
END
END;
Assign (outf, outfnam);
{$I-}
REWRITE (outf);
{$I+};
ok := (IOResult = 0);
IF NOT ok
THEN
BEGIN
alarm; alarm; alarm;
WRITELN; WRITELN;
makecursor (full);
alarm;
NormVideo;
WRITE (' ... Unable to open file ',outfnam, ' ... PRESS ',CHR(17),'┘ ');
READLN;
makecursor (invisible);
LowVideo
END
END;
{-----------------------------------------------------------------------------}
PROCEDURE getoutfnam;
{-----------------------------------------------------------------------------}
BEGIN {getoutfnam};
REPEAT
ClrScr;
banner;
outfnam := nullstr;
WRITELN;
NormVideo;
WRITELN (' pFORMAT will generate a copy of ',infnam);
LowVideo;
get_attr (infnam);
WRITELN;
WRITELN (' Options :');
WRITELN (' ■ You may enter a DOS file name to capture the copy on disk,');
WRITELN (' ■ OR, you may quit by pressing a lone ',CHR(17),'┘');
WRITE (' --- Please designate a destination for the pFORMAT copy : ');
makecursor (full);
READLN (outfnam);
trim (outfnam);
checkoutput;
UNTIL ok;
makecursor (normal)
END; {getinfnam}
{-----------------------------------------------------------------------------}
PROCEDURE preamble;
{-----------------------------------------------------------------------------}
PROCEDURE oneparm;
{-----------------------------------------------------------------------------}
BEGIN
ok := TRUE;
infnam := upstrg(ParamStr(1));
checkinput;
IF NOT ok
THEN
getinfnam;
getoutfnam;
END;
{-----------------------------------------------------------------------------}
PROCEDURE twoparms;
{-----------------------------------------------------------------------------}
BEGIN
ok := TRUE;
infnam := upstrg(ParamStr(1));
outfnam:= upstrg(ParamStr(2));
checkinput;
IF NOT ok
THEN
getinfnam;
checkoutput;
IF NOT ok
THEN
BEGIN
getoutfnam;
parmcnt := 0;
END;
END;
BEGIN
{___ initialize global variables ___}
mixedcase := FALSE; commentactive := FALSE;
case4reserved := upper; case4nonreserved := lower;
reservedcount := 0; linecount := 0;
charcount := 0; commentcount:= 0;
LowVideo;
ClrScr; banner;
WRITE (
' To quit, press a lone ',CHR(17),
'┘ in response to the prompts for file names.');
WRITELN;
IF parmcnt = 0
THEN
BEGIN {no Command Line Parms}
getinfnam;
getoutfnam;
END
ELSE
IF parmcnt = 1
THEN
oneparm
ELSE
twoparms;
checksettings;
TextColor (Black);
TextBackGround (White);
legend := Concat ('Reading ',infnam,' & generating ',outfnam);
ClrScr;
banner;
WRITELN;
IF (Length (legend) <= 80)
THEN {centre if it fits 80-char line}
WRITE (legend:((80 + Length(legend)) DIV 2))
ELSE
WRITE (legend);
WRITELN;
NormVideo;
FOR cnt := 1 TO 80
DO
WRITE ('═');
LowVideo;
makecursor (invisible);
NormVideo;
GoToXY (25, 5); WRITE (' Lines processed : ');
GoToXY (25, 6); WRITE (' Characters encountered : ');
GoToXY (25, 7); WRITE (' Reserved words processed : ');
GoToXY (25, 8); WRITE (' Comments encountered : ');
LowVideo
END;
{-----------------------------------------------------------------------------}
PROCEDURE task;
{-----------------------------------------------------------------------------}
BEGIN
preamble;
WHILE NOT (EOF(inf))
DO
BEGIN
iobuf := nullstr;
READLN (inf, iobuf);
IF Length(iobuf) <> 0
THEN
parse;
linecount := linecount + 1;
GoToXY (56, 5); WRITE (linecount:7:0);
GoToXY (56, 6); WRITE (charcount:7:0);
GoToXY (56, 7); WRITE (reservedcount:7:0);
GoToXY (56, 8); WRITE (commentcount:7:0);
WRITELN(outf, iobuf)
END;
alarm; alarm; alarm;
makecursor (normal);
alarm;
Close (inf);
Close (outf);
END;
{-- pFORMAT begins here --------------------------------------------------}
BEGIN
TextMode;
initarray;
infnam := nullstr;
parmcnt := ParamCount;
ok := TRUE;
REPEAT
task;
WRITELN; WRITELN; WRITELN;
parmcnt := 0;
WRITE (' Quit pFORMAT?')
UNTIL yes;
userquits
END. {---------------------------------------------------------------pFormat}