verbose.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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 fpcdefs.inc}
  20. { Don't include messages in the executable }
  21. {$ifdef Delphi}
  22. {$define EXTERN_MSG}
  23. {$endif}
  24. interface
  25. uses
  26. cutils,
  27. globals,finput,
  28. cmsgs;
  29. {$ifndef EXTERN_MSG}
  30. {$i msgtxt.inc}
  31. {$endif}
  32. {$i msgidx.inc}
  33. Const
  34. { <$10000 will show file and line }
  35. V_None = $0;
  36. V_Fatal = $1;
  37. V_Error = $2;
  38. V_Normal = $4; { doesn't show a text like Error: }
  39. V_Warning = $8;
  40. V_Note = $10;
  41. V_Hint = $20;
  42. V_Macro = $100;
  43. V_Procedure = $200;
  44. V_Conditional = $400;
  45. V_Assem = $800;
  46. V_Declarations = $1000;
  47. V_Info = $10000;
  48. V_Status = $20000;
  49. V_Used = $40000;
  50. V_Tried = $80000;
  51. V_Debug = $100000;
  52. V_Executable = $200000;
  53. V_ShowFile = $ffff;
  54. V_All = longint($ffffffff);
  55. V_Default = V_Fatal + V_Error + V_Normal;
  56. var
  57. msg : pmessage;
  58. const
  59. msgfilename : string = '';
  60. procedure SetRedirectFile(const fn:string);
  61. function SetVerbosity(const s:string):boolean;
  62. procedure SetCompileModule(p:tmodulebase);
  63. procedure Stop;
  64. procedure ShowStatus;
  65. function ErrorCount:longint;
  66. procedure SetErrorFlags(const s:string);
  67. procedure GenerateError;
  68. procedure Internalerror(i:longint);
  69. procedure Comment(l:longint;s:string);
  70. function MessagePchar(w:longint):pchar;
  71. procedure Message(w:longint);
  72. procedure Message1(w:longint;const s1:string);
  73. procedure Message2(w:longint;const s1,s2:string);
  74. procedure Message3(w:longint;const s1,s2,s3:string);
  75. procedure Message4(w:longint;const s1,s2,s3,s4:string);
  76. procedure MessagePos(const pos:tfileposinfo;w:longint);
  77. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  78. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  79. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  80. procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string);
  81. procedure InitVerbose;
  82. procedure DoneVerbose;
  83. implementation
  84. uses
  85. comphook;
  86. var
  87. compiling_module : tmodulebase;
  88. {****************************************************************************
  89. Extra Handlers for default compiler
  90. ****************************************************************************}
  91. procedure DoneRedirectFile;
  92. begin
  93. if status.use_redir then
  94. begin
  95. close(status.redirfile);
  96. status.use_redir:=false;
  97. end;
  98. end;
  99. procedure SetRedirectFile(const fn:string);
  100. begin
  101. assign(status.redirfile,fn);
  102. {$I-}
  103. append(status.redirfile);
  104. if ioresult <> 0 then
  105. rewrite(status.redirfile);
  106. {$I+}
  107. status.use_redir:=(ioresult=0);
  108. end;
  109. function SetVerbosity(const s:string):boolean;
  110. var
  111. m : Longint;
  112. i : Integer;
  113. inverse : boolean;
  114. c : char;
  115. begin
  116. Setverbosity:=false;
  117. val(s,m,i);
  118. if (i=0) and (s<>'') then
  119. status.verbosity:=m
  120. else
  121. begin
  122. i:=1;
  123. while i<=length(s) do
  124. begin
  125. c:=upcase(s[i]);
  126. inverse:=false;
  127. { on/off ? }
  128. if (i<length(s)) then
  129. case s[i+1] of
  130. '-' : begin
  131. inc(i);
  132. inverse:=true;
  133. end;
  134. '+' : inc(i);
  135. end;
  136. { handle switch }
  137. case c of
  138. { Special cases }
  139. 'A' : status.verbosity:=V_All;
  140. '0' : status.verbosity:=V_Default;
  141. 'R' : begin
  142. if inverse then
  143. begin
  144. status.use_gccoutput:=false;
  145. status.use_stderr:=false;
  146. end
  147. else
  148. begin
  149. status.use_gccoutput:=true;
  150. status.use_stderr:=true;
  151. end;
  152. end;
  153. { Normal cases - do an or }
  154. 'E' : if inverse then
  155. status.verbosity:=status.verbosity and (not V_Error)
  156. else
  157. status.verbosity:=status.verbosity or V_Error;
  158. 'I' : if inverse then
  159. status.verbosity:=status.verbosity and (not V_Info)
  160. else
  161. status.verbosity:=status.verbosity or V_Info;
  162. 'W' : if inverse then
  163. status.verbosity:=status.verbosity and (not V_Warning)
  164. else
  165. status.verbosity:=status.verbosity or V_Warning;
  166. 'N' : if inverse then
  167. status.verbosity:=status.verbosity and (not V_Note)
  168. else
  169. status.verbosity:=status.verbosity or V_Note;
  170. 'H' : if inverse then
  171. status.verbosity:=status.verbosity and (not V_Hint)
  172. else
  173. status.verbosity:=status.verbosity or V_Hint;
  174. 'L' : if inverse then
  175. status.verbosity:=status.verbosity and (not V_Status)
  176. else
  177. status.verbosity:=status.verbosity or V_Status;
  178. 'U' : if inverse then
  179. status.verbosity:=status.verbosity and (not V_Used)
  180. else
  181. status.verbosity:=status.verbosity or V_Used;
  182. 'T' : if inverse then
  183. status.verbosity:=status.verbosity and (not V_Tried)
  184. else
  185. status.verbosity:=status.verbosity or V_Tried;
  186. 'M' : if inverse then
  187. status.verbosity:=status.verbosity and (not V_Macro)
  188. else
  189. status.verbosity:=status.verbosity or V_Macro;
  190. 'P' : if inverse then
  191. status.verbosity:=status.verbosity and (not V_Procedure)
  192. else
  193. status.verbosity:=status.verbosity or V_Procedure;
  194. 'C' : if inverse then
  195. status.verbosity:=status.verbosity and (not V_Conditional)
  196. else
  197. status.verbosity:=status.verbosity or V_Conditional;
  198. 'D' : if inverse then
  199. status.verbosity:=status.verbosity and (not V_Debug)
  200. else
  201. status.verbosity:=status.verbosity or V_Debug;
  202. 'B' : if inverse then
  203. status.verbosity:=status.verbosity and (not V_Declarations)
  204. else
  205. status.verbosity:=status.verbosity or V_Declarations;
  206. 'X' : if inverse then
  207. status.verbosity:=status.verbosity and (not V_Executable)
  208. else
  209. status.verbosity:=status.verbosity or V_Executable;
  210. 'Z' : if inverse then
  211. status.verbosity:=status.verbosity and (not V_Assem)
  212. else
  213. status.verbosity:=status.verbosity or V_Assem;
  214. end;
  215. inc(i);
  216. end;
  217. end;
  218. if status.verbosity=0 then
  219. status.verbosity:=V_Default;
  220. setverbosity:=true;
  221. end;
  222. procedure Loadprefixes;
  223. function loadprefix(w:longint):string;
  224. var
  225. s : string;
  226. idx : longint;
  227. begin
  228. s:=msg^.get(w);
  229. idx:=pos('_',s);
  230. if idx>0 then
  231. Loadprefix:=Copy(s,idx+1,255)
  232. else
  233. Loadprefix:=s;
  234. end;
  235. begin
  236. { Load the prefixes }
  237. fatalstr:=Loadprefix(general_i_fatal);
  238. errorstr:=Loadprefix(general_i_error);
  239. warningstr:=Loadprefix(general_i_warning);
  240. notestr:=Loadprefix(general_i_note);
  241. hintstr:=Loadprefix(general_i_hint);
  242. end;
  243. procedure LoadMsgFile(const fn:string);
  244. begin
  245. { reload the internal messages if not already loaded }
  246. {$ifndef EXTERN_MSG}
  247. if not msg^.msgintern then
  248. msg^.LoadIntern(@msgtxt,msgtxtsize);
  249. {$endif}
  250. if not msg^.LoadExtern(fn) then
  251. begin
  252. {$ifdef EXTERN_MSG}
  253. writeln('Fatal: Cannot find error message file.');
  254. halt(3);
  255. {$else}
  256. msg^.LoadIntern(@msgtxt,msgtxtsize);
  257. {$endif}
  258. end;
  259. { reload the prefixes using the new messages }
  260. Loadprefixes;
  261. end;
  262. procedure MaybeLoadMessageFile;
  263. begin
  264. { Load new message file }
  265. if (msgfilename<>'') then
  266. begin
  267. LoadMsgFile(msgfilename);
  268. msgfilename:='';
  269. end;
  270. end;
  271. procedure SetCompileModule(p:tmodulebase);
  272. begin
  273. compiling_module:=p;
  274. end;
  275. var
  276. lastfileidx,
  277. lastmoduleidx : longint;
  278. Procedure UpdateStatus;
  279. begin
  280. { fix status }
  281. status.currentline:=aktfilepos.line;
  282. status.currentcolumn:=aktfilepos.column;
  283. if assigned(compiling_module) and
  284. assigned(compiling_module.sourcefiles) and
  285. ((compiling_module.unit_index<>lastmoduleidx) or
  286. (aktfilepos.fileindex<>lastfileidx)) then
  287. begin
  288. { update status record }
  289. status.currentmodule:=compiling_module.modulename^;
  290. status.currentsource:=compiling_module.sourcefiles.get_file_name(aktfilepos.fileindex);
  291. status.currentsourcepath:=compiling_module.sourcefiles.get_file_path(aktfilepos.fileindex);
  292. { update lastfileidx only if name known PM }
  293. if status.currentsource<>'' then
  294. lastfileidx:=aktfilepos.fileindex
  295. else
  296. lastfileidx:=0;
  297. lastmoduleidx:=compiling_module.unit_index;
  298. end;
  299. if assigned(compiling_module) then
  300. status.compiling_current:=compiling_module.in_compile;
  301. end;
  302. procedure stop;
  303. begin
  304. do_stop{$ifdef FPCPROCVAR}(){$endif};
  305. end;
  306. procedure ShowStatus;
  307. begin
  308. UpdateStatus;
  309. if do_status{$ifdef FPCPROCVAR}(){$endif} then
  310. stop;
  311. end;
  312. function ErrorCount:longint;
  313. begin
  314. ErrorCount:=status.errorcount;
  315. end;
  316. procedure SetErrorFlags(const s:string);
  317. var
  318. code : integer;
  319. i,j,l : longint;
  320. begin
  321. { empty string means error count = 1 for backward compatibility (PFV) }
  322. if s='' then
  323. begin
  324. status.maxerrorcount:=1;
  325. exit;
  326. end;
  327. i:=0;
  328. while (i<length(s)) do
  329. begin
  330. inc(i);
  331. case s[i] of
  332. '0'..'9' :
  333. begin
  334. j:=i;
  335. while (j<=length(s)) and (s[j] in ['0'..'9']) do
  336. inc(j);
  337. val(copy(s,i,j-i),l,code);
  338. if code<>0 then
  339. l:=1;
  340. status.maxerrorcount:=l;
  341. i:=j;
  342. end;
  343. 'w','W' :
  344. status.errorwarning:=true;
  345. 'n','N' :
  346. status.errornote:=true;
  347. 'h','H' :
  348. status.errorhint:=true;
  349. end;
  350. end;
  351. end;
  352. procedure GenerateError;
  353. begin
  354. inc(status.errorcount);
  355. end;
  356. procedure internalerror(i : longint);
  357. begin
  358. UpdateStatus;
  359. do_internalerror(i);
  360. inc(status.errorcount);
  361. stop;
  362. end;
  363. procedure Comment(l:longint;s:string);
  364. var
  365. dostop : boolean;
  366. begin
  367. dostop:=((l and V_Fatal)<>0);
  368. if ((l and V_Error)<>0) or
  369. (status.errorwarning and ((l and V_Warning)<>0)) or
  370. (status.errornote and ((l and V_Note)<>0)) or
  371. (status.errorhint and ((l and V_Hint)<>0)) then
  372. inc(status.errorcount);
  373. { check verbosity level }
  374. if (status.verbosity and l)<>l then
  375. exit;
  376. { Create status info }
  377. UpdateStatus;
  378. { Fix replacements }
  379. DefaultReplacements(s);
  380. { show comment }
  381. if do_comment(l,s) or dostop then
  382. stop;
  383. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  384. begin
  385. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  386. status.skip_error:=true;
  387. stop;
  388. end;
  389. end;
  390. Procedure Msg2Comment(s:string);
  391. var
  392. idx,i,v : longint;
  393. dostop : boolean;
  394. begin
  395. {Reset}
  396. dostop:=false;
  397. v:=0;
  398. {Parse options}
  399. idx:=pos('_',s);
  400. if idx=0 then
  401. v:=V_Normal
  402. else
  403. if (idx >= 1) And (idx <= 5) then
  404. begin
  405. for i:=1 to idx do
  406. begin
  407. case upcase(s[i]) of
  408. 'F' :
  409. begin
  410. v:=v or V_Fatal;
  411. inc(status.errorcount);
  412. dostop:=true;
  413. end;
  414. 'E' :
  415. begin
  416. v:=v or V_Error;
  417. inc(status.errorcount);
  418. end;
  419. 'O' :
  420. v:=v or V_Normal;
  421. 'W':
  422. begin
  423. v:=v or V_Warning;
  424. if status.errorwarning then
  425. inc(status.errorcount);
  426. end;
  427. 'N' :
  428. begin
  429. v:=v or V_Note;
  430. if status.errornote then
  431. inc(status.errorcount);
  432. end;
  433. 'H' :
  434. begin
  435. v:=v or V_Hint;
  436. if status.errorhint then
  437. inc(status.errorcount);
  438. end;
  439. 'I' :
  440. v:=v or V_Info;
  441. 'L' :
  442. v:=v or V_Status;
  443. 'U' :
  444. v:=v or V_Used;
  445. 'T' :
  446. v:=v or V_Tried;
  447. 'M' :
  448. v:=v or V_Macro;
  449. 'P' :
  450. v:=v or V_Procedure;
  451. 'C' :
  452. v:=v or V_Conditional;
  453. 'D' :
  454. v:=v or V_Debug;
  455. 'B' :
  456. v:=v or V_Declarations;
  457. 'X' :
  458. v:=v or V_Executable;
  459. 'Z' :
  460. v:=v or V_Assem;
  461. 'S' :
  462. dostop:=true;
  463. '_' : ;
  464. end;
  465. end;
  466. end;
  467. Delete(s,1,idx);
  468. { check verbosity level }
  469. if (status.verbosity and v)<>v then
  470. exit;
  471. { fix status }
  472. UpdateStatus;
  473. { Fix replacements }
  474. DefaultReplacements(s);
  475. { show comment }
  476. if do_comment(v,s) or dostop then
  477. stop;
  478. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  479. begin
  480. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  481. status.skip_error:=true;
  482. stop;
  483. end;
  484. end;
  485. function MessagePchar(w:longint):pchar;
  486. begin
  487. MaybeLoadMessageFile;
  488. MessagePchar:=msg^.GetPchar(w)
  489. end;
  490. procedure Message(w:longint);
  491. begin
  492. MaybeLoadMessageFile;
  493. Msg2Comment(msg^.Get(w));
  494. end;
  495. procedure Message1(w:longint;const s1:string);
  496. begin
  497. MaybeLoadMessageFile;
  498. Msg2Comment(msg^.Get1(w,s1));
  499. end;
  500. procedure Message2(w:longint;const s1,s2:string);
  501. begin
  502. MaybeLoadMessageFile;
  503. Msg2Comment(msg^.Get2(w,s1,s2));
  504. end;
  505. procedure Message3(w:longint;const s1,s2,s3:string);
  506. begin
  507. MaybeLoadMessageFile;
  508. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  509. end;
  510. procedure Message4(w:longint;const s1,s2,s3,s4:string);
  511. begin
  512. MaybeLoadMessageFile;
  513. Msg2Comment(msg^.Get4(w,s1,s2,s3,s4));
  514. end;
  515. procedure MessagePos(const pos:tfileposinfo;w:longint);
  516. var
  517. oldpos : tfileposinfo;
  518. begin
  519. oldpos:=aktfilepos;
  520. aktfilepos:=pos;
  521. MaybeLoadMessageFile;
  522. Msg2Comment(msg^.Get(w));
  523. aktfilepos:=oldpos;
  524. end;
  525. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  526. var
  527. oldpos : tfileposinfo;
  528. begin
  529. oldpos:=aktfilepos;
  530. aktfilepos:=pos;
  531. MaybeLoadMessageFile;
  532. Msg2Comment(msg^.Get1(w,s1));
  533. aktfilepos:=oldpos;
  534. end;
  535. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  536. var
  537. oldpos : tfileposinfo;
  538. begin
  539. oldpos:=aktfilepos;
  540. aktfilepos:=pos;
  541. MaybeLoadMessageFile;
  542. Msg2Comment(msg^.Get2(w,s1,s2));
  543. aktfilepos:=oldpos;
  544. end;
  545. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  546. var
  547. oldpos : tfileposinfo;
  548. begin
  549. oldpos:=aktfilepos;
  550. aktfilepos:=pos;
  551. MaybeLoadMessageFile;
  552. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  553. aktfilepos:=oldpos;
  554. end;
  555. procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string);
  556. var
  557. oldpos : tfileposinfo;
  558. begin
  559. oldpos:=aktfilepos;
  560. aktfilepos:=pos;
  561. MaybeLoadMessageFile;
  562. Msg2Comment(msg^.Get4(w,s1,s2,s3,s4));
  563. aktfilepos:=oldpos;
  564. end;
  565. procedure InitVerbose;
  566. begin
  567. { Init }
  568. msg:=new(pmessage,Init(20,msgidxmax));
  569. if msg=nil then
  570. begin
  571. writeln('Fatal: MsgIdx Wrong');
  572. halt(3);
  573. end;
  574. {$ifndef EXTERN_MSG}
  575. msg^.LoadIntern(@msgtxt,msgtxtsize);
  576. {$else EXTERN_MSG}
  577. LoadMsgFile(exepath+'errore.msg');
  578. {$endif EXTERN_MSG}
  579. FillChar(Status,sizeof(TCompilerStatus),0);
  580. status.verbosity:=V_Default;
  581. Status.MaxErrorCount:=50;
  582. Loadprefixes;
  583. lastfileidx:=-1;
  584. lastmoduleidx:=-1;
  585. status.currentmodule:='';
  586. status.currentsource:='';
  587. status.currentsourcepath:='';
  588. status.compiling_current:=false;
  589. end;
  590. procedure DoneVerbose;
  591. begin
  592. if assigned(msg) then
  593. begin
  594. dispose(msg,Done);
  595. msg:=nil;
  596. end;
  597. if status.use_redir then
  598. DoneRedirectFile;
  599. end;
  600. end.
  601. {
  602. $Log$
  603. Revision 1.21 2002-10-05 12:43:29 carl
  604. * fixes for Delphi 6 compilation
  605. (warning : Some features do not work under Delphi)
  606. Revision 1.20 2002/08/18 19:59:03 peter
  607. * renamed local current_module to compiling_module because it
  608. confused a lot in gdb
  609. Revision 1.19 2002/05/18 13:34:21 peter
  610. * readded missing revisions
  611. Revision 1.18 2002/05/16 19:46:47 carl
  612. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  613. + try to fix temp allocation (still in ifdef)
  614. + generic constructor calls
  615. + start of tassembler / tmodulebase class cleanup
  616. }