verbose.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit handles the verbose management
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit verbose;
  19. interface
  20. uses
  21. messages,cobjects;
  22. {$ifdef TP}
  23. {$define EXTERN_MSG}
  24. {$endif}
  25. {$ifndef EXTERN_MSG}
  26. {$i msgtxt.inc}
  27. {$endif}
  28. {$i msgidx.inc}
  29. Const
  30. { <$10000 will show file and line }
  31. V_None = $0;
  32. V_Fatal = $1;
  33. V_Error = $2;
  34. V_Normal = $4; { doesn't show a text like Error: }
  35. V_Warning = $8;
  36. V_Note = $10;
  37. V_Hint = $20;
  38. V_Macro = $100;
  39. V_Procedure = $200;
  40. V_Conditional = $400;
  41. V_Assem = $800;
  42. V_Declarations = $1000;
  43. V_Info = $10000;
  44. V_Status = $20000;
  45. V_Used = $40000;
  46. V_Tried = $80000;
  47. V_Debug = $100000;
  48. V_Executable = $200000;
  49. V_ShowFile = $ffff;
  50. V_All = $ffffffff;
  51. V_Default = V_Fatal + V_Error + V_Normal;
  52. var
  53. msg : pmessage;
  54. procedure SetRedirectFile(const fn:string);
  55. function SetVerbosity(const s:string):boolean;
  56. procedure LoadMsgFile(const fn:string);
  57. procedure Stop;
  58. procedure ShowStatus;
  59. function ErrorCount:longint;
  60. procedure SetErrorFlags(const s:string);
  61. procedure GenerateError;
  62. procedure Internalerror(i:longint);
  63. procedure Comment(l:longint;s:string);
  64. function MessagePchar(w:longint):pchar;
  65. procedure Message(w:longint);
  66. procedure Message1(w:longint;const s1:string);
  67. procedure Message2(w:longint;const s1,s2:string);
  68. procedure Message3(w:longint;const s1,s2,s3:string);
  69. procedure MessagePos(const pos:tfileposinfo;w:longint);
  70. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  71. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  72. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  73. procedure InitVerbose;
  74. procedure DoneVerbose;
  75. implementation
  76. uses
  77. files,comphook,
  78. version,globals;
  79. var
  80. redirexitsave : pointer;
  81. {****************************************************************************
  82. Extra Handlers for default compiler
  83. ****************************************************************************}
  84. procedure DoneRedirectFile;{$ifndef FPC}far;{$ENDIF}
  85. begin
  86. exitproc:=redirexitsave;
  87. if status.use_redir then
  88. close(status.redirfile);
  89. end;
  90. procedure SetRedirectFile(const fn:string);
  91. begin
  92. assign(status.redirfile,fn);
  93. {$I-}
  94. append(status.redirfile);
  95. if ioresult <> 0 then
  96. rewrite(status.redirfile);
  97. {$I+}
  98. status.use_redir:=(ioresult=0);
  99. if status.use_redir then
  100. begin
  101. redirexitsave:=exitproc;
  102. exitproc:=@DoneRedirectFile;
  103. end;
  104. end;
  105. function SetVerbosity(const s:string):boolean;
  106. var
  107. m : Longint;
  108. i : Integer;
  109. inverse : boolean;
  110. c : char;
  111. begin
  112. Setverbosity:=false;
  113. val(s,m,i);
  114. if (i=0) and (s<>'') then
  115. status.verbosity:=m
  116. else
  117. begin
  118. i:=1;
  119. while i<=length(s) do
  120. begin
  121. c:=upcase(s[i]);
  122. inverse:=false;
  123. { on/off ? }
  124. if (i<length(s)) then
  125. case s[i+1] of
  126. '-' : begin
  127. inc(i);
  128. inverse:=true;
  129. end;
  130. '+' : inc(i);
  131. end;
  132. { handle switch }
  133. case c of
  134. { Special cases }
  135. 'A' : status.verbosity:=V_All;
  136. '0' : status.verbosity:=V_Default;
  137. 'R' : begin
  138. if inverse then
  139. begin
  140. status.use_gccoutput:=false;
  141. status.use_stderr:=false;
  142. end
  143. else
  144. begin
  145. status.use_gccoutput:=true;
  146. status.use_stderr:=true;
  147. end;
  148. end;
  149. { Normal cases - do an or }
  150. 'E' : if inverse then
  151. status.verbosity:=status.verbosity and (not V_Error)
  152. else
  153. status.verbosity:=status.verbosity or V_Error;
  154. 'I' : if inverse then
  155. status.verbosity:=status.verbosity and (not V_Info)
  156. else
  157. status.verbosity:=status.verbosity or V_Info;
  158. 'W' : if inverse then
  159. status.verbosity:=status.verbosity and (not V_Warning)
  160. else
  161. status.verbosity:=status.verbosity or V_Warning;
  162. 'N' : if inverse then
  163. status.verbosity:=status.verbosity and (not V_Note)
  164. else
  165. status.verbosity:=status.verbosity or V_Note;
  166. 'H' : if inverse then
  167. status.verbosity:=status.verbosity and (not V_Hint)
  168. else
  169. status.verbosity:=status.verbosity or V_Hint;
  170. 'L' : if inverse then
  171. status.verbosity:=status.verbosity and (not V_Status)
  172. else
  173. status.verbosity:=status.verbosity or V_Status;
  174. 'U' : if inverse then
  175. status.verbosity:=status.verbosity and (not V_Used)
  176. else
  177. status.verbosity:=status.verbosity or V_Used;
  178. 'T' : if inverse then
  179. status.verbosity:=status.verbosity and (not V_Tried)
  180. else
  181. status.verbosity:=status.verbosity or V_Tried;
  182. 'M' : if inverse then
  183. status.verbosity:=status.verbosity and (not V_Macro)
  184. else
  185. status.verbosity:=status.verbosity or V_Macro;
  186. 'P' : if inverse then
  187. status.verbosity:=status.verbosity and (not V_Procedure)
  188. else
  189. status.verbosity:=status.verbosity or V_Procedure;
  190. 'C' : if inverse then
  191. status.verbosity:=status.verbosity and (not V_Conditional)
  192. else
  193. status.verbosity:=status.verbosity or V_Conditional;
  194. 'D' : if inverse then
  195. status.verbosity:=status.verbosity and (not V_Debug)
  196. else
  197. status.verbosity:=status.verbosity or V_Debug;
  198. 'B' : if inverse then
  199. status.verbosity:=status.verbosity and (not V_Declarations)
  200. else
  201. status.verbosity:=status.verbosity or V_Declarations;
  202. 'X' : if inverse then
  203. status.verbosity:=status.verbosity and (not V_Executable)
  204. else
  205. status.verbosity:=status.verbosity or V_Executable;
  206. 'Z' : if inverse then
  207. status.verbosity:=status.verbosity and (not V_Assem)
  208. else
  209. status.verbosity:=status.verbosity or V_Assem;
  210. end;
  211. inc(i);
  212. end;
  213. end;
  214. if status.verbosity=0 then
  215. status.verbosity:=V_Default;
  216. setverbosity:=true;
  217. end;
  218. procedure LoadMsgFile(const fn:string);
  219. begin
  220. if not msg^.LoadExtern(fn) then
  221. begin
  222. {$IFDEF TP}
  223. writeln('Fatal: Cannot find error message file.');
  224. halt(3);
  225. {$ELSE}
  226. msg^.LoadIntern(@msgtxt,msgtxtsize);
  227. {$ENDIF TP}
  228. end;
  229. end;
  230. var
  231. lastfileidx,
  232. lastmoduleidx : longint;
  233. Procedure UpdateStatus;
  234. begin
  235. { fix status }
  236. status.currentline:=aktfilepos.line;
  237. status.currentcolumn:=aktfilepos.column;
  238. if assigned(current_module) and assigned(current_module^.sourcefiles) and
  239. ((current_module^.unit_index<>lastmoduleidx) or
  240. (aktfilepos.fileindex<>lastfileidx)) then
  241. begin
  242. { update status record }
  243. status.currentmodule:=current_module^.modulename^;
  244. status.currentsource:=current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex);
  245. status.currentsourcepath:=current_module^.sourcefiles^.get_file_path(aktfilepos.fileindex);
  246. { update lastfileidx only if name known PM }
  247. if status.currentsource<>'' then
  248. lastfileidx:=aktfilepos.fileindex
  249. else
  250. lastfileidx:=0;
  251. lastmoduleidx:=current_module^.unit_index;
  252. end;
  253. end;
  254. procedure stop;
  255. begin
  256. {$ifndef TP}
  257. do_stop();
  258. {$else}
  259. do_stop;
  260. {$endif}
  261. end;
  262. procedure ShowStatus;
  263. begin
  264. UpdateStatus;
  265. {$ifndef TP}
  266. if do_status() then
  267. stop;
  268. {$else}
  269. if do_status then
  270. stop;
  271. {$endif}
  272. end;
  273. function ErrorCount:longint;
  274. begin
  275. ErrorCount:=status.errorcount;
  276. end;
  277. procedure SetErrorFlags(const s:string);
  278. var
  279. code : integer;
  280. i,j,l : longint;
  281. begin
  282. { empty string means error count = 1 for backward compatibility (PFV) }
  283. if s='' then
  284. begin
  285. status.maxerrorcount:=1;
  286. exit;
  287. end;
  288. i:=0;
  289. while (i<length(s)) do
  290. begin
  291. inc(i);
  292. case s[i] of
  293. '0'..'9' :
  294. begin
  295. j:=i;
  296. while (j<=length(s)) and (s[j] in ['0'..'9']) do
  297. inc(j);
  298. val(copy(s,i,j-i),l,code);
  299. if code<>0 then
  300. l:=1;
  301. status.maxerrorcount:=l;
  302. i:=j;
  303. end;
  304. 'w','W' :
  305. status.errorwarning:=true;
  306. 'n','N' :
  307. status.errornote:=true;
  308. 'h','H' :
  309. status.errorhint:=true;
  310. end;
  311. end;
  312. end;
  313. procedure GenerateError;
  314. begin
  315. inc(status.errorcount);
  316. end;
  317. procedure internalerror(i : longint);
  318. begin
  319. UpdateStatus;
  320. do_internalerror(i);
  321. inc(status.errorcount);
  322. stop;
  323. end;
  324. procedure Comment(l:longint;s:string);
  325. var
  326. dostop : boolean;
  327. begin
  328. dostop:=((l and V_Fatal)<>0);
  329. if ((l and V_Error)<>0) or
  330. (status.errorwarning and ((l and V_Warning)<>0)) or
  331. (status.errornote and ((l and V_Note)<>0)) or
  332. (status.errorhint and ((l and V_Hint)<>0)) then
  333. inc(status.errorcount);
  334. { Create status info }
  335. UpdateStatus;
  336. { Fix replacements }
  337. DefaultReplacements(s);
  338. { show comment }
  339. if do_comment(l,s) or dostop then
  340. stop;
  341. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  342. begin
  343. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  344. status.skip_error:=true;
  345. stop;
  346. end;
  347. end;
  348. Procedure Msg2Comment(s:string);
  349. var
  350. idx,i,v : longint;
  351. dostop : boolean;
  352. begin
  353. {Reset}
  354. dostop:=false;
  355. v:=0;
  356. {Parse options}
  357. idx:=pos('_',s);
  358. if idx=0 then
  359. v:=V_Normal
  360. else
  361. if (idx >= 1) And (idx <= 5) then
  362. begin
  363. for i:=1 to idx do
  364. begin
  365. case upcase(s[i]) of
  366. 'F' :
  367. begin
  368. v:=v or V_Fatal;
  369. inc(status.errorcount);
  370. dostop:=true;
  371. end;
  372. 'E' :
  373. begin
  374. v:=v or V_Error;
  375. inc(status.errorcount);
  376. end;
  377. 'O' :
  378. v:=v or V_Normal;
  379. 'W':
  380. begin
  381. v:=v or V_Warning;
  382. if status.errorwarning then
  383. inc(status.errorcount);
  384. end;
  385. 'N' :
  386. begin
  387. v:=v or V_Note;
  388. if status.errornote then
  389. inc(status.errorcount);
  390. end;
  391. 'H' :
  392. begin
  393. v:=v or V_Hint;
  394. if status.errorhint then
  395. inc(status.errorcount);
  396. end;
  397. 'I' :
  398. v:=v or V_Info;
  399. 'L' :
  400. v:=v or V_Status;
  401. 'U' :
  402. v:=v or V_Used;
  403. 'T' :
  404. v:=v or V_Tried;
  405. 'M' :
  406. v:=v or V_Macro;
  407. 'P' :
  408. v:=v or V_Procedure;
  409. 'C' :
  410. v:=v or V_Conditional;
  411. 'D' :
  412. v:=v or V_Debug;
  413. 'B' :
  414. v:=v or V_Declarations;
  415. 'X' :
  416. v:=v or V_Executable;
  417. 'Z' :
  418. v:=v or V_Assem;
  419. 'S' :
  420. dostop:=true;
  421. '_' : ;
  422. end;
  423. end;
  424. end;
  425. Delete(s,1,idx);
  426. { fix status }
  427. UpdateStatus;
  428. { Fix replacements }
  429. DefaultReplacements(s);
  430. { show comment }
  431. if do_comment(v,s) or dostop then
  432. stop;
  433. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  434. begin
  435. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  436. status.skip_error:=true;
  437. stop;
  438. end;
  439. end;
  440. function MessagePchar(w:longint):pchar;
  441. begin
  442. MessagePchar:=msg^.GetPchar(w)
  443. end;
  444. procedure Message(w:longint);
  445. begin
  446. Msg2Comment(msg^.Get(w));
  447. end;
  448. procedure Message1(w:longint;const s1:string);
  449. begin
  450. Msg2Comment(msg^.Get1(w,s1));
  451. end;
  452. procedure Message2(w:longint;const s1,s2:string);
  453. begin
  454. Msg2Comment(msg^.Get2(w,s1,s2));
  455. end;
  456. procedure Message3(w:longint;const s1,s2,s3:string);
  457. begin
  458. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  459. end;
  460. procedure MessagePos(const pos:tfileposinfo;w:longint);
  461. var
  462. oldpos : tfileposinfo;
  463. begin
  464. oldpos:=aktfilepos;
  465. aktfilepos:=pos;
  466. Msg2Comment(msg^.Get(w));
  467. aktfilepos:=oldpos;
  468. end;
  469. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  470. var
  471. oldpos : tfileposinfo;
  472. begin
  473. oldpos:=aktfilepos;
  474. aktfilepos:=pos;
  475. Msg2Comment(msg^.Get1(w,s1));
  476. aktfilepos:=oldpos;
  477. end;
  478. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  479. var
  480. oldpos : tfileposinfo;
  481. begin
  482. oldpos:=aktfilepos;
  483. aktfilepos:=pos;
  484. Msg2Comment(msg^.Get2(w,s1,s2));
  485. aktfilepos:=oldpos;
  486. end;
  487. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  488. var
  489. oldpos : tfileposinfo;
  490. begin
  491. oldpos:=aktfilepos;
  492. aktfilepos:=pos;
  493. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  494. aktfilepos:=oldpos;
  495. end;
  496. procedure InitVerbose;
  497. begin
  498. { Init }
  499. msg:=new(pmessage,Init(20,msgidxmax));
  500. if msg=nil then
  501. begin
  502. writeln('Fatal: MsgIdx Wrong');
  503. halt(3);
  504. end;
  505. {$ifndef EXTERN_MSG}
  506. msg^.LoadIntern(@msgtxt,msgtxtsize);
  507. {$else}
  508. LoadMsgFile(exepath+'errore.msg');
  509. {$endif}
  510. FillChar(Status,sizeof(TCompilerStatus),0);
  511. status.verbosity:=V_Default;
  512. Status.MaxErrorCount:=50;
  513. end;
  514. procedure DoneVerbose;
  515. begin
  516. if assigned(msg) then
  517. begin
  518. dispose(msg,Done);
  519. msg:=nil;
  520. end;
  521. end;
  522. end.
  523. {
  524. $Log$
  525. Revision 1.3 2000-08-13 12:54:55 peter
  526. * class member decl wrong then no other error after it
  527. * -vb has now also line numbering
  528. * -vb is also used for interface/implementation different decls and
  529. doesn't list the current function (merged)
  530. Revision 1.2 2000/07/13 11:32:54 michael
  531. + removed logs
  532. }