verbose.pas 20 KB

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