fpcompil.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Compiler call routines for the IDE
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$i globdir.inc}
  13. unit FPCompil;
  14. interface
  15. { don't redir under linux, because all stdout (also from the ide!) will
  16. then be redired (PFV) }
  17. { this should work now correctly because
  18. RedirDisableAll and RedirEnableAll function are added in fpredir (PM) }
  19. { $define VERBOSETXT}
  20. {$mode objfpc}
  21. uses
  22. { We need to include the exceptions from SysUtils, but the types from
  23. Objects need to be used. Keep the order SysUtils,Objects }
  24. SysUtils,
  25. Objects,
  26. FInput,
  27. Drivers,Views,Dialogs,
  28. WUtils,WViews,WCEdit,
  29. FPSymbol,
  30. FPViews;
  31. type
  32. TCompileMode = (cBuild,cMake,cCompile,cRun);
  33. type
  34. PCompilerMessage = ^TCompilerMessage;
  35. TCompilerMessage = object(TMessageItem)
  36. function GetText(MaxLen: Sw_Integer): String; virtual;
  37. end;
  38. PCompilerMessageListBox = ^TCompilerMessageListBox;
  39. TCompilerMessageListBox = object(TMessageListBox)
  40. function GetPalette: PPalette; virtual;
  41. procedure SelectFirstError;
  42. end;
  43. PCompilerMessageWindow = ^TCompilerMessageWindow;
  44. TCompilerMessageWindow = object(TFPWindow)
  45. constructor Init;
  46. procedure HandleEvent(var Event: TEvent); virtual;
  47. function GetPalette: PPalette; virtual;
  48. procedure Close;virtual;
  49. destructor Done; virtual;
  50. procedure SizeLimits(var Min, Max: TPoint); virtual;
  51. procedure AddMessage(AClass: longint;const Msg, Module: string; Line, Column: longint);
  52. procedure ClearMessages;
  53. constructor Load(var S: TStream);
  54. procedure Store(var S: TStream);
  55. procedure SetState(AState: Word; Enable: Boolean); virtual;
  56. procedure UpdateCommands; virtual;
  57. private
  58. {CompileShowed : boolean;}
  59. {Mode : TCompileMode;}
  60. MsgLB : PCompilerMessageListBox;
  61. {CurrST,
  62. InfoST : PColorStaticText;}
  63. end;
  64. PCompilerStatusDialog = ^TCompilerStatusDialog;
  65. TCompilerStatusDialog = object(TCenterDialog)
  66. ST : PAdvancedStaticText;
  67. KeyST : PColorStaticText;
  68. constructor Init;
  69. destructor Done;virtual;
  70. procedure Update;
  71. end;
  72. TFPInputFile = class(tinputfile)
  73. constructor Create(AEditor: PFileEditor);
  74. protected
  75. function fileopen(const filename: string): boolean; override;
  76. function fileseek(pos: longint): boolean; override;
  77. function fileread(var databuf; maxsize: longint): longint; override;
  78. function fileeof: boolean; override;
  79. function fileclose: boolean; override;
  80. procedure filegettime; override;
  81. private
  82. Editor: PFileEditor;
  83. S: PStream;
  84. end;
  85. const
  86. CompilerMessageWindow : PCompilerMessageWindow = nil;
  87. CompilerStatusDialog : PCompilerStatusDialog = nil;
  88. CompileStamp : longint = 0;
  89. RestartingDebugger : boolean = false;
  90. procedure DoCompile(Mode: TCompileMode);
  91. function NeedRecompile(Mode :TCompileMode; verbose : boolean): boolean;
  92. procedure ParseUserScreen;
  93. procedure RegisterFPCompile;
  94. const
  95. CompilingHiddenFile : PSourceWindow = nil;
  96. implementation
  97. uses
  98. {$ifdef Unix}
  99. {$ifdef VER1_0}
  100. Linux,
  101. {$else}
  102. Unix, BaseUnix,
  103. {$endif}
  104. {$endif}
  105. {$ifdef go32v2}
  106. dpmiexcp,
  107. {$endif}
  108. {$ifdef win32}
  109. signals,
  110. {$endif}
  111. { $ifdef HasSignal}
  112. fpcatch,
  113. { $endif HasSignal}
  114. Dos,
  115. {$ifdef fpc}
  116. Video,
  117. {$endif fpc}
  118. globals,
  119. StdDlg,App,tokens,
  120. FVConsts,
  121. CompHook, Compiler, systems, browcol,
  122. WEditor,
  123. FPString,FPRedir,FPDesk,
  124. FPUsrScr,FPHelp,
  125. {$ifndef NODEBUG}FPDebug,{$endif}
  126. FPConst,FPVars,FPUtils,
  127. FPCodCmp,FPIntf,FPSwitch;
  128. {$ifndef NOOBJREG}
  129. const
  130. RCompilerMessageListBox: TStreamRec = (
  131. ObjType: 1211;
  132. VmtLink: Ofs(TypeOf(TCompilerMessageListBox)^);
  133. Load: @TCompilerMessageListBox.Load;
  134. Store: @TCompilerMessageListBox.Store
  135. );
  136. RCompilerMessageWindow: TStreamRec = (
  137. ObjType: 1212;
  138. VmtLink: Ofs(TypeOf(TCompilerMessageWindow)^);
  139. Load: @TCompilerMessageWindow.Load;
  140. Store: @TCompilerMessageWindow.Store
  141. );
  142. {$endif}
  143. procedure ParseUserScreen;
  144. var
  145. y : longint;
  146. Text,Attr : String;
  147. DisplayCompilerWindow : boolean;
  148. cc: integer;
  149. procedure SearchBackTrace;
  150. var AText,ModuleName,st : String;
  151. row : longint;
  152. begin
  153. if pos(' 0x',Text)=1 then
  154. begin
  155. AText:=Text;
  156. Delete(Text,1,10);
  157. While pos(' ',Text)=1 do
  158. Delete(Text,1,1);
  159. if pos('of ',Text)>0 then
  160. begin
  161. ModuleName:=Copy(Text,pos('of ',Text)+3,255);
  162. While ModuleName[Length(ModuleName)]=' ' do
  163. Delete(ModuleName,Length(ModuleName),1);
  164. end
  165. else
  166. ModuleName:='';
  167. if pos('line ',Text)>0 then
  168. begin
  169. Text:=Copy(Text,Pos('line ',Text)+5,255);
  170. st:=Copy(Text,1,Pos(' ',Text)-1);
  171. Val(st,row,cc);
  172. end
  173. else
  174. row:=0;
  175. CompilerMessageWindow^.AddMessage(V_Fatal,AText
  176. ,ModuleName,row,1);
  177. DisplayCompilerWindow:=true;
  178. end;
  179. end;
  180. procedure InsertInMessages(Const TypeStr : String;_Type : longint;EnableDisplay : boolean);
  181. var p,p2,col,row : longint;
  182. St,ModuleName : string;
  183. begin
  184. p:=pos(TypeStr,Text);
  185. p2:=Pos('(',Text);
  186. if (p>0) and (p2>0) and (p2<p) then
  187. begin
  188. ModuleName:=Copy(Text,1,p2-1);
  189. st:=Copy(Text,p2+1,255);
  190. Val(Copy(st,1,pos(',',st)-1),row,cc);
  191. st:=Copy(st,Pos(',',st)+1,255);
  192. Val(Copy(st,1,pos(')',st)-1),col,cc);
  193. CompilerMessageWindow^.AddMessage(_type,Copy(Text,pos(':',Text)+1,255)
  194. ,ModuleName,row,col);
  195. If EnableDisplay then
  196. DisplayCompilerWindow:=true;
  197. end;
  198. end;
  199. begin
  200. if not assigned(UserScreen) then
  201. exit;
  202. DisplayCompilerWindow:=false;
  203. PushStatus('Parsing User Screen');
  204. CompilerMessageWindow^.Lock;
  205. for Y:=0 to UserScreen^.GetHeight do
  206. begin
  207. UserScreen^.GetLine(Y,Text,Attr);
  208. SearchBackTrace;
  209. InsertInMessages(' Fatal:',v_Fatal or v_lineinfo,true);
  210. InsertInMessages(' Error:',v_Error or v_lineinfo,true);
  211. InsertInMessages(' Warning:',v_Warning or v_lineinfo,false);
  212. InsertInMessages(' Note:',v_Note or v_lineinfo,false);
  213. InsertInMessages(' Info:',v_Info or v_lineinfo,false);
  214. InsertInMessages(' Hint:',v_Hint or v_lineinfo,false);
  215. end;
  216. if DisplayCompilerWindow then
  217. begin
  218. if not CompilerMessageWindow^.GetState(sfVisible) then
  219. CompilerMessageWindow^.Show;
  220. CompilerMessageWindow^.MakeFirst;
  221. CompilerMessageWindow^.MsgLB^.SelectFirstError;
  222. end;
  223. CompilerMessageWindow^.UnLock;
  224. PopStatus;
  225. end;
  226. {*****************************************************************************
  227. TCompilerMessage
  228. *****************************************************************************}
  229. function TCompilerMessage.GetText(MaxLen: Sw_Integer): String;
  230. var
  231. ClassS: string[20];
  232. S: string;
  233. begin
  234. case TClass and V_LevelMask of
  235. V_Fatal : ClassS:=msg_class_Fatal;
  236. V_Error : ClassS:=msg_class_Error;
  237. V_Normal : ClassS:=msg_class_Normal;
  238. V_Warning : ClassS:=msg_class_Warning;
  239. V_Note : ClassS:=msg_class_Note;
  240. V_Hint : ClassS:=msg_class_Hint;
  241. {$ifdef VERBOSETXT}
  242. V_Conditional : ClassS:=msg_class_conditional;
  243. V_Info : ClassS:=msg_class_info;
  244. V_Status : ClassS:=msg_class_status;
  245. V_Used : ClassS:=msg_class_used;
  246. V_Tried : ClassS:=msg_class_tried;
  247. V_Debug : ClassS:=msg_class_debug;
  248. else
  249. ClassS:='???';
  250. {$endif}
  251. else
  252. ClassS:='';
  253. end;
  254. if ClassS<>'' then
  255. ClassS:=RExpand(ClassS,0)+': ';
  256. if assigned(Module) and
  257. ((TClass and V_LineInfo)=V_LineInfo) then
  258. begin
  259. if Row>0 then
  260. begin
  261. if Col>0 then
  262. S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+','+IntToStr(Col)+') '+ClassS
  263. else
  264. S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+') '+ClassS;
  265. end
  266. else
  267. S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+') '+ClassS
  268. end
  269. else
  270. S:=ClassS;
  271. if assigned(Text) then
  272. S:=S+Text^;
  273. if length(S)>MaxLen then
  274. S:=copy(S,1,MaxLen-2)+'..';
  275. GetText:=S;
  276. end;
  277. {*****************************************************************************
  278. TCompilerMessageListBox
  279. *****************************************************************************}
  280. function TCompilerMessageListBox.GetPalette: PPalette;
  281. const
  282. P: string[length(CBrowserListBox)] = CBrowserListBox;
  283. begin
  284. GetPalette:=@P;
  285. end;
  286. procedure TCompilerMessageListBox.SelectFirstError;
  287. function IsError(P : PCompilerMessage) : boolean;
  288. begin
  289. IsError:=(P^.TClass and (V_Fatal or V_Error))<>0;
  290. end;
  291. var
  292. P : PCompilerMessage;
  293. begin
  294. P:=List^.FirstThat(@IsError);
  295. If Assigned(P) then
  296. Begin
  297. FocusItem(List^.IndexOf(P));
  298. DrawView;
  299. End;
  300. end;
  301. {*****************************************************************************
  302. TCompilerMessageWindow
  303. *****************************************************************************}
  304. constructor TCompilerMessageWindow.Init;
  305. var R: TRect;
  306. HSB,VSB: PScrollBar;
  307. begin
  308. Desktop^.GetExtent(R);
  309. R.A.Y:=R.B.Y-7;
  310. inherited Init(R,dialog_compilermessages,{SearchFreeWindowNo}wnNoNumber);
  311. HelpCtx:=hcCompilerMessagesWindow;
  312. AutoNumber:=true;
  313. HSB:=StandardScrollBar(sbHorizontal+sbHandleKeyboard);
  314. HSB^.GrowMode:=gfGrowLoY+gfGrowHiX+gfGrowHiY;
  315. Insert(HSB);
  316. VSB:=StandardScrollBar(sbVertical+sbHandleKeyboard);
  317. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  318. Insert(VSB);
  319. GetExtent(R);
  320. R.Grow(-1,-1);
  321. New(MsgLB, Init(R, HSB, VSB));
  322. MsgLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  323. Insert(MsgLB);
  324. CompilerMessageWindow:=@self;
  325. end;
  326. procedure TCompilerMessageWindow.AddMessage(AClass: longint;const Msg, Module: string; Line, Column: longint);
  327. begin
  328. if (AClass and V_LineInfo)<>V_LineInfo then
  329. Line:=0;
  330. MsgLB^.AddItem(New(PCompilerMessage,Init(AClass, Msg, MsgLB^.AddModuleName(Module), Line, Column)));
  331. if (@Self=CompilerMessageWindow) and ((AClass = V_fatal) or (AClass = V_Error)) then
  332. begin
  333. if not GetState(sfVisible) then
  334. Show;
  335. if Desktop^.First<>PView(CompilerMessageWindow) then
  336. MakeFirst;
  337. end;
  338. end;
  339. procedure TCompilerMessageWindow.ClearMessages;
  340. begin
  341. MsgLB^.Clear;
  342. ReDraw;
  343. end;
  344. {procedure TCompilerMessageWindow.Updateinfo;
  345. begin
  346. if CompileShowed then
  347. begin
  348. InfoST^.SetText(
  349. RExpand(' Main file : '#1#$7f+Copy(SmartPath(MainFile),1,39),40)+#2+
  350. 'Total lines : '#1#$7e+IntToStr(Status.CompiledLines)+#2#13+
  351. RExpand(' Target : '#1#$7f+KillTilde(TargetSwitches^.ItemName(TargetSwitches^.GetCurrSel)),40)+#2+
  352. 'Total errors : '#1#$7e+IntToStr(Status.ErrorCount)
  353. );
  354. if status.currentline>0 then
  355. CurrST^.SetText(' Status: '#1#$7e+status.currentsource+'('+IntToStr(status.currentline)+')'#2)
  356. else
  357. CurrST^.SetText(' Status: '#1#$7e+status.currentsource+#2);
  358. end;
  359. ReDraw;
  360. end;}
  361. procedure TCompilerMessageWindow.HandleEvent(var Event: TEvent);
  362. begin
  363. case Event.What of
  364. evBroadcast :
  365. case Event.Command of
  366. cmListFocusChanged :
  367. if Event.InfoPtr=MsgLB then
  368. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  369. end;
  370. end;
  371. inherited HandleEvent(Event);
  372. end;
  373. procedure TCompilerMessageWindow.SizeLimits(var Min, Max: TPoint);
  374. begin
  375. inherited SizeLimits(Min,Max);
  376. Min.X:=20;
  377. Min.Y:=4;
  378. end;
  379. procedure TCompilerMessageWindow.Close;
  380. begin
  381. Hide;
  382. end;
  383. function TCompilerMessageWindow.GetPalette: PPalette;
  384. const
  385. S : string[length(CBrowserWindow)] = CBrowserWindow;
  386. begin
  387. GetPalette:=@S;
  388. end;
  389. constructor TCompilerMessageWindow.Load(var S: TStream);
  390. begin
  391. inherited Load(S);
  392. GetSubViewPtr(S,MsgLB);
  393. end;
  394. procedure TCompilerMessageWindow.Store(var S: TStream);
  395. begin
  396. if MsgLB^.List=nil then
  397. MsgLB^.NewList(New(PCollection, Init(100,100)));
  398. inherited Store(S);
  399. PutSubViewPtr(S,MsgLB);
  400. end;
  401. procedure TCompilerMessageWindow.UpdateCommands;
  402. var Active: boolean;
  403. begin
  404. Active:=GetState(sfActive);
  405. SetCmdState(CompileCmds,Active);
  406. Message(Application,evBroadcast,cmCommandSetChanged,nil);
  407. end;
  408. procedure TCompilerMessageWindow.SetState(AState: Word; Enable: Boolean);
  409. var OldState: word;
  410. begin
  411. OldState:=State;
  412. inherited SetState(AState,Enable);
  413. if ((AState and sfActive)<>0) and (((OldState xor State) and sfActive)<>0) then
  414. UpdateCommands;
  415. end;
  416. destructor TCompilerMessageWindow.Done;
  417. begin
  418. CompilerMessageWindow:=nil;
  419. inherited Done;
  420. end;
  421. {****************************************************************************
  422. CompilerStatusDialog
  423. ****************************************************************************}
  424. constructor TCompilerStatusDialog.Init;
  425. var R: TRect;
  426. begin
  427. R.Assign(0,0,56,11);
  428. ClearFormatParams; AddFormatParamStr(KillTilde(SwitchesModeName[SwitchesMode]));
  429. inherited Init(R, FormatStrF(dialog_compilingwithmode, FormatParams));
  430. GetExtent(R); R.B.Y:=11;
  431. R.Grow(-3,-2);
  432. New(ST, Init(R, ''));
  433. Insert(ST);
  434. GetExtent(R); R.B.Y:=11;
  435. R.Grow(-1,-1); R.A.Y:=R.B.Y-1;
  436. New(KeyST, Init(R, '', Blue*16+White+longint($80+Blue*16+White)*256,true));
  437. Insert(KeyST);
  438. { Reset Status infos see bug 1585 }
  439. Fillchar(Status,SizeOf(Status),#0);
  440. end;
  441. destructor TCompilerStatusDialog.Done;
  442. begin
  443. if @Self=CompilerStatusDialog then
  444. CompilerStatusDialog:=nil;
  445. Inherited Done;
  446. end;
  447. procedure TCompilerStatusDialog.Update;
  448. var
  449. StatusS,KeyS: string;
  450. {$ifdef HASGETHEAPSTATUS}
  451. hstatus : TFPCHeapStatus;
  452. {$endif HASGETHEAPSTATUS}
  453. const
  454. MaxFileNameSize = 46;
  455. begin
  456. case CompilationPhase of
  457. cpCompiling :
  458. begin
  459. ClearFormatParams;
  460. if Status.Compiling_current then
  461. begin
  462. AddFormatParamStr(ShrinkPath(SmartPath(Status.Currentsourcepath+Status.CurrentSource),
  463. MaxFileNameSize - Length(msg_compilingfile)));
  464. StatusS:=FormatStrF(msg_compilingfile,FormatParams);
  465. end
  466. else
  467. begin
  468. if Status.CurrentSource='' then
  469. StatusS:=''
  470. else
  471. begin
  472. StatusS:=ShrinkPath(SmartPath(DirAndNameOf(Status.Currentsourcepath+Status.CurrentSource)),
  473. MaxFileNameSize-Length(msg_loadingunit));
  474. AddFormatParamStr(StatusS);
  475. StatusS:=FormatStrF(msg_loadingunit,FormatParams);
  476. end;
  477. end;
  478. KeyS:=msg_hint_pressesctocancel;
  479. end;
  480. cpLinking :
  481. begin
  482. ClearFormatParams;
  483. AddFormatParamStr(ShrinkPath(ExeFile,
  484. MaxFileNameSize-Length(msg_linkingfile)));
  485. StatusS:=FormatStrF(msg_linkingfile,FormatParams);
  486. KeyS:=msg_hint_pleasewait;
  487. end;
  488. cpDone :
  489. begin
  490. StatusS:=msg_compiledone;
  491. KeyS:=msg_hint_compilesuccessfulpressenter;
  492. end;
  493. cpFailed :
  494. begin
  495. StatusS:=msg_failedtocompile;
  496. KeyS:=msg_hint_compilefailed;
  497. end;
  498. cpAborted :
  499. begin
  500. StatusS:=msg_compilationaborted;
  501. KeyS:=msg_hint_compileaborted;
  502. end;
  503. end;
  504. ClearFormatParams;
  505. AddFormatParamStr(ShrinkPath(SmartPath(MainFile),
  506. MaxFileNameSize-Length('Main file: %s')));
  507. AddFormatParamStr(StatusS);
  508. AddFormatParamStr(KillTilde(TargetSwitches^.ItemName(TargetSwitches^.GetCurrSel)));
  509. AddFormatParamInt(Status.CurrentLine);
  510. AddFormatParamInt(Status.CompiledLines);
  511. {$ifdef HASGETHEAPSTATUS}
  512. hstatus:=GetFPCHeapStatus;
  513. AddFormatParamInt(hstatus.CurrHeapUsed div 1024);
  514. AddFormatParamInt(hstatus.CurrHeapSize div 1024);
  515. {$else}
  516. AddFormatParamInt((Heapsize-MemAvail) div 1024);
  517. AddFormatParamInt(Heapsize div 1024);
  518. {$endif}
  519. AddFormatParamInt(Status.ErrorCount);
  520. ST^.SetText(
  521. FormatStrF(
  522. 'Main file: %s'#13+
  523. '%s'+#13#13+
  524. 'Target: %s'#13+
  525. 'Line number: %6d '+'Total lines: %6d'+#13+
  526. 'Used memory: %6dK '+'Allocated memory: %6dK'#13+
  527. 'Total errors: %5d',
  528. FormatParams)
  529. );
  530. KeyST^.SetText(^C+KeyS);
  531. end;
  532. {****************************************************************************
  533. Compiler Hooks
  534. ****************************************************************************}
  535. function getrealtime : real;
  536. var
  537. {$IFDEF USE_SYSUTILS}
  538. h,m,s,s1000 : word;
  539. {$ELSE USE_SYSUTILS}
  540. h,m,s,s100 : word;
  541. {$ENDIF USE_SYSUTILS}
  542. begin
  543. {$IFDEF USE_SYSUTILS}
  544. DecodeTime(Time,h,m,s,s1000);
  545. getrealtime:=h*3600.0+m*60.0+s+s1000/1000.0;
  546. {$ELSE USE_SYSUTILS}
  547. gettime(h,m,s,s100);
  548. getrealtime:=h*3600.0+m*60.0+s+s100/100.0;
  549. {$ENDIF USE_SYSUTILS}
  550. end;
  551. const
  552. lasttime : real = 0;
  553. function CompilerStatus: boolean; {$ifndef FPC}far;{$endif}
  554. var
  555. event : tevent;
  556. begin
  557. GetKeyEvent(Event);
  558. if (Event.What=evKeyDown) and (Event.KeyCode=kbEsc) then
  559. begin
  560. CompilationPhase:=cpAborted;
  561. { update info messages }
  562. if assigned(CompilerStatusDialog) then
  563. begin
  564. {$ifdef redircompiler}
  565. RedirDisableAll;
  566. {$endif}
  567. CompilerStatusDialog^.Update;
  568. {$ifdef redircompiler}
  569. RedirEnableAll;
  570. {$endif}
  571. end;
  572. CompilerStatus:=true;
  573. exit;
  574. end;
  575. { only display line info every 100 lines, ofcourse all other messages
  576. will be displayed directly }
  577. if (getrealtime-lasttime>=CompilerStatusUpdateDelay) or (status.compiledlines=1) then
  578. begin
  579. lasttime:=getrealtime;
  580. { update info messages }
  581. {$ifdef redircompiler}
  582. RedirDisableAll;
  583. {$endif}
  584. if assigned(CompilerStatusDialog) then
  585. CompilerStatusDialog^.Update;
  586. {$ifdef redircompiler}
  587. RedirEnableAll;
  588. {$endif}
  589. { update memory usage }
  590. { HeapView^.Update; }
  591. end;
  592. CompilerStatus:=false;
  593. end;
  594. Function CompilerGetNamedFileTime(const filename : string) : Longint; {$ifndef FPC}far;{$endif}
  595. var t: longint;
  596. W: PSourceWindow;
  597. begin
  598. W:=EditorWindowFile(FExpand(filename));
  599. if Assigned(W) and (W^.Editor^.GetModified) then
  600. t:=Now
  601. else
  602. t:=def_getnamedfiletime(filename);
  603. CompilerGetNamedFileTime:=t;
  604. end;
  605. function CompilerOpenInputFile(const filename: string): tinputfile; {$ifndef FPC}far;{$endif}
  606. var f: tinputfile;
  607. W: PSourceWindow;
  608. begin
  609. if assigned(CompilingHiddenFile) and
  610. (NameandExtof(filename)=CompilingHiddenFile^.Editor^.Filename) then
  611. W:=CompilingHiddenFile
  612. else
  613. W:=EditorWindowFile(FExpand(filename));
  614. if Assigned(W) and (W^.Editor^.GetModified) then
  615. f:=TFPInputFile.Create(W^.Editor)
  616. else
  617. f:=def_openinputfile(filename);
  618. if assigned(W) then
  619. W^.Editor^.CompileStamp:=CompileStamp;
  620. CompilerOpenInputFile:=f;
  621. end;
  622. function CompilerComment(Level:Longint; const s:string):boolean; {$ifndef FPC}far;{$endif}
  623. begin
  624. CompilerComment:=false;
  625. if (status.verbosity and Level)<>0 then
  626. begin
  627. {$ifdef redircompiler}
  628. RedirDisableAll;
  629. {$endif}
  630. if not CompilerMessageWindow^.GetState(sfVisible) then
  631. CompilerMessageWindow^.Show;
  632. if Desktop^.First<>PView(CompilerMessageWindow) then
  633. CompilerMessageWindow^.MakeFirst;
  634. CompilerMessageWindow^.AddMessage(Level,S,status.currentsourcepath+status.currentsource,
  635. status.currentline,status.currentcolumn);
  636. { update info messages }
  637. if assigned(CompilerStatusDialog) then
  638. CompilerStatusDialog^.Update;
  639. {$ifdef redircompiler}
  640. RedirEnableAll;
  641. {$endif}
  642. { update memory usage }
  643. { HeapView^.Update; }
  644. end;
  645. end;
  646. {****************************************************************************
  647. DoCompile
  648. ****************************************************************************}
  649. { This function must return '' if
  650. "Options|Directories|Exe and PPU directory" is empty }
  651. function GetExePath: string;
  652. var Path: string;
  653. I: Sw_integer;
  654. begin
  655. Path:='';
  656. if DirectorySwitches<>nil then
  657. with DirectorySwitches^ do
  658. for I:=0 to ItemCount-1 do
  659. begin
  660. if ItemParam(I)='-FE' then
  661. begin
  662. Path:=GetStringItem(I);
  663. Break;
  664. end;
  665. end;
  666. if Path<>'' then
  667. GetExePath:=CompleteDir(FExpand(Path))
  668. else
  669. GetExePath:='';
  670. end;
  671. function GetMainFile(Mode: TCompileMode): string;
  672. var FileName: string;
  673. P : PSourceWindow;
  674. begin
  675. if assigned(CompilingHiddenFile) then
  676. P:=CompilingHiddenFile
  677. else
  678. P:=Message(Desktop,evBroadcast,cmSearchWindow,nil);
  679. if (PrimaryFileMain='') and (P=nil) then
  680. FileName:='' { nothing to compile }
  681. else
  682. begin
  683. if (PrimaryFileMain<>'') and (Mode<>cCompile) then
  684. FileName:=PrimaryFileMain
  685. else if assigned(P) then
  686. begin
  687. FileName:=P^.Editor^.FileName;
  688. if FileName='' then
  689. begin
  690. P^.Editor^.SaveAsk(true);
  691. FileName:=P^.Editor^.FileName;
  692. end;
  693. end
  694. else
  695. FileName:='';
  696. end;
  697. If (FileName<>'') then
  698. FileName:=FixFileName(FExpand(FileName));
  699. GetMainFile:=FileName;
  700. end;
  701. procedure ResetErrorMessages;
  702. procedure ResetErrorLine(P: PView); {$ifndef FPC}far;{$endif}
  703. begin
  704. if assigned(P) and
  705. (TypeOf(P^)=TypeOf(TSourceWindow)) then
  706. PSourceWindow(P)^.Editor^.SetErrorMessage('');
  707. end;
  708. begin
  709. Desktop^.ForEach(@ResetErrorLine);
  710. end;
  711. procedure DoCompile(Mode: TCompileMode);
  712. function IsExitEvent(E: TEvent): boolean;
  713. begin
  714. { following suggestion by Harsha Senanayake }
  715. IsExitEvent:=(E.What=evKeyDown);
  716. end;
  717. function GetTargetExeExt : string;
  718. begin
  719. GetTargetExeExt:=target_info.exeext;
  720. end;
  721. var
  722. s,FileName: string;
  723. ErrFile : Text;
  724. MustRestartDebugger,
  725. Error,LinkErrorCount : longint;
  726. E : TEvent;
  727. DummyView: PView;
  728. PPasFile : string[64];
  729. begin
  730. AskRecompileIfModifiedFlag:=true;
  731. { Get FileName }
  732. FileName:=GetMainFile(Mode);
  733. if FileName='' then
  734. begin
  735. ErrorBox(msg_nothingtocompile,nil);
  736. Exit;
  737. end else
  738. { THis is not longer necessary as unsaved files are loaded from a memorystream,
  739. and with the file as primaryfile set it is already incompatible with itself
  740. if FileName='*' then
  741. begin
  742. ErrorBox(msg_cantcompileunsavedfile,nil);
  743. Exit;
  744. end; }
  745. PushStatus('Beginning compilation...');
  746. { Show Compiler Messages Window }
  747. { if not CompilerMessageWindow^.GetState(sfVisible) then
  748. CompilerMessageWindow^.Show;
  749. CompilerMessageWindow^.MakeFirst;}
  750. CompilerMessageWindow^.ClearMessages;
  751. { Tell why we compile }
  752. NeedRecompile(Mode,true);
  753. MainFile:=FileName;
  754. SetStatus('Writing switches to file...');
  755. WriteSwitches(SwitchesPath);
  756. { leaving open browsers leads to crashes !! (PM) }
  757. SetStatus('Preparing symbol info...');
  758. CloseAllBrowsers;
  759. if ((DesktopFileFlags and dfSymbolInformation)<>0) then
  760. WriteSymbolsFile(BrowserName);
  761. { MainFile:=FixFileName(FExpand(FileName));}
  762. SetStatus('Preparing to compile...'+NameOf(MainFile));
  763. { Reset }
  764. CtrlBreakHit:=false;
  765. { Create Compiler Status Dialog }
  766. CompilationPhase:=cpCompiling;
  767. if not assigned(CompilingHiddenFile) then
  768. begin
  769. New(CompilerStatusDialog, Init);
  770. CompilerStatusDialog^.SetState(sfModal,true);
  771. { disable window closing }
  772. CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags and not wfclose;
  773. Application^.Insert(CompilerStatusDialog);
  774. CompilerStatusDialog^.Update;
  775. end;
  776. { Restore dir that could be changed during debugging }
  777. {$I-}
  778. ChDir(StartUpDir);
  779. {$I+}
  780. EatIO;
  781. { hook compiler output }
  782. do_status:=@CompilerStatus;
  783. do_comment:=@CompilerComment;
  784. do_openinputfile:=@CompilerOpenInputFile;
  785. do_getnamedfiletime:=@CompilerGetNamedFileTime;
  786. do_initsymbolinfo:=@InitBrowserCol;
  787. do_donesymbolinfo:=@DoneBrowserCol;
  788. do_extractsymbolinfo:=@CreateBrowserCol;
  789. { Compile ! }
  790. {$ifdef redircompiler}
  791. ChangeRedirOut(FPOutFileName,false);
  792. ChangeRedirError(FPErrFileName,false);
  793. {$endif}
  794. { insert "" around name so that spaces are allowed }
  795. { only supported in compiler after 2000/01/14 PM }
  796. if pos(' ',FileName)>0 then
  797. FileName:='"'+FileName+'"';
  798. if mode=cBuild then
  799. FileName:='-B '+FileName;
  800. { tokens are created and distroed by compiler.compile !! PM }
  801. DoneTokens;
  802. PPasFile:='ppas'+source_info.scriptext;
  803. WUtils.DeleteFile(GetExePath+PpasFile);
  804. SetStatus('Compiling...');
  805. inc(CompileStamp);
  806. ResetErrorMessages;
  807. {$ifndef NODEBUG}
  808. MustRestartDebugger:=false;
  809. if assigned(Debugger) then
  810. if Debugger^.HasExe then
  811. begin
  812. Debugger^.Reset;
  813. MustRestartDebugger:=true;
  814. end;
  815. {$endif NODEBUG}
  816. try
  817. FpIntF.Compile(FileName,SwitchesPath);
  818. except
  819. on ECompilerAbort do
  820. CompilerMessageWindow^.AddMessage(V_error,'Error during compilation','',0,0);
  821. on E:Exception do
  822. CompilerMessageWindow^.AddMessage(V_error,E.Message+' during compilation','',0,0);
  823. end;
  824. SetStatus('Finished compiling...');
  825. { Retrieve created exefile }
  826. If GetEXEPath<>'' then
  827. EXEFile:=FixFileName(GetEXEPath+NameOf(MainFile)+GetTargetExeExt)
  828. else
  829. EXEFile:=DirOf(MainFile)+NameOf(MainFile)+GetTargetExeExt;
  830. DefaultReplacements(ExeFile);
  831. { tokens are created and distroyed by compiler.compile !! PM }
  832. InitTokens;
  833. if LinkAfter and
  834. ExistsFile(GetExePath+PpasFile) and
  835. (CompilationPhase<>cpAborted) and
  836. (status.errorCount=0) then
  837. begin
  838. CompilationPhase:=cpLinking;
  839. if assigned(CompilerStatusDialog) then
  840. CompilerStatusDialog^.Update;
  841. SetStatus('Assembling and/or linking...');
  842. {$ifndef redircompiler}
  843. { At least here we want to catch output
  844. of batch file PM }
  845. ChangeRedirOut(FPOutFileName,false);
  846. ChangeRedirError(FPErrFileName,false);
  847. {$endif}
  848. {$ifdef Unix}
  849. {$ifdef ver1_0}
  850. Shell(GetExePath+PpasFile);
  851. Error:=LinuxError;
  852. {$else}
  853. error:=0;
  854. If Shell(GetExePath+PpasFile)=-1 Then
  855. Error:=fpgeterrno;
  856. {$endif}
  857. {$else}
  858. DosExecute(GetEnv('COMSPEC'),'/C '+GetExePath+PpasFile);
  859. Error:=DosError;
  860. {$endif}
  861. SetStatus('Finished linking...');
  862. RestoreRedirOut;
  863. RestoreRedirError;
  864. if Error<>0 then
  865. Inc(status.errorCount);
  866. if Status.IsExe and not Status.IsLibrary and not ExistsFile(EXEFile) then
  867. begin
  868. Inc(status.errorCount);
  869. ClearFormatParams; AddFormatParamStr(ExeFile);
  870. CompilerMessageWindow^.AddMessage(V_error,FormatStrF(msg_couldnotcreatefile,FormatParams),'',0,0);
  871. {$I-}
  872. Assign(ErrFile,FPErrFileName);
  873. Reset(ErrFile);
  874. if EatIO<>0 then
  875. ErrorBox(FormatStrStr(msg_cantopenfile,FPErrFileName),nil)
  876. else
  877. begin
  878. LinkErrorCount:=0;
  879. While not eof(ErrFile) and (LinkErrorCount<25) do
  880. begin
  881. readln(ErrFile,s);
  882. CompilerMessageWindow^.AddMessage(V_error,s,'',0,0);
  883. inc(LinkErrorCount);
  884. end;
  885. if not eof(ErrFile) then
  886. begin
  887. ClearFormatParams; AddFormatParamStr(FPErrFileName);
  888. CompilerMessageWindow^.AddMessage(V_error,
  889. FormatStrF(msg_therearemoreerrorsinfile,FormatParams),'',0,0);
  890. end;
  891. Close(ErrFile);
  892. end;
  893. EatIO;
  894. {$I+}
  895. end
  896. else if error=0 then
  897. WUtils.DeleteFile(GetExePath+PpasFile);
  898. end;
  899. {$ifdef redircompiler}
  900. RestoreRedirOut;
  901. RestoreRedirError;
  902. {$endif}
  903. PopStatus;
  904. { Set end status }
  905. if not (CompilationPhase in [cpAborted,cpFailed]) then
  906. if (status.errorCount=0) then
  907. begin
  908. CompilationPhase:=cpDone;
  909. LastCompileTime := cardinal(Now);
  910. end
  911. else
  912. CompilationPhase:=cpFailed;
  913. { Show end status }
  914. { reenable window closing }
  915. if assigned(CompilerStatusDialog) then
  916. begin
  917. CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags or wfclose;
  918. CompilerStatusDialog^.Update;
  919. CompilerStatusDialog^.ReDraw;
  920. CompilerStatusDialog^.SetState(sfModal,false);
  921. if ((CompilationPhase in [cpAborted,cpDone,cpFailed]) or (ShowStatusOnError))
  922. and ((Mode<>cRun) or (CompilationPhase<>cpDone)) then
  923. repeat
  924. CompilerStatusDialog^.GetEvent(E);
  925. if IsExitEvent(E)=false then
  926. CompilerStatusDialog^.HandleEvent(E);
  927. until IsExitEvent(E) or not assigned(CompilerStatusDialog);
  928. {if IsExitEvent(E) then
  929. Application^.PutEvent(E);}
  930. if assigned(CompilerStatusDialog) then
  931. begin
  932. Application^.Delete(CompilerStatusDialog);
  933. Dispose(CompilerStatusDialog, Done);
  934. end;
  935. end;
  936. CompilerStatusDialog:=nil;
  937. { end compilation returns true if the messagewindow should be removed }
  938. if CompilationPhase=cpDone then
  939. begin
  940. CompilerMessageWindow^.Hide;
  941. { This is the last compiled main file }
  942. PrevMainFile:=MainFile;
  943. MainHasDebugInfo:=DebugInfoSwitches^.GetCurrSelParam<>'-';
  944. end;
  945. { Update the app }
  946. Message(Application,evCommand,cmUpdate,nil);
  947. DummyView:=Desktop^.First;
  948. while (DummyView<>nil) and (DummyView^.GetState(sfVisible)=false) do
  949. begin
  950. DummyView:=DummyView^.NextView;
  951. end;
  952. with DummyView^ do
  953. if GetState(sfVisible) then
  954. begin
  955. SetState(sfSelected,false);
  956. SetState(sfSelected,true);
  957. end;
  958. if Assigned(CompilerMessageWindow) then
  959. with CompilerMessageWindow^ do
  960. begin
  961. if GetState(sfVisible) then
  962. begin
  963. SetState(sfSelected,false);
  964. SetState(sfSelected,true);
  965. end;
  966. if (status.errorCount>0) then
  967. MsgLB^.SelectFirstError;
  968. end;
  969. { ^^^ we need this trick to reactivate the desktop }
  970. EditorModified:=false;
  971. {$ifndef NODEBUG}
  972. if MustRestartDebugger then
  973. InitDebugger;
  974. {$endif NODEBUG}
  975. { In case we have something that the compiler touched }
  976. AskToReloadAllModifiedFiles;
  977. { Try to read Browser info in again if compilation failure !! }
  978. if Not Assigned(Modules) and (CompilationPhase<>cpDone) and
  979. ((DesktopFileFlags and dfSymbolInformation)<>0) then
  980. ReadSymbolsFile(BrowserName);
  981. if UseAllUnitsInCodeComplete and not assigned(CompilingHiddenFile) then
  982. AddAvailableUnitsToCodeComplete(false);
  983. end;
  984. function NeedRecompile(Mode :TCompileMode; verbose : boolean): boolean;
  985. var Need: boolean;
  986. I: sw_integer;
  987. SF: PSourceFile;
  988. SourceTime,PPUTime,ObjTime: longint;
  989. W: PSourceWindow;
  990. begin
  991. if Assigned(SourceFiles)=false then
  992. Need:={(EditorModified=true)}true
  993. else
  994. begin
  995. Need:=(PrevMainFile<>GetMainFile(Mode)) and (PrevMainFile<>'');
  996. if Need then
  997. begin
  998. if verbose then
  999. begin
  1000. ClearFormatParams; AddFormatParamStr(GetMainFile(Mode));
  1001. CompilerMessageWindow^.AddMessage(V_info,
  1002. FormatStrF(msg_firstcompilationof,FormatParams),
  1003. '',0,0);
  1004. end;
  1005. end
  1006. else
  1007. for I:=0 to SourceFiles^.Count-1 do
  1008. begin
  1009. SF:=SourceFiles^.At(I);
  1010. SourceTime:=wutils.GetFileTime(SF^.GetSourceFileName);
  1011. PPUTime:=wutils.GetFileTime(SF^.GetPPUFileName);
  1012. ObjTime:=wutils.GetFileTime(SF^.GetObjFileName);
  1013. { writeln('S: ',SF^.GetSourceFileName,' - ',SourceTime);
  1014. writeln('P: ',SF^.GetPPUFileName,' - ',PPUTime);
  1015. writeln('O: ',SF^.GetObjFileName,' - ',ObjTime);
  1016. writeln('------');}
  1017. { some units don't generate object files }
  1018. W:=EditorWindowFile(SF^.GetSourceFileName);
  1019. if (SourceTime<>-1) then
  1020. if ((SourceTime>PPUTime) or
  1021. ((SourceTime>ObjTime) and
  1022. (ObjTime<>-1))) or
  1023. (assigned(W) and (W^.Editor^.CompileStamp<0)) then
  1024. begin
  1025. Need:=true;
  1026. if verbose then
  1027. begin
  1028. ClearFormatParams; AddFormatParamStr(SF^.GetSourceFileName);
  1029. CompilerMessageWindow^.AddMessage(V_info,
  1030. FormatStrF(msg_recompilingbecauseof,FormatParams),
  1031. SF^.GetSourceFileName,1,1);
  1032. end;
  1033. Break;
  1034. end;
  1035. end;
  1036. { writeln('Need?', Need); system.readln;}
  1037. end;
  1038. NeedRecompile:=Need;
  1039. end;
  1040. constructor TFPInputFile.Create(AEditor: PFileEditor);
  1041. begin
  1042. if not Assigned(AEditor) then Fail;
  1043. if inherited Create(AEditor^.FileName)=nil then
  1044. Fail;
  1045. Editor:=AEditor;
  1046. end;
  1047. function TFPInputFile.fileopen(const filename: string): boolean;
  1048. var OK: boolean;
  1049. begin
  1050. S:=New(PMemoryStream, Init(0,0));
  1051. OK:=Assigned(S) and (S^.Status=stOK);
  1052. if OK then OK:=Editor^.SaveToStream(S);
  1053. if OK then
  1054. S^.Seek(0)
  1055. else
  1056. begin
  1057. if Assigned(S) then Dispose(S, Done);
  1058. S:=nil;
  1059. end;
  1060. fileopen:=OK;
  1061. end;
  1062. function TFPInputFile.fileseek(pos: longint): boolean;
  1063. var OK: boolean;
  1064. begin
  1065. OK:=assigned(S);
  1066. if OK then
  1067. begin
  1068. S^.Reset;
  1069. S^.Seek(pos);
  1070. OK:=(S^.Status=stOK);
  1071. end;
  1072. fileseek:=OK;
  1073. end;
  1074. function TFPInputFile.fileread(var databuf; maxsize: longint): longint;
  1075. var
  1076. size: longint;
  1077. begin
  1078. if not assigned(S) then size:=0 else
  1079. begin
  1080. size:=min(maxsize,(S^.GetSize-S^.GetPos));
  1081. S^.Read(databuf,size);
  1082. if S^.Status<>stOK then size:=0;
  1083. end;
  1084. fileread:=size;
  1085. end;
  1086. function TFPInputFile.fileeof: boolean;
  1087. var EOF: boolean;
  1088. begin
  1089. EOF:=not assigned(S);
  1090. if not EOF then
  1091. EOF:=(S^.Status<>stOK) or (S^.GetPos=S^.GetSize);
  1092. fileeof:=EOF;
  1093. end;
  1094. function TFPInputFile.fileclose: boolean;
  1095. var OK: boolean;
  1096. begin
  1097. OK:=assigned(S);
  1098. if OK then
  1099. begin
  1100. S^.Reset;
  1101. Dispose(S, Done);
  1102. S:=nil;
  1103. OK:=true;
  1104. end;
  1105. fileclose:=OK;
  1106. end;
  1107. procedure tfpinputfile.filegettime;
  1108. var
  1109. dt : datetime;
  1110. hsec,wday : word;
  1111. begin
  1112. { current time }
  1113. dos.getdate(dt.year,dt.month,dt.day,wday);
  1114. dos.gettime(dt.hour,dt.min,dt.sec,hsec);
  1115. packtime(dt,filetime);
  1116. end;
  1117. procedure RegisterFPCompile;
  1118. begin
  1119. {$ifndef NOOBJREG}
  1120. RegisterType(RCompilerMessageListBox);
  1121. RegisterType(RCompilerMessageWindow);
  1122. {$endif}
  1123. end;
  1124. end.
  1125. {
  1126. $Log$
  1127. Revision 1.40 2005-04-24 21:03:16 peter
  1128. * always use exceptions to stop the compiler
  1129. - remove stop, do_stop
  1130. Revision 1.39 2005/04/02 23:56:54 hajny
  1131. * fix for targets missing exception handler implementation
  1132. Revision 1.38 2005/03/06 13:48:59 florian
  1133. + Units & Exe dir may now contain $fpc... valus
  1134. * version to 1.0.4 increased
  1135. Revision 1.37 2005/02/28 15:38:38 marco
  1136. * getFPCheapstatus (no, FPC HEAP, not FP CHEAP!)
  1137. Revision 1.36 2005/02/14 17:13:18 peter
  1138. * truncate log
  1139. Revision 1.35 2005/02/10 20:57:02 peter
  1140. * implement tinputfile.getfiletime
  1141. Revision 1.34 2005/01/08 12:05:13 florian
  1142. * user screen parsing fixed
  1143. }