home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
turbopas
/
conv_p18.arc
/
CONV_P18.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-11-21
|
31KB
|
822 lines
PROGRAM UpConv;
{$B-} {shortcut Boolean}
{$D-} {no debug}
{$L-} {no local symbols}
{$S-} {no stack checking}
{$V-} {no VAR-string checking}
Uses Dos,Strings; {v1.3 for all the wildcard stuff
v1.8 STRINGS.TPU for some string stuff}
{ DEFINE NO_OVERWRITE} {this enables .FMT file existence checking.
I suggest you leave it .. that keeps the
system from trying to reformat earlier
.FMT files during a wildcard run where the user
specified *.* or something equally dumb!
}
{
Original based on a bulletin board program by Jeff Firestone
This version based on a program by Douglas S. Stivison in his book:
'Turbo Pascal Library' published by Sybex.
One peculiarity about the comment-handling: Anything within the usual
'}{' comments is skipped over; anything within the "parenthesis asterisk"
type comment IS processed! So .. put real comments within '}{' comments,
and commented-out code within the '(* *)' type comments.
v1.8, Toad Hall, 20 Nov 89
- Adding ability to use user-selected reserved word .DAT data files
(from the command line).
Default data file will be CONV_P.DAT.
- Totally rewrote TOK_STR to handle multiple reserved word text files
to build a reserved word .DAT file.
We don't have sorted reserved words any more (but that's ok).
- Using STRINGS.TPU for some string-related functions.
- Rebuilt Args into records of strings and filename type
(to handle cmdline switches, data files, source files).
- Using newer (slightly tweaked) POSBM2 POS() replacement.
v1.7, Toad Hall, 25 Oct 89
- Bug in TOK_STR.PAS (missing tokens when a concatenated token
string reached max length). Fixed.
- No changes in UPCONV itself, just in the TOKENS.DAT file
TOK_STR.EXE produces. Replace your existing TOKENS.DAT with
the new one and UPCONV16 will run just fine.
v1.6, Toad Hall, 20 Oct 89
- Moved the reserved word strings to an external file (UPCONV.DAT),
created by the TOK_STR utility.
- Now uses linked lists of string pointers to dynamic reserved
word strings (rather than the previous "hard-coded" typed constant
array of reserved word strings).
- Add a couple more missing reserved words (ParamCnt, ParamStr),
changed 'Assign' to "ASSIGN".
- Executable is now smaller, loads faster, runs faster.
v1.5, Toad Hall, 13 Oct 89
- Adding some missing reserved words (LongInt, Word)
- Added a modicum of file write error-trapping.
v1.4, Toad Hall, 15 Jun 89
- Added some missing reserved words (FillChar, FOR, FUNCTION).
- Adding faster replacement for the POS() function (POSBM).
- Made Args array dynamic (e.g., via pointers)
- Buffering string reads, writes via two dynamic buffers to reduce
disk thrashing, slightly speed up program (maybe 10%).
(Not doing any memory testing yet, so I hope your system
has sufficient memory.)
- Writing a terminating ^Z to our output file
(just to be neat, keep same file size, etc.).
v1.3, Toad Hall, 14 Apr 89
- Tweaking for Turbo Pascal v5.0
- Adding a bunch of TP 4.0 and 5.0 Borland words.
- Tightening up a little.
- Added commandline multiple filename/wildcard capability.
- Added '/L' switch for Pascal (non-Borland) reserved word
lowercase conversion.
- Building formatted output string (WorkLine). Saved only a little
processing time, but did cut out about 60-70 bytes of code.
time size
$DEFINE: 1:16.35 12160 bytes
No DEFINE: 1:15.79 12096 bytes
- Tried a Move instruction to concatenate strings to WorkLine
(vs. WorkLine := WorkLine + String); gained no time, only saved
16 bytes .. not worth the obtuseness.
- Adding chars to WorkLine the hard way (see code) vs. normal way
(WorkLine := WorkLine + char) saved code, time:
1:17.34 12208 bytes
v1.2, Toad Hall, 12 Oct 88
- Bug in Scan_Till procedure. Fixed.
- Isn't leaving quoted strings alone. Fixed.
v1.1 Toad Hall Tweak, Sep 88
- Added command line filename input.
- Moved Identifier char set to a global typed constant.
- Changed simple Reserved Word uppercasing to include Turbo Pascal
formatted reserved words.
- Added more reserved words for Turbo Pascal. (Complete thru v3.0,
I think .. don't have 4.0, so that should be added.)
- Command line switch ('-U') to force all reserved words to uppercase
(e.g., ignore Turbo Pascal format).
- Considering how to change other text (non-quoted, non-comments)
to all-upper, all-lower, As-Is, like PFORMAT.PAS does.
- Still suspect a fancy hash procedure to confirm a RamWord as a
reserved word would be better than this "if word is in line"
business. Later.
v1.0
- Found in SIMTEL20's PD1:<MSDOS.TURBOPAS>UPCONV.ARC.
Original author unknown.
David Kirschbaum
Toad Hall
kirsch@arsocomvax.socom.mil
}
CONST
Default_DataName : STRING[12] = 'CONV_P.DAT'; {default data file v1.8}
TYPE
StrPtr = ^Str_Rec; {v1.6}
Str_Rec = RECORD
S : STRING;
next : Pointer;
END;
VAR
ReservedWords : StrPtr; {v1.6 pointer to first dynamic
reserved word string record}
UCReserved : StrPtr; {v1.6 pointer to first dynamic
uppercase reserved word string record}
curr,curruc : StrPtr; {for current normal and uppercased
str recs v1.8}
CONST
APOS = #39; {This is the ' symbol.}
OPENCOMMENT = '{';
CLOSECOMMENT = '}';
{Note: These are the only valid characters that can be used in Turbo
identifiers.}
Identifier : SET OF CHAR = ['A'..'Z', '0'..'9', '_'];
VAR
charpsn,
linenum : Word;
GotData, {flag true if we have a /I file on cmdline v1.8}
Lower, {If TRUE, all Pascal reserved words v1.3
lowercased (but not the Borland ones!)}
AllUpper : BOOLEAN; {if TRUE, ALL reserved words uppercased
(Borland ones also)}
UcWord, {possible keyword, uppercased}
Padded : STRING[20]; {UcWord, padded with spaces}
WorkLine, {v1.3 Build formatted output line}
ProgLine : STRING; {v1.3 STRING[128]}
worklen : Byte Absolute WorkLine; {v1.3}
RamWord : STRING [100];
InFile,
OutFile : TEXT;
{ Multiple cmdline parm/wildcard stuff }
CONST
MAXARGS = 10; {change as you like}
TYPE
ArgType = (switch,data,source); {v1.8 types of files}
ArgRec = RECORD
Pth : PathStr; {filename}
Typ : ArgType; {whether it's data, source,}
END; { or a -L or -U switch}
VAR
Ok : BOOLEAN;
argv, argc : Byte;
Args : ARRAY[1..MAXARGS] {v1.4 array of cmdline parm ptrs}
OF ArgRec; {v1.8}
Dir : DirStr; {STRING[79]}
Name: NameStr; {STRING[8]}
Ext : ExtStr; {STRING[4]}
OutName : PathStr; {STRING[79]}
{SearchRec is declared in the Dos unit:}
(*
TYPE SearchRec = RECORD
fill : ARRAY[1..21] OF Byte;
Attr : Byte;
Time : LongInt;
size : LongInt;
Name : STRING[12];
END;
*)
SrchRec : SearchRec;
CONST
MAXBUFFLINES = 256; {v1.4 seems a likely number}
{v1.4 Our new read/write string buffers}
TYPE
BuffPtr = ^STRING; {v1.4}
Buffer = ARRAY[1..MAXBUFFLINES] OF BuffPtr;
VAR
InBuff,OutBuff : Buffer;
inlines,
currin, currout : Word;
PROCEDURE Usage;
{Give user help, terminate.
Happens on cmd line of '?', '-?', '/?', '-h', '/h', or empty.
}
BEGIN
WRITELN(
'CONV_P v1.8 - Convert Pascal reserved words to uppercase,');
WRITELN(
' If Turbo Pascal reserved words, convert to Borland style');
WRITELN(
'Usage: UPCONV [[-][/]U][L] [/Idatafile.typ] [/I...] file1[.typ]');
WRITELN( 'Switches:');
WRITELN(
' -u, -U, /u, or /U : uppercase ALL reserved words');
WRITELN(
' (overriding the Borland Style)');
WRITELN(
' -l, -L, /l, or /L : lowercase Pascal (non-Borland) reserved words');
WRITELN( {v1.8}
' /I : Use this text file (with YOUR set of reserved words)');
WRITELN(
' instead of the default CONV_P.DAT reserved word data file.');
WRITELN(
'Source filename file1 will be forced to .PAS if no type is given.');
WRITELN(
'Formatted output filename forced to .FMT type.');
WRITELN('Wildcards may be used for file1.typ');
HALT;
END; {of Usage}
{v1.4 Replacement for POS() function
Dr Dobbs, Jul 89
}
{Link in the POSBM Boyer-Moore function }
{$F+}
{$L POSBM2} {v1.8}
FUNCTION posBM(Pat,S : STRING) : Byte; EXTERNAL;
{$F-}
PROCEDURE Uc_Str(VAR S : STRING);
{v1.3 Same as STRINGS' Uppercase, but changes the string "in place".}
BEGIN
InLine(
$8C/$DB/ { mov bx,DS ;preserve DS}
$C5/$B6/>S/ { lds si,>S[bp] ;get the VAR addr}
$31/$C0/ { xor ax,ax}
$8A/$04/ { mov al,[si] ;snarf the length}
$89/$C1/ { mov cx,ax ;loop counter}
$E3/$0E/ { jcxz Exit ;zero length, forget it}
{;}
$BA/$61/$20/ { mov dx,$2061 ;DL='a',DH=$20}
{L1:}
$46/ { inc si ;next char}
$8A/$04/ { mov al,[si] ;snarf the char}
$38/$D0/ { cmp al,dl}
$72/$02/ { jb S1 ;already uppercase}
$28/$34/ { sub [si],dh ;uppercase it}
{S1:}
$E2/$F5/ { loop L1}
{Exit:}
$8E/$DB); { mov DS,bx ;restore DS}
END; {of Uc_Str}
PROCEDURE Lo_Str (VAR S : STRING);
{v1.3 Lowercase a string}
BEGIN
InLine(
$1E/ { push DS}
$C5/$B6/>S/ { lds si,>S[bp]}
$31/$C0/ { xor ax,ax}
$8A/$04/ { mov al,[si];snarf the length}
$09/$C0/ { or ax,ax ;0 length?}
$74/$16/ { je Exit ;yep, exit}
$89/$C1/ { mov cx,ax}
$BA/$41/$5A/ { mov dx,$5A41 ;DL='A',DH='Z'}
$B4/$20/ { mov ah,$20 ;handy constant}
{L1:}
$46/ { inc si ;next char}
$8A/$04/ { mov al,[si];snarf the char}
$38/$D0/ { cmp al,dl ;<'A'?}
$72/$06/ { jb S1 ;yep}
$38/$F0/ { cmp al,dh ;>'Z'?}
$77/$02/ { ja S1 ;yep}
$00/$24/ { add [si],ah ;lowercase}
{S1:}
$E2/$F1/ { loop L1}
{Exit:}
$1F); { pop DS ;restore}
END; {of Lo_Str}
FUNCTION ReadLn_B(VAR S : STRING) : BOOLEAN;
{v1.4 Returns a string from our input buffer.
If buffer is exhausted, refills from InFile.
Returns FALSE IF (1) buffer is exhausted, and
(2) EOF(InFile)
Else returns TRUE.
}
BEGIN
ReadLn_B := TRUE; {assume success}
Inc(currin); {bump to next line}
IF currin <= inlines THEN BEGIN {we still have lines in buffer}
S := InBuff[currin]^; {return the string}
Exit; {done}
END;
{We've hit buffer end .. read in a new buffer full
(or as much as is available).
}
currin := 1; {start at InBuff[1]}
inlines := 0; {init input buffer string counter}
WHILE NOT EOF(InFile) {stop at EOF}
AND (inlines < MAXBUFFLINES) {or when input buffer is full}
DO BEGIN
Inc(inlines); {bump input buffer string counter}
READLN(InFile,InBuff[inlines]^); {Read in a buffer string}
{(Let Turbo handle any errors for now)}
END;
IF inlines > 0 {we did read at least one line}
THEN S := InBuff[currin]^
ELSE ReadLn_B := FALSE; {EOF, no lines read}
END; {of ReadLn_B}
PROCEDURE WriteLn_B(S : STRING);
{v1.4 Buffered string output.
Move S to our output buffer OutBuff.
If OutBuff is full, write it to disk.
}
VAR err : INTEGER; {v1.5}
BEGIN
Inc(currout); {bump output line counter}
IF currout > MAXBUFFLINES {output buffer's full}
THEN BEGIN
FOR currout := 1 TO MAXBUFFLINES DO BEGIN
{$I-}
WRITELN(OutFile,OutBuff[currout]^); {write to file}
{(Let Turbo handle any errors for now)}
err := IOResult; {v1.5}
{$I+}
IF err <> 0 THEN BEGIN
WRITELN('File Write Error');
HALT(err);
END;
END;
currout := 1; {back to output buffer start}
END;
OutBuff[currout]^ := S; {move string into output buffer}
END; {of Writeln_B}
PROCEDURE Flush_OutBuff;
{v1.4 If any output strings are left in our output buffer,
write them to disk.
(We really should test to see if we've written ANYTHING
to our output file, and delete it if it's empty (or something).
Not messing with that for now (since you can't do a FileSize
on text files, and we'd have to reopen as some other type, etc.).
}
VAR
i : Word;
err : INTEGER;
BEGIN
IF currout > 0 {if there are any buffer lines}
THEN FOR i := 1 TO currout DO BEGIN {write them all out}
{$I-}
WRITELN(OutFile,OutBuff[i]^);
err := IOResult; {v1.5}
{$I+}
IF err <> 0 THEN BEGIN
WRITELN('File Write Error');
HALT(err);
END;
END;
WRITE(OutFile,^Z); {v1.4 terminating ^Z}
{$I-}
CLOSE(InFile);
CLOSE(OutFile); {close up}
{$I+}
IF IOResult <> 0 THEN ; {we don't care}
END; {of Flush_OutBuff}
PROCEDURE Get_Args;
{v1.4 Process command line for all target filenames.
Move them into an array of Args records.
v1.8 We may have "/IDATAFILE.DAT" data files on the cmdline.
Move them (if any) into that same Args record array,
but flag the file type as "data" rather than "source".
}
CONST
HelpArgs : STRING[13] = ' -? /? -H /H '; {v1.8}
SwitchArgs : STRING[13] = ' -U /U -L /L '; {v1.8}
VAR
Ch : CHAR;
TStr : STRING;
p : Byte;
BEGIN
argc := ParamCount;
IF (argc = 0) {no parms at all}
OR (argc > MAXARGS) {or more than we can handle}
THEN Usage; {display help, die}
Lower := FALSE; {assume no switches}
AllUpper := FALSE;
GotData := FALSE; {and no /I data file}
FOR argv := 1 TO argc DO BEGIN {process args}
Args[argv].Pth := Uppercase(ParamStr(argv)); {snarf parm, uppercased}
Args[argv].Typ := source; {assume source file v1.8}
{ The first arg could've been a '-U' or '/U', or a '-L' or '/L'.
Check that out now. If so, we set the arg type to switch
so we can skip that arg when it comes time to open files.
}
IF Args[argv].Pth[1] IN ['-','/'] {may be a switch}
THEN BEGIN {so let's see what kind}
TStr := ' ' + Args[argv].Pth + ' '; {pad with spaces}
IF posBM(TStr, HelpArgs) <> 0 {help arg? v1.8}
THEN Usage; {help, die}
p := posBM(TStr,SwitchArgs); {see if any switches}
IF p <> 0 THEN BEGIN {we have a /U or /L switch}
Args[argv].Typ := switch; {flag as a switch}
IF p < 7 THEN AllUpper := TRUE {-U or /U}
ELSE Lower := TRUE; {-L or /L}
END
{Not a lower/upper switch, might be a '/I' switch}
ELSE IF Args[argv].Pth[2] = 'I' {'/I switch}
THEN BEGIN {it's an input data file}
DELETE(Args[argv].Pth,1,2); {delete the '/I' chars}
Args[argv].Typ := data; {flag as data file}
GotData := TRUE; {flag we got one}
END;
END; {if first char is '-/'
{Else this Arg is flagged as a source file}
END; {argc loop}
END; {of Get_Args}
{$IFDEF NO_OVERWRITE} {v1.3 only if we want no overwriting}
FUNCTION Exists(Name : PathStr) : BOOLEAN;
{Returns TRUE if Name exists on current drive:\dir}
VAR F : TEXT;
BEGIN
ASSIGN(F, Name);
{$I-} RESET (F); {$I+}
IF IOResult = 0 THEN BEGIN
Exists := TRUE;
CLOSE(F);
END
ELSE Exists := FALSE;
END; {of Exists}
{$ENDIF}
FUNCTION Open_Files : BOOLEAN;
{Works FindNext if appropriate, else uses a new Arg string.
v1.4 Returns TRUE or FALSE per success/failure.
}
VAR FName : PathStr;
BEGIN
Open_Files := FALSE; {v1.4 assume failure}
IF SrchRec.Name = '' THEN BEGIN {time for a new name}
REPEAT
Inc(argv); {bump for first/next name}
IF argv > argc THEN Exit; {all done, return FALSE v1.8}
UNTIL Args[argv].Typ = source; {until we get a new source file v1.8}
FSplit(Args[argv].Pth, Dir, Name, Ext); {split up the new name v1.4}
IF Ext = '' THEN Ext := '.PAS'; {force to .PAS type}
FName := Dir + Name + Ext; {build new name}
FindFirst(FName,ReadOnly OR Archive,SrchRec) {first time thru}
END
ELSE FindNext(SrchRec); {working a wildcard}
Ok := (DosError = 0); {from FindFirst or FindNext}
IF NOT Ok THEN BEGIN {not found}
SrchRec.Name := ''; {Flag we need a new arg
and FindFirst}
Exit; {v1.4 return FALSE}
END;
FName := Dir + SrchRec.Name; {new name from FindFirst/FindNext}
Args[argv].Pth := FName; {Update Args for outside display v1.8}
{v1.3 We'll always force the '.FMT' file type for output.}
FSplit(FName, Dir, Name, Ext);
OutName := Name + '.FMT'; {build a new output path
(current drive:\directory) }
{$IFDEF NO_OVERWRITE}
IF Exists(OutName) THEN BEGIN {If .FMT file already exists...}
WRITELN(Outname + ' already exists .. skipping!');
Exit; {v1.4 return FALSE}
END;
{$ENDIF}
ASSIGN(InFile, FName);
RESET(InFile); {open input file}
ASSIGN(OutFile, OutName);
{$I-} REWRITE (OutFile); {$I+}
Ok := (IOResult = 0);
IF NOT Ok THEN BEGIN
CLOSE(InFile); {be neat}
WRITELN('Unable to open file [' + OutName + ']');
END {v1.4 return FALSE}
ELSE BEGIN
currin := 0; {init input string buffer ptr}
currout := 0; {init output string buffer ptr}
inlines := 0; {insure initial input buffer fill}
Open_Files := TRUE; {v1.4 return TRUE}
END;
END; {of Open_Files}
PROCEDURE Build_Reserved_Arrays;
{v1.6 Read in our file of reserved word strings.
Create two linked lists of string records:
one normal (Borland and Pascal reserved words with mixed case),
one all uppercased).
We just do this once.
}
PROCEDURE Read_DataFile(DataName : PathStr);
VAR
p : StrPtr; {working string record pointer}
TokenFile : TEXT; {file of reserved word strings}
BEGIN
ASSIGN(TokenFile,DataName); {file of reserved word strings v1.8}
{$I-} RESET(TokenFile); {$I+} {open it}
IF IOResult <> 0 THEN BEGIN {not found .. die}
WRITELN(DataName + ' file not found. Aborting!'); {v1.8}
HALT(1); {die}
END;
WHILE NOT EOF(TokenFile) DO BEGIN {read in all the strings}
READLN(TokenFile,curr^.S); {read in string}
NEW(p); {allocate new normal record}
curr^.next := p; {point THIS record to next one}
curruc^.S := Uppercase(curr^.S); {create uppercased reserve word}
curr := p; {bump to next normal record}
NEW(p); {allocate new uppercased record}
curruc^.next := p; {assume no next uppercase rec}
curruc := p; {bump to next uppercase rec}
END;
curr^.S := ''; {last string is empty}
curr^.next := NIL; {..and points nowhere}
curruc^ := curr^; {also empty}
{$I-} CLOSE(TokenFile); {$I+} {close up}
IF IOResult <> 0 THEN ; {we don't care}
END; {of Read_DataFile}
BEGIN {Build_Reserved_Arrays}
NEW(ReservedWords); {allocate first reserved string
record}
ReservedWords^.S := ''; {build first string ptr}
ReservedWords^.next := NIL; {no next}
NEW(UcReserved); {create first dynamic uppercased
string ptr}
UcReserved^ := ReservedWords^; {initialize it also}
curr := ReservedWords; {point to first string ptr}
curruc := UcReserved; {and first uppercased str ptr}
IF NOT GotData {no arg was a data filename v1.8}
THEN Read_DataFile(Default_DataName) {so use default v1.8}
ELSE BEGIN
FOR argv := 1 TO argc DO {check all the arg filenames v1.8}
IF Args[argv].Typ = data {ok, it's a data type v1.8}
THEN Read_DataFile(Args[argv].Pth); {so read THAT data file in v1.8}
END; {using arg datafile name}
END; {of Build_Reserved_Arrays}
PROCEDURE Test_For_Reserved_Words;
{Test if the current word (RamWord) is a reserved word.
If so, write its equivalent (uppercased or Turbo Pascal format)
out to our output file.
Else just write it as it is.
}
VAR
p,len : Word;
BEGIN
Padded := ' ' + Uppercase(RamWord) + ' '; {Uppercase, bracket with spaces}
len := LENGTH(RamWord); {v1.3}
curruc := UcReserved; {ptr to first dynamic uppercased
reserved word string record}
IF NOT AllUpper {not just uppercase}
THEN curr := ReservedWords {use Borland/normal case array also}
ELSE curr := UcReserved;
WHILE curruc^.next <> NIL DO BEGIN {check all the reserved words}
p := posBM(Padded, curruc^.S); {v1.6 is this uppercased, padded
word in the reserved word line?}
IF p > 0 THEN BEGIN {yep}
Inc(p); {bump past the space}
IF AllUpper {converting to uppercase..}
THEN Padded := COPY(curruc^.S, {..so move in the uppercased word}
p, len)
ELSE BEGIN {more processing}
Padded := COPY(curr^.S, {word per our Reserved table}
p, len); {uppercase or Borlandized}
IF Lower
THEN IF Padded = Uppercase(Padded) {If the mixed-case Table word
matches the uppercased word..
it's non-Borland...}
THEN Lo_Str(Padded); {..so lowercase it}
END;
WorkLine := WorkLine + Padded; {v1.3 build in WorkLine}
Exit; {don't look at any more lines}
END; {if Padded in line}
curruc := curruc^.next; {point to next uppercased reserved
word string record}
curr := curr^.next; {point to next normal string}
END; {line-checking loop}
{We checked all the lines, didn't find our RamWord as a Reserved word}
WorkLine := WorkLine + RamWord; {v1.3 build WorkLine with orig word}
END; {of Test_For_Reserved_Words}
PROCEDURE Process_A_Word;
VAR
len : Byte; {v1.3}
strt : Word; {v1.3}
BEGIN
strt := charpsn; {v1.3 remember where we started}
WHILE (UpCase (ProgLine [charpsn]) IN Identifier) {it's a legal char}
AND (charpsn <= LENGTH (ProgLine) ) {and line isn't done}
DO Inc(charpsn); {v1.3 bump ProgLine ptr}
len := (charpsn - strt); {v1.3 nr chars in word}
RamWord[0] := CHAR(len); {v1.3 force string length}
Move(ProgLine[strt], RamWord[1], len); {v1.3 copy portion of ProgLine}
Test_For_Reserved_Words; {check RamWord for reserved
words, write out}
END; {of Process_A_Word}
PROCEDURE Scan_Till (SearchChar: CHAR);
VAR
Ch : CHAR; {v1.2}
BEGIN
REPEAT
IF charpsn > LENGTH (ProgLine) THEN BEGIN
WriteLn_B(WorkLIne); {v1.4 Write the Workline we have
(Buffered string output)
(Ok if it's empty) }
IF NOT ReadLn_B(ProgLine) {v1.4 If we have another input line
(buffered string input) }
THEN Exit; {FALSE means EOF}
charpsn := 1;
WorkLine := ''; {v1.3 Reinit WorkLine}
END;
IF ProgLine <> '' THEN BEGIN {do non-blank lines}
Ch := ProgLine[charpsn]; {v1.2 remember what this char was}
Inc(worklen); {v1.3 bump workline length}
WorkLine[worklen] := Ch; {v1.3 stuff char in line}
(* same as
WorkLine := WorkLine + Ch;
but faster, tighter
*)
Inc(charpsn); {v1.3 bump char ptr}
END
ELSE Ch := #0; {v1.2 blank line, clear Ch}
UNTIL (Ch = SearchChar); {v1.2 the LAST char was end of
quoted string or comment}
{v1.4 If we hit EOF, we exit above}
END; {of Scan_Till}
PROCEDURE Convert;
VAR Ch : CHAR;
BEGIN
WRITE('Converting ', Args[argv].Pth, ' => ', OutName, {v1.4}
', Processing line: ');
linenum := 0;
WHILE ReadLn_B(ProgLine) DO BEGIN {v1.4 buffered string input
FALSE means EOF}
charpsn := 1;
WorkLine := ''; {v1.3 clear WorkLine string}
IF LENGTH(ProgLine) <> 0 THEN BEGIN {v1.3 nonblank line}
REPEAT
Ch := UpCase(ProgLine[charpsn]);
IF Ch IN Identifier {could be a reserved word}
THEN Process_A_Word {so process it}
ELSE BEGIN
Inc(worklen); {v1.3 bump WorkLine length}
WorkLine[worklen] := Ch; {v1.3 stuff char in WorkLine}
(* Same as
WorkLine := WorkLine + Ch;
but tighter, faster
*)
Inc(charpsn); {v1.3 bump ptr}
IF Ch = OPENCOMMENT
THEN Scan_Till(CLOSECOMMENT) {v1.2 write until
closing comment}
ELSE IF Ch = APOS
THEN Scan_Till(APOS); {v1.2 write until 2d '}
END;
UNTIL (charpsn > LENGTH (ProgLine));
END; {If nonblank}
Writeln_B(WorkLine); {v1.4 Output Workline
(buffered string output)
(Ok if blank) }
WRITE(linenum:6,^H^H^H^H^H^H); {display, back up}
Inc(linenum); {v1.3 bump linenr}
END; {While}
WRITELN; {v1.3 clean up screen}
Flush_OutBuff; {v1.4 flush output buffer,
close up everything}
END; {of Convert}
BEGIN {main}
Get_Args; {process cmdline args
(may die)}
Build_Reserved_Arrays; {v1.6 build two linked lists
of reserved word records
(one normal, one uppercased) }
{v1.4 So far, so good. Initialize our dynamic input and output
buffer array pointers.
Later, check for avail memory, constrain buffers, etc.
}
FOR currin := 1 TO MAXBUFFLINES DO
NEW(InBuff[currin]);
FOR currout := 1 TO MAXBUFFLINES DO
NEW(OutBuff[currout]);
{Now we go into our file loop.
We continue until FindNext returns no more files.
Get_Args set argv appropriately.
}
SrchRec.Name := ''; {clear for first file}
argv := 0; {start with first arg}
WHILE (SrchRec.Name <> '') {we're working a wildcard}
OR (argv < argc) {no wildcard, but still got args}
DO BEGIN
IF Open_Files {v1.4 open InFile,OutFile}
THEN Convert; {v1.4 files open, do the conversion}
END; {until all done}
END.