verbose.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  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. {$else }
  28. Const
  29. MsgCRCValue : longint = 0;
  30. {$endif}
  31. {$i msgidx.inc}
  32. Const
  33. { <$10000 will show file and line }
  34. V_None = $0;
  35. V_Fatal = $1;
  36. V_Error = $2;
  37. V_Normal = $4; { doesn't show a text like Error: }
  38. V_Warning = $8;
  39. V_Note = $10;
  40. V_Hint = $20;
  41. V_Macro = $100;
  42. V_Procedure = $200;
  43. V_Conditional = $400;
  44. V_Assem = $800;
  45. V_Info = $10000;
  46. V_Status = $20000;
  47. V_Used = $40000;
  48. V_Tried = $80000;
  49. V_Debug = $100000;
  50. V_Declarations = $200000;
  51. V_Executable = $400000;
  52. V_ShowFile = $ffff;
  53. V_All = $ffffffff;
  54. V_Default = V_Fatal + V_Error + V_Normal;
  55. var
  56. msg : pmessage;
  57. procedure SetRedirectFile(const fn:string);
  58. function SetVerbosity(const s:string):boolean;
  59. procedure LoadMsgFile(const fn:string);
  60. procedure Stop;
  61. procedure ShowStatus;
  62. function ErrorCount:longint;
  63. procedure SetErrorFlags(const s:string);
  64. procedure GenerateError;
  65. procedure Internalerror(i:longint);
  66. procedure Comment(l:longint;s:string);
  67. procedure Message(w:tmsgconst);
  68. procedure Message1(w:tmsgconst;const s1:string);
  69. procedure Message2(w:tmsgconst;const s1,s2:string);
  70. procedure Message3(w:tmsgconst;const s1,s2,s3:string);
  71. procedure MessagePos(const pos:tfileposinfo;w:tmsgconst);
  72. procedure MessagePos1(const pos:tfileposinfo;w:tmsgconst;const s1:string);
  73. procedure MessagePos2(const pos:tfileposinfo;w:tmsgconst;const s1,s2:string);
  74. procedure MessagePos3(const pos:tfileposinfo;w:tmsgconst;const s1,s2,s3:string);
  75. procedure InitVerbose;
  76. procedure DoneVerbose;
  77. implementation
  78. uses
  79. files,comphook,
  80. version,globals;
  81. var
  82. redirexitsave : pointer;
  83. {****************************************************************************
  84. Extra Handlers for default compiler
  85. ****************************************************************************}
  86. procedure DoneRedirectFile;{$ifndef FPC}far;{$ENDIF}
  87. begin
  88. exitproc:=redirexitsave;
  89. if status.use_redir then
  90. close(status.redirfile);
  91. end;
  92. procedure SetRedirectFile(const fn:string);
  93. begin
  94. assign(status.redirfile,fn);
  95. {$I-}
  96. append(status.redirfile);
  97. if ioresult <> 0 then
  98. rewrite(status.redirfile);
  99. {$I+}
  100. status.use_redir:=(ioresult=0);
  101. if status.use_redir then
  102. begin
  103. redirexitsave:=exitproc;
  104. exitproc:=@DoneRedirectFile;
  105. end;
  106. end;
  107. function SetVerbosity(const s:string):boolean;
  108. var
  109. m : Longint;
  110. i : Integer;
  111. inverse : boolean;
  112. c : char;
  113. begin
  114. Setverbosity:=false;
  115. val(s,m,i);
  116. if (i=0) and (s<>'') then
  117. status.verbosity:=m
  118. else
  119. begin
  120. i:=1;
  121. while i<=length(s) do
  122. begin
  123. c:=upcase(s[i]);
  124. inverse:=false;
  125. { on/off ? }
  126. if (i<length(s)) then
  127. case s[i+1] of
  128. '-' : begin
  129. inc(i);
  130. inverse:=true;
  131. end;
  132. '+' : inc(i);
  133. end;
  134. { handle switch }
  135. case c of
  136. { Special cases }
  137. 'A' : status.verbosity:=V_All;
  138. '0' : status.verbosity:=V_Default;
  139. 'R' : begin
  140. if inverse then
  141. begin
  142. status.use_gccoutput:=false;
  143. status.use_stderr:=false;
  144. end
  145. else
  146. begin
  147. status.use_gccoutput:=true;
  148. status.use_stderr:=true;
  149. end;
  150. end;
  151. { Normal cases - do an or }
  152. 'E' : if inverse then
  153. status.verbosity:=status.verbosity and (not V_Error)
  154. else
  155. status.verbosity:=status.verbosity or V_Error;
  156. 'I' : if inverse then
  157. status.verbosity:=status.verbosity and (not V_Info)
  158. else
  159. status.verbosity:=status.verbosity or V_Info;
  160. 'W' : if inverse then
  161. status.verbosity:=status.verbosity and (not V_Warning)
  162. else
  163. status.verbosity:=status.verbosity or V_Warning;
  164. 'N' : if inverse then
  165. status.verbosity:=status.verbosity and (not V_Note)
  166. else
  167. status.verbosity:=status.verbosity or V_Note;
  168. 'H' : if inverse then
  169. status.verbosity:=status.verbosity and (not V_Hint)
  170. else
  171. status.verbosity:=status.verbosity or V_Hint;
  172. 'L' : if inverse then
  173. status.verbosity:=status.verbosity and (not V_Status)
  174. else
  175. status.verbosity:=status.verbosity or V_Status;
  176. 'U' : if inverse then
  177. status.verbosity:=status.verbosity and (not V_Used)
  178. else
  179. status.verbosity:=status.verbosity or V_Used;
  180. 'T' : if inverse then
  181. status.verbosity:=status.verbosity and (not V_Tried)
  182. else
  183. status.verbosity:=status.verbosity or V_Tried;
  184. 'M' : if inverse then
  185. status.verbosity:=status.verbosity and (not V_Macro)
  186. else
  187. status.verbosity:=status.verbosity or V_Macro;
  188. 'P' : if inverse then
  189. status.verbosity:=status.verbosity and (not V_Procedure)
  190. else
  191. status.verbosity:=status.verbosity or V_Procedure;
  192. 'C' : if inverse then
  193. status.verbosity:=status.verbosity and (not V_Conditional)
  194. else
  195. status.verbosity:=status.verbosity or V_Conditional;
  196. 'D' : if inverse then
  197. status.verbosity:=status.verbosity and (not V_Debug)
  198. else
  199. status.verbosity:=status.verbosity or V_Debug;
  200. 'B' : if inverse then
  201. status.verbosity:=status.verbosity and (not V_Declarations)
  202. else
  203. status.verbosity:=status.verbosity or V_Declarations;
  204. 'X' : if inverse then
  205. status.verbosity:=status.verbosity and (not V_Executable)
  206. else
  207. status.verbosity:=status.verbosity or V_Executable;
  208. 'Z' : if inverse then
  209. status.verbosity:=status.verbosity and (not V_Assem)
  210. else
  211. status.verbosity:=status.verbosity or V_Assem;
  212. end;
  213. inc(i);
  214. end;
  215. end;
  216. if status.verbosity=0 then
  217. status.verbosity:=V_Default;
  218. setverbosity:=true;
  219. end;
  220. procedure LoadMsgFile(const fn:string);
  221. begin
  222. if not(msg=nil) then
  223. dispose(msg,Done);
  224. msg:=new(pmessage,InitExtern(fn,ord(endmsgconst)));
  225. {$IFDEF TP}
  226. if msg=nil then
  227. begin
  228. writeln('Fatal: Cannot find error message file.');
  229. halt(3);
  230. end;
  231. {$ELSE}
  232. if msg=nil then
  233. msg:=new(pmessage,Init(@msgtxt,ord(endmsgconst)));
  234. {$ENDIF TP}
  235. end;
  236. var
  237. lastfileidx,
  238. lastmoduleidx : longint;
  239. Procedure UpdateStatus;
  240. begin
  241. { fix status }
  242. status.currentline:=aktfilepos.line;
  243. status.currentcolumn:=aktfilepos.column;
  244. if assigned(current_module) and assigned(current_module^.sourcefiles) and
  245. ((current_module^.unit_index<>lastmoduleidx) or
  246. (aktfilepos.fileindex<>lastfileidx)) then
  247. begin
  248. { update status record }
  249. status.currentmodule:=current_module^.modulename^;
  250. status.currentsource:=current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex);
  251. status.currentsourcepath:=current_module^.sourcefiles^.get_file_path(aktfilepos.fileindex);
  252. { update lastfileidx only if name known PM }
  253. if status.currentsource<>'' then
  254. lastfileidx:=aktfilepos.fileindex
  255. else
  256. lastfileidx:=0;
  257. lastmoduleidx:=current_module^.unit_index;
  258. end;
  259. end;
  260. procedure stop;
  261. begin
  262. {$ifndef TP}
  263. do_stop();
  264. {$else}
  265. do_stop;
  266. {$endif}
  267. end;
  268. procedure ShowStatus;
  269. begin
  270. UpdateStatus;
  271. {$ifndef TP}
  272. if do_status() then
  273. stop;
  274. {$else}
  275. if do_status then
  276. stop;
  277. {$endif}
  278. end;
  279. function ErrorCount:longint;
  280. begin
  281. ErrorCount:=status.errorcount;
  282. end;
  283. procedure SetErrorFlags(const s:string);
  284. var
  285. code : integer;
  286. i,j,l : longint;
  287. begin
  288. { empty string means error count = 1 for backward compatibility (PFV) }
  289. if s='' then
  290. begin
  291. status.maxerrorcount:=1;
  292. exit;
  293. end;
  294. i:=0;
  295. while (i<length(s)) do
  296. begin
  297. inc(i);
  298. case s[i] of
  299. '0'..'9' :
  300. begin
  301. j:=i;
  302. while (j<=length(s)) and (s[j] in ['0'..'9']) do
  303. inc(j);
  304. val(copy(s,i,j-i),l,code);
  305. if code<>0 then
  306. l:=1;
  307. status.maxerrorcount:=l;
  308. i:=j;
  309. end;
  310. 'w','W' :
  311. status.errorwarning:=true;
  312. 'n','N' :
  313. status.errornote:=true;
  314. 'h','H' :
  315. status.errorhint:=true;
  316. end;
  317. end;
  318. end;
  319. procedure GenerateError;
  320. begin
  321. inc(status.errorcount);
  322. end;
  323. procedure internalerror(i : longint);
  324. begin
  325. UpdateStatus;
  326. do_internalerror(i);
  327. inc(status.errorcount);
  328. stop;
  329. end;
  330. procedure Comment(l:longint;s:string);
  331. var
  332. dostop : boolean;
  333. begin
  334. dostop:=((l and V_Fatal)<>0);
  335. if ((l and V_Error)<>0) or
  336. (status.errorwarning and ((l and V_Warning)<>0)) or
  337. (status.errornote and ((l and V_Note)<>0)) or
  338. (status.errorhint and ((l and V_Hint)<>0)) then
  339. inc(status.errorcount);
  340. { Create status info }
  341. UpdateStatus;
  342. { Fix replacements }
  343. DefaultReplacements(s);
  344. { show comment }
  345. if do_comment(l,s) or dostop then
  346. stop;
  347. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  348. begin
  349. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  350. status.skip_error:=true;
  351. stop;
  352. end;
  353. end;
  354. Procedure Msg2Comment(s:string);
  355. var
  356. idx,i,v : longint;
  357. dostop : boolean;
  358. begin
  359. {Reset}
  360. dostop:=false;
  361. v:=0;
  362. {Parse options}
  363. idx:=pos('_',s);
  364. if idx=0 then
  365. v:=V_Normal
  366. else
  367. if (idx >= 1) And (idx <= 5) then
  368. begin
  369. for i:=1 to idx do
  370. begin
  371. case upcase(s[i]) of
  372. 'F' :
  373. begin
  374. v:=v or V_Fatal;
  375. inc(status.errorcount);
  376. dostop:=true;
  377. end;
  378. 'E' :
  379. begin
  380. v:=v or V_Error;
  381. inc(status.errorcount);
  382. end;
  383. 'O' :
  384. v:=v or V_Normal;
  385. 'W':
  386. begin
  387. v:=v or V_Warning;
  388. if status.errorwarning then
  389. inc(status.errorcount);
  390. end;
  391. 'N' :
  392. begin
  393. v:=v or V_Note;
  394. if status.errornote then
  395. inc(status.errorcount);
  396. end;
  397. 'H' :
  398. begin
  399. v:=v or V_Hint;
  400. if status.errorhint then
  401. inc(status.errorcount);
  402. end;
  403. 'I' :
  404. v:=v or V_Info;
  405. 'L' :
  406. v:=v or V_Status;
  407. 'U' :
  408. v:=v or V_Used;
  409. 'T' :
  410. v:=v or V_Tried;
  411. 'M' :
  412. v:=v or V_Macro;
  413. 'P' :
  414. v:=v or V_Procedure;
  415. 'C' :
  416. v:=v or V_Conditional;
  417. 'D' :
  418. v:=v or V_Debug;
  419. 'B' :
  420. v:=v or V_Declarations;
  421. 'X' :
  422. v:=v or V_Executable;
  423. 'Z' :
  424. v:=v or V_Assem;
  425. 'S' :
  426. dostop:=true;
  427. '_' : ;
  428. end;
  429. end;
  430. end;
  431. Delete(s,1,idx);
  432. { fix status }
  433. UpdateStatus;
  434. { Fix replacements }
  435. DefaultReplacements(s);
  436. { show comment }
  437. if do_comment(v,s) or dostop then
  438. stop;
  439. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  440. begin
  441. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  442. status.skip_error:=true;
  443. stop;
  444. end;
  445. end;
  446. procedure Message(w:tmsgconst);
  447. begin
  448. Msg2Comment(msg^.Get(ord(w)));
  449. end;
  450. procedure Message1(w:tmsgconst;const s1:string);
  451. begin
  452. Msg2Comment(msg^.Get1(ord(w),s1));
  453. end;
  454. procedure Message2(w:tmsgconst;const s1,s2:string);
  455. begin
  456. Msg2Comment(msg^.Get2(ord(w),s1,s2));
  457. end;
  458. procedure Message3(w:tmsgconst;const s1,s2,s3:string);
  459. begin
  460. Msg2Comment(msg^.Get3(ord(w),s1,s2,s3));
  461. end;
  462. procedure MessagePos(const pos:tfileposinfo;w:tmsgconst);
  463. var
  464. oldpos : tfileposinfo;
  465. begin
  466. oldpos:=aktfilepos;
  467. aktfilepos:=pos;
  468. Msg2Comment(msg^.Get(ord(w)));
  469. aktfilepos:=oldpos;
  470. end;
  471. procedure MessagePos1(const pos:tfileposinfo;w:tmsgconst;const s1:string);
  472. var
  473. oldpos : tfileposinfo;
  474. begin
  475. oldpos:=aktfilepos;
  476. aktfilepos:=pos;
  477. Msg2Comment(msg^.Get1(ord(w),s1));
  478. aktfilepos:=oldpos;
  479. end;
  480. procedure MessagePos2(const pos:tfileposinfo;w:tmsgconst;const s1,s2:string);
  481. var
  482. oldpos : tfileposinfo;
  483. begin
  484. oldpos:=aktfilepos;
  485. aktfilepos:=pos;
  486. Msg2Comment(msg^.Get2(ord(w),s1,s2));
  487. aktfilepos:=oldpos;
  488. end;
  489. procedure MessagePos3(const pos:tfileposinfo;w:tmsgconst;const s1,s2,s3:string);
  490. var
  491. oldpos : tfileposinfo;
  492. begin
  493. oldpos:=aktfilepos;
  494. aktfilepos:=pos;
  495. Msg2Comment(msg^.Get3(ord(w),s1,s2,s3));
  496. aktfilepos:=oldpos;
  497. end;
  498. procedure InitVerbose;
  499. begin
  500. { Init }
  501. {$ifndef EXTERN_MSG}
  502. msg:=new(pmessage,Init(@msgtxt,ord(endmsgconst)));
  503. {$else}
  504. LoadMsgFile(exepath+'errore.msg');
  505. {$endif}
  506. FillChar(Status,sizeof(TCompilerStatus),0);
  507. status.verbosity:=V_Default;
  508. Status.MaxErrorCount:=50;
  509. end;
  510. procedure DoneVerbose;
  511. begin
  512. if assigned(msg) then
  513. begin
  514. dispose(msg,Done);
  515. msg:=nil;
  516. end;
  517. end;
  518. end.
  519. {
  520. $Log$
  521. Revision 1.53 2000-05-15 14:05:40 pierre
  522. Declare MsgCrcValue with cond EXTERN_MSG
  523. Revision 1.52 2000/05/10 19:20:23 pierre
  524. * Use integer third arg for val in SetErrorFlags
  525. to allow compilation with Delphi
  526. reported by Kovacs Attila Zoltan
  527. Revision 1.51 2000/05/10 13:40:19 peter
  528. * -Se<x> option extended to increase errorcount for
  529. warning,notes or hints
  530. Revision 1.50 2000/04/01 10:46:29 hajny
  531. * logfile appended if exists
  532. Revision 1.49 2000/03/12 08:24:45 daniel
  533. * Made check for message file TP compilable.
  534. Revision 1.48 2000/03/01 22:29:18 peter
  535. * message files are check for amount of msgs found. If not correct a
  536. line is written to stdout and switched to internal messages
  537. Revision 1.47 2000/03/01 21:45:42 peter
  538. * lowercase .INC -> .inc
  539. Revision 1.46 2000/02/28 17:23:57 daniel
  540. * Current work of symtable integration committed. The symtable can be
  541. activated by defining 'newst', but doesn't compile yet. Changes in type
  542. checking and oop are completed. What is left is to write a new
  543. symtablestack and adapt the parser to use it.
  544. Revision 1.45 2000/02/09 13:23:09 peter
  545. * log truncated
  546. Revision 1.44 2000/01/07 01:14:49 peter
  547. * updated copyright to 2000
  548. Revision 1.43 1999/11/06 14:34:32 peter
  549. * truncated log to 20 revs
  550. Revision 1.42 1999/08/05 16:53:28 peter
  551. * V_Fatal=1, all other V_ are also increased
  552. * Check for local procedure when assigning procvar
  553. * fixed comment parsing because directives
  554. * oldtp mode directives better supported
  555. * added some messages to errore.msg
  556. }