home *** CD-ROM | disk | FTP | other *** search
- PROGRAM PrettyPrinter;
-
- (*
- ** Filename: PRETTY.PAS
- ** Language: Turbo Pascal
- ** Target machine: Tested on H89 & CP/M 2.2, but should work on any
- ** computer or operating system which runs Turbo.
- ** By: Don McCrady (June 27, 1985)
- ** Updated: July 14, 1985
- **
- ** This program is a "Pascal Program Spiffyizer". It takes an
- ** ordinary Pascal program and produces a copy of it with all
- ** reserved words in upper case. (If the source file is written
- ** entirely in upper case, then this program will have no effect
- ** at all on it.)
- **
- ** The output from PRETTY can be written to the terminal, the printer,
- ** a disk file, or all three at once.
- **
- ** The user can turn off the marking of reserved words, and the page
- ** formatting if printer output is selected. If disk file output is
- ** requested, the user can also tell the program to erase the original
- ** file when finished.
- **
- ** There is one bug: If the source file contains a word which is longer
- ** than 16 characters, the pretty printer will drop characters. A word
- ** with 16 characters is pretty long, so the bug shouldn't present much
- ** of a problem with most Pascal programs.
- *)
-
- CONST NumReserved = 41; { Number of reserved words in Turbo. }
- StrLength = 16; { Maximum word length. This program won't }
- bell = ^G; { work properly if there are any words in }
- cr = ^M; { the source file which are larger than 16 }
- lf = ^J; { characters. }
- esc = ^[;
- tab = ^I;
- ff = ^L;
- space = ' ';
- blank16 = ' '; { 16 spaces. }
-
- TYPE str = PACKED ARRAY [1..StrLength] OF char;
- string15 = STRING[15];
- string80 = STRING[80];
- CharSet = SET OF char;
-
- CONST AlphaNum : CharSet = ['A'..'Z','a'..'z','0'..'9'];
- (* WARNING: To modify the following list, change the *)
- (* NumReserved constant to the new number of reserved *)
- (* words. Then insert/delete reserved words in the *)
- (* following declaration -- but MAKE SURE THAT THE *)
- (* NEW LIST REMAINS IN ALPHABETICAL ORDER!!! *)
- KeyWord : ARRAY [1..NumReserved] OF str =
- ('ABSOLUTE ', 'AND ', 'ARRAY ',
- 'BEGIN ', 'CASE ', 'CONST ',
- 'DIV ', 'DO ', 'DOWNTO ',
- 'ELSE ', 'END ', 'EXTERNAL ',
- 'FILE ', 'FOR ', 'FORWARD ',
- 'FUNCTION ', 'GOTO ', 'IF ',
- 'IN ', 'LABEL ', 'MOD ',
- 'NIL ', 'NOT ', 'OF ',
- 'OR ', 'PACKED ', 'PROCEDURE ',
- 'PROGRAM ', 'RECORD ', 'REPEAT ',
- 'SET ', 'SHL ', 'SHR ',
- 'STRING ', 'THEN ', 'TO ',
- 'TYPE ', 'UNTIL ', 'VAR ',
- 'WHILE ', 'WITH ');
-
- VAR infile,outfile : text;
- InfileName,OutfileName,OldInfileName : string15;
- NextCh : char;
- FormatPage, { Boolean flags... control output format. }
- MarkReserved,
- EraseOld,
- ConOut,
- FileOut,
- ListOut : Boolean;
- LineNum,
- PageNum : byte;
-
- { Read the next character from the source file. Store the look-ahead }
- { character into the global variable NextCh. }
- PROCEDURE ReadChar(VAR ch : char);
- BEGIN
- ch := NextCh;
- read(infile,NextCh)
- END;
-
- { Convert a PACKED ARRAY string to uppercase. }
- PROCEDURE ToUpper(VAR s : str);
- VAR wptr : byte;
- BEGIN
- FOR wptr := 1 TO StrLength DO
- s[wptr] := upcase(s[wptr])
- END;
-
- { Write a character (ch) to the output device(s). }
- PROCEDURE out(ch : char);
- CONST MaxLine = 60;
- BEGIN
- IF ConOut THEN
- write(con,ch);
- IF ListOut THEN
- BEGIN
- IF FormatPage THEN
- BEGIN
- IF ch = ^M THEN
- LineNum := succ(LineNum);
- IF LineNum = MaxLine THEN
- BEGIN
- LineNum := 1;
- PageNum := succ(PageNum);
- write(lst,cr,ff,InfileName,cr,InfileName);
- write(lst,tab,tab,tab,tab,tab,tab,tab,tab,'Page ',PageNum);
- writeln(lst,lf,lf)
- END
- END;
- write(lst,ch)
- END;
- IF FileOut THEN
- write(outfile,ch)
- END;
-
- { Sound terminal bell. }
- PROCEDURE beep;
- BEGIN
- write(bell)
- END;
-
- { Display error message (msg), sound terminal bell, and exit. }
- PROCEDURE error(msg : string80);
- BEGIN
- beep;
- writeln(msg);
- halt
- END;
-
- { Read a single character from keyboard. The only acceptable chara- }
- { acters are SPACE, CR, ESCAPE, Y, and N. If the parameter "default" }
- { is "false", then SPACE, CR, or ESCAPE will produce the same result }
- { as typing N. If "default" is "true", then SPACE, CR, or ESCAPE will }
- { be the same as typing Y. }
- { If the user enters Y, the function will write "Yes" to the terminal }
- { and return a value of true; otherwise it will write "No" and return }
- { a value of false. If an unacceptable key is entered, the terminal }
- { bell is sounded, and the function will await a legal response. }
- FUNCTION yes(default : Boolean) : Boolean;
- VAR ch : char;
- BEGIN
- REPEAT
- read(kbd,ch);
- IF ch IN [cr,space,esc] THEN
- IF default = false THEN
- ch := 'N'
- ELSE
- ch := 'Y';
- ch := upcase(ch);
- CASE ch OF
- 'Y': BEGIN
- yes := true;
- writeln('Yes')
- END;
- 'N': BEGIN
- yes := false;
- writeln('No')
- END
- ELSE beep
- END{case}
- UNTIL ch IN ['Y','N']
- END;
-
- { If the parameter string "fname" does not have an extension, then the }
- { default extension '.PAS' is appended to it. }
- PROCEDURE MakeFileName(VAR fname : string15);
- VAR ExtPos : byte;
- BEGIN
- ExtPos := pos('.',fname);
- IF ExtPos = 0 THEN
- fname := fname + '.PAS'
- END;
-
- { Opens a text file for input or output, depending on the parameter }
- { "mode". MODE is either "I" for input or "O" for output. }
- PROCEDURE open(mode : char; VAR f : text; name : string15);
- BEGIN
- {$I-}
- assign(f,name);
- CASE upcase(mode) OF
- 'I': BEGIN
- reset(f);
- IF IOresult <> 0 THEN
- error('Can''t open '+name)
- END;
- 'O': BEGIN
- reset(f);
- IF IOresult = 0 THEN
- BEGIN
- beep;
- write('File ',name,' exists. Overwrite? ');
- IF NOT yes(false) THEN
- error('Aborting')
- END
- ELSE
- rewrite(f)
- END
- ELSE error('Bad file mode')
- END{case}
- {$I+}
- END; { open }
-
- PROCEDURE MakeBackup(VAR InfileName : string15);
- VAR i : byte;
- BEGIN
- OldInfileName := InfileName;
- assign(infile,InfileName);
- i := pos('.',InfileName);
- IF i <> 0 THEN
- InfileName := copy(InfileName,1,i) + 'BAK'
- ELSE
- InfileName := InfileName + '.BAK';
- rename(infile,InfileName)
- END;
-
- { Set Boolean flags. }
- PROCEDURE SetParams;
- BEGIN
- FormatPage := true;
- MarkReserved := true;
- ConOut := true;
- ListOut := false;
- FileOut := false;
- EraseOld := false;
- writeln;
- write('Source file name? ');
- readln(InfileName);
- MakeFileName(InfileName);
- MakeBackup(InfileName);
- open('i',infile,InfileName);
- writeln;
- write('Suppress marking of reserved words? ');
- IF yes(NOT MarkReserved) THEN
- MarkReserved := NOT MarkReserved;
- write('Disk file output? ');
- IF yes(FileOut) THEN
- FileOut := NOT FileOut;
- IF FileOut THEN
- BEGIN
- write(tab,'Output file name? ');
- readln(OutfileName);
- MakeFileName(OutfileName);
- open('o',outfile,OutfileName);
- write(tab,'Erase original file? ');
- IF yes(false) THEN
- EraseOld := true
- END;
- write('Console output? ');
- IF NOT yes(ConOut) THEN
- ConOut := NOT ConOut;
- write('Printer output? ');
- IF yes(ListOut) THEN
- ListOut := NOT ListOut;
- IF ListOut THEN
- BEGIN
- write('Suppress page formatting? ');
- IF yes(NOT FormatPage) THEN
- FormatPage := NOT FormatPage
- END
- END; { SetParams }
-
- { Main procedure. Maps any reserved words to upper case. }
- PROCEDURE PrettyPrint;
- VAR ch : char;
- state : (InWord,InStr,InComment,copying);
- word,TestWord : str;
- wptr : byte;
-
- { Display a PACKED ARRAY string to the output device(s) with all }
- { trailing blanks removed. }
- PROCEDURE PrintWord(word : str);
- VAR i : byte;
- BEGIN
- i := 1;
- WHILE (word[i] <> ' ') AND (i <= StrLength) DO
- BEGIN
- out(word[i]);
- i := succ(i)
- END
- END;
-
- { Binary searches the KEYWORD list (global) to see if the parameter }
- { "word" is a reserved word. }
- FUNCTION IsReserved(word : str) : Boolean;
- VAR top,bottom,mid : byte;
- BEGIN
- top := NumReserved;
- bottom := 1;
- WHILE top > bottom DO
- BEGIN
- mid := (top + bottom) SHR 1; { Same as (top+bottom) DIV 2. }
- IF word > KeyWord[mid] THEN
- bottom := succ(mid)
- ELSE
- top := mid
- END;{while}
- IF word = KeyWord[top] THEN
- IsReserved := true
- ELSE
- IsReserved := false
- END; { IsReserved }
-
- BEGIN { PrettyPrint }
- state := copying;
- word := blank16;
- read(infile,NextCh); { Initialize the global NextCh. }
- WHILE NOT eof(infile) DO
- BEGIN
- ReadChar(ch);
- CASE state OF
- copying: BEGIN
- IF ((ch='(') AND (NextCh='*')) OR (ch='{') THEN
- BEGIN
- state := InComment;
- out(ch)
- END{if}
- ELSE IF ch = '''' THEN
- BEGIN
- state := InStr;
- out(ch)
- END{if}
- ELSE IF ch IN AlphaNum THEN
- BEGIN
- word := blank16;
- state := InWord;
- wptr := 1;
- word[wptr] := ch
- END{if}
- ELSE
- out(ch)
- END;{case copying}
- InComment: BEGIN
- IF ((ch='*') AND (NextCh=')')) OR (ch = '}') THEN
- state := copying;
- out(ch)
- END;{case InComment}
- InStr: BEGIN
- IF ch = '''' THEN
- state := copying;
- out(ch)
- END;{case InStr}
- InWord: BEGIN
- WHILE (ch IN AlphaNum) AND (wptr <= StrLength) DO
- BEGIN
- wptr := succ(wptr);
- word[wptr] := ch;
- ReadChar(ch)
- END;{while}
- IF MarkReserved THEN
- BEGIN
- TestWord := word;
- ToUpper(TestWord);
- IF IsReserved(TestWord) THEN
- PrintWord(TestWord)
- ELSE
- PrintWord(word)
- END{if}
- ELSE
- PrintWord(word);
- word := blank16;
- out(ch);
- IF ((ch='(') AND (NextCh='*')) OR (ch = '{') THEN
- state := InComment
- ELSE
- state := copying
- END{case InWord}
- END{case}
- END{while}
- END; { PrettyPrint }
-
- BEGIN (* Main Program *)
- SetParams;
- IF FormatPage AND ListOut THEN
- BEGIN
- PageNum := 1;
- LineNum := 1;
- write(lst,InfileName,cr,InfileName);
- write(lst,tab,tab,tab,tab,tab,tab,tab,tab,'Page ',PageNum);
- writeln(lst,lf,lf)
- END;
- IF ConOut THEN
- ClrScr;
- PrettyPrint;
- IF FileOut THEN
- BEGIN
- close(outfile);
- IF EraseOld THEN
- erase(infile)
- END
- ELSE
- rename(infile,OldInfileName)
- END.
-
-
-
-
-
-
-
-
-
-
- ┘╪yß"Sz!≤ 9∙δ φ