ptopu.pp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. Unit PtoPu;
  2. {
  3. $Id$
  4. This file is part of the Free Pascal run time library.
  5. Copyright (c) 1999-2000 by Michael Van Canneyt, member of
  6. the Free Pascal development team
  7. Pascal Pretty-Printer object implementation
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. {
  15. This unit is based heavily on the code by
  16. Author: Peter Grogono
  17. This program is based on a Pascal pretty-printer written by Ledgard,
  18. Hueras, and Singer. See SIGPLAN Notices, Vol. 12, No. 7, July 1977,
  19. pages 101-105, and PP.DOC/HLP.
  20. This version of PP developed under Pascal/Z V4.0 or later.
  21. Very minor modifications for Turbo Pascal made by Willett Kempton
  22. March 1984 and Oct 84. Runs under 8-bit Turbo or 16-bit Turbo.
  23. Toad Hall tweak, rewrite for TP 5, 28 Nov 89
  24. The following was changed :
  25. - Object oriented
  26. - Uses streams
  27. - Run-time customizable.
  28. }
  29. Interface
  30. Uses objects;
  31. Const
  32. MAXSYMBOLSIZE = 65500;
  33. MAXSHOWSIZE = 40;
  34. MAXSTACKSIZE = 100;
  35. MAXKEYLENGTH = 15; { The longest keywords are IMPLEMENTATION INITIALIZATION }
  36. MAXLINESIZE = 90; { Maximum length of output line }
  37. TYPE
  38. {Token = String[MAXSYMBOLSIZE];}
  39. Token = AnsiString;
  40. {XXX this is not used String0 = STRING[1];} {Pascal/z had 0}
  41. FileName = STRING;
  42. { Keysymbols }
  43. { If you add keysyms, adjust the definition of lastkey }
  44. keysymbol = { keywords }
  45. (endsym,beginsym,ifsym,thensym,elsesym,procsym,varsym,ofsym,
  46. whilesym,dosym,casesym,withsym,forsym,repeatsym,untilsym,
  47. funcsym,labelsym,constsym,typesym,recordsym,stringsym,progsym,
  48. { TP and Delphi keywords}
  49. asmsym, trysym, finallysym,exceptsym,raisesym,classsym,objectsym,
  50. constructorsym,destructorsym,inheritedsym,propertysym,
  51. privatesym,publicsym,protectedsym,publishedsym,
  52. initializationsym,finalizationsym,
  53. inlinesym,librarysym,interfacesym,implementationsym,
  54. readsym,writesym,unitsym,
  55. { Not used for formatting }
  56. andsym,arrsym,divsym,downsym,filesym,gotosym,insym,modsym,
  57. notsym,nilsym,orsym,setsym,tosym,virtualsym,usessym,
  58. casevarsym,
  59. { other symbols }
  60. becomes,delphicomment,dopencomment,dclosecomment,opencomment,closecomment,semicolon,colon,equals,
  61. openparen,closeparen,period,endoffile,othersym);
  62. { Formatting options }
  63. { If you add options, adjust the definition of lastopt }
  64. options = (crsupp,crbefore,blinbefore,
  65. dindonkey,dindent,spbef,
  66. spaft,gobsym,inbytab,crafter,upper,lower,capital);
  67. optionset = SET OF options;
  68. keysymset = SET OF keysymbol;
  69. tableentry = RECORD
  70. selected : optionset;
  71. dindsym : keysymset;
  72. terminators : keysymset
  73. END;
  74. { Character identification }
  75. charname = (letter,digit,space,quote,endofline,
  76. filemark,otherchar);
  77. charinfo = RECORD
  78. name : charname;
  79. Value : CHAR
  80. END;
  81. symbol = RECORD
  82. name : keysymbol;
  83. Value : Token;
  84. IsKeyWord : BOOLEAN;
  85. length, spacesbefore, crsbefore : INTEGER;
  86. END;
  87. symbolinfo = ^ symbol;
  88. stackentry = RECORD
  89. indentsymbol : keysymbol;
  90. prevmargin : INTEGER
  91. END;
  92. symbolstack = ARRAY [1..MAXSTACKSIZE] OF stackentry;
  93. Const FirstOpt = crsupp;
  94. LastOpt = capital; { Adjust this if you add options }
  95. FirstKey = endsym;
  96. LastKey = othersym; { Adjust this if you add options }
  97. LastFormatsym = usessym;
  98. Type
  99. tableptr = ^tableentry;
  100. optiontable = ARRAY [keysymbol] OF tableptr;
  101. OEntriesTable = Array [keysymbol] OF String[15];
  102. ONamesTable = Array [Options] of String[15];
  103. KeywordTable = ARRAY [endsym..lastFormatsym] OF String[MAXKEYLENGTH];
  104. SpecialChar = ARRAY [1..2] OF CHAR;
  105. dblcharset = SET OF endsym..othersym;
  106. DblCharTable = ARRAY [becomes..dclosecomment] OF SpecialChar;
  107. SglCharTable = ARRAY [opencomment..period] OF CHAR;
  108. TPrettyPrinter=Object(TObject)
  109. Private
  110. RecordSeen,
  111. CRPending : BOOLEAN;
  112. currchar,nextchar : charinfo;
  113. currsym,nextsym : symbolinfo;
  114. inlines,outlines : INTEGER;
  115. stack : symbolstack;
  116. top,startpos,currlinepos,currmargin : Integer;
  117. option : OptionTable;
  118. Procedure Verbose (Const Msg : String);
  119. Procedure GetChar;
  120. Procedure StoreNextChar(VAR lngth: INTEGER;
  121. VAR Value: Token);
  122. Procedure SkipBlanks(VAR spacesbefore, crsbefore: INTEGER);
  123. Procedure GetComment(sym: symbolinfo);
  124. Procedure GetDoubleComment(sym: symbolinfo);
  125. Procedure GetDelphiComment(sym: symbolinfo);
  126. Procedure GetNumber(sym: symbolinfo);
  127. Procedure GetCharLiteral(sym: symbolinfo);
  128. Function char_Type: keysymbol;
  129. Procedure GetSpecialChar(sym: symbolinfo);
  130. Procedure GetNextSymbol(sym: symbolinfo);
  131. Procedure GetIdentifier(sym: symbolinfo);
  132. Procedure GetSymbol;
  133. Procedure PopStack(VAR indentsymbol: keysymbol;
  134. VAR prevmargin: INTEGER);
  135. Procedure PushStack(indentsymbol: keysymbol;
  136. prevmargin: INTEGER );
  137. Procedure WriteCRs(numberofcrs: INTEGER);
  138. Procedure InsertCR;
  139. Procedure InsertBlankLine;
  140. Procedure LShiftOn(dindsym: keysymset);
  141. Procedure LShift;
  142. Procedure InsertSpace(VAR symbol: symbolinfo);
  143. Procedure MoveLinePos(newlinepos: INTEGER);
  144. Procedure PrintSymbol;
  145. Procedure PPSymbol;
  146. Procedure Gobble(terminators: keysymset);
  147. Procedure RShift(currmsym: keysymbol);
  148. Function ReadConfigFile: Boolean;
  149. Public
  150. LineSize : longint;
  151. Indent : Integer; { How many characters to indent ? }
  152. InS,
  153. OutS,
  154. DiagS,cfgS : PStream;
  155. Constructor Create;
  156. Function PrettyPrint : Boolean;
  157. end;
  158. Procedure GenerateCfgFile(S: PStream);
  159. Implementation
  160. CONST
  161. version = '20 February 2005'; {was '11 October 1984','28 November 1989'; ..ancient stuff!}
  162. NUL = 0; { ASCII null character }
  163. TAB = 9; { ASCII tab character }
  164. FF = 12; { ASCII formfeed character }
  165. CR = 13; { ASCII carriage return }
  166. ESC = 27; { ASCII escape character }
  167. Blank = ' ';
  168. MAXBYTE = 255;{ Largest value of 1 byte variable }
  169. Type
  170. hashentry = RECORD
  171. Keyword : String[MAXKEYLENGTH];
  172. symtype : keysymbol
  173. END;
  174. VAR
  175. sets : tableptr;
  176. dblch : dblcharset;
  177. hashtable : ARRAY [Byte] OF hashentry;
  178. CONST
  179. Keyword : KeywordTable =
  180. ('END', 'BEGIN', 'IF', 'THEN',
  181. 'ELSE', 'PROCEDURE', 'VAR', 'OF',
  182. 'WHILE', 'DO', 'CASE', 'WITH',
  183. 'FOR', 'REPEAT', 'UNTIL', 'FUNCTION',
  184. 'LABEL', 'CONST', 'TYPE', 'RECORD',
  185. 'STRING', 'PROGRAM',
  186. 'ASM','TRY','FINALLY','EXCEPT','RAISE','CLASS','OBJECT',
  187. 'CONSTRUCTOR','DESCTRUCTOR','INHERITED','PROPERTY',
  188. 'PRIVATE','PUBLIC','PROTECTED','PUBLISHED',
  189. 'INITIALIZATION','FINALIZATION',
  190. 'INLINE','LIBRARY','INTERFACE','IMPLEMENTATION',
  191. 'READ','WRITE','UNIT',
  192. {keywords not used for formatting }
  193. 'AND', 'ARRAY', 'DIV', 'DOWNTO',
  194. 'FILE', 'GOTO', 'IN', 'MOD',
  195. 'NOT', 'NIL', 'OR', 'SET','TO','VIRTUAL','USES'
  196. );
  197. EntryNames : OEntriesTable =
  198. ('end','begin','if','then','else','proc','var',
  199. 'of','while','do','case','with','for','repeat','until',
  200. 'func','label','const','type','record','string',
  201. 'prog',
  202. 'asm','try','finally','except','raise','class','object',
  203. 'constructor','destructor','inherited','property',
  204. 'private','public','protected','published',
  205. 'initialization','finalization',
  206. 'inline','library','interface','implementation',
  207. 'read','write','unit',
  208. 'and','arr','div','down','file','goto',
  209. 'in','mod','not','nil','or','set','to','virtual','uses',
  210. 'casevar',
  211. 'becomes','delphicomment','dopencomment','dclosecomment',
  212. 'opencomment','closecomment','semicolon',
  213. 'colon','equals',
  214. 'openparen','closeparen','period','endoffile','other');
  215. OptionNames : ONamesTable =
  216. ('crsupp','crbefore','blinbefore',
  217. 'dindonkey','dindent','spbef','spaft',
  218. 'gobsym','inbytab','crafter','upper',
  219. 'lower','capital');
  220. DblChar : DblCharTable =
  221. ( ':=', '//','(*','*)' );
  222. SglChar : SglCharTable =
  223. ('{', '}', ';', ':', '=', '(', ')', '.' );
  224. { ---------------------------------------------------------------------
  225. General functions, not part of the object.
  226. ---------------------------------------------------------------------}
  227. function upperStr(const s : string) : string;
  228. var
  229. i : longint;
  230. begin
  231. setLength(upperStr,length(s));
  232. for i:=1 to length(s) do
  233. if s[i] in ['a'..'z'] then
  234. upperStr[i]:=char(byte(s[i])-32)
  235. else
  236. upperStr[i]:=s[i];
  237. end;
  238. function LowerStr(const s : string) : string;
  239. var
  240. i : longint;
  241. begin
  242. setLength(LowerStr,length(s));
  243. for i:=1 to length(s) do
  244. if s[i] in ['A'..'Z'] then
  245. LowerStr[i]:=char(byte(s[i])+32)
  246. else
  247. LowerStr[i]:=s[i];
  248. end;
  249. Function IntToStr(I : LongInt) : String;
  250. var
  251. s : string;
  252. begin
  253. str(I,s);
  254. IntToStr := s;
  255. end;
  256. Function StrToInt(Const S : String) : Integer;
  257. Var Code : integer;
  258. Res : Integer;
  259. begin
  260. Val(S, Res, Code);
  261. StrToInt := Res;
  262. If Code<>0 then StrToInt:=0;
  263. end;
  264. Procedure Strip (Var S : String);
  265. Const WhiteSpace = [#32,#9,#10,#13];
  266. Var I,J : Longint;
  267. begin
  268. If length(s)=0 then exit;
  269. I:=1;
  270. While (S[I] in whitespace) and (I<Length(S)) do inc(i);
  271. J:=length(S);
  272. While (S[J] in whitespace) and (J>1) do dec(j);
  273. If I<=J then
  274. S:=Copy(S,i,j-i+1)
  275. else
  276. S:='';
  277. end;
  278. { ---------------------------------------------------------------------
  279. Hash table related functions
  280. ---------------------------------------------------------------------}
  281. Function hash(Symbol: String): Byte;
  282. { Hashing function for identifiers. The formula gives a unique value
  283. in the range 0..255 for each Pascal/Z keyword. Note that range and
  284. overflow checking must be turned off for this function even if they
  285. are enabled for the rest of the program. }
  286. BEGIN
  287. {$R-}
  288. hash := (ORD(Symbol[1]) * 5 + ORD(Symbol[length(Symbol)])) * 5 + length(Symbol);
  289. {$R+}
  290. END; { of hash }
  291. Procedure CreateHash;
  292. Var psn : Byte;
  293. sym : keysymbol;
  294. begin
  295. FOR psn := 0 TO MAXBYTE DO BEGIN
  296. hashtable[psn].Keyword := ' ';
  297. hashtable[psn].symtype := othersym
  298. END;
  299. FOR sym := endsym TO lastformatsym DO BEGIN
  300. psn := hash(Keyword[sym]);
  301. hashtable[psn].Keyword := Keyword[sym];
  302. hashtable[psn].symtype := sym
  303. END; { for }
  304. end;
  305. Procedure ClassID(Value: Token;
  306. lngth: INTEGER;
  307. VAR idtype: keysymbol;
  308. VAR IsKeyWord: BOOLEAN);
  309. { Classify an identifier. We are only interested
  310. in it if it is a keyword, so we use the hash table. }
  311. VAR
  312. Keyvalue: String[MAXKEYLENGTH];
  313. tabent: INTEGER;
  314. BEGIN
  315. IF lngth > MAXKEYLENGTH THEN BEGIN
  316. idtype := othersym;
  317. IsKeyWord := FALSE
  318. END
  319. ELSE BEGIN
  320. KeyValue:= UpperStr(Value);
  321. tabent := hash(Keyvalue);
  322. IF Keyvalue = hashtable[tabent].Keyword THEN BEGIN
  323. idtype := hashtable[tabent].symtype;
  324. IsKeyWord := TRUE;
  325. END
  326. ELSE BEGIN
  327. idtype := othersym;
  328. IsKeyWord := FALSE;
  329. END
  330. END
  331. END; { of ClassID }
  332. { ---------------------------------------------------------------------
  333. Functions to create options and set defaults.
  334. ---------------------------------------------------------------------}
  335. Procedure CreateOptions (Var Option : OptionTable);
  336. Var Sym : KeySymbol;
  337. begin
  338. FOR sym := endsym TO othersym DO BEGIN
  339. NEW(option[sym]);
  340. option[sym]^.selected := [];
  341. option[sym]^.dindsym := [];
  342. option[sym]^.terminators := []
  343. END;
  344. end;
  345. Procedure SetTerminators(Var Option : OptionTable);
  346. begin
  347. option[casesym]^.terminators := [ofsym];
  348. option[casevarsym]^.terminators := [ofsym];
  349. option[forsym]^.terminators := [dosym];
  350. option[whilesym]^.terminators := [dosym];
  351. option[withsym]^.terminators := [dosym];
  352. option[ifsym]^.terminators := [thensym];
  353. option[untilsym]^.terminators := [endsym, untilsym, elsesym, semicolon];
  354. option[becomes]^.terminators := [endsym, untilsym, elsesym, semicolon];
  355. option[openparen]^.terminators := [closeparen];
  356. option[usessym]^.terminators := [semicolon];
  357. end;
  358. Procedure SetDefaultIndents (Var Option : OptionTable);
  359. begin
  360. option[recordsym]^.dindsym := [endsym];
  361. option[funcsym]^.dindsym := [labelsym, constsym, typesym, varsym];
  362. option[procsym]^.dindsym := [labelsym, constsym, typesym, varsym];
  363. option[constsym]^.dindsym := [labelsym, constsym, typesym, varsym];
  364. option[typesym]^.dindsym := [labelsym, constsym, typesym, varsym];
  365. option[varsym]^.dindsym := [labelsym, constsym, typesym, varsym];
  366. option[beginsym]^.dindsym := [labelsym, constsym, typesym, varsym];
  367. option[publicsym]^.dindsym := [protectedsym,privatesym,publicsym,publishedsym];
  368. option[privatesym]^.dindsym := [protectedsym,privatesym,publicsym,publishedsym];
  369. option[protectedsym]^.dindsym := [protectedsym,privatesym,publicsym,publishedsym];
  370. option[publishedsym]^.dindsym := [protectedsym,privatesym,publicsym,publishedsym];
  371. option[finallysym]^.dindsym := [trysym];
  372. option[exceptsym]^.dindsym := [trysym];
  373. option[elsesym]^.dindsym := [ifsym, thensym, elsesym];
  374. option[untilsym]^.dindsym := [ifsym, thensym, elsesym, forsym, whilesym,
  375. withsym, colon, equals];
  376. option[endsym]^.dindsym := [ifsym, thensym, elsesym, forsym, whilesym,
  377. withsym, casevarsym, colon, equals, recordsym,
  378. classsym,objectsym];
  379. option[semicolon]^.dindsym := [ifsym, thensym, elsesym, forsym,
  380. whilesym, withsym, colon, equals];
  381. end;
  382. Procedure SetDefaults (Var Option : OptionTable);
  383. { Sets default values for the formatting rules. }
  384. begin
  385. option[progsym]^.selected := [capital,blinbefore, spaft];
  386. option[unitsym]^.selected := [capital,blinbefore, spaft];
  387. option[librarysym]^.selected := [capital,blinbefore, spaft];
  388. option[funcsym]^.selected := [capital,blinbefore, dindonkey, spaft];
  389. option[procsym]^.selected := [capital,blinbefore, dindonkey, spaft];
  390. option[labelsym]^.selected := [capital,blinbefore, spaft, inbytab];
  391. option[constsym]^.selected := [capital,blinbefore, dindonkey, spaft, inbytab];
  392. option[typesym]^.selected := [capital,blinbefore, dindonkey, spaft, inbytab];
  393. option[varsym]^.selected := [capital,blinbefore, dindonkey, spaft, inbytab];
  394. option[beginsym]^.selected := [capital,dindonkey, crbefore, crafter, inbytab];
  395. option[repeatsym]^.selected := [capital,inbytab, crafter];
  396. option[recordsym]^.selected := [capital,inbytab, crafter];
  397. option[objectsym]^.selected := [capital,inbytab, crafter];
  398. option[classsym]^.selected := [capital,inbytab, crafter];
  399. option[publicsym]^.selected := [capital,crbefore, dindonkey, spaft, inbytab];
  400. option[publishedsym]^.selected := [capital,crbefore, dindonkey, spaft, inbytab];
  401. option[protectedsym]^.selected := [capital,crbefore, dindonkey, spaft, inbytab];
  402. option[privatesym]^.selected := [capital,crbefore, dindonkey, spaft, inbytab];
  403. option[trysym]^.Selected := [capital,crbefore,crafter,inbytab];
  404. option[finallysym]^.selected := [capital,crbefore,dindonkey,crafter,inbytab];
  405. option[exceptsym]^.selected := [capital,crbefore,dindonkey,crafter,inbytab];
  406. option[casesym]^.selected := [capital,spaft, inbytab, gobsym, crafter];
  407. option[casevarsym]^.selected := [capital,spaft, inbytab, gobsym, crafter];
  408. option[ofsym]^.selected := [capital,crsupp, spbef];
  409. option[forsym]^.selected := [capital,spaft, inbytab, gobsym, crafter];
  410. option[whilesym]^.selected := [capital,spaft, inbytab, gobsym, crafter];
  411. option[withsym]^.selected := [capital,spaft, inbytab, gobsym, crafter];
  412. option[dosym]^.selected := [capital,crsupp, spbef];
  413. option[ifsym]^.selected := [capital,spaft, inbytab, gobsym];
  414. option[thensym]^.selected := [capital];
  415. option[elsesym]^.selected := [capital,crbefore, dindonkey, inbytab];
  416. option[endsym]^.selected := [capital,crbefore, crafter,dindonkey,dindent];
  417. option[untilsym]^.selected := [capital,crbefore, dindonkey, dindent, spaft,
  418. gobsym, crafter];
  419. option[becomes]^.selected := [capital,spbef, spaft, gobsym];
  420. option[Delphicomment]^.Selected := [crafter];
  421. option[opencomment]^.selected := [capital,crsupp];
  422. option[closecomment]^.selected := [capital,crsupp];
  423. option[semicolon]^.selected := [capital,crsupp, dindonkey, crafter];
  424. option[colon]^.selected := [capital,inbytab];
  425. option[equals]^.selected := [capital,spbef, spaft, inbytab];
  426. option[openparen]^.selected := [capital,gobsym];
  427. option[period]^.selected := [capital,crsupp];
  428. end;
  429. { ---------------------------------------------------------------------
  430. Stream handling routines
  431. ---------------------------------------------------------------------}
  432. Function ReadChar (S : PStream) : Char;
  433. Var C : Char;
  434. begin
  435. repeat
  436. if S^.GetPos = S^.GetSize then
  437. C:=#0
  438. else
  439. S^.Read(C,1);
  440. Until C<>#13;
  441. ReadChar:=C;
  442. end;
  443. Function EoSLn (S : PStream) : Char;
  444. Const WhiteSpace = [' ', #9, #13 ];
  445. Var C : Char;
  446. begin
  447. Repeat
  448. if S^.GetPos = S^.GetSize then
  449. C:=#0
  450. else
  451. S^.Read(C,1);
  452. Until (Not (C in WhiteSpace)) or ((C=#10));
  453. EoSln:=C;
  454. end;
  455. Function ReadString (S: PStream): String;
  456. Var Buffer : String;
  457. I : Byte;
  458. begin
  459. Buffer:='';
  460. I:=0;
  461. Repeat
  462. S^.Read(Buffer[I+1],1);
  463. Inc(I);
  464. until (I=255) or (Buffer[I]=#10) Or (S^.Status=StReadError);
  465. If S^.Status=stReadError then Dec(I);
  466. If Buffer[i]=#10 Then Dec(I);
  467. If Buffer[I]=#13 then Dec(I);
  468. Buffer[0] := chr(I);
  469. ReadString:=Buffer;
  470. end;
  471. Procedure WriteString (S : PStream; ST : String);
  472. begin
  473. S^.Write(St[1],length(St));
  474. end;
  475. Procedure WriteAnsiString (S : PStream; ST : AnsiString);
  476. begin
  477. S^.Write(St[1],length(St));
  478. end;
  479. Procedure WriteCR (S: PStream);
  480. Const
  481. Newline = System.LineEnding;
  482. begin
  483. WriteString(S,Newline);
  484. end;
  485. Procedure WriteLnString (S : PStream; ST : String);
  486. begin
  487. WriteString(S,ST);
  488. WriteCR(S);
  489. end;
  490. { ---------------------------------------------------------------------
  491. TPrettyPrinter object
  492. ---------------------------------------------------------------------}
  493. Procedure TPrettyPrinter.Verbose (Const Msg : String);
  494. begin
  495. If Assigned (DiagS) then
  496. WriteLnString (DiagS,Msg);
  497. end;
  498. Procedure TPrettyPrinter.GetChar;
  499. { Read the next character and classify it }
  500. VAR Ch: CHAR;
  501. BEGIN
  502. currchar := nextchar;
  503. WITH nextchar DO
  504. begin
  505. Ch:=ReadCHar(Ins);
  506. If Ch=#0 then
  507. BEGIN
  508. name := filemark;
  509. Value := Blank
  510. END
  511. ELSE If (Ch=#10) THEN
  512. BEGIN
  513. name := endofline;
  514. Value := Ch;
  515. Inc(inlines);
  516. END
  517. ELSE
  518. BEGIN
  519. Value := Ch;
  520. IF Ch IN ['a'..'z', 'A'..'Z', '_'] THEN name := letter
  521. ELSE IF Ch IN ['0'..'9'] THEN name := digit
  522. ELSE IF Ch = '''' THEN name := quote
  523. ELSE IF Ch in [#13,' ',#9] THEN name := space
  524. ELSE name := otherchar
  525. END
  526. end;
  527. END; { of GetChar }
  528. Procedure TPrettyPrinter.StoreNextChar(VAR lngth: INTEGER;
  529. VAR Value: Token);
  530. { Store a character in the current symbol }
  531. BEGIN
  532. GetChar;
  533. IF lngth < MAXSYMBOLSIZE THEN BEGIN {XXX - should there be a limit at all?}
  534. Inc(lngth);
  535. setlength(Value,lngth);
  536. Value[lngth] := currchar.Value;
  537. END;
  538. END; { of StoreNextChar }
  539. Procedure TPrettyPrinter.SkipBlanks(VAR spacesbefore, crsbefore: INTEGER);
  540. { Count the spaces between symbols }
  541. BEGIN
  542. spacesbefore := 0;
  543. crsbefore := 0;
  544. WHILE nextchar.name IN [space, endofline] DO BEGIN
  545. GetChar;
  546. CASE currchar.name OF
  547. space: Inc(spacesbefore);
  548. endofline: BEGIN
  549. Inc(crsbefore);
  550. spacesbefore := 0;
  551. END;
  552. END; {case}
  553. END;
  554. END; { of SkipBlanks }
  555. Procedure TPrettyPrinter.GetComment(sym: symbolinfo);
  556. { Process comments using brace notation }
  557. BEGIN
  558. sym^.name := opencomment;
  559. WHILE NOT ((currchar.Value = '}')
  560. OR (nextchar.name = filemark)) DO
  561. StoreNextChar(sym^.length, sym^.Value);
  562. IF currchar.Value = '}' THEN sym^.name := closecomment;
  563. END; { of GetCommment }
  564. Procedure TPrettyPrinter.GetDoubleComment(sym: symbolinfo);
  565. { Process comments using parenthesis notation }
  566. BEGIN
  567. sym^.name := dopencomment;
  568. WHILE NOT (((currchar.Value = '*') AND (nextchar.Value = ')'))
  569. OR (nextchar.name = filemark)) DO
  570. StoreNextChar(sym^.length, sym^.Value);
  571. IF (currchar.Value = '*') AND (nextchar.Value = ')') THEN BEGIN
  572. StoreNextChar(sym^.length, sym^.Value);
  573. sym^.name := dclosecomment;
  574. END;
  575. END; { of GetDoubleCommment }
  576. Procedure TPrettyPrinter.GetDelphiComment(sym: symbolinfo);
  577. { Process comments using either brace or parenthesis notation }
  578. BEGIN
  579. sym^.name := Delphicomment;
  580. WHILE NOT ((nextchar.name = endofline) OR (nextchar.name = filemark)) DO
  581. StoreNextChar(sym^.length, sym^.Value);
  582. END; { of GetDelphiCommment }
  583. Procedure TPrettyPrinter.GetIdentifier(sym: symbolinfo);
  584. { Read an identifier and classify it }
  585. BEGIN
  586. WHILE nextchar.name IN [letter, digit] DO
  587. StoreNextChar(sym^.length, sym^.Value);
  588. ClassID(sym^.Value, sym^.length, sym^.name, sym^.IsKeyWord);
  589. IF sym^.name IN [recordsym, casesym, endsym] THEN
  590. CASE sym^.name OF
  591. recordsym : RecordSeen := TRUE;
  592. casesym : IF RecordSeen THEN sym^.name := casevarsym;
  593. endsym : RecordSeen := FALSE;
  594. END; {case}
  595. END; { of GetIdentifier }
  596. { Read a number and store it as a string }
  597. Procedure TPrettyPrinter.GetNumber(sym: symbolinfo);
  598. BEGIN
  599. WHILE nextchar.name = digit DO StoreNextChar(sym^.length, sym^.Value);
  600. sym^.name := othersym;
  601. END; { of GetNumber }
  602. PROCEDURE TPrettyPrinter.GetCharLiteral(sym: symbolinfo);
  603. { Read a quoted string }
  604. BEGIN
  605. WHILE nextchar.name = quote DO BEGIN
  606. StoreNextChar(sym^.length, sym^.Value);
  607. WHILE NOT (nextchar.name IN [quote, endofline, filemark]) DO
  608. StoreNextChar(sym^.length, sym^.Value);
  609. IF nextchar.name = quote THEN StoreNextChar(sym^.length, sym^.Value);
  610. END;
  611. sym^.name := othersym;
  612. END; { of GetCharLiteral }
  613. FUNCTION TPrettyPrinter.char_Type: keysymbol;
  614. { Classify a character pair }
  615. VAR
  616. NextTwoChars: SpecialChar;
  617. Hit: BOOLEAN;
  618. thischar: keysymbol;
  619. BEGIN
  620. NextTwoChars[1] := currchar.Value;
  621. NextTwoChars[2] := nextchar.Value;
  622. thischar := becomes;
  623. Hit := FALSE;
  624. WHILE NOT (Hit OR (thischar = opencomment)) DO BEGIN
  625. IF NextTwoChars = DblChar[thischar] THEN Hit := TRUE
  626. ELSE Inc(thischar);
  627. END;
  628. IF NOT Hit THEN BEGIN
  629. thischar := opencomment;
  630. WHILE NOT (Hit OR (PRED(thischar) = period)) DO BEGIN
  631. IF currchar.Value = SglChar[thischar] THEN Hit := TRUE
  632. ELSE Inc(thischar);
  633. END;
  634. END;
  635. IF Hit THEN char_Type := thischar
  636. ELSE char_Type := othersym;
  637. END; { of char_Type }
  638. Procedure TPrettyPrinter.GetSpecialChar(sym: symbolinfo);
  639. { Read special characters }
  640. BEGIN
  641. StoreNextChar(sym^.length, sym^.Value);
  642. sym^.name := char_Type;
  643. IF sym^.name IN dblch THEN StoreNextChar(sym^.length, sym^.Value)
  644. END; { of GetSpecialChar }
  645. Procedure TPrettyPrinter.GetNextSymbol(sym: symbolinfo);
  646. { Read a symbol using the appropriate procedure }
  647. BEGIN
  648. CASE nextchar.name OF
  649. letter: GetIdentifier(sym);
  650. digit: GetNumber(sym);
  651. quote: GetCharLiteral(sym);
  652. otherchar: BEGIN
  653. GetSpecialChar(sym);
  654. IF sym^.name = opencomment THEN GetComment(sym)
  655. else IF sym^.name = dopencomment THEN GetDoubleComment(sym)
  656. else IF sym^.name= DelphiComment then GetDelphiComment(Sym)
  657. END;
  658. filemark: sym^.name := endoffile;
  659. ELSE {:} {Turbo}
  660. WRITELN('Unknown character type: ', ORD(nextchar.name));
  661. END; {case}
  662. END; { of GetNextSymbol }
  663. Procedure TprettyPrinter.GetSymbol;
  664. { Store the next symbol in NEXTSYM }
  665. VAR
  666. dummy: symbolinfo;
  667. BEGIN
  668. dummy := currsym;
  669. currsym := nextsym;
  670. nextsym := dummy;
  671. SkipBlanks(nextsym^.spacesbefore, nextsym^.crsbefore);
  672. nextsym^.length := 0;
  673. nextsym^.IsKeyWord := FALSE;
  674. IF currsym^.name = opencomment THEN GetComment(nextsym)
  675. ELSE IF currsym^.name = dopencomment THEN GetDoubleComment(nextsym)
  676. ELSE GetNextSymbol(nextsym);
  677. END; {of GetSymbol}
  678. Procedure TprettyPrinter.PopStack(VAR indentsymbol: keysymbol;
  679. VAR prevmargin: INTEGER);
  680. { Manage stack of indentation symbols and margins }
  681. BEGIN
  682. IF top > 0 THEN BEGIN
  683. indentsymbol := stack[top].indentsymbol;
  684. prevmargin := stack[top].prevmargin;
  685. Dec(top);
  686. END
  687. ELSE BEGIN
  688. indentsymbol := othersym;
  689. prevmargin := 0;
  690. END;
  691. END; { of PopStack }
  692. Procedure TPrettyPrinter.PushStack(indentsymbol: keysymbol;
  693. prevmargin: INTEGER );
  694. BEGIN
  695. Inc(top);
  696. stack[top].indentsymbol := indentsymbol;
  697. stack[top].prevmargin := prevmargin;
  698. END; { of PushStack }
  699. Procedure TPrettyPrinter.WriteCRs(numberofcrs: INTEGER);
  700. VAR
  701. i: INTEGER;
  702. BEGIN
  703. IF numberofcrs > 0 THEN BEGIN
  704. FOR i := 1 TO numberofcrs DO
  705. WriteCr(OutS);
  706. Inc(outlines,numberofcrs);
  707. currlinepos := 0;
  708. END;
  709. END; { of WriteCRs }
  710. Procedure TPrettyPrinter.InsertCR;
  711. BEGIN
  712. IF currsym^.crsbefore = 0 THEN BEGIN
  713. WriteCRs(1);
  714. currsym^.spacesbefore := 0;
  715. END;
  716. END; { of InsertCR }
  717. Procedure TPrettyPrinter.InsertBlankLine;
  718. BEGIN
  719. IF currsym^.crsbefore = 0 THEN BEGIN
  720. IF currlinepos = 0 THEN WriteCRs(1)
  721. ELSE WriteCRs(2);
  722. currsym^.spacesbefore := 0;
  723. END
  724. ELSE IF currsym^.crsbefore = 1 THEN
  725. IF currlinepos > 0 THEN WriteCRs(1);
  726. END; { of InsertBlankLine }
  727. Procedure TPrettyPrinter.LShiftOn(dindsym: keysymset);
  728. { Move margin left according to stack configuration and current symbol }
  729. VAR
  730. indentsymbol: keysymbol;
  731. prevmargin: INTEGER;
  732. BEGIN
  733. IF top > 0 THEN BEGIN
  734. REPEAT
  735. PopStack(indentsymbol, prevmargin);
  736. IF indentsymbol IN dindsym THEN currmargin := prevmargin;
  737. UNTIL NOT (indentsymbol IN dindsym) OR (top = 0);
  738. IF NOT (indentsymbol IN dindsym) THEN
  739. PushStack(indentsymbol, prevmargin);
  740. END;
  741. END; { of LShiftOn }
  742. Procedure TprettyPrinter.LShift;
  743. { Move margin left according to stack top }
  744. VAR
  745. indentsymbol: keysymbol;
  746. prevmargin: INTEGER;
  747. BEGIN
  748. IF top > 0 THEN BEGIN
  749. PopStack(indentsymbol, prevmargin);
  750. currmargin := prevmargin;
  751. (* maybe PopStack(indentsymbol,currmargin); *)
  752. END;
  753. END; { of LShift }
  754. Procedure TPrettyPrinter.InsertSpace(VAR symbol: symbolinfo);
  755. { Insert space if room on line }
  756. BEGIN
  757. IF currlinepos < LineSize THEN BEGIN
  758. WriteString(OutS, Blank);
  759. Inc(currlinepos);
  760. IF (symbol^.crsbefore = 0) AND (symbol^.spacesbefore > 0)
  761. THEN Dec(symbol^.spacesbefore);
  762. END;
  763. END; { of InsertSpace }
  764. Procedure TPrettyPrinter.MoveLinePos(newlinepos: INTEGER);
  765. { Insert spaces until correct line position reached }
  766. VAR i: INTEGER;
  767. BEGIN
  768. FOR i := SUCC(currlinepos) TO newlinepos DO
  769. WriteString(OutS, Blank);
  770. currlinepos := newlinepos;
  771. END; { of MoveLinePos }
  772. Procedure TPrettyPrinter.PrintSymbol;
  773. BEGIN
  774. IF (currsym^.IsKeyWord) then
  775. begin
  776. If upper in sets^.selected Then
  777. WriteString (OutS,UpperStr(currsym^.value))
  778. else if lower in sets^.selected then
  779. WriteString (OutS,LowerStr(currsym^.value))
  780. else if capital in sets^.selected then
  781. begin
  782. WriteString(OutS,UpCase(CurrSym^.Value[1]));
  783. WriteString(OutS,LowerStr(Copy(CurrSym^.Value,2,MAXSYMBOLSIZE)));{XXX - ?should it be length?}
  784. end
  785. else
  786. WriteString(OutS,Currsym^.Value);
  787. end
  788. ELSE
  789. WriteAnsiString(OutS, currsym^.Value);
  790. startpos := currlinepos;
  791. Inc(currlinepos,currsym^.length);
  792. END; { of PrintSymbol }
  793. Procedure TPrettyPrinter.PPSymbol;
  794. { Find position for symbol and then print it }
  795. VAR newlinepos: INTEGER;
  796. BEGIN
  797. WriteCRs(currsym^.crsbefore);
  798. IF (currlinepos + currsym^.spacesbefore > currmargin)
  799. OR (currsym^.name IN [opencomment, closecomment,dopencomment, dclosecomment])
  800. THEN newlinepos := currlinepos + currsym^.spacesbefore
  801. ELSE newlinepos := currmargin;
  802. IF newlinepos + currsym^.length > LINESIZE THEN BEGIN {XXX - this needs to be cleaned for case of long symbol values}
  803. WriteCRs(1);
  804. IF currmargin + currsym^.length <= LINESIZE
  805. THEN newlinepos := currmargin
  806. ELSE IF currsym^.length < LINESIZE
  807. THEN newlinepos := LINESIZE - currsym^.length
  808. ELSE newlinepos := 0;
  809. END;
  810. MoveLinePos(newlinepos);
  811. PrintSymbol;
  812. END; { of PPSymbol }
  813. Procedure TPrettyPrinter.Gobble(terminators: keysymset);
  814. { Print symbols which follow a formatting symbol but which do not
  815. affect layout }
  816. BEGIN
  817. IF top < MAXSTACKSIZE THEN PushStack(currsym^.name, currmargin);
  818. currmargin := currlinepos;
  819. WHILE NOT ((nextsym^.name IN terminators)
  820. OR (nextsym^.name = endoffile)) DO BEGIN
  821. GetSymbol;
  822. PPSymbol;
  823. END;
  824. LShift;
  825. END; { of Gobble }
  826. Procedure TprettyPrinter.RShift(currmsym: keysymbol);
  827. { Move right, stacking margin positions }
  828. BEGIN
  829. IF top < MAXSTACKSIZE THEN PushStack(currmsym, currmargin);
  830. IF startpos > currmargin THEN currmargin := startpos;
  831. Inc(currmargin,INDENT);
  832. END; { of RShift }
  833. Function TPrettyPrinter.ReadConfigFile : Boolean;
  834. Var I,J : Longint;
  835. Procedure SetOption(TheKey : KeySymbol;Var OptionList : String);
  836. Var TheOpt : Options;
  837. Found : Boolean;
  838. K : longint;
  839. opt : string;
  840. begin
  841. Repeat
  842. K:=pos(',',optionlist);
  843. If k>0 then
  844. begin
  845. opt:=Copy(OptionList,1,k-1);
  846. strip(opt);
  847. Delete(OptionList,1,k);
  848. end
  849. else
  850. opt:=OptionList;
  851. If Length(Opt)>0 then
  852. begin
  853. Found:=False;
  854. for TheOpt :=firstopt to lastopt do
  855. begin
  856. found:=opt=OptionNames[Theopt];
  857. If found then break;
  858. end;
  859. If not found then
  860. Verbose ('Unknown option on line '+inttostr(i)+': '+Opt)
  861. else
  862. Option[TheKey]^.Selected:=Option[TheKey]^.Selected+[TheOpt];
  863. end;
  864. until k=0;
  865. end;
  866. Procedure SetIndent(TheKey : KeySymbol; Var OptionList : String);
  867. Var
  868. TheIndent : Keysymbol;
  869. Found : Boolean;
  870. K : longint;
  871. opt : string;
  872. begin
  873. Repeat
  874. K:=pos(',',optionlist);
  875. If k>0 then
  876. begin
  877. opt:=Copy(OptionList,1,k-1);
  878. strip(opt);
  879. Delete(OptionList,1,k);
  880. end
  881. else
  882. opt:=OptionList;
  883. If Length(Opt)>0 then
  884. begin
  885. Found:=False;
  886. for TheIndent :=firstKey to lastKey do
  887. begin
  888. found:=opt=EntryNames[Theindent];
  889. If found then break;
  890. end;
  891. If not found then
  892. begin
  893. Verbose ('Unknown indent keysym on line '+inttostr(i)+': '+Opt);
  894. exit;
  895. end;
  896. Option[TheKey]^.dindsym:=Option[TheKey]^.dindsym+[Theindent];
  897. end;
  898. until k=0;
  899. end;
  900. Var TheKey : KeySymbol;
  901. Found,DoIndent : Boolean;
  902. Line, Name : String;
  903. begin
  904. ReadConfigFile:=false;
  905. I:=0;
  906. while not (CfgS^.Status=stReadError) do
  907. begin
  908. inc(i);
  909. Line:='';
  910. Line:=ReadString(cfgS);
  911. { Strip comment }
  912. If pos('#',Line)<>0 then
  913. Line:=Copy(Line,1,Pos('#',Line)-1);
  914. If length(Line)<>0 then
  915. begin
  916. J:=Pos('=',Line);
  917. If J>0 then
  918. begin
  919. Line:=LowerStr(Line);
  920. Name:=Copy(Line,1,j-1);
  921. Delete(Line,1,J);
  922. { indents or options ? }
  923. If (Name[1]='[') and
  924. (Name[Length(Name)]=']') then
  925. begin
  926. Name:=Copy(Name,2,Length(Name)-2);
  927. Doindent:=True;
  928. end
  929. else
  930. DoIndent:=False;
  931. Strip(Name);
  932. found:=false;
  933. for thekey:=firstkey to lastkey do
  934. begin
  935. found:=Name=EntryNames[thekey];
  936. If Found then break;
  937. end;
  938. If not found then
  939. Verbose ('Unknown keyword on line '+inttostr(i)+': '+Name)
  940. else
  941. If DoIndent then
  942. SetIndent(TheKey,Line)
  943. else
  944. SetOption(TheKey,Line)
  945. end
  946. else
  947. verbose ('Error in config file on line '+IntToStr(i));
  948. end;
  949. end;
  950. Verbose ('Processed configfile: read '+IntToStr(I)+' lines');
  951. ReadConfigFile:=true;
  952. end;
  953. Procedure GenerateCfgFile(S : PStream);
  954. Var TheKey,TheIndent : KeySymbol;
  955. TheOpt : Options;
  956. Written : Boolean;
  957. Option : OptionTable;
  958. begin
  959. CreateOptions(option);
  960. SetDefaults(option);
  961. SetDefaultIndents(option);
  962. For TheKey:=Firstkey to lastkey do
  963. begin
  964. { Write options }
  965. WriteString (S,EntryNames[TheKey]+'=');
  966. Written:=False;
  967. for TheOpt:=FirstOpt to LastOpt do
  968. If TheOpt in Option[TheKey]^.Selected then
  969. begin
  970. if written then
  971. WriteString (S,',')
  972. else
  973. Written:=True;
  974. writeString (S,OptionNames[TheOpt]);
  975. end;
  976. WriteCr (S);
  977. { Write de-indent keysyms, if any }
  978. If Option[TheKey]^.dindsym<>[] then
  979. begin
  980. WriteString (S,'['+EntryNames[TheKey]+']=');
  981. Written:=False;
  982. For TheIndent:=FirstKey to lastkey do
  983. If TheIndent in Option[TheKey]^.dindsym then
  984. begin
  985. if written then
  986. WriteString (S,',')
  987. else
  988. Written:=True;
  989. WriteString (S,EntryNames[Theindent]);
  990. end;
  991. WriteCr (S);
  992. end;
  993. end;
  994. end;
  995. Function trimMiddle ( a:ansistring; lnght: integer; size: integer):string;
  996. var
  997. half:Integer;
  998. begin
  999. if lnght > size
  1000. then
  1001. begin
  1002. half := (size - 3) div 2;
  1003. trimMiddle := copy(a,1,half) + '...' + copy(a,lnght-half+1,half);
  1004. end
  1005. else
  1006. trimMiddle := a;
  1007. end;
  1008. Function TPrettyPrinter.PrettyPrint : Boolean;
  1009. Begin
  1010. PrettyPrint:=False;
  1011. If Not Assigned(Ins) or Not Assigned(OutS) then
  1012. exit;
  1013. If Not Assigned(CfgS) then
  1014. begin
  1015. SetDefaults(Option);
  1016. SetDefaultIndents(Option);
  1017. end
  1018. else
  1019. ReadConfigFile;
  1020. { Initialize variables }
  1021. top := 0;
  1022. currlinepos := 0;
  1023. currmargin := 0;
  1024. inlines := 0;
  1025. outlines := 0;
  1026. CrPending := FALSE;
  1027. RecordSeen := FALSE;
  1028. GetChar;
  1029. NEW(currsym);
  1030. NEW(nextsym);
  1031. GetSymbol;
  1032. WHILE nextsym^.name <> endoffile DO BEGIN
  1033. GetSymbol;
  1034. Verbose('line in-'+IntToStr(inlines)+' out-'+IntToStr(outlines)+
  1035. ' symbol "'+EntryNames[currsym^.name]+'" = "'+
  1036. trimMiddle(currsym^.value,length(currsym^.value),MAXSHOWSIZE)+'"');
  1037. sets := option[currsym^.name];
  1038. IF (CrPending AND NOT (crsupp IN sets^.selected))
  1039. OR (crbefore IN sets^.selected) THEN BEGIN
  1040. InsertCR;
  1041. CrPending := FALSE
  1042. END;
  1043. IF blinbefore IN sets^.selected THEN BEGIN
  1044. InsertBlankLine;
  1045. CrPending := FALSE
  1046. END;
  1047. IF dindonkey IN sets^.selected THEN LShiftOn(sets^.dindsym);
  1048. IF dindent IN sets^.selected THEN LShift;
  1049. IF spbef IN sets^.selected THEN InsertSpace(currsym);
  1050. PPSymbol;
  1051. IF spaft IN sets^.selected THEN InsertSpace(nextsym);
  1052. IF inbytab IN sets^.selected THEN RShift(currsym^.name);
  1053. IF gobsym IN sets^.selected THEN Gobble(sets^.terminators);
  1054. IF crafter IN sets^.selected THEN CrPending := TRUE
  1055. END;
  1056. IF CrPending THEN WriteCRs(1);
  1057. Verbose(IntToStr(inlines)+' lines read, '+IntToStr(outlines)+' lines written.');
  1058. PrettyPrint:=True;
  1059. end;
  1060. Constructor TPrettyPrinter.Create;
  1061. Begin
  1062. LineSize:=MaxLineSize;
  1063. CreateOptions (Option);
  1064. SetTerminators(Option);
  1065. DiagS:=Nil;
  1066. InS:=Nil;
  1067. OutS:=Nil;
  1068. CfgS:=Nil;
  1069. End;
  1070. { ---------------------------------------------------------------------
  1071. Unit initialization
  1072. ---------------------------------------------------------------------}
  1073. Begin
  1074. CreateHash;
  1075. dblch := [becomes, opencomment];
  1076. end.
  1077. {
  1078. $Log$
  1079. Revision 1.8 2005-02-21 07:59:10 michael
  1080. - keywords 'virtual' and 'uses' were added.
  1081. - '{}' and '(**)' comment types were separated.
  1082. - tokens now AnsiStrings
  1083. - the comments are now handled better, ptop now does multi line comments.
  1084. - added debug prints to verbose option
  1085. 'line in-<number> out-<number> symbol "<name>" = "<value>"'
  1086. the <value> is truncated in the middle. this means visible beginning and
  1087. the end.
  1088. Revision 1.7 2003/11/24 22:39:25 michael
  1089. + set maxsymbolsize to 255
  1090. Revision 1.6 2003/03/27 14:23:00 michael
  1091. + Fixed use of linesize property, reported by Wolfgang Waffenschmidt
  1092. Revision 1.5 2002/09/07 15:40:31 peter
  1093. * old logs removed and tabs fixed
  1094. Revision 1.4 2002/07/14 13:39:45 carl
  1095. * use special symbols for portability's sake
  1096. Revision 1.3 2002/06/01 18:39:14 marco
  1097. * Renamefest
  1098. Revision 1.2 2002/02/27 16:35:31 carl
  1099. * bugfix of stream errors - would always give error!
  1100. }