verbose.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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. 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.55 2000-06-30 20:23:38 peter
  526. * new message files layout with msg numbers (but still no code to
  527. show the number on the screen)
  528. Revision 1.54 2000/05/23 20:32:48 peter
  529. * removed dup msgcrcvalue
  530. Revision 1.53 2000/05/15 14:05:40 pierre
  531. Declare MsgCrcValue with cond EXTERN_MSG
  532. Revision 1.52 2000/05/10 19:20:23 pierre
  533. * Use integer third arg for val in SetErrorFlags
  534. to allow compilation with Delphi
  535. reported by Kovacs Attila Zoltan
  536. Revision 1.51 2000/05/10 13:40:19 peter
  537. * -Se<x> option extended to increase errorcount for
  538. warning,notes or hints
  539. Revision 1.50 2000/04/01 10:46:29 hajny
  540. * logfile appended if exists
  541. Revision 1.49 2000/03/12 08:24:45 daniel
  542. * Made check for message file TP compilable.
  543. Revision 1.48 2000/03/01 22:29:18 peter
  544. * message files are check for amount of msgs found. If not correct a
  545. line is written to stdout and switched to internal messages
  546. Revision 1.47 2000/03/01 21:45:42 peter
  547. * lowercase .INC -> .inc
  548. Revision 1.46 2000/02/28 17:23:57 daniel
  549. * Current work of symtable integration committed. The symtable can be
  550. activated by defining 'newst', but doesn't compile yet. Changes in type
  551. checking and oop are completed. What is left is to write a new
  552. symtablestack and adapt the parser to use it.
  553. Revision 1.45 2000/02/09 13:23:09 peter
  554. * log truncated
  555. Revision 1.44 2000/01/07 01:14:49 peter
  556. * updated copyright to 2000
  557. Revision 1.43 1999/11/06 14:34:32 peter
  558. * truncated log to 20 revs
  559. Revision 1.42 1999/08/05 16:53:28 peter
  560. * V_Fatal=1, all other V_ are also increased
  561. * Check for local procedure when assigning procvar
  562. * fixed comment parsing because directives
  563. * oldtp mode directives better supported
  564. * added some messages to errore.msg
  565. }