fp.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998-2000 by Berczi Gabor
  4. Main program of 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. program FP;
  12. {$ifdef IncRes}
  13. {$ifdef Windows}
  14. {$R fpw32t.rc}
  15. {$R fpw32ico.rc}
  16. {$endif Windows}
  17. {$endif IncRes}
  18. {$I globdir.inc}
  19. (**********************************************************************)
  20. (* CONDITIONAL DEFINES *)
  21. (* - NODEBUG No Debugging support *)
  22. (* - i386 Target is an i386 IDE *)
  23. (**********************************************************************)
  24. uses
  25. {$ifdef Windows}
  26. windows,
  27. {$endif Windows}
  28. {$ifndef NODEBUG}
  29. {$ifdef Windows}
  30. fpcygwin,
  31. {$endif Windows}
  32. {$endif NODEBUG}
  33. {$ifdef IDEHeapTrc}
  34. PPheap,
  35. {$endif IDEHeapTrc}
  36. {$ifdef Use_DBGHEAP}
  37. dbgheap,
  38. {$endif Use_DBGHEAP}
  39. {$ifdef go32v2}
  40. dpmiexcp,
  41. {$endif go32v2}
  42. keyboard,video,mouse,
  43. {$ifdef HasSignal}
  44. fpcatch,
  45. {$endif HasSignal}
  46. Dos,Objects,
  47. BrowCol,Version,
  48. {$ifndef NODEBUG}
  49. gdbint,
  50. {$endif NODEBUG}
  51. FVConsts,
  52. Drivers,Views,App,Dialogs,HistList,
  53. Menus,StdDlg,Validate,
  54. WEditor,WCEdit,
  55. {$ifdef COLORSEL}
  56. ColorSel,
  57. {$endif COLORSEL}
  58. ASCIITab,
  59. WUtils,WViews,WHTMLScn,WHelp,
  60. FPIDE,FPCalc,FPCompil,
  61. FPIni,FPViews,FPConst,FPVars,FPUtils,FPHelp,FPSwitch,FPUsrScr,
  62. FPTools,
  63. {$ifndef NODEBUG}
  64. FPDebug,FPRegs,
  65. {$endif}
  66. FPTemplt,FPRedir,FPDesk,
  67. FPCodTmp,FPCodCmp,
  68. systems,globtype,globals;
  69. Const
  70. DummyMouseDriver : TMouseDriver = (
  71. useDefaultQueue : true;
  72. InitDriver : nil;
  73. DoneDriver : nil;
  74. DetectMouse : nil;
  75. ShowMouse : nil;
  76. HideMouse : nil;
  77. GetMouseX : nil;
  78. GetMouseY : nil;
  79. GetMouseButtons : nil;
  80. SetMouseXY : nil;
  81. GetMouseEvent : nil;
  82. PollMouseEvent : nil;
  83. PutMouseEvent : nil;
  84. );
  85. {$ifdef useresstrings}
  86. resourcestring
  87. {$else}
  88. const
  89. {$endif}
  90. { caught signals or abnormal exits }
  91. { Debugger messages and status hints }
  92. error_programexitedwitherror = #3'Program generated a RTE %d'#13+
  93. #3'at address $%s.'#13+
  94. #3'Save your sources and restart the IDE.';
  95. error_programexitedwithsignal = #3'Program generated a signal %d.'#13+
  96. #3'Save your sources and restart the IDE.';
  97. continue_despite_error = #3'The IDE generated an internal error'#13+
  98. #3'Do you really want to continue?'#13+
  99. #3'The IDE could be in an unstable state.';
  100. leaving_after_error = #3'The IDE generated an internal error'#13+
  101. #3'and will now be closed.';
  102. {$ifdef DEBUG}
  103. const
  104. CloseImmediately : boolean = false;
  105. var
  106. StartTime : real;
  107. function getrealtime : real;
  108. var
  109. h,m,s,s100 : word;
  110. begin
  111. gettime(h,m,s,s100);
  112. getrealtime:=h*3600.0+m*60.0+s+s100/100.0;
  113. end;
  114. {$endif DEBUG}
  115. procedure ProcessParams(BeforeINI: boolean);
  116. function IsSwitch(const Param: string): boolean;
  117. begin
  118. IsSwitch:=(Param<>'') and (Param[1]<>DirSep) { <- allow UNIX root-relative paths }
  119. and (Param[1] in ['-','/']); { <- but still accept dos switch char, eg. '/' }
  120. end;
  121. var I: Sw_integer;
  122. Param: string;
  123. begin
  124. for I:=1 to ParamCount do
  125. begin
  126. Param:=System.ParamStr(I);
  127. if IsSwitch(Param) then
  128. begin
  129. Param:=copy(Param,2,255);
  130. if Param<>'' then
  131. if UpcaseStr(copy(Param,1,2))='HM' then
  132. { HeapMonitor }
  133. begin
  134. if (copy(Param,3,1)='+') or (copy(Param,3,1)='') then
  135. StartupOptions:=StartupOptions or soHeapMonitor
  136. else
  137. if (copy(Param,3,1)='-') then
  138. StartupOptions:=StartupOptions and not soHeapMonitor;
  139. end else
  140. {$ifdef go32v2}
  141. if UpcaseStr(Param)='NOLFN' then
  142. begin
  143. LFNSupport:=false;
  144. end else
  145. {$endif go32v2}
  146. if UpcaseStr(Param)='README' then
  147. begin
  148. ShowReadme:=true;
  149. end else
  150. case Upcase(Param[1]) of
  151. 'C' : { custom config file (BP compatiblity) }
  152. if BeforeINI then
  153. begin
  154. if (length(Param)>=1) and (Param[1] in['=',':']) then
  155. Delete(Param,1,1); { eat separator }
  156. IniFileName:=Param;
  157. end;
  158. 'R' : { enter the directory last exited from (BP comp.) }
  159. begin
  160. Param:=copy(Param,2,255);
  161. if (Param='') or (Param='+') then
  162. StartupOptions:=StartupOptions or soReturnToLastDir
  163. else
  164. if (Param='-') then
  165. StartupOptions:=StartupOptions and (not soReturnToLastDir);
  166. end;
  167. 'S' :
  168. if Length(Param)=1 then
  169. begin
  170. UseMouse:=false;
  171. DoneMouse;
  172. SetMouseDriver(DummyMouseDriver);
  173. ButtonCount:=0;
  174. end;
  175. { 'F' :
  176. if Length(Param)=1 then
  177. NoExtendedFrame:=true;}
  178. {$ifdef Unix}
  179. 'T' : DebuggeeTTY:=Copy(Param,2,High(Param));
  180. {$endif Unix}
  181. { 'M' : TryToMaximizeScreen:=true;}
  182. {$ifdef DEBUG}
  183. 'Z' : UseOldBufStreamMethod:=true;
  184. 'X' : CloseImmediately:=true;
  185. {$endif DEBUG}
  186. end;
  187. end
  188. else
  189. if not BeforeINI then
  190. TryToOpenFileMulti(nil,Param,0,0,{false}true);
  191. end;
  192. end;
  193. Procedure MyStreamError(Var S: TStream);
  194. var ErrS: string;
  195. begin
  196. case S.Status of
  197. stGetError : ErrS:='Get of unregistered object type';
  198. stPutError : ErrS:='Put of unregistered object type';
  199. else ErrS:='';
  200. end;
  201. if ErrS<>'' then
  202. begin
  203. if (application<>nil) and (ideapp.displaymode=dmIDE) then
  204. ErrorBox('Stream error: '+#13+ErrS,nil)
  205. else
  206. writeln('Error: ',ErrS);
  207. end;
  208. end;
  209. {$ifdef linux}
  210. procedure detect_debian;
  211. var attr:word;
  212. f:text;
  213. begin
  214. assign(f,'/etc/debian_version');
  215. getfattr(f,attr);
  216. if doserror=0 then
  217. errorbox('Debian system detected!'#13#13+
  218. 'Debian systems use an incompatible gpm'#13+
  219. 'daemon, therefore your system might'#13+
  220. 'suffer from Debian bug 412927. Please'#13+
  221. 'see http://bugs.debian.org/cgi-bin/'#13+
  222. 'bugreport.cgi?bug=412927 for details.',nil);
  223. end;
  224. {$endif}
  225. procedure DelTempFiles;
  226. begin
  227. DeleteFile(FPOutFileName);
  228. DeleteFile(FPErrFileName);
  229. DeleteFile(GDBOutFileName);
  230. DeleteFile(GDBOutPutFileName);
  231. DeleteFile(GREPOutName);
  232. DeleteFile(GREPErrName);
  233. end;
  234. procedure RegisterIDEObjects;
  235. begin
  236. RegisterApp;
  237. RegisterCodeComplete;
  238. RegisterCodeTemplates;
  239. {$ifdef COLORSEL}
  240. RegisterColorSel;
  241. {$endif COLORSEL}
  242. RegisterAsciiTab;
  243. RegisterDialogs;
  244. RegisterWEditor;
  245. RegisterWCEdit;
  246. RegisterFPCalc;
  247. RegisterFPCompile;
  248. RegisterFPTools;
  249. RegisterFPViews;
  250. {$ifndef NODEBUG}
  251. RegisterFPDebugViews;
  252. RegisterFPRegsViews;
  253. {$endif}
  254. RegisterMenus;
  255. RegisterStdDlg;
  256. RegisterSymbols;
  257. RegisterObjects;
  258. RegisterValidate;
  259. RegisterViews;
  260. RegisterWHTMLScan;
  261. RegisterWUtils;
  262. RegisterWViews;
  263. end;
  264. var CanExit : boolean;
  265. SetJmpRes : longint;
  266. StoreExitProc : pointer;
  267. ErrS : String;
  268. P : record
  269. l1 : longint;
  270. s : pstring;
  271. end;
  272. const
  273. ExitIntercepted : boolean = false;
  274. SeenExitCode : longint =0;
  275. SeenErrorAddr : pointer = nil;
  276. UserWantsToGoOn: boolean = false;
  277. procedure InterceptExit;
  278. begin
  279. {$IFDEF HasSignal}
  280. if StopJmpValid then
  281. begin
  282. ExitIntercepted:=true;
  283. SeenExitCode:=ExitCode;
  284. SeenErrorAddr:=ErrorAddr;
  285. LongJmp(StopJmp,1);
  286. end;
  287. {$ENDIF}
  288. end;
  289. procedure InitCompilerSwitches;
  290. begin
  291. default_settings.globalswitches:=[cs_check_unit_name];
  292. default_settings.moduleswitches:=[cs_extsyntax,cs_implicit_exceptions];
  293. default_settings.localswitches:=[cs_typed_const_writable];
  294. end;
  295. {The square bullet needs an MS-DOS code page. On Unix it is for sure the code
  296. page is not available before video is initialized. (And only in certain
  297. circumstances after that, so, use a plain ascii character as bullet on Unix.)}
  298. {$ifdef unix}
  299. const bullet='*';
  300. {$else}
  301. const bullet='þ';
  302. {$endif}
  303. BEGIN
  304. {$IFDEF HasSignal}
  305. EnableCatchSignals;
  306. {$ENDIF}
  307. {$ifdef DEV}
  308. HeapLimit:=4096;
  309. {$endif}
  310. HistorySize:=16384;
  311. { Startup info }
  312. writeln(bullet+' Free Pascal IDE Version '+VersionStr+' ['+{$i %date%}+']');
  313. writeln(bullet+' Compiler Version '+Full_Version_String);
  314. {$ifndef NODEBUG}
  315. writeln(bullet+' GDB Version '+GDBVersion);
  316. {$ifdef Windows}
  317. writeln(bullet+' Cygwin "',GetCygwinFullName,'" version ',GetCygwinVersionString);
  318. CheckCygwinVersion;
  319. {$endif Windows}
  320. {$endif NODEBUG}
  321. ProcessParams(true);
  322. {$ifdef DEBUG}
  323. StartTime:=getrealtime;
  324. {$endif DEBUG}
  325. InitDirs;
  326. RegisterIDEObjects;
  327. StreamError:=@MyStreamError;
  328. ShowReadme:=ShowReadme or (LocateFile(INIFileName)='');
  329. if LocateFile(INIFileName)<>'' then
  330. writeln(bullet+' Using configuration files from: ',DirOf(LocateFile(INIFileName)));
  331. InitCompilerSwitches;
  332. {$ifdef VESA}
  333. InitVESAScreenModes;
  334. {$endif}
  335. InitRedir;
  336. {$ifndef NODEBUG}
  337. InitBreakpoints;
  338. InitWatches;
  339. {$endif}
  340. InitReservedWords;
  341. InitHelpFiles;
  342. InitSwitches;
  343. InitINIFile;
  344. InitUserScreen;
  345. InitTools;
  346. InitTemplates;
  347. InitCodeTemplates;
  348. InitCodeComplete;
  349. { init target information etc. }
  350. InitSystems;
  351. IDEApp.Init;
  352. CheckINIFile;
  353. ReadSwitches(SwitchesPath);
  354. { load all options after init because of open files }
  355. ReadINIFile;
  356. InitDesktopFile;
  357. LoadDesktop;
  358. {Menubar might be changed because of loading INI file.}
  359. IDEapp.reload_menubar;
  360. { Handle Standard Units }
  361. if UseAllUnitsInCodeComplete then
  362. AddAvailableUnitsToCodeComplete(false);
  363. if UseStandardUnitsInCodeComplete and not assigned(UnitsCodeCompleteWords) then
  364. AddStandardUnitsToCodeComplete;
  365. { why are the screen contents parsed at startup? Gabor
  366. to be able to find location of error in last compilation
  367. from command line PM }
  368. ParseUserScreen;
  369. { Update IDE }
  370. IDEApp.Update;
  371. IDEApp.UpdateMode;
  372. IDEApp.UpdateTarget;
  373. ProcessParams(false);
  374. if ShowReadme then
  375. begin
  376. {$ifdef linux}
  377. {Regrettably we do not have a proper solution.}
  378. detect_debian;
  379. {$endif}
  380. PutCommand(Application,evCommand,cmShowReadme,nil);
  381. ShowReadme:=false; { do not show next time }
  382. end;
  383. StoreExitProc:=ExitProc;
  384. ExitProc:=@InterceptExit;
  385. repeat
  386. {$IFDEF HasSignal}
  387. SetJmpRes:=setjmp(StopJmp);
  388. StopJmpValid:=true;
  389. {$ENDIF}
  390. UserWantsToGoOn:=false;
  391. if SetJmpRes=0 then
  392. begin
  393. {$ifdef DEBUG}
  394. if not CloseImmediately then
  395. {$endif DEBUG}
  396. IDEApp.Run;
  397. end
  398. else
  399. begin
  400. if (SetJmpRes=1) and ExitIntercepted then
  401. begin
  402. { If ExitProc=@InterceptExit then
  403. ExitProc:=StoreExitProc;}
  404. Str(SeenExitCode,ErrS);
  405. if (application<>nil) and (ideapp.displaymode=dmIDE) then
  406. begin
  407. P.l1:=SeenExitCode;
  408. ErrS:=hexstr(PtrUInt(SeenErrorAddr),sizeof(PtrUInt)*2);
  409. P.s:=@ErrS;
  410. if OKCancelBox(error_programexitedwitherror,@P)=cmCancel then
  411. UserWantsToGoOn:=true;
  412. end
  413. else
  414. writeln('Abnormal exit error: ',ErrS);
  415. end
  416. else
  417. begin
  418. Str(SetJmpRes,ErrS);
  419. { Longjmp was called by fpcatch }
  420. if (application<>nil) and (ideapp.displaymode=dmIDE) then
  421. begin
  422. P.l1:=SetJmpRes;
  423. if OKCancelBox(error_programexitedwithsignal,@P)=cmCancel then
  424. UserWantsToGoOn:=true;
  425. end
  426. else
  427. writeln('Signal error: ',ErrS);
  428. end;
  429. if ideapp.displaymode=dmUser then
  430. begin
  431. writeln('Fatal exception occured while in user screen mode. File save message boxes');
  432. writeln('cannot be displayed. We are sorry, but need to terminate now.');
  433. halt(255);
  434. end;
  435. end;
  436. if (AutoSaveOptions and asEditorFiles)=0 then
  437. CanExit:=IDEApp.AskSaveAll
  438. else
  439. CanExit:=IDEApp.SaveAll;
  440. {$IFDEF HasSignal}
  441. StopJmpValid:=false;
  442. {$ENDIF}
  443. if (SetJmpRes<>0) then
  444. begin
  445. if (not CanExit) or UserWantsToGoOn then
  446. begin
  447. if ConfirmBox(continue_despite_error,nil,false)=cmNo then
  448. CanExit:=true
  449. else
  450. CanExit:=false;
  451. end
  452. else
  453. begin
  454. ErrorBox(leaving_after_error,nil);
  455. end;
  456. end;
  457. until CanExit;
  458. If ExitProc=pointer(@InterceptExit) then
  459. ExitProc:=StoreExitProc;
  460. IDEApp.AutoSave;
  461. DoneDesktopFile;
  462. DelTempFiles;
  463. IDEApp.Done;
  464. WriteSwitches(SwitchesPath);
  465. {$IFDEF HasSignal}
  466. DisableCatchSignals;
  467. {$ENDIF}
  468. DoneCodeComplete;
  469. DoneCodeTemplates;
  470. DoneTemplates;
  471. DoneTools;
  472. DoneUserScreen;
  473. DoneSwitches;
  474. DoneHelpFiles;
  475. DoneHelpFilesTypes;
  476. DoneReservedWords;
  477. DoneToolMessages;
  478. DoneBrowserCol;
  479. {$ifndef NODEBUG}
  480. DoneDebugger;
  481. DoneBreakpoints;
  482. DoneWatches;
  483. {$endif}
  484. {$ifdef unix}
  485. Video.ClearScreen;
  486. {$endif unix}
  487. { Video.DoneVideo;
  488. Keyboard.DoneKeyboard;}
  489. {$ifdef VESA}
  490. DoneVESAScreenModes;
  491. {$endif}
  492. {$if defined(unix)}
  493. Keyboard.RestoreStartMode;
  494. {$endif defined(unix)}
  495. {$if defined(windows)}
  496. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)),StartupConsoleMode);
  497. {$endif defined(windows)}
  498. StreamError:=nil;
  499. {$ifdef DEBUG}
  500. if CloseImmediately then
  501. writeln('Used time is ',getrealtime-StartTime:0:2);
  502. {$endif DEBUG}
  503. END.