fpcompil.pas 34 KB

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