fpcompil.pas 34 KB

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