comphook.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman
  3. This unit handles the compilerhooks for output to external programs
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit comphook;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. {$IFNDEF USE_FAKE_SYSUTILS}
  22. sysutils,
  23. {$ELSE}
  24. fksysutl,
  25. {$ENDIF}
  26. globtype,
  27. finput;
  28. const
  29. { RHIDE expect gcc like error output }
  30. fatalstr : string[6] = 'Fatal:';
  31. errorstr : string[6] = 'Error:';
  32. warningstr : string[8] = 'Warning:';
  33. notestr : string[5] = 'Note:';
  34. hintstr : string[5] = 'Hint:';
  35. warningerrorstr : string[29] = 'Warning: (treated as error)';
  36. noteerrorstr : string[27] = 'Note: (treated as error)';
  37. hinterrorstr : string[27] = 'Hint: (treated as error)';
  38. type
  39. PCompilerStatus = ^TCompilerStatus;
  40. TCompilerStatus = record
  41. { Current status }
  42. currentmodule,
  43. currentsourceppufilename, { the name of the ppu where the source file
  44. comes from where the error location is given }
  45. currentsourcepath,
  46. currentsource : string; { filename }
  47. currentline,
  48. currentcolumn : longint; { current line and column }
  49. currentmodulestate : string[20];
  50. { Total Status }
  51. compiledlines : longint; { the number of lines which are compiled }
  52. errorcount, { this field should never be increased directly,
  53. use Verbose.GenerateError procedure to do this,
  54. this allows easier error catching using GDB by
  55. adding a single breakpoint at this procedure }
  56. countWarnings,
  57. countNotes,
  58. countHints : longint; { number of found errors/warnings/notes/hints }
  59. codesize,
  60. datasize : qword;
  61. { program info }
  62. isexe,
  63. ispackage,
  64. islibrary : boolean;
  65. { Settings for the output }
  66. showmsgnrs : boolean;
  67. verbosity : longint;
  68. maxerrorcount : longint;
  69. errorwarning,
  70. errornote,
  71. errorhint,
  72. skip_error,
  73. use_stderr,
  74. use_redir,
  75. use_bugreport,
  76. use_gccoutput,
  77. sources_avail,
  78. print_source_path : boolean;
  79. { Redirection support }
  80. redirfile : text;
  81. { Special file for bug report }
  82. reportbugfile : text;
  83. end;
  84. type
  85. EControlCAbort=class(Exception)
  86. constructor Create;
  87. end;
  88. ECompilerAbort=class(Exception)
  89. constructor Create;
  90. end;
  91. ECompilerAbortSilent=class(Exception)
  92. constructor Create;
  93. end;
  94. var
  95. status : tcompilerstatus;
  96. { Default Functions }
  97. Function def_status:boolean;
  98. Function def_comment(Level:Longint;const s:ansistring):boolean;
  99. function def_internalerror(i:longint):boolean;
  100. function def_internalerrorEx(i:longint;const s:ansistring):boolean;
  101. function def_CheckVerbosity(v:longint):boolean;
  102. procedure def_initsymbolinfo;
  103. procedure def_donesymbolinfo;
  104. procedure def_extractsymbolinfo;
  105. function def_openinputfile(const filename: TPathStr): tinputfile;
  106. Function def_getnamedfiletime(Const F : TPathStr) : Longint;
  107. { Function redirecting for IDE support }
  108. type
  109. tstopprocedure = procedure(err:longint);
  110. tstatusfunction = function:boolean;
  111. tcommentfunction = function(Level:Longint;const s:ansistring):boolean;
  112. tinternalerrorfunction = function(i:longint):boolean;
  113. tinternalerrorexfunction = function(i:longint; const s : ansistring):boolean;
  114. tcheckverbosityfunction = function(i:longint):boolean;
  115. tinitsymbolinfoproc = procedure;
  116. tdonesymbolinfoproc = procedure;
  117. textractsymbolinfoproc = procedure;
  118. topeninputfilefunc = function(const filename: TPathStr): tinputfile;
  119. tgetnamedfiletimefunc = function(const filename: TPathStr): longint;
  120. const
  121. do_status : tstatusfunction = @def_status;
  122. do_comment : tcommentfunction = @def_comment;
  123. do_internalerror : tinternalerrorfunction = @def_internalerror deprecated 'use do_internalerrorex';
  124. do_internalerrorex : tinternalerrorexfunction = @def_internalerrorex;
  125. do_checkverbosity : tcheckverbosityfunction = @def_checkverbosity;
  126. do_initsymbolinfo : tinitsymbolinfoproc = @def_initsymbolinfo;
  127. do_donesymbolinfo : tdonesymbolinfoproc = @def_donesymbolinfo;
  128. do_extractsymbolinfo : textractsymbolinfoproc = @def_extractsymbolinfo;
  129. needsymbolinfo : boolean =false;
  130. do_openinputfile : topeninputfilefunc = @def_openinputfile;
  131. do_getnamedfiletime : tgetnamedfiletimefunc = @def_getnamedfiletime;
  132. implementation
  133. uses
  134. cutils, systems, globals, comptty;
  135. {****************************************************************************
  136. Helper Routines
  137. ****************************************************************************}
  138. function gccfilename(const s : string) : string;
  139. var
  140. i : longint;
  141. begin
  142. for i:=1to length(s) do
  143. begin
  144. case s[i] of
  145. '\' : gccfilename[i]:='/';
  146. 'A'..'Z' : if not (tf_files_case_aware in source_info.flags) and
  147. not (tf_files_case_sensitive in source_info.flags) then
  148. gccfilename[i]:=chr(ord(s[i])+32)
  149. else
  150. gccfilename[i]:=s[i];
  151. else
  152. gccfilename[i]:=s[i];
  153. end;
  154. end;
  155. gccfilename[0]:=s[0];
  156. end;
  157. function tostr(i : longint) : string;
  158. var
  159. hs : string;
  160. begin
  161. str(i,hs);
  162. tostr:=hs;
  163. end;
  164. type
  165. TOutputColor = (oc_black,oc_red,oc_green,oc_orange,oc_blue,oc_magenta,oc_cyan,oc_lightgray);
  166. procedure WriteColoredOutput(var t: Text;color: TOutputColor;const s : AnsiString);
  167. begin
  168. if TTYCheckSupported and IsATTY(t) then
  169. begin
  170. case color of
  171. oc_black:
  172. write(t,#27'[1m'#27'[30m');
  173. oc_red:
  174. write(t,#27'[1m'#27'[31m');
  175. oc_green:
  176. write(t,#27'[1m'#27'[32m');
  177. oc_orange:
  178. write(t,#27'[1m'#27'[33m');
  179. oc_blue:
  180. write(t,#27'[1m'#27'[34m');
  181. oc_magenta:
  182. write(t,#27'[1m'#27'[35m');
  183. oc_cyan:
  184. write(t,#27'[1m'#27'[36m');
  185. oc_lightgray:
  186. write(t,#27'[1m'#27'[37m');
  187. end;
  188. end;
  189. write(t,s);
  190. if TTYCheckSupported and IsATTY(t) then
  191. write(t,#27'[0m');
  192. end;
  193. {****************************************************************************
  194. Stopping the compiler
  195. ****************************************************************************}
  196. constructor EControlCAbort.Create;
  197. begin
  198. inherited Create('Ctrl-C Signaled!');
  199. end;
  200. constructor ECompilerAbort.Create;
  201. begin
  202. inherited Create('Compilation Aborted');
  203. end;
  204. constructor ECompilerAbortSilent.Create;
  205. begin
  206. inherited Create('Compilation Aborted');
  207. end;
  208. {****************************************************************************
  209. Predefined default Handlers
  210. ****************************************************************************}
  211. function def_status:boolean;
  212. var
  213. hstatus : TFPCHeapStatus;
  214. begin
  215. def_status:=false; { never stop }
  216. { Status info?, Called every line }
  217. if ((status.verbosity and V_Status)<>0) then
  218. begin
  219. if (status.compiledlines=1) or
  220. (status.currentline mod 100=0) then
  221. begin
  222. if status.currentline>0 then
  223. Write(status.currentmodule,':',status.currentline,' ');
  224. hstatus:=GetFPCHeapStatus;
  225. WriteLn(DStr(hstatus.CurrHeapUsed shr 10),'/',DStr(hstatus.CurrHeapSize shr 10),' Kb Used');
  226. flush(output);
  227. end;
  228. end;
  229. {$ifdef macos}
  230. Yield;
  231. {$endif}
  232. end;
  233. Function def_comment(Level:Longint;const s:ansistring):boolean;
  234. const
  235. rh_errorstr = 'error:';
  236. rh_warningstr = 'warning:';
  237. procedure WriteMsgTypeColored(var t : text;const s : AnsiString);
  238. begin
  239. case (status.verbosity and Level) of
  240. V_Warning:
  241. WriteColoredOutput(t,oc_magenta,s);
  242. V_Error,
  243. V_Fatal:
  244. WriteColoredOutput(t,oc_red,s);
  245. else
  246. write(t,s);
  247. end;
  248. end;
  249. var
  250. hs2,
  251. MsgTypeStr,
  252. MsgLocStr,
  253. MsgTimeStr: AnsiString;
  254. begin
  255. def_comment:=false; { never stop }
  256. MsgTypeStr:='';
  257. MsgLocStr:='';
  258. MsgTimeStr:='';
  259. if not(status.use_gccoutput) then
  260. begin
  261. if (status.verbosity and Level)=V_Hint then
  262. if status.errorhint then
  263. MsgTypeStr:=hinterrorstr
  264. else
  265. MsgTypeStr:=hintstr;
  266. if (status.verbosity and Level)=V_Note then
  267. if status.errornote then
  268. MsgTypeStr:=noteerrorstr
  269. else
  270. MsgTypeStr:=notestr;
  271. if (status.verbosity and Level)=V_Warning then
  272. if status.errorwarning then
  273. MsgTypeStr:=warningerrorstr
  274. else
  275. MsgTypeStr:=warningstr;
  276. if (status.verbosity and Level)=V_Error then
  277. MsgTypeStr:=errorstr;
  278. if (status.verbosity and Level)=V_Fatal then
  279. MsgTypeStr:=fatalstr;
  280. if (status.verbosity and V_Parallel)=V_Parallel then
  281. begin
  282. if (inputfilename<>'') and (status.currentmodule<>'') then
  283. MsgTypeStr:=MsgTypeStr+'('+inputfilename+'/'+status.currentmodule+')'
  284. else if (status.currentmodule<>'') then
  285. MsgTypeStr:=MsgTypeStr+'('+status.currentmodule+')'
  286. else if (inputfilename<>'') then
  287. MsgTypeStr:=MsgTypeStr+'('+inputfilename+')';
  288. end
  289. else if (status.verbosity and Level)=V_Used then
  290. MsgTypeStr:=PadSpace('('+status.currentmodule+')',10);
  291. end
  292. else
  293. begin
  294. if (status.verbosity and Level)=V_Hint then
  295. MsgTypeStr:=rh_warningstr;
  296. if (status.verbosity and Level)=V_Note then
  297. MsgTypeStr:=rh_warningstr;
  298. if (status.verbosity and Level)=V_Warning then
  299. MsgTypeStr:=rh_warningstr;
  300. if (status.verbosity and Level)=V_Error then
  301. MsgTypeStr:=rh_errorstr;
  302. if (status.verbosity and Level)=V_Fatal then
  303. MsgTypeStr:=rh_errorstr;
  304. end;
  305. { Generate line prefix }
  306. if ((Level and V_LineInfo)=V_LineInfo) and
  307. (status.currentsource<>'') and
  308. (status.currentline>0) then
  309. begin
  310. {$ifndef macos}
  311. { Adding the column should not confuse RHIDE,
  312. even if it does not yet use it PM
  313. but only if it is after error or warning !! PM }
  314. if status.currentcolumn>0 then
  315. begin
  316. if status.use_gccoutput then
  317. MsgLocStr:=gccfilename(status.currentsource)+':'+tostr(status.currentline)+':'+tostr(status.currentcolumn)+':'
  318. else
  319. MsgLocStr:=status.currentsource+'('+tostr(status.currentline)+','+tostr(status.currentcolumn)+')';
  320. end
  321. else
  322. begin
  323. if status.use_gccoutput then
  324. MsgLocStr:=gccfilename(status.currentsource)+':'+tostr(status.currentline)+':'
  325. else
  326. MsgLocStr:=status.currentsource+'('+tostr(status.currentline)+')';
  327. end;
  328. if status.print_source_path then
  329. if status.sources_avail then
  330. MsgLocStr:=status.currentsourcepath+MsgLocStr
  331. else
  332. MsgLocStr:=status.currentsourceppufilename+':'+MsgLocStr;
  333. {$else macos}
  334. { MPW style error }
  335. if status.currentcolumn>0 then
  336. MsgLocStr:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+' #[' + tostr(status.currentcolumn) + ']'
  337. else
  338. MsgLocStr:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+' # ';
  339. {$endif macos}
  340. end;
  341. if MsgLocStr<>'' then
  342. MsgLocStr:=MsgLocStr+' ';
  343. if MsgTypeStr<>'' then
  344. MsgTypeStr:=MsgTypeStr+' ';
  345. if (status.verbosity and V_TimeStamps)<>0 then
  346. begin
  347. system.str(getrealtime-starttime:0:3,hs2);
  348. MsgTimeStr:='['+hs2+'] ';
  349. end;
  350. { Display line }
  351. if (Level<>V_None) and
  352. ((status.verbosity and (Level and V_LevelMask))=(Level and V_LevelMask)) then
  353. begin
  354. if status.use_stderr then
  355. begin
  356. write(StdErr,MsgTimeStr+MsgLocStr);
  357. WriteMsgTypeColored(StdErr,MsgTypeStr);
  358. writeln(StdErr,s);
  359. flush(StdErr);
  360. end
  361. else
  362. begin
  363. if status.use_redir then
  364. begin
  365. writeln(status.redirfile,MsgTimeStr+MsgLocStr+MsgTypeStr+s);
  366. flush(status.redirfile);
  367. end
  368. else
  369. begin
  370. write(MsgTimeStr+MsgLocStr);
  371. WriteMsgTypeColored(Output,MsgTypeStr);
  372. writeln(s);
  373. end;
  374. end;
  375. end;
  376. { include everything in the bugreport file }
  377. if status.use_bugreport then
  378. begin
  379. Write(status.reportbugfile,hexstr(level,8)+':');
  380. Writeln(status.reportbugfile,MsgTimeStr+MsgLocStr+MsgTypeStr+s);
  381. end;
  382. end;
  383. function def_internalerror(i : longint) : boolean;
  384. begin
  385. result:=def_internalerrorex(i,'');
  386. end;
  387. function def_internalerrorex(i : longint; const s : ansistring) : boolean;
  388. var
  389. msg : ansistring;
  390. begin
  391. msg:=S;
  392. if msg<>'' then
  393. msg:=': '+msg;
  394. msg:='Internal error '+tostr(i)+msg;
  395. do_comment(V_Fatal+V_LineInfo,msg);
  396. {$ifdef EXTDEBUG}
  397. { Internalerror() and def_internalerror() do not
  398. have a stackframe }
  399. dump_stack(stdout,get_caller_frame(get_frame));
  400. {$endif EXTDEBUG}
  401. def_internalerrorex:=true;
  402. end;
  403. function def_CheckVerbosity(v:longint):boolean;
  404. begin
  405. result:=status.use_bugreport or
  406. ((v<>V_None) and
  407. ((status.verbosity and (v and V_LevelMask))=(v and V_LevelMask)));
  408. end;
  409. procedure def_initsymbolinfo;
  410. begin
  411. end;
  412. procedure def_donesymbolinfo;
  413. begin
  414. end;
  415. procedure def_extractsymbolinfo;
  416. begin
  417. end;
  418. function def_openinputfile(const filename: TPathStr): tinputfile;
  419. begin
  420. def_openinputfile:=tdosinputfile.create(filename);
  421. end;
  422. Function def_GetNamedFileTime (Const F : TPathStr) : Longint;
  423. begin
  424. Result:=FileAge(F);
  425. end;
  426. end.