verbose.pas 16 KB

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