Contributor: SWAG SUPPORT TEAM (* >Does anyone know of a utility Program that will apply some sort of >reasonable structuring to a pascal source File? I'm not sure if it's what you want, but the source For a Pascal reFormatter, etc, was entered in the Fidonet PASCAL Programming Competition, and came third (I came second!!). As you can see by the File dates, this is a very recent thing and since it is Nearly too late I toyed With the idea of just keeping it to myself. It certainly is not an example of inspired Programming. But then, I thought, if everyone felt that way you'd have nothing to chose from and even if this is not a prize winner, mayby someone else will find it useful. So here it is... not extensively tested, but I couldn't find any bugs. Used Pretty to reFormat itself and it still Compiled and worked. Anyway, the only possible use is to another Turbo Pascal Programmer who shouldn't have any difficult modifying to suit himself. They'd probably do that anyway since the output represents my own peculiar notion as to what a readable Format should be. 'Pretty Printers' date back to the earliest Computer days and Variations existed For just about any language. However, I've been unable to find a current one For Turbo Pascal. Here's what this one does: Pretty With no parameters generates a syntax message. Input is scanned line-by-line, Word-by-Word and Byte-by-Byte. Any identifiers recognized as part of TP's language are replaced by mixed Case (in a style which _I_ like). Someone else can edit Constants Borland1 through Borland5 and TP3. (Why TP3 later.) The first one on a line is capitalized anyway. A fallout of this is to use selected ones to determine indentation in increments of 'IndentSpcs' which I arbitrarily set to 3. Change if you like. Indentation is incremented whenever one of the 'IndentIDs' appears and decremented With 'UnindentIDs' (surprise!). Single indents are also provided For 'SectionIDs' (Const, Type, Uses, Var) and For 'NestIDs' (Procedure Function) to make these more visible. White space is what does it, right? On the other hand, no attempt is made to affect white space in the vertical direction. Since that generally stays the way you originate it. Any '{', '(' or '''' (Single quote) detected during the line scan trigger a 'skipit' mode which moves the enclosed stuff directly to output, unmodified. With one exception. {Comments} which begin a line are aligned to the left margin (where I like to see Compiler directives and one line Procedure/Function explanations). Other {Comments} which begin/end on the same line are shifted so the '}' aligns at the (80th column) right margin. I think this makes them more visible than when snuggled up to a semi-colon and getting them away from the code makes it more legible, too. and it did look better originally when it used some of my personal Units. Hastily modified to stand alone. There are, no doubt, some obvious ways the Programming can be improved (you would probably have used some nice hash tables to look up key Words) but, as I say, I thought I would be the only one using this and speed in this Case is not all that important. With one exception. Something I worked up For an earlier application and may be worth looking at -- 'LowCase'. It will Compile With TP4-TP5.5 and probably TP6 (if it still supports Inline). I included TP3 stuff because some of the old software I was looking at was written in it. and it recognizes Units in a clumsy sort of way. Switching to chat mode here. if you're Really busy, you can skip the following. This thing actually began as a 'Case-converter'. I was trying to avoid re-inventing some wheels by re-working some old Pascal source dating back to the late 70's and 80's. Upper Case Programs became a 'standard' back in the days when you talked to main frames through a teleType machine, which has no lower Case. Sadly, this persisted long after it was no longer necessary and I find those all-upper-Case Programs almost unreadable. That is I can't find what I'm looking For. They were making me crazy. (BTW I suspect some of this has to do With why Pascal has UpCase but no LoCase.) I stole the orginal LowCase included here from someone who had done the intuitive thing -- first test For 'A', then For 'Z'. Changing to an initial test For 'Z' does two things. A whopping 164 of the 255 possible Characters can be eliminated With just one test and, since ordinary Text consists of mostly lower Case, these will be passed over rapidly. When you received this you thought, "Who the heck is Art Weller? I don't remember him on the Pascal Echo." Right. I'm a 'lurker'! Been reading the echo since beFore it had a moderator. (Now we have an excellent one. Thank you.) I have a machine on a timer which calls the BBS each morning to read and store several echos which I read later. Rarely get inspired enough to call back and enter a discussion. Things usually get resolved nicely without me. I especially don't want to get involved in such as the 'Goto' wars. But I monitor the better discussions to enhance my TP skills. I'm not Really a Programmer (no Formal training, that is -- Computers hadn't been invented when I was in school!), but an engineer. I'm retired from White Sands Missile Range where I was Chief of Plans and Programs For (mumble, mumble) years. I self-taught myself Computers when folks from our Analysis and Computation Directorate started using jargon on me. I did that well enough to later help Write a book For people who wanted to convert from BASIC to Pascal then after "retiring" was an editor For a small Computer magazine (68 Micro-Journal). In summary, if you think this worth sharing With others I'll be pleased enough even without a prize. not even sure it will get there in time. Snail-Mail, you know. *) Program Pretty; {A 'Pretty Printer' For Turbo Pascal Programs} { This Program converts Turbo Pascal identifiers in a source code File to mixed Case and indents the code. Released into Public Domain June, 1992 on an 'AS IS' basis. Enjoy at your own risk. Art Weller 3217 Pagosa Court El Paso, Texas 79904 U. S. A. Ph. (915) 755-2516} {Uses Strings;} Const IndentSpcs = 3; Borland1 = ' Absolute Addr and ArcTan Array Assign AuxInptr AuxOutptr BDos begin Bios '+ ' BlockRead BlockWrite Boolean Buflen Byte Case Chain Char Chr Close ClrEol '+ ' ClrScr Color Concat Const Copy Cos Delay Delete DelLine Dispose div do '; Borland2 = ' Downto Draw else end Eof Eoln Erase Execute Exp External False File '+ ' FilePos FileSize FillChar Flush For Forward Frac Freemem Function Getmem '+ ' Goto GotoXY Halt HeapPtr Hi HighVideo HiRes if Implementation in Inline '; Borland3 = ' Input Insert InsLine Int Integer Interface Intr IOResult KeyPressed '+ ' Label Length Ln Lo LowVideo Lst Mark MaxAvail Maxint Mem MemAvail Memw Mod '+ ' Move New Nil NormVideo not Odd of Ofs or Ord Output Overlay Packed '; Borland4 = ' Pallette Pi Plot Port Pos Pred Procedure Program Ptr Random Randomize Read '+ ' ReadLn Real Record Release Rename Repeat Reset ReWrite Round Seek Seg Set '+ ' Shl Shr Sin SizeOf Sound Sqr Sqrt Str String Succ Swap Text then to '; Borland5 = ' True Trunc Type Unit Until UpCase Uses UsrOutPtr Val Var While Window With '+ ' Write WriteLn xor '; TP3 = ' AUX CONinPTR CON CONOUTPTR ConstPTR CrtEXIT CrtinIT ERRorPTR Kbd '+ ' LStoUTPTR TRM USR USRinPTR '; IndentIDs = ' begin Case Const Record Repeat Type Uses Var '; UnIndentIDs = ' end Until '; SectionIDs = ' Const Type Uses Var '; endSection = ' begin Const Uses Var Function Implementation Interface '+ ' Procedure Type Unit '; NestIDs = ' Function Procedure Unit '; IDAlphas = ['a'..'z', '1'..'0', '_']; Var Indent, endPend, Pending, UnitFlag : Boolean; NestLevel, NestIndent, IndentNext, IndentNow, Pntr, LineNum : Integer; IDs, InFile, OutFile, ProgWrd, ProgLine : String; Idents, OutID : Array [1..5] of String; f1, f2 : Text; Function LowCase(Ch: Char): Char; begin Inline( $8A/$86/>Ch/ { mov al,>Ch[bp] ;Char to check} $3C/$5A/ { cmp al,'Z' } $7F/$06/ { jg Done } $3C/$41/ { cmp al,'A' } $7C/$02/ { jl Done } $0C/$20/ { or al,$20 } $88/$86/>LowCase); {Done :mov >LowCase[bp],al } end; Function LowCaseStr(InStr : String): String; Var i : Integer; len: Byte Absolute InStr; begin LowCaseStr[0] := Chr(len); For i := 1 to len do LowCaseStr[i] := LowCase(InStr[i]); end; Function Blanks(Count: Byte): String; {return String of 'Count' spaces} Var Result: String; begin FillChar(Result[1], Count+1, ' '); Result[0] := Chr(Count); Blanks := Result; end; Procedure StripLeading(Var Str: String); {remove all leading spaces} begin While (Str[1] = #32) and (length(Str) > 0) do Delete(Str,1,1); end; Procedure Initialize; begin IDs := IndentIDs + UnIndentIDs + endSection; OutID[1] := Borland1; Idents[1] := LowCaseStr(OutID[1]); OutID[2] := Borland2; Idents[2] := LowCaseStr(OutID[2]); OutID[3] := Borland3; Idents[3] := LowCaseStr(OutID[3]); OutID[4] := Borland4; Idents[4] := LowCaseStr(OutID[4]); OutID[5] := Borland5 + TP3; Idents[5] := LowCaseStr(OutID[5]); Pending := False; UnitFlag := False; IndentNext := 0; IndentNow := 0; LineNum := 0; NestIndent := 0; NestLevel := 0; end; Procedure Greeting; begin Writeln; Writeln('Pascal Program Indenter'); Writeln; Writeln; Writeln('SYNTAX: INDENT InputFile OutPutFile'); Writeln(' INDENT InputFile > OutPut'); Writeln; Writeln; Halt(0); end; Procedure OpenFiles; begin if paramcount <> 0 then begin InFile := ParamStr(1); if (pos('.', InFile) = 0) then InFile := InFile + '.pas'; OutFile := Paramstr(2); end else Greeting; Assign(f1, InFile); Reset(f1); Assign(f2, OutFile); ReWrite(f2); end; Procedure GetWord; Var i, index, TmpPtr, WrdPos : Integer; Procedure DecIndent; begin if (IndentNext > IndentNow) then {begin/end on same line} Dec(IndentNext) else if IndentNow > 0 then dec(IndentNow); IndentNext := IndentNow; {next line, too} end; begin ProgWrd := ' '; TmpPtr := Pntr; While (LowCase(ProgLine[Pntr]) in IDAlphas) {Convert checked For LCase alpha} and (Pntr <= length(ProgLine)) do begin ProgWrd := ProgWrd + LowCase(ProgLine[Pntr]); Inc(Pntr); end; ProgWrd := ProgWrd+' '; {surrounded With blanks to make it unique!} index := 0; Repeat; {is it a Turbo Pascal Word?} inc(index); WrdPos := Pos(ProgWrd, Idents[index]); Until (WrdPos <> 0) or (index = 5); if WrdPos <> 0 then {found a Pascal Word} begin Move(OutID[index][WrdPos+1], ProgLine[TmpPtr], Length(ProgWrd)-2); if TmpPtr = 1 then ProgLine[1] := UpCase(ProgLine[1]); if Pos(ProgWrd, IDs) <> 0 then {only checked if a Pascal Word ^} begin if Pos(ProgWrd, endSection) <> 0 then {this includes "SectionIDs"} begin {and "NestIDs"} if (pos(ProgWrd, NestIDs) <> 0) then begin if ProgWrd = ' Unit ' then UnitFlag := True; if not UnitFlag then inc(NestLevel); end; if Pending then DecIndent; Pending := Pos(ProgWrd, SectionIDs) <> 0; if ProgWrd = ' Implementation ' then UnitFlag := False; end; if Pos(ProgWrd, IndentIDs) <> 0 then inc(IndentNext); {Indent 1 level} if Pos(ProgWrd, UnIndentIDs) <> 0 then begin DecIndent; {Unindent 1 level} if (IndentNow = 0) and (NestLevel > 0) then dec(NestLevel); end; if NestLevel > 1 then NestIndent := 1; end; end; end; Procedure Convert; Procedure OutLine; Var Tabs : String[40]; begin Tabs := Blanks((IndentNow+NestIndent) * IndentSpcs); if ProgLine[1] = '{' then Writeln(f2, ProgLine) else Writeln(f2, Tabs, ProgLine); IndentNow := IndentNext; { get ready For next line } if NestLevel < 2 then NestIndent := 0; end; Procedure Skipto(SearchChar: Char); begin Repeat if pntr > Length(ProgLine) then begin OutLine; Readln(f1, ProgLine); {get another line} Pntr := 0; end; Inc(pntr); Until (ProgLine[pntr] = SearchChar) or Eof(f1); end; Procedure MoveComments; Var TmpIndent : Integer; begin if (ProgLine[1] = '{') or (ProgLine[Pntr+1] = '$') then begin Skipto('}'); Exit; end; TmpIndent := (IndentNow+NestIndent) * IndentSpcs; While Length(ProgLine) < 80-TmpIndent do Insert(' ', ProgLine, Pntr); While (pos('}', ProgLine) > 80-TmpIndent) and (pos(' {', ProgLine) > 1) do begin Delete(ProgLine, Pos(' {', ProgLine), 1); Dec(Pntr); end; Skipto('}'); end; begin While not Eof(f1) do begin Readln(f1, ProgLine); StripLeading(ProgLine); if Length(ProgLine) = 0 then Writeln(f2) else begin Pntr := 1; Repeat Case LowCase(ProgLine[pntr]) of 'a'..'z','_' : GetWord; '{' : MoveComments; '(' : Skipto(')'); #39 : Skipto(#39) {Single quote} end; Inc(pntr) Until (pntr >= length(ProgLine)); OutLine; end; end; { While } Close(f1); Close(f2); end; begin Initialize; OpenFiles; Convert; end.