2 This file is part of the Free Pascal Integrated Development Environment
3 Copyright (c) 1998 by Berczi Gabor
5 Compiler call routines for the IDE
7 See the file COPYING.FPC, included in this distribution,
8 for details about the copyright.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 **********************************************************************}
21 {$define resourcestring := const}
26 { don't redir under linux, because all stdout (also from the ide!) will
27 then be redired (PFV) }
28 { this should work now correctly because
29 RedirDisableAll and RedirEnableAll function are added in fpredir (PM) }
36 { We need to include the exceptions from SysUtils, but the types from
37 Objects need to be used. Keep the order SysUtils,Objects }
41 Drivers,Views,Dialogs,
47 TCompileMode = (cBuild,cMake,cCompile,cRun);
50 PCompilerMessage = ^TCompilerMessage;
51 TCompilerMessage = object(TMessageItem)
52 function GetText(MaxLen: Sw_Integer): String; virtual;
55 PCompilerMessageListBox = ^TCompilerMessageListBox;
56 TCompilerMessageListBox = object(TMessageListBox)
57 function GetPalette: PPalette; virtual;
58 procedure SelectFirstError;
61 PCompilerMessageWindow = ^TCompilerMessageWindow;
62 TCompilerMessageWindow = object(TFPWindow)
64 procedure HandleEvent(var Event: TEvent); virtual;
65 function GetPalette: PPalette; virtual;
66 procedure Close;virtual;
67 destructor Done; virtual;
68 procedure SizeLimits(var Min, Max: TPoint); virtual;
69 procedure AddMessage(AClass: longint;const Msg, Module: string; Line, Column: longint);
70 procedure ClearMessages;
71 constructor Load(var S: TStream);
72 procedure Store(var S: TStream);
73 procedure SetState(AState: Word; Enable: Boolean); virtual;
74 procedure UpdateCommands; virtual;
76 {CompileShowed : boolean;}
77 {Mode : TCompileMode;}
78 MsgLB : PCompilerMessageListBox;
80 InfoST : PColorStaticText;}
83 PCompilerStatusDialog = ^TCompilerStatusDialog;
84 TCompilerStatusDialog = object(TCenterDialog)
85 ST : PAdvancedStaticText;
86 KeyST : PColorStaticText;
89 destructor Done;virtual;
91 procedure SetStartTime(r : real);
94 TFPInputFile = class(tinputfile)
95 constructor Create(AEditor: PFileEditor);
97 function fileopen(const filename: ansistring): boolean; override;
98 function fileseek(pos: longint): boolean; override;
99 function fileread(var databuf; maxsize: longint): longint; override;
100 function fileeof: boolean; override;
101 function fileclose: boolean; override;
102 procedure filegettime; override;
109 CompilerMessageWindow : PCompilerMessageWindow = nil;
110 CompilerStatusDialog : PCompilerStatusDialog = nil;
111 CompileStamp : longint = 0;
112 RestartingDebugger : boolean = false;
114 procedure DoCompile(Mode: TCompileMode);
115 function NeedRecompile(Mode :TCompileMode; verbose : boolean): boolean;
116 procedure ParseUserScreen;
118 procedure RegisterFPCompile;
121 CompilingHiddenFile : PSourceWindow = nil;
145 CompHook, Compiler, systems, browcol,
149 {$ifndef NODEBUG}FPDebug,{$endif}
150 FPConst,FPVars,FPUtils,
151 FPCodCmp,FPIntf,FPSwitch;
155 RCompilerMessageListBox: TStreamRec = (
157 VmtLink: Ofs(TypeOf(TCompilerMessageListBox)^);
158 Load: @TCompilerMessageListBox.Load;
159 Store: @TCompilerMessageListBox.Store
161 RCompilerMessageWindow: TStreamRec = (
163 VmtLink: Ofs(TypeOf(TCompilerMessageWindow)^);
164 Load: @TCompilerMessageWindow.Load;
165 Store: @TCompilerMessageWindow.Store
168 {$ifdef useresstrings}
173 dialog_compilermessages = 'Compiler Messages';
174 dialog_compilingwithmode = 'Compiling (%s mode)';
176 { Compiler message classes }
177 msg_class_normal = '';
178 msg_class_fatal = 'Fatal';
179 msg_class_error = 'Error';
180 msg_class_warning = 'Warning';
181 msg_class_note = 'Note';
182 msg_class_hint = 'Hint';
183 msg_class_macro = 'Macro';
184 msg_class_procedure= 'Procedure';
185 msg_class_conditional = 'Conditional';
186 msg_class_info = 'Info';
187 msg_class_status = 'Status';
188 msg_class_used = 'Used';
189 msg_class_tried = 'Tried';
190 msg_class_debug = 'Debug';
192 { Compile status dialog texts }
193 msg_compilingfile = 'Compiling %s';
194 msg_loadingunit = 'Loading %s unit';
195 msg_linkingfile = 'Linking %s';
196 msg_compiledone = 'Done.';
197 msg_failedtocompile = 'Failed to compile...';
198 msg_compilationaborted = 'Compilation aborted...';
200 msg_nothingtocompile = 'Oooops, nothing to compile.';
201 msg_cantcompileunsavedfile = 'Can''t compile unsaved file.';
203 msg_couldnotcreatefile = 'could not create %s';
204 msg_therearemoreerrorsinfile = 'There are more errors in file %s';
205 msg_firstcompilationof = 'First compilation of %s';
206 msg_recompilingbecauseof = 'Recompiling because of %s';
208 msg_errorinexternalcompilation = 'Error in external compilation';
209 msg_iostatusis = 'IOStatus = %d';
210 msg_executeresultis = 'ExecuteResult = %d';
212 { Status hints during compilation }
213 msg_hint_pressesctocancel = 'Press ESC to cancel';
214 msg_hint_compilesuccessfulpressenter = 'Compile successful: ~Press any key~';
215 msg_hint_compilefailed = 'Compile failed';
216 msg_hint_compileaborted = 'Compile aborted';
217 msg_hint_pleasewait = 'Please wait...';
219 msg_cantopenfile = 'Can''t open %s';
221 procedure ParseUserScreen;
226 DisplayCompilerWindow : boolean;
229 procedure SearchBackTrace;
230 var AText,ModuleName,st : String;
233 if pos(' $',Text)=1 then
237 While pos(' ',Text)=1 do
239 if pos('of ',Text)>0 then
241 ModuleName:=Copy(Text,pos('of ',Text)+3,255);
242 While ModuleName[Length(ModuleName)]=' ' do
243 Delete(ModuleName,Length(ModuleName),1);
247 if pos('line ',Text)>0 then
249 Text:=Copy(Text,Pos('line ',Text)+5,255);
250 st:=Copy(Text,1,Pos(' ',Text)-1);
255 CompilerMessageWindow^.AddMessage(V_Fatal or v_lineinfo,AText
257 DisplayCompilerWindow:=true;
261 procedure InsertInMessages(Const TypeStr : String;_Type : longint;EnableDisplay : boolean);
262 var p,p2,col,row : longint;
263 St,ModuleName : string;
266 p:=pos(TypeStr,Text);
268 if (p>0) and (p2>0) and (p2<p) then
270 ModuleName:=Copy(Text,1,p2-1);
271 st:=Copy(Text,p2+1,255);
272 Val(Copy(st,1,pos(',',st)-1),row,cc);
273 st:=Copy(st,Pos(',',st)+1,255);
274 Val(Copy(st,1,pos(')',st)-1),col,cc);
275 CompilerMessageWindow^.AddMessage(_type,Copy(Text,pos(':',Text)+1,255)
276 ,ModuleName,row,col);
277 If EnableDisplay then
278 DisplayCompilerWindow:=true;
283 if not assigned(UserScreen) then
285 DisplayCompilerWindow:=false;
286 YMax:=UserScreen^.GetHeight;
287 PushStatus('Parsing User Screen');
288 CompilerMessageWindow^.Lock;
291 UserScreen^.GetLine(Y,Text,Attr);
292 if (y mod 10) = 0 then
294 CompilerMessageWindow^.Unlock;
295 SetStatus('Parsing User Screen line '+IntToStr(y)+'/'+IntToStr(YMax));
296 CompilerMessageWindow^.Lock;
299 if (LEvent.What=evKeyDown) and (LEvent.KeyCode=kbEsc) then
302 InsertInMessages(' Fatal:',v_Fatal or v_lineinfo,true);
303 InsertInMessages(' Error:',v_Error or v_lineinfo,true);
304 InsertInMessages(' Warning:',v_Warning or v_lineinfo,false);
305 InsertInMessages(' Note:',v_Note or v_lineinfo,false);
306 InsertInMessages(' Info:',v_Info or v_lineinfo,false);
307 InsertInMessages(' Hint:',v_Hint or v_lineinfo,false);
309 if DisplayCompilerWindow then
311 if not CompilerMessageWindow^.GetState(sfVisible) then
312 CompilerMessageWindow^.Show;
313 CompilerMessageWindow^.MakeFirst;
314 CompilerMessageWindow^.MsgLB^.SelectFirstError;
316 CompilerMessageWindow^.UnLock;
320 {*****************************************************************************
322 *****************************************************************************}
324 function TCompilerMessage.GetText(MaxLen: Sw_Integer): String;
329 case TClass and V_LevelMask of
330 V_Fatal : ClassS:=msg_class_Fatal;
331 V_Error : ClassS:=msg_class_Error;
332 V_Normal : ClassS:=msg_class_Normal;
333 V_Warning : ClassS:=msg_class_Warning;
334 V_Note : ClassS:=msg_class_Note;
335 V_Hint : ClassS:=msg_class_Hint;
337 V_Conditional : ClassS:=msg_class_conditional;
338 V_Info : ClassS:=msg_class_info;
339 V_Status : ClassS:=msg_class_status;
340 V_Used : ClassS:=msg_class_used;
341 V_Tried : ClassS:=msg_class_tried;
342 V_Debug : ClassS:=msg_class_debug;
350 ClassS:=RExpand(ClassS,0)+': ';
351 if assigned(Module) and
352 ((TClass and V_LineInfo)=V_LineInfo) then
357 S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+','+IntToStr(Col)+') '+ClassS
359 S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+') '+ClassS;
362 S:=NameAndExtOf(Module^)+'('+IntToStr(Row)+') '+ClassS
366 if assigned(Text) then
368 if length(S)>MaxLen then
369 S:=copy(S,1,MaxLen-2)+'..';
374 {*****************************************************************************
375 TCompilerMessageListBox
376 *****************************************************************************}
378 function TCompilerMessageListBox.GetPalette: PPalette;
380 P: string[length(CBrowserListBox)] = CBrowserListBox;
382 GetPalette:=PPalette(@P);
385 procedure TCompilerMessageListBox.SelectFirstError;
386 function IsError(P : PCompilerMessage) : boolean;
388 IsError:=(P^.TClass and (V_Fatal or V_Error))<>0;
391 P : PCompilerMessage;
393 P:=List^.FirstThat(@IsError);
396 FocusItem(List^.IndexOf(P));
402 {*****************************************************************************
403 TCompilerMessageWindow
404 *****************************************************************************}
406 constructor TCompilerMessageWindow.Init;
410 Desktop^.GetExtent(R);
412 inherited Init(R,dialog_compilermessages,{SearchFreeWindowNo}wnNoNumber);
413 HelpCtx:=hcCompilerMessagesWindow;
417 HSB:=StandardScrollBar(sbHorizontal+sbHandleKeyboard);
418 HSB^.GrowMode:=gfGrowLoY+gfGrowHiX+gfGrowHiY;
420 VSB:=StandardScrollBar(sbVertical+sbHandleKeyboard);
421 VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
426 New(MsgLB, Init(R, HSB, VSB));
428 MsgLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
430 CompilerMessageWindow:=@self;
434 procedure TCompilerMessageWindow.AddMessage(AClass: longint;const Msg, Module: string; Line, Column: longint);
436 if (AClass and V_LineInfo)<>V_LineInfo then
438 MsgLB^.AddItem(New(PCompilerMessage,Init(AClass, Msg, MsgLB^.AddModuleName(Module), Line, Column)));
439 if (@Self=CompilerMessageWindow) and ((AClass = V_fatal) or (AClass = V_Error)) then
441 if not GetState(sfVisible) then
443 if Desktop^.First<>PView(CompilerMessageWindow) then
449 procedure TCompilerMessageWindow.ClearMessages;
456 {procedure TCompilerMessageWindow.Updateinfo;
458 if CompileShowed then
461 RExpand(' Main file : '#1#$7f+Copy(SmartPath(MainFile),1,39),40)+#2+
462 'Total lines : '#1#$7e+IntToStr(Status.CompiledLines)+#2#13+
463 RExpand(' Target : '#1#$7f+KillTilde(TargetSwitches^.ItemName(TargetSwitches^.GetCurrSel)),40)+#2+
464 'Total errors : '#1#$7e+IntToStr(Status.ErrorCount)
466 if status.currentline>0 then
467 CurrST^.SetText(' Status: '#1#$7e+status.currentsource+'('+IntToStr(status.currentline)+')'#2)
469 CurrST^.SetText(' Status: '#1#$7e+status.currentsource+#2);
475 procedure TCompilerMessageWindow.HandleEvent(var Event: TEvent);
479 case Event.Command of
481 if Event.InfoPtr=MsgLB then
482 Message(Application,evBroadcast,cmClearLineHighlights,@Self);
485 inherited HandleEvent(Event);
489 procedure TCompilerMessageWindow.SizeLimits(var Min, Max: TPoint);
491 inherited SizeLimits(Min,Max);
497 procedure TCompilerMessageWindow.Close;
503 function TCompilerMessageWindow.GetPalette: PPalette;
505 S : string[length(CBrowserWindow)] = CBrowserWindow;
507 GetPalette:=PPalette(@S);
511 constructor TCompilerMessageWindow.Load(var S: TStream);
514 GetSubViewPtr(S,MsgLB);
518 procedure TCompilerMessageWindow.Store(var S: TStream);
520 if MsgLB^.List=nil then
521 MsgLB^.NewList(New(PCollection, Init(100,100)));
523 PutSubViewPtr(S,MsgLB);
526 procedure TCompilerMessageWindow.UpdateCommands;
529 Active:=GetState(sfActive);
530 SetCmdState(CompileCmds,Active);
531 Message(Application,evBroadcast,cmCommandSetChanged,nil);
534 procedure TCompilerMessageWindow.SetState(AState: Word; Enable: Boolean);
538 inherited SetState(AState,Enable);
539 if ((AState and sfActive)<>0) and (((OldState xor State) and sfActive)<>0) then
543 destructor TCompilerMessageWindow.Done;
545 CompilerMessageWindow:=nil;
550 {****************************************************************************
552 ****************************************************************************}
554 function getrealtime : real;
556 {$IFDEF USE_SYSUTILS}
560 {$ENDIF USE_SYSUTILS}
562 {$IFDEF USE_SYSUTILS}
563 DecodeTime(Time,h,m,s,s1000);
564 getrealtime:=h*3600.0+m*60.0+s+s1000/1000.0;
567 getrealtime:=h*3600.0+m*60.0+s+s100/100.0;
568 {$ENDIF USE_SYSUTILS}
571 constructor TCompilerStatusDialog.Init;
575 ClearFormatParams; AddFormatParamStr(KillTilde(SwitchesModeName[SwitchesMode]));
576 inherited Init(R, FormatStrF(dialog_compilingwithmode, FormatParams));
577 starttime:=getrealtime;
578 GetExtent(R); R.B.Y:=11;
580 New(ST, Init(R, ''));
582 GetExtent(R); R.B.Y:=11;
583 R.Grow(-1,-1); R.A.Y:=R.B.Y-1;
584 New(KeyST, Init(R, '', Blue*16+White+longint($80+Blue*16+White)*256,true));
586 { Reset Status infos see bug 1585 }
587 Fillchar(Status,SizeOf(Status),#0);
590 destructor TCompilerStatusDialog.Done;
592 if @Self=CompilerStatusDialog then
593 CompilerStatusDialog:=nil;
597 procedure TCompilerStatusDialog.SetStartTime(r : real);
602 procedure TCompilerStatusDialog.Update;
604 StatusS,KeyS: string;
605 hstatus : TFPCHeapStatus;
608 MaxFileNameSize = 46;
610 case CompilationPhase of
614 if Upcase(Status.currentmodulestate)='COMPILE' then
616 AddFormatParamStr(ShrinkPath(SmartPath(Status.Currentsourcepath+Status.CurrentSource),
617 MaxFileNameSize - Length(msg_compilingfile)));
618 StatusS:=FormatStrF(msg_compilingfile,FormatParams);
622 if Status.CurrentSource='' then
626 StatusS:=ShrinkPath(SmartPath(DirAndNameOf(Status.Currentsourcepath+Status.CurrentSource)),
627 MaxFileNameSize-Length(msg_loadingunit));
628 AddFormatParamStr(StatusS);
629 StatusS:=FormatStrF(msg_loadingunit,FormatParams);
632 KeyS:=msg_hint_pressesctocancel;
637 AddFormatParamStr(ShrinkPath(ExeFile,
638 MaxFileNameSize-Length(msg_linkingfile)));
639 StatusS:=FormatStrF(msg_linkingfile,FormatParams);
640 KeyS:=msg_hint_pleasewait;
644 StatusS:=msg_compiledone;
645 KeyS:=msg_hint_compilesuccessfulpressenter;
649 StatusS:=msg_failedtocompile;
650 KeyS:=msg_hint_compilefailed;
654 StatusS:=msg_compilationaborted;
655 KeyS:=msg_hint_compileaborted;
659 AddFormatParamStr(ShrinkPath(SmartPath(MainFile),
660 MaxFileNameSize-Length('Main file: %s')));
661 AddFormatParamStr(StatusS);
662 AddFormatParamStr(KillTilde(TargetSwitches^.ItemName(TargetSwitches^.GetCurrSel)));
663 AddFormatParamInt(Status.CurrentLine);
664 AddFormatParamInt(Status.CompiledLines);
665 hstatus:=GetFPCHeapStatus;
666 AddFormatParamInt(hstatus.CurrHeapUsed div 1024);
667 AddFormatParamInt(hstatus.CurrHeapSize div 1024);
668 AddFormatParamInt(Status.ErrorCount);
670 AddFormatParamInt(trunc(r-starttime));
671 AddFormatParamInt(trunc(frac(r-starttime)*10));
677 'Line number: %6d '+'Total lines: %6d'+#13+
678 'Used memory: %6dK '+'Allocated memory: %6dK'#13+
679 'Total errors:%6d '+'Compile time: %8d.%1ds',
682 KeyST^.SetText(^C+KeyS);
686 {****************************************************************************
688 ****************************************************************************}
693 function CompilerStatus: boolean;
699 if (Event.What=evKeyDown) and (Event.KeyCode=kbEsc) then
701 CompilationPhase:=cpAborted;
702 { update info messages }
703 if assigned(CompilerStatusDialog) then
705 {$ifdef redircompiler}
708 CompilerStatusDialog^.Update;
709 {$ifdef redircompiler}
713 CompilerStatus:=true;
716 { only display line info every 100 lines, ofcourse all other messages
717 will be displayed directly }
718 if (getrealtime-lasttime>=CompilerStatusUpdateDelay) or (status.compiledlines=1) then
720 lasttime:=getrealtime;
721 { update info messages }
722 {$ifdef redircompiler}
725 if assigned(CompilerStatusDialog) then
726 CompilerStatusDialog^.Update;
727 {$ifdef redircompiler}
730 { update memory usage }
731 { HeapView^.Update; }
733 CompilerStatus:=false;
736 Function CompilerGetNamedFileTime(const filename : ansistring) : Longint;
740 W:=EditorWindowFile(FExpand(filename));
741 if Assigned(W) and (W^.Editor^.GetModified) then
744 t:=def_getnamedfiletime(filename);
745 CompilerGetNamedFileTime:=t;
748 function CompilerOpenInputFile(const filename: ansistring): tinputfile;
752 if assigned(CompilingHiddenFile) and
753 (NameandExtof(filename)=CompilingHiddenFile^.Editor^.Filename) then
754 W:=CompilingHiddenFile
756 W:=EditorWindowFile(FExpand(filename));
757 if Assigned(W) and (W^.Editor^.GetModified) then
758 f:=TFPInputFile.Create(W^.Editor)
760 f:=def_openinputfile(filename);
762 W^.Editor^.CompileStamp:=CompileStamp;
763 CompilerOpenInputFile:=f;
766 function CompilerComment(Level:Longint; const s:ansistring):boolean;
768 CompilerComment:=false;
769 if (status.verbosity and Level)<>0 then
771 {$ifdef redircompiler}
775 if not CompilerMessageWindow^.GetState(sfVisible) then
776 CompilerMessageWindow^.Show;
777 if Desktop^.First<>PView(CompilerMessageWindow) then
778 CompilerMessageWindow^.MakeFirst;
779 CompilerMessageWindow^.AddMessage(Level,S,status.currentsourcepath+status.currentsource,
780 status.currentline,status.currentcolumn);
781 { update info messages }
782 if assigned(CompilerStatusDialog) then
783 CompilerStatusDialog^.Update;
784 {$ifdef redircompiler}
787 { update memory usage }
788 { HeapView^.Update; }
793 {****************************************************************************
795 ****************************************************************************}
797 { This function must return '' if
798 "Options|Directories|Exe and PPU directory" is empty }
799 function GetExePath: string;
804 if DirectorySwitches<>nil then
805 with DirectorySwitches^ do
806 for I:=0 to ItemCount-1 do
808 if ItemParam(I)='-FE' then
810 Path:=GetStringItem(I);
815 GetExePath:=CompleteDir(FExpand(Path))
820 function GetMainFile(Mode: TCompileMode): string;
821 var FileName: string;
824 if assigned(CompilingHiddenFile) then
825 P:=CompilingHiddenFile
827 P:=Message(Desktop,evBroadcast,cmSearchWindow,nil);
828 if (PrimaryFileMain='') and (P=nil) then
829 FileName:='' { nothing to compile }
832 if (PrimaryFileMain<>'') and (Mode<>cCompile) then
833 FileName:=PrimaryFileMain
834 else if assigned(P) then
836 FileName:=P^.Editor^.FileName;
839 P^.Editor^.SaveAsk(true);
840 FileName:=P^.Editor^.FileName;
847 If (FileName<>'') then
848 FileName:=FExpand(FileName);
850 If (FileName<>'') then
851 FileName:=FixFileName(FExpand(FileName));
853 GetMainFile:=FileName;
856 procedure ResetErrorMessages;
857 procedure ResetErrorLine(P: PView);
860 (TypeOf(P^)=TypeOf(TSourceWindow)) then
861 PSourceWindow(P)^.Editor^.SetErrorMessage('');
864 Desktop^.ForEach(@ResetErrorLine);
868 procedure DoCompile(Mode: TCompileMode);
870 function IsExitEvent(E: TEvent): boolean;
872 { following suggestion by Harsha Senanayake }
873 IsExitEvent:=(E.What=evKeyDown);
875 function GetTargetExeExt : string;
877 GetTargetExeExt:=target_info.exeext;
882 MustRestartDebugger : boolean;
883 Error,LinkErrorCount : longint;
886 PPasFile : string[64];
888 AskRecompileIfModifiedFlag:=true;
890 FileName:=GetMainFile(Mode);
893 ErrorBox(msg_nothingtocompile,nil);
896 { THis is not longer necessary as unsaved files are loaded from a memorystream,
897 and with the file as primaryfile set it is already incompatible with itself
900 ErrorBox(msg_cantcompileunsavedfile,nil);
903 PushStatus('Beginning compilation...');
904 { Show Compiler Messages Window }
905 { if not CompilerMessageWindow^.GetState(sfVisible) then
906 CompilerMessageWindow^.Show;
907 CompilerMessageWindow^.MakeFirst;}
908 CompilerMessageWindow^.ClearMessages;
909 { Tell why we compile }
910 NeedRecompile(Mode,true);
913 SetStatus('Writing switches to file...');
914 WriteSwitches(SwitchesPath);
915 { leaving open browsers leads to crashes !! (PM) }
916 SetStatus('Preparing symbol info...');
918 if ((DesktopFileFlags and dfSymbolInformation)<>0) then
919 WriteSymbolsFile(BrowserName);
920 { MainFile:=FixFileName(FExpand(FileName));}
921 SetStatus('Preparing to compile...'+NameOf(MainFile));
924 { Create Compiler Status Dialog }
925 CompilationPhase:=cpCompiling;
926 if not assigned(CompilingHiddenFile) then
928 New(CompilerStatusDialog, Init);
929 CompilerStatusDialog^.SetStartTime(getrealtime);
930 CompilerStatusDialog^.SetState(sfModal,true);
931 { disable window closing }
932 CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags and not wfclose;
933 Application^.Insert(CompilerStatusDialog);
934 CompilerStatusDialog^.Update;
936 { Restore dir that could be changed during debugging }
941 { hook compiler output }
942 do_status:=@CompilerStatus;
943 do_comment:=@CompilerComment;
944 do_openinputfile:=@CompilerOpenInputFile;
945 do_getnamedfiletime:=@CompilerGetNamedFileTime;
946 do_initsymbolinfo:=@InitBrowserCol;
947 do_donesymbolinfo:=@DoneBrowserCol;
948 do_extractsymbolinfo:=@CreateBrowserCol;
950 {$ifdef redircompiler}
951 ChangeRedirOut(FPOutFileName,false);
952 ChangeRedirError(FPErrFileName,false);
954 { insert "" around name so that spaces are allowed }
955 { only supported in compiler after 2000/01/14 PM }
956 if pos(' ',FileName)>0 then
957 FileName:='"'+FileName+'"';
959 FileName:='-B '+FileName;
960 { tokens are created and distroed by compiler.compile !! PM }
962 PPasFile:='ppas'+source_info.scriptext;
963 WUtils.DeleteFile(GetExePath+PpasFile);
964 SetStatus('Compiling...');
968 MustRestartDebugger:=false;
969 if assigned(Debugger) then
970 if Debugger^.HasExe then
973 MustRestartDebugger:=true;
977 FpIntF.Compile(FileName,SwitchesPath);
980 CompilerMessageWindow^.AddMessage(V_error,'Error during compilation','',0,0);
982 CompilerMessageWindow^.AddMessage(V_error,E.Message+' during compilation','',0,0);
984 SetStatus('Finished compiling...');
986 { Retrieve created exefile }
987 If GetEXEPath<>'' then
988 EXEFile:=FixFileName(GetEXEPath+NameOf(MainFile)+GetTargetExeExt)
990 EXEFile:=DirOf(MainFile)+NameOf(MainFile)+GetTargetExeExt;
991 DefaultReplacements(ExeFile);
992 { tokens are created and distroyed by compiler.compile !! PM }
995 ExistsFile(GetExePath+PpasFile) and
996 (CompilationPhase<>cpAborted) and
997 (status.errorCount=0) then
999 CompilationPhase:=cpLinking;
1000 if assigned(CompilerStatusDialog) then
1001 CompilerStatusDialog^.Update;
1002 SetStatus('Assembling and/or linking...');
1003 {$ifndef redircompiler}
1004 { At least here we want to catch output
1006 ChangeRedirOut(FPOutFileName,false);
1007 ChangeRedirError(FPErrFileName,false);
1011 If fpsystem(GetExePath+PpasFile)=-1 Then
1014 DosExecute(GetEnv('COMSPEC'),'/C '+GetExePath+PpasFile);
1017 SetStatus('Finished linking...');
1021 Inc(status.errorCount);
1022 if Status.IsExe and not Status.IsLibrary and not ExistsFile(EXEFile) then
1024 Inc(status.errorCount);
1025 ClearFormatParams; AddFormatParamStr(ExeFile);
1026 CompilerMessageWindow^.AddMessage(V_error,FormatStrF(msg_couldnotcreatefile,FormatParams),'',0,0);
1028 Assign(ErrFile,FPErrFileName);
1031 ErrorBox(FormatStrStr(msg_cantopenfile,FPErrFileName),nil)
1035 While not eof(ErrFile) and (LinkErrorCount<25) do
1038 CompilerMessageWindow^.AddMessage(V_error,s,'',0,0);
1039 inc(LinkErrorCount);
1041 if not eof(ErrFile) then
1043 ClearFormatParams; AddFormatParamStr(FPErrFileName);
1044 CompilerMessageWindow^.AddMessage(V_error,
1045 FormatStrF(msg_therearemoreerrorsinfile,FormatParams),'',0,0);
1053 else if error=0 then
1054 WUtils.DeleteFile(GetExePath+PpasFile);
1056 {$ifdef redircompiler}
1062 if not (CompilationPhase in [cpAborted,cpFailed]) then
1063 if (status.errorCount=0) then
1065 CompilationPhase:=cpDone;
1066 LastCompileTime := cardinal(Now);
1069 CompilationPhase:=cpFailed;
1071 { reenable window closing }
1072 if assigned(CompilerStatusDialog) then
1074 CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags or wfclose;
1075 CompilerStatusDialog^.Update;
1076 CompilerStatusDialog^.ReDraw;
1077 CompilerStatusDialog^.SetState(sfModal,false);
1078 if ((CompilationPhase in [cpAborted,cpDone,cpFailed]) or (ShowStatusOnError))
1079 and ((Mode<>cRun) or (CompilationPhase<>cpDone)) then
1081 CompilerStatusDialog^.GetEvent(E);
1082 if IsExitEvent(E)=false then
1083 CompilerStatusDialog^.HandleEvent(E);
1084 until IsExitEvent(E) or not assigned(CompilerStatusDialog);
1085 {if IsExitEvent(E) then
1086 Application^.PutEvent(E);}
1087 if assigned(CompilerStatusDialog) then
1089 Application^.Delete(CompilerStatusDialog);
1090 Dispose(CompilerStatusDialog, Done);
1093 CompilerStatusDialog:=nil;
1094 { end compilation returns true if the messagewindow should be removed }
1095 if CompilationPhase=cpDone then
1097 CompilerMessageWindow^.Hide;
1098 { This is the last compiled main file }
1099 PrevMainFile:=MainFile;
1100 MainHasDebugInfo:=DebugInfoSwitches^.GetCurrSelParam<>'-';
1103 Message(Application,evCommand,cmUpdate,nil);
1104 DummyView:=Desktop^.First;
1105 while (DummyView<>nil) and (DummyView^.GetState(sfVisible)=false) do
1107 DummyView:=DummyView^.NextView;
1110 if GetState(sfVisible) then
1112 SetState(sfSelected,false);
1113 SetState(sfSelected,true);
1115 if Assigned(CompilerMessageWindow) then
1116 with CompilerMessageWindow^ do
1118 if GetState(sfVisible) then
1120 SetState(sfSelected,false);
1121 SetState(sfSelected,true);
1123 if (status.errorCount>0) then
1124 MsgLB^.SelectFirstError;
1126 { ^^^ we need this trick to reactivate the desktop }
1127 EditorModified:=false;
1129 if MustRestartDebugger then
1132 { In case we have something that the compiler touched }
1133 AskToReloadAllModifiedFiles;
1134 { Try to read Browser info in again if compilation failure !! }
1135 if Not Assigned(Modules) and (CompilationPhase<>cpDone) and
1136 ((DesktopFileFlags and dfSymbolInformation)<>0) then
1137 ReadSymbolsFile(BrowserName);
1138 if UseAllUnitsInCodeComplete and not assigned(CompilingHiddenFile) then
1139 AddAvailableUnitsToCodeComplete(false);
1142 function NeedRecompile(Mode :TCompileMode; verbose : boolean): boolean;
1146 SourceTime,PPUTime,ObjTime: longint;
1149 if Assigned(SourceFiles)=false then
1150 Need:={(EditorModified=true)}true
1153 Need:=(PrevMainFile<>GetMainFile(Mode)) and (PrevMainFile<>'');
1158 ClearFormatParams; AddFormatParamStr(GetMainFile(Mode));
1159 CompilerMessageWindow^.AddMessage(V_info,
1160 FormatStrF(msg_firstcompilationof,FormatParams),
1165 for I:=0 to SourceFiles^.Count-1 do
1167 SF:=SourceFiles^.At(I);
1168 SourceTime:=wutils.GetFileTime(SF^.GetSourceFileName);
1169 PPUTime:=wutils.GetFileTime(SF^.GetPPUFileName);
1170 ObjTime:=wutils.GetFileTime(SF^.GetObjFileName);
1171 { writeln('S: ',SF^.GetSourceFileName,' - ',SourceTime);
1172 writeln('P: ',SF^.GetPPUFileName,' - ',PPUTime);
1173 writeln('O: ',SF^.GetObjFileName,' - ',ObjTime);
1175 { some units don't generate object files }
1176 W:=EditorWindowFile(SF^.GetSourceFileName);
1177 if (SourceTime<>-1) then
1178 if ((SourceTime>PPUTime) or
1179 ((SourceTime>ObjTime) and
1181 (assigned(W) and (W^.Editor^.CompileStamp<0)) then
1186 ClearFormatParams; AddFormatParamStr(SF^.GetSourceFileName);
1187 CompilerMessageWindow^.AddMessage(V_info,
1188 FormatStrF(msg_recompilingbecauseof,FormatParams),
1189 SF^.GetSourceFileName,1,1);
1194 { writeln('Need?', Need); system.readln;}
1197 NeedRecompile:=Need;
1201 constructor TFPInputFile.Create(AEditor: PFileEditor);
1203 if not Assigned(AEditor) then Fail;
1204 if inherited Create(AEditor^.FileName)=nil then
1210 function TFPInputFile.fileopen(const filename: ansistring): boolean;
1213 S:=New(PMemoryStream, Init(0,0));
1214 OK:=Assigned(S) and (S^.Status=stOK);
1215 if OK then OK:=Editor^.SaveToStream(S);
1220 if Assigned(S) then Dispose(S, Done);
1226 function TFPInputFile.fileseek(pos: longint): boolean;
1234 OK:=(S^.Status=stOK);
1239 function TFPInputFile.fileread(var databuf; maxsize: longint): longint;
1243 if not assigned(S) then size:=0 else
1245 size:=min(maxsize,(S^.GetSize-S^.GetPos));
1246 S^.Read(databuf,size);
1247 if S^.Status<>stOK then size:=0;
1252 function TFPInputFile.fileeof: boolean;
1255 EOF:=not assigned(S);
1257 EOF:=(S^.Status<>stOK) or (S^.GetPos=S^.GetSize);
1261 function TFPInputFile.fileclose: boolean;
1275 procedure tfpinputfile.filegettime;
1281 dos.getdate(dt.year,dt.month,dt.day,wday);
1282 dos.gettime(dt.hour,dt.min,dt.sec,hsec);
1283 packtime(dt,filetime);
1286 procedure RegisterFPCompile;
1289 RegisterType(RCompilerMessageListBox);
1290 RegisterType(RCompilerMessageWindow);