verbose.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  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. 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 = $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:pmodulebase);
  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. version,globals;
  82. var
  83. redirexitsave : pointer;
  84. current_module : pmodulebase;
  85. {****************************************************************************
  86. Extra Handlers for default compiler
  87. ****************************************************************************}
  88. procedure DoneRedirectFile;
  89. begin
  90. exitproc:=redirexitsave;
  91. if status.use_redir then
  92. close(status.redirfile);
  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. if status.use_redir then
  104. begin
  105. redirexitsave:=exitproc;
  106. exitproc:=@DoneRedirectFile;
  107. end;
  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 SetCompileModule(p:pmodulebase);
  263. begin
  264. current_module:=p;
  265. end;
  266. var
  267. lastfileidx,
  268. lastmoduleidx : longint;
  269. Procedure UpdateStatus;
  270. begin
  271. { fix status }
  272. status.currentline:=aktfilepos.line;
  273. status.currentcolumn:=aktfilepos.column;
  274. if assigned(current_module) and
  275. assigned(current_module^.sourcefiles) and
  276. ((current_module^.unit_index<>lastmoduleidx) or
  277. (aktfilepos.fileindex<>lastfileidx)) then
  278. begin
  279. { update status record }
  280. status.currentmodule:=current_module^.modulename^;
  281. status.currentsource:=current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex);
  282. status.currentsourcepath:=current_module^.sourcefiles^.get_file_path(aktfilepos.fileindex);
  283. { update lastfileidx only if name known PM }
  284. if status.currentsource<>'' then
  285. lastfileidx:=aktfilepos.fileindex
  286. else
  287. lastfileidx:=0;
  288. lastmoduleidx:=current_module^.unit_index;
  289. end;
  290. end;
  291. procedure stop;
  292. begin
  293. do_stop{$ifdef FPCPROCVAR}(){$endif};
  294. end;
  295. procedure ShowStatus;
  296. begin
  297. UpdateStatus;
  298. if do_status{$ifdef FPCPROCVAR}(){$endif} then
  299. stop;
  300. end;
  301. function ErrorCount:longint;
  302. begin
  303. ErrorCount:=status.errorcount;
  304. end;
  305. procedure SetErrorFlags(const s:string);
  306. var
  307. code : integer;
  308. i,j,l : longint;
  309. begin
  310. { empty string means error count = 1 for backward compatibility (PFV) }
  311. if s='' then
  312. begin
  313. status.maxerrorcount:=1;
  314. exit;
  315. end;
  316. i:=0;
  317. while (i<length(s)) do
  318. begin
  319. inc(i);
  320. case s[i] of
  321. '0'..'9' :
  322. begin
  323. j:=i;
  324. while (j<=length(s)) and (s[j] in ['0'..'9']) do
  325. inc(j);
  326. val(copy(s,i,j-i),l,code);
  327. if code<>0 then
  328. l:=1;
  329. status.maxerrorcount:=l;
  330. i:=j;
  331. end;
  332. 'w','W' :
  333. status.errorwarning:=true;
  334. 'n','N' :
  335. status.errornote:=true;
  336. 'h','H' :
  337. status.errorhint:=true;
  338. end;
  339. end;
  340. end;
  341. procedure GenerateError;
  342. begin
  343. inc(status.errorcount);
  344. end;
  345. procedure internalerror(i : longint);
  346. begin
  347. UpdateStatus;
  348. do_internalerror(i);
  349. inc(status.errorcount);
  350. stop;
  351. end;
  352. procedure Comment(l:longint;s:string);
  353. var
  354. dostop : boolean;
  355. begin
  356. dostop:=((l and V_Fatal)<>0);
  357. if ((l and V_Error)<>0) or
  358. (status.errorwarning and ((l and V_Warning)<>0)) or
  359. (status.errornote and ((l and V_Note)<>0)) or
  360. (status.errorhint and ((l and V_Hint)<>0)) then
  361. inc(status.errorcount);
  362. { Create status info }
  363. UpdateStatus;
  364. { Fix replacements }
  365. DefaultReplacements(s);
  366. { show comment }
  367. if do_comment(l,s) or dostop then
  368. stop;
  369. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  370. begin
  371. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  372. status.skip_error:=true;
  373. stop;
  374. end;
  375. end;
  376. Procedure Msg2Comment(s:string);
  377. var
  378. idx,i,v : longint;
  379. dostop : boolean;
  380. begin
  381. {Reset}
  382. dostop:=false;
  383. v:=0;
  384. {Parse options}
  385. idx:=pos('_',s);
  386. if idx=0 then
  387. v:=V_Normal
  388. else
  389. if (idx >= 1) And (idx <= 5) then
  390. begin
  391. for i:=1 to idx do
  392. begin
  393. case upcase(s[i]) of
  394. 'F' :
  395. begin
  396. v:=v or V_Fatal;
  397. inc(status.errorcount);
  398. dostop:=true;
  399. end;
  400. 'E' :
  401. begin
  402. v:=v or V_Error;
  403. inc(status.errorcount);
  404. end;
  405. 'O' :
  406. v:=v or V_Normal;
  407. 'W':
  408. begin
  409. v:=v or V_Warning;
  410. if status.errorwarning then
  411. inc(status.errorcount);
  412. end;
  413. 'N' :
  414. begin
  415. v:=v or V_Note;
  416. if status.errornote then
  417. inc(status.errorcount);
  418. end;
  419. 'H' :
  420. begin
  421. v:=v or V_Hint;
  422. if status.errorhint then
  423. inc(status.errorcount);
  424. end;
  425. 'I' :
  426. v:=v or V_Info;
  427. 'L' :
  428. v:=v or V_Status;
  429. 'U' :
  430. v:=v or V_Used;
  431. 'T' :
  432. v:=v or V_Tried;
  433. 'M' :
  434. v:=v or V_Macro;
  435. 'P' :
  436. v:=v or V_Procedure;
  437. 'C' :
  438. v:=v or V_Conditional;
  439. 'D' :
  440. v:=v or V_Debug;
  441. 'B' :
  442. v:=v or V_Declarations;
  443. 'X' :
  444. v:=v or V_Executable;
  445. 'Z' :
  446. v:=v or V_Assem;
  447. 'S' :
  448. dostop:=true;
  449. '_' : ;
  450. end;
  451. end;
  452. end;
  453. Delete(s,1,idx);
  454. { fix status }
  455. UpdateStatus;
  456. { Fix replacements }
  457. DefaultReplacements(s);
  458. { show comment }
  459. if do_comment(v,s) or dostop then
  460. stop;
  461. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  462. begin
  463. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  464. status.skip_error:=true;
  465. stop;
  466. end;
  467. end;
  468. function MessagePchar(w:longint):pchar;
  469. begin
  470. MessagePchar:=msg^.GetPchar(w)
  471. end;
  472. procedure Message(w:longint);
  473. begin
  474. Msg2Comment(msg^.Get(w));
  475. end;
  476. procedure Message1(w:longint;const s1:string);
  477. begin
  478. Msg2Comment(msg^.Get1(w,s1));
  479. end;
  480. procedure Message2(w:longint;const s1,s2:string);
  481. begin
  482. Msg2Comment(msg^.Get2(w,s1,s2));
  483. end;
  484. procedure Message3(w:longint;const s1,s2,s3:string);
  485. begin
  486. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  487. end;
  488. procedure MessagePos(const pos:tfileposinfo;w:longint);
  489. var
  490. oldpos : tfileposinfo;
  491. begin
  492. oldpos:=aktfilepos;
  493. aktfilepos:=pos;
  494. Msg2Comment(msg^.Get(w));
  495. aktfilepos:=oldpos;
  496. end;
  497. procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string);
  498. var
  499. oldpos : tfileposinfo;
  500. begin
  501. oldpos:=aktfilepos;
  502. aktfilepos:=pos;
  503. Msg2Comment(msg^.Get1(w,s1));
  504. aktfilepos:=oldpos;
  505. end;
  506. procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string);
  507. var
  508. oldpos : tfileposinfo;
  509. begin
  510. oldpos:=aktfilepos;
  511. aktfilepos:=pos;
  512. Msg2Comment(msg^.Get2(w,s1,s2));
  513. aktfilepos:=oldpos;
  514. end;
  515. procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string);
  516. var
  517. oldpos : tfileposinfo;
  518. begin
  519. oldpos:=aktfilepos;
  520. aktfilepos:=pos;
  521. Msg2Comment(msg^.Get3(w,s1,s2,s3));
  522. aktfilepos:=oldpos;
  523. end;
  524. procedure InitVerbose;
  525. begin
  526. { Init }
  527. msg:=new(pmessage,Init(20,msgidxmax));
  528. if msg=nil then
  529. begin
  530. writeln('Fatal: MsgIdx Wrong');
  531. halt(3);
  532. end;
  533. {$ifndef EXTERN_MSG}
  534. msg^.LoadIntern(@msgtxt,msgtxtsize);
  535. {$else}
  536. LoadMsgFile(exepath+'errore.msg');
  537. {$endif}
  538. FillChar(Status,sizeof(TCompilerStatus),0);
  539. status.verbosity:=V_Default;
  540. Status.MaxErrorCount:=50;
  541. LoadPrefixes;
  542. end;
  543. procedure DoneVerbose;
  544. begin
  545. if assigned(msg) then
  546. begin
  547. dispose(msg,Done);
  548. msg:=nil;
  549. end;
  550. end;
  551. end.
  552. {
  553. $Log$
  554. Revision 1.7 2000-10-31 22:02:55 peter
  555. * symtable splitted, no real code changes
  556. Revision 1.6 2000/09/24 21:33:48 peter
  557. * message updates merges
  558. Revision 1.5 2000/09/24 15:06:33 peter
  559. * use defines.inc
  560. Revision 1.4 2000/08/27 16:11:55 peter
  561. * moved some util functions from globals,cobjects to cutils
  562. * splitted files into finput,fmodule
  563. Revision 1.3 2000/08/13 12:54:55 peter
  564. * class member decl wrong then no other error after it
  565. * -vb has now also line numbering
  566. * -vb is also used for interface/implementation different decls and
  567. doesn't list the current function (merged)
  568. Revision 1.2 2000/07/13 11:32:54 michael
  569. + removed logs
  570. }