verbose.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  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. {$i defines.inc}
  20. { Don't include messages in the executable }
  21. {.$define EXTERN_MSG}
  22. interface
  23. uses
  24. cutils,cobjects,
  25. globals,finput,
  26. messages;
  27. {$ifndef EXTERN_MSG}
  28. {$i msgtxt.inc}
  29. {$endif}
  30. {$i msgidx.inc}
  31. Const
  32. { <$10000 will show file and line }
  33. V_None = $0;
  34. V_Fatal = $1;
  35. V_Error = $2;
  36. V_Normal = $4; { doesn't show a text like Error: }
  37. V_Warning = $8;
  38. V_Note = $10;
  39. V_Hint = $20;
  40. V_Macro = $100;
  41. V_Procedure = $200;
  42. V_Conditional = $400;
  43. V_Assem = $800;
  44. V_Declarations = $1000;
  45. V_Info = $10000;
  46. V_Status = $20000;
  47. V_Used = $40000;
  48. V_Tried = $80000;
  49. V_Debug = $100000;
  50. V_Executable = $200000;
  51. V_ShowFile = $ffff;
  52. V_All = longint($ffffffff);
  53. V_Default = V_Fatal + V_Error + V_Normal;
  54. var
  55. msg : pmessage;
  56. const
  57. msgfilename : string = '';
  58. procedure SetRedirectFile(const fn:string);
  59. function SetVerbosity(const s:string):boolean;
  60. procedure SetCompileModule(p:tmodulebase);
  61. procedure Stop;
  62. procedure ShowStatus;
  63. function ErrorCount:longint;
  64. procedure SetErrorFlags(const s:string);
  65. procedure GenerateError;
  66. procedure Internalerror(i:longint);
  67. procedure Comment(l:longint;s:string);
  68. function MessagePchar(w:longint):pchar;
  69. procedure Message(w:longint);
  70. procedure Message1(w:longint;const s1:string);
  71. procedure Message2(w:longint;const s1,s2:string);
  72. procedure Message3(w:longint;const s1,s2,s3:string);
  73. procedure MessagePos(const pos:tfileposinfo;w:longint);
  74. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  75. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  76. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  77. procedure InitVerbose;
  78. procedure DoneVerbose;
  79. implementation
  80. uses
  81. comphook;
  82. var
  83. current_module : tmodulebase;
  84. {****************************************************************************
  85. Extra Handlers for default compiler
  86. ****************************************************************************}
  87. procedure DoneRedirectFile;
  88. begin
  89. if status.use_redir then
  90. begin
  91. close(status.redirfile);
  92. status.use_redir:=false;
  93. end;
  94. end;
  95. procedure SetRedirectFile(const fn:string);
  96. begin
  97. assign(status.redirfile,fn);
  98. {$I-}
  99. append(status.redirfile);
  100. if ioresult <> 0 then
  101. rewrite(status.redirfile);
  102. {$I+}
  103. status.use_redir:=(ioresult=0);
  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 LoadPrefixes;
  219. function loadprefix(w:longint):string;
  220. var
  221. s : string;
  222. idx : longint;
  223. begin
  224. s:=msg^.get(w);
  225. idx:=pos('_',s);
  226. if idx>0 then
  227. LoadPrefix:=Copy(s,idx+1,255)
  228. else
  229. LoadPrefix:=s;
  230. end;
  231. begin
  232. { Load the prefixes }
  233. fatalstr:=LoadPrefix(general_i_fatal);
  234. errorstr:=LoadPrefix(general_i_error);
  235. warningstr:=LoadPrefix(general_i_warning);
  236. notestr:=LoadPrefix(general_i_note);
  237. hintstr:=LoadPrefix(general_i_hint);
  238. end;
  239. procedure LoadMsgFile(const fn:string);
  240. begin
  241. { reload the internal messages if not already loaded }
  242. {$ifndef EXTERN_MSG}
  243. if not msg^.msgintern then
  244. msg^.LoadIntern(@msgtxt,msgtxtsize);
  245. {$endif}
  246. if not msg^.LoadExtern(fn) then
  247. begin
  248. {$ifdef EXTERN_MSG}
  249. writeln('Fatal: Cannot find error message file.');
  250. halt(3);
  251. {$else}
  252. msg^.LoadIntern(@msgtxt,msgtxtsize);
  253. {$endif}
  254. end;
  255. { reload the prefixes using the new messages }
  256. LoadPrefixes;
  257. end;
  258. procedure MaybeLoadMessageFile;
  259. begin
  260. { Load new message file }
  261. if (msgfilename<>'') then
  262. begin
  263. LoadMsgFile(msgfilename);
  264. msgfilename:='';
  265. end;
  266. end;
  267. procedure SetCompileModule(p:tmodulebase);
  268. begin
  269. current_module:=p;
  270. end;
  271. var
  272. lastfileidx,
  273. lastmoduleidx : longint;
  274. Procedure UpdateStatus;
  275. begin
  276. { fix status }
  277. status.currentline:=aktfilepos.line;
  278. status.currentcolumn:=aktfilepos.column;
  279. if assigned(current_module) and
  280. assigned(current_module.sourcefiles) and
  281. ((current_module.unit_index<>lastmoduleidx) or
  282. (aktfilepos.fileindex<>lastfileidx)) then
  283. begin
  284. { update status record }
  285. status.currentmodule:=current_module.modulename^;
  286. status.currentsource:=current_module.sourcefiles.get_file_name(aktfilepos.fileindex);
  287. status.currentsourcepath:=current_module.sourcefiles.get_file_path(aktfilepos.fileindex);
  288. { update lastfileidx only if name known PM }
  289. if status.currentsource<>'' then
  290. lastfileidx:=aktfilepos.fileindex
  291. else
  292. lastfileidx:=0;
  293. lastmoduleidx:=current_module.unit_index;
  294. end;
  295. end;
  296. procedure stop;
  297. begin
  298. do_stop{$ifdef FPCPROCVAR}(){$endif};
  299. end;
  300. procedure ShowStatus;
  301. begin
  302. UpdateStatus;
  303. if do_status{$ifdef FPCPROCVAR}(){$endif} then
  304. stop;
  305. end;
  306. function ErrorCount:longint;
  307. begin
  308. ErrorCount:=status.errorcount;
  309. end;
  310. procedure SetErrorFlags(const s:string);
  311. var
  312. code : integer;
  313. i,j,l : longint;
  314. begin
  315. { empty string means error count = 1 for backward compatibility (PFV) }
  316. if s='' then
  317. begin
  318. status.maxerrorcount:=1;
  319. exit;
  320. end;
  321. i:=0;
  322. while (i<length(s)) do
  323. begin
  324. inc(i);
  325. case s[i] of
  326. '0'..'9' :
  327. begin
  328. j:=i;
  329. while (j<=length(s)) and (s[j] in ['0'..'9']) do
  330. inc(j);
  331. val(copy(s,i,j-i),l,code);
  332. if code<>0 then
  333. l:=1;
  334. status.maxerrorcount:=l;
  335. i:=j;
  336. end;
  337. 'w','W' :
  338. status.errorwarning:=true;
  339. 'n','N' :
  340. status.errornote:=true;
  341. 'h','H' :
  342. status.errorhint:=true;
  343. end;
  344. end;
  345. end;
  346. procedure GenerateError;
  347. begin
  348. inc(status.errorcount);
  349. end;
  350. procedure internalerror(i : longint);
  351. begin
  352. UpdateStatus;
  353. do_internalerror(i);
  354. inc(status.errorcount);
  355. stop;
  356. end;
  357. procedure Comment(l:longint;s:string);
  358. var
  359. dostop : boolean;
  360. begin
  361. dostop:=((l and V_Fatal)<>0);
  362. if ((l and V_Error)<>0) or
  363. (status.errorwarning and ((l and V_Warning)<>0)) or
  364. (status.errornote and ((l and V_Note)<>0)) or
  365. (status.errorhint and ((l and V_Hint)<>0)) then
  366. inc(status.errorcount);
  367. { check verbosity level }
  368. if (status.verbosity and l)<>l then
  369. exit;
  370. { Create status info }
  371. UpdateStatus;
  372. { Fix replacements }
  373. DefaultReplacements(s);
  374. { show comment }
  375. if do_comment(l,s) or dostop then
  376. stop;
  377. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  378. begin
  379. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  380. status.skip_error:=true;
  381. stop;
  382. end;
  383. end;
  384. Procedure Msg2Comment(s:string);
  385. var
  386. idx,i,v : longint;
  387. dostop : boolean;
  388. begin
  389. {Reset}
  390. dostop:=false;
  391. v:=0;
  392. {Parse options}
  393. idx:=pos('_',s);
  394. if idx=0 then
  395. v:=V_Normal
  396. else
  397. if (idx >= 1) And (idx <= 5) then
  398. begin
  399. for i:=1 to idx do
  400. begin
  401. case upcase(s[i]) of
  402. 'F' :
  403. begin
  404. v:=v or V_Fatal;
  405. inc(status.errorcount);
  406. dostop:=true;
  407. end;
  408. 'E' :
  409. begin
  410. v:=v or V_Error;
  411. inc(status.errorcount);
  412. end;
  413. 'O' :
  414. v:=v or V_Normal;
  415. 'W':
  416. begin
  417. v:=v or V_Warning;
  418. if status.errorwarning then
  419. inc(status.errorcount);
  420. end;
  421. 'N' :
  422. begin
  423. v:=v or V_Note;
  424. if status.errornote then
  425. inc(status.errorcount);
  426. end;
  427. 'H' :
  428. begin
  429. v:=v or V_Hint;
  430. if status.errorhint then
  431. inc(status.errorcount);
  432. end;
  433. 'I' :
  434. v:=v or V_Info;
  435. 'L' :
  436. v:=v or V_Status;
  437. 'U' :
  438. v:=v or V_Used;
  439. 'T' :
  440. v:=v or V_Tried;
  441. 'M' :
  442. v:=v or V_Macro;
  443. 'P' :
  444. v:=v or V_Procedure;
  445. 'C' :
  446. v:=v or V_Conditional;
  447. 'D' :
  448. v:=v or V_Debug;
  449. 'B' :
  450. v:=v or V_Declarations;
  451. 'X' :
  452. v:=v or V_Executable;
  453. 'Z' :
  454. v:=v or V_Assem;
  455. 'S' :
  456. dostop:=true;
  457. '_' : ;
  458. end;
  459. end;
  460. end;
  461. Delete(s,1,idx);
  462. { check verbosity level }
  463. if (status.verbosity and v)<>v then
  464. exit;
  465. { fix status }
  466. UpdateStatus;
  467. { Fix replacements }
  468. DefaultReplacements(s);
  469. { show comment }
  470. if do_comment(v,s) or dostop then
  471. stop;
  472. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  473. begin
  474. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  475. status.skip_error:=true;
  476. stop;
  477. end;
  478. end;
  479. function MessagePchar(w:longint):pchar;
  480. begin
  481. MaybeLoadMessageFile;
  482. MessagePchar:=msg^.GetPchar(w)
  483. end;
  484. procedure Message(w:longint);
  485. begin
  486. MaybeLoadMessageFile;
  487. Msg2Comment(msg^.Get(w));
  488. end;
  489. procedure Message1(w:longint;const s1:string);
  490. begin
  491. MaybeLoadMessageFile;
  492. Msg2Comment(msg^.Get1(w,s1));
  493. end;
  494. procedure Message2(w:longint;const s1,s2:string);
  495. begin
  496. MaybeLoadMessageFile;
  497. Msg2Comment(msg^.Get2(w,s1,s2));
  498. end;
  499. procedure Message3(w:longint;const s1,s2,s3:string);
  500. begin
  501. MaybeLoadMessageFile;
  502. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  503. end;
  504. procedure MessagePos(const pos:tfileposinfo;w:longint);
  505. var
  506. oldpos : tfileposinfo;
  507. begin
  508. oldpos:=aktfilepos;
  509. aktfilepos:=pos;
  510. MaybeLoadMessageFile;
  511. Msg2Comment(msg^.Get(w));
  512. aktfilepos:=oldpos;
  513. end;
  514. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  515. var
  516. oldpos : tfileposinfo;
  517. begin
  518. oldpos:=aktfilepos;
  519. aktfilepos:=pos;
  520. MaybeLoadMessageFile;
  521. Msg2Comment(msg^.Get1(w,s1));
  522. aktfilepos:=oldpos;
  523. end;
  524. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  525. var
  526. oldpos : tfileposinfo;
  527. begin
  528. oldpos:=aktfilepos;
  529. aktfilepos:=pos;
  530. MaybeLoadMessageFile;
  531. Msg2Comment(msg^.Get2(w,s1,s2));
  532. aktfilepos:=oldpos;
  533. end;
  534. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  535. var
  536. oldpos : tfileposinfo;
  537. begin
  538. oldpos:=aktfilepos;
  539. aktfilepos:=pos;
  540. MaybeLoadMessageFile;
  541. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  542. aktfilepos:=oldpos;
  543. end;
  544. procedure InitVerbose;
  545. begin
  546. { Init }
  547. msg:=new(pmessage,Init(20,msgidxmax));
  548. if msg=nil then
  549. begin
  550. writeln('Fatal: MsgIdx Wrong');
  551. halt(3);
  552. end;
  553. {$ifndef EXTERN_MSG}
  554. msg^.LoadIntern(@msgtxt,msgtxtsize);
  555. {$else EXTERN_MSG}
  556. LoadMsgFile(exepath+'errore.msg');
  557. {$endif EXTERN_MSG}
  558. FillChar(Status,sizeof(TCompilerStatus),0);
  559. status.verbosity:=V_Default;
  560. Status.MaxErrorCount:=50;
  561. LoadPrefixes;
  562. end;
  563. procedure DoneVerbose;
  564. begin
  565. if assigned(msg) then
  566. begin
  567. dispose(msg,Done);
  568. msg:=nil;
  569. end;
  570. if status.use_redir then
  571. DoneRedirectFile;
  572. end;
  573. end.
  574. {
  575. $Log$
  576. Revision 1.12 2001-03-13 20:59:56 peter
  577. * message loading fixes from Sergey (merged)
  578. Revision 1.11 2000/12/26 15:58:29 peter
  579. * check for verbosity in verbose instead of comphook
  580. Revision 1.10 2000/12/25 00:07:30 peter
  581. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  582. tlinkedlist objects)
  583. Revision 1.9 2000/12/07 17:19:45 jonas
  584. * new constant handling: from now on, hex constants >$7fffffff are
  585. parsed as unsigned constants (otherwise, $80000000 got sign extended
  586. and became $ffffffff80000000), all constants in the longint range
  587. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  588. are cardinals and the rest are int64's.
  589. * added lots of longint typecast to prevent range check errors in the
  590. compiler and rtl
  591. * type casts of symbolic ordinal constants are now preserved
  592. * fixed bug where the original resulttype wasn't restored correctly
  593. after doing a 64bit rangecheck
  594. Revision 1.8 2000/11/29 00:30:43 florian
  595. * unused units removed from uses clause
  596. * some changes for widestrings
  597. Revision 1.7 2000/10/31 22:02:55 peter
  598. * symtable splitted, no real code changes
  599. Revision 1.6 2000/09/24 21:33:48 peter
  600. * message updates merges
  601. Revision 1.5 2000/09/24 15:06:33 peter
  602. * use defines.inc
  603. Revision 1.4 2000/08/27 16:11:55 peter
  604. * moved some util functions from globals,cobjects to cutils
  605. * splitted files into finput,fmodule
  606. Revision 1.3 2000/08/13 12:54:55 peter
  607. * class member decl wrong then no other error after it
  608. * -vb has now also line numbering
  609. * -vb is also used for interface/implementation different decls and
  610. doesn't list the current function (merged)
  611. Revision 1.2 2000/07/13 11:32:54 michael
  612. + removed logs
  613. }