verbose.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  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 SetMaxErrorCount(count:longint);
  61. procedure GenerateError;
  62. procedure Internalerror(i:longint);
  63. procedure Comment(l:longint;s:string);
  64. procedure Message(w:tmsgconst);
  65. procedure Message1(w:tmsgconst;const s1:string);
  66. procedure Message2(w:tmsgconst;const s1,s2:string);
  67. procedure Message3(w:tmsgconst;const s1,s2,s3:string);
  68. procedure MessagePos(const pos:tfileposinfo;w:tmsgconst);
  69. procedure MessagePos1(const pos:tfileposinfo;w:tmsgconst;const s1:string);
  70. procedure MessagePos2(const pos:tfileposinfo;w:tmsgconst;const s1,s2:string);
  71. procedure MessagePos3(const pos:tfileposinfo;w:tmsgconst;const s1,s2,s3:string);
  72. procedure InitVerbose;
  73. procedure DoneVerbose;
  74. implementation
  75. uses
  76. files,comphook,
  77. version,globals;
  78. var
  79. redirexitsave : pointer;
  80. {****************************************************************************
  81. Extra Handlers for default compiler
  82. ****************************************************************************}
  83. procedure DoneRedirectFile;{$ifndef FPC}far;{$ENDIF}
  84. begin
  85. exitproc:=redirexitsave;
  86. if status.use_redir then
  87. close(status.redirfile);
  88. end;
  89. procedure SetRedirectFile(const fn:string);
  90. begin
  91. assign(status.redirfile,fn);
  92. {$I-}
  93. rewrite(status.redirfile);
  94. {$I+}
  95. status.use_redir:=(ioresult=0);
  96. if status.use_redir then
  97. begin
  98. redirexitsave:=exitproc;
  99. exitproc:=@DoneRedirectFile;
  100. end;
  101. end;
  102. function SetVerbosity(const s:string):boolean;
  103. var
  104. m : Longint;
  105. i : Integer;
  106. inverse : boolean;
  107. c : char;
  108. begin
  109. Setverbosity:=false;
  110. val(s,m,i);
  111. if (i=0) and (s<>'') then
  112. status.verbosity:=m
  113. else
  114. begin
  115. i:=1;
  116. while i<=length(s) do
  117. begin
  118. c:=upcase(s[i]);
  119. inverse:=false;
  120. { on/off ? }
  121. if (i<length(s)) then
  122. case s[i+1] of
  123. '-' : begin
  124. inc(i);
  125. inverse:=true;
  126. end;
  127. '+' : inc(i);
  128. end;
  129. { handle switch }
  130. case c of
  131. { Special cases }
  132. 'A' : status.verbosity:=V_All;
  133. '0' : status.verbosity:=V_Default;
  134. 'R' : begin
  135. if inverse then
  136. begin
  137. status.use_gccoutput:=false;
  138. status.use_stderr:=false;
  139. end
  140. else
  141. begin
  142. status.use_gccoutput:=true;
  143. status.use_stderr:=true;
  144. end;
  145. end;
  146. { Normal cases - do an or }
  147. 'E' : if inverse then
  148. status.verbosity:=status.verbosity and (not V_Error)
  149. else
  150. status.verbosity:=status.verbosity or V_Error;
  151. 'I' : if inverse then
  152. status.verbosity:=status.verbosity and (not V_Info)
  153. else
  154. status.verbosity:=status.verbosity or V_Info;
  155. 'W' : if inverse then
  156. status.verbosity:=status.verbosity and (not V_Warning)
  157. else
  158. status.verbosity:=status.verbosity or V_Warning;
  159. 'N' : if inverse then
  160. status.verbosity:=status.verbosity and (not V_Note)
  161. else
  162. status.verbosity:=status.verbosity or V_Note;
  163. 'H' : if inverse then
  164. status.verbosity:=status.verbosity and (not V_Hint)
  165. else
  166. status.verbosity:=status.verbosity or V_Hint;
  167. 'L' : if inverse then
  168. status.verbosity:=status.verbosity and (not V_Status)
  169. else
  170. status.verbosity:=status.verbosity or V_Status;
  171. 'U' : if inverse then
  172. status.verbosity:=status.verbosity and (not V_Used)
  173. else
  174. status.verbosity:=status.verbosity or V_Used;
  175. 'T' : if inverse then
  176. status.verbosity:=status.verbosity and (not V_Tried)
  177. else
  178. status.verbosity:=status.verbosity or V_Tried;
  179. 'M' : if inverse then
  180. status.verbosity:=status.verbosity and (not V_Macro)
  181. else
  182. status.verbosity:=status.verbosity or V_Macro;
  183. 'P' : if inverse then
  184. status.verbosity:=status.verbosity and (not V_Procedure)
  185. else
  186. status.verbosity:=status.verbosity or V_Procedure;
  187. 'C' : if inverse then
  188. status.verbosity:=status.verbosity and (not V_Conditional)
  189. else
  190. status.verbosity:=status.verbosity or V_Conditional;
  191. 'D' : if inverse then
  192. status.verbosity:=status.verbosity and (not V_Debug)
  193. else
  194. status.verbosity:=status.verbosity or V_Debug;
  195. 'B' : if inverse then
  196. status.verbosity:=status.verbosity and (not V_Declarations)
  197. else
  198. status.verbosity:=status.verbosity or V_Declarations;
  199. 'X' : if inverse then
  200. status.verbosity:=status.verbosity and (not V_Executable)
  201. else
  202. status.verbosity:=status.verbosity or V_Executable;
  203. 'Z' : if inverse then
  204. status.verbosity:=status.verbosity and (not V_Assem)
  205. else
  206. status.verbosity:=status.verbosity or V_Assem;
  207. end;
  208. inc(i);
  209. end;
  210. end;
  211. if status.verbosity=0 then
  212. status.verbosity:=V_Default;
  213. setverbosity:=true;
  214. end;
  215. procedure LoadMsgFile(const fn:string);
  216. begin
  217. if not(msg=nil) then
  218. dispose(msg,Done);
  219. msg:=new(pmessage,InitExtern(fn,ord(endmsgconst)));
  220. {$IFDEF TP}
  221. if msg=nil then
  222. begin
  223. writeln('Fatal: Cannot find error message file.');
  224. halt(3);
  225. end;
  226. {$ELSE}
  227. if msg=nil then
  228. msg:=new(pmessage,Init(@msgtxt,ord(endmsgconst)));
  229. {$ENDIF TP}
  230. end;
  231. var
  232. lastfileidx,
  233. lastmoduleidx : longint;
  234. Procedure UpdateStatus;
  235. begin
  236. { fix status }
  237. status.currentline:=aktfilepos.line;
  238. status.currentcolumn:=aktfilepos.column;
  239. if assigned(current_module) and assigned(current_module^.sourcefiles) and
  240. ((current_module^.unit_index<>lastmoduleidx) or
  241. (aktfilepos.fileindex<>lastfileidx)) then
  242. begin
  243. { update status record }
  244. status.currentmodule:=current_module^.modulename^;
  245. status.currentsource:=current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex);
  246. status.currentsourcepath:=current_module^.sourcefiles^.get_file_path(aktfilepos.fileindex);
  247. { update lastfileidx only if name known PM }
  248. if status.currentsource<>'' then
  249. lastfileidx:=aktfilepos.fileindex
  250. else
  251. lastfileidx:=0;
  252. lastmoduleidx:=current_module^.unit_index;
  253. end;
  254. end;
  255. procedure stop;
  256. begin
  257. {$ifndef TP}
  258. do_stop();
  259. {$else}
  260. do_stop;
  261. {$endif}
  262. end;
  263. procedure ShowStatus;
  264. begin
  265. UpdateStatus;
  266. {$ifndef TP}
  267. if do_status() then
  268. stop;
  269. {$else}
  270. if do_status then
  271. stop;
  272. {$endif}
  273. end;
  274. function ErrorCount:longint;
  275. begin
  276. ErrorCount:=status.errorcount;
  277. end;
  278. procedure SetMaxErrorCount(count:longint);
  279. begin
  280. status.maxerrorcount:=count;
  281. end;
  282. procedure GenerateError;
  283. begin
  284. inc(status.errorcount);
  285. end;
  286. procedure internalerror(i : longint);
  287. begin
  288. UpdateStatus;
  289. do_internalerror(i);
  290. inc(status.errorcount);
  291. stop;
  292. end;
  293. procedure Comment(l:longint;s:string);
  294. var
  295. dostop : boolean;
  296. begin
  297. dostop:=((l and V_Fatal)<>0);
  298. if (l and V_Error)<>0 then
  299. inc(status.errorcount);
  300. { Create status info }
  301. UpdateStatus;
  302. { Fix replacements }
  303. DefaultReplacements(s);
  304. { show comment }
  305. if do_comment(l,s) or dostop then
  306. stop;
  307. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  308. begin
  309. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  310. status.skip_error:=true;
  311. stop;
  312. end;
  313. end;
  314. Procedure Msg2Comment(s:string);
  315. var
  316. idx,i,v : longint;
  317. dostop : boolean;
  318. begin
  319. {Reset}
  320. dostop:=false;
  321. v:=0;
  322. {Parse options}
  323. idx:=pos('_',s);
  324. if idx=0 then
  325. v:=V_Normal
  326. else
  327. if (idx >= 1) And (idx <= 5) then
  328. begin
  329. for i:=1 to idx do
  330. begin
  331. case upcase(s[i]) of
  332. 'F' : begin
  333. v:=v or V_Fatal;
  334. inc(status.errorcount);
  335. dostop:=true;
  336. end;
  337. 'E' : begin
  338. v:=v or V_Error;
  339. inc(status.errorcount);
  340. end;
  341. 'O' : v:=v or V_Normal;
  342. 'W':
  343. v:=v or V_Warning;
  344. 'N' : v:=v or V_Note;
  345. 'H' : v:=v or V_Hint;
  346. 'I' : v:=v or V_Info;
  347. 'L' : v:=v or V_Status;
  348. 'U' : v:=v or V_Used;
  349. 'T' : v:=v or V_Tried;
  350. 'M' : v:=v or V_Macro;
  351. 'P' : v:=v or V_Procedure;
  352. 'C' : v:=v or V_Conditional;
  353. 'D' : v:=v or V_Debug;
  354. 'B' : v:=v or V_Declarations;
  355. 'X' : v:=v or V_Executable;
  356. 'Z' : v:=v or V_Assem;
  357. 'S' : dostop:=true;
  358. '_' : ;
  359. end;
  360. end;
  361. end;
  362. Delete(s,1,idx);
  363. { fix status }
  364. UpdateStatus;
  365. { Fix replacements }
  366. DefaultReplacements(s);
  367. { show comment }
  368. if do_comment(v,s) or dostop then
  369. stop;
  370. if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
  371. begin
  372. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  373. status.skip_error:=true;
  374. stop;
  375. end;
  376. end;
  377. procedure Message(w:tmsgconst);
  378. begin
  379. Msg2Comment(msg^.Get(ord(w)));
  380. end;
  381. procedure Message1(w:tmsgconst;const s1:string);
  382. begin
  383. Msg2Comment(msg^.Get1(ord(w),s1));
  384. end;
  385. procedure Message2(w:tmsgconst;const s1,s2:string);
  386. begin
  387. Msg2Comment(msg^.Get2(ord(w),s1,s2));
  388. end;
  389. procedure Message3(w:tmsgconst;const s1,s2,s3:string);
  390. begin
  391. Msg2Comment(msg^.Get3(ord(w),s1,s2,s3));
  392. end;
  393. procedure MessagePos(const pos:tfileposinfo;w:tmsgconst);
  394. var
  395. oldpos : tfileposinfo;
  396. begin
  397. oldpos:=aktfilepos;
  398. aktfilepos:=pos;
  399. Msg2Comment(msg^.Get(ord(w)));
  400. aktfilepos:=oldpos;
  401. end;
  402. procedure MessagePos1(const pos:tfileposinfo;w:tmsgconst;const s1:string);
  403. var
  404. oldpos : tfileposinfo;
  405. begin
  406. oldpos:=aktfilepos;
  407. aktfilepos:=pos;
  408. Msg2Comment(msg^.Get1(ord(w),s1));
  409. aktfilepos:=oldpos;
  410. end;
  411. procedure MessagePos2(const pos:tfileposinfo;w:tmsgconst;const s1,s2:string);
  412. var
  413. oldpos : tfileposinfo;
  414. begin
  415. oldpos:=aktfilepos;
  416. aktfilepos:=pos;
  417. Msg2Comment(msg^.Get2(ord(w),s1,s2));
  418. aktfilepos:=oldpos;
  419. end;
  420. procedure MessagePos3(const pos:tfileposinfo;w:tmsgconst;const s1,s2,s3:string);
  421. var
  422. oldpos : tfileposinfo;
  423. begin
  424. oldpos:=aktfilepos;
  425. aktfilepos:=pos;
  426. Msg2Comment(msg^.Get3(ord(w),s1,s2,s3));
  427. aktfilepos:=oldpos;
  428. end;
  429. procedure InitVerbose;
  430. begin
  431. { Init }
  432. {$ifndef EXTERN_MSG}
  433. msg:=new(pmessage,Init(@msgtxt,ord(endmsgconst)));
  434. {$else}
  435. LoadMsgFile(exepath+'errore.msg');
  436. {$endif}
  437. FillChar(Status,sizeof(TCompilerStatus),0);
  438. status.verbosity:=V_Default;
  439. Status.MaxErrorCount:=50;
  440. end;
  441. procedure DoneVerbose;
  442. begin
  443. if assigned(msg) then
  444. begin
  445. dispose(msg,Done);
  446. msg:=nil;
  447. end;
  448. end;
  449. end.
  450. {
  451. $Log$
  452. Revision 1.49 2000-03-12 08:24:45 daniel
  453. * Made check for message file TP compilable.
  454. Revision 1.48 2000/03/01 22:29:18 peter
  455. * message files are check for amount of msgs found. If not correct a
  456. line is written to stdout and switched to internal messages
  457. Revision 1.47 2000/03/01 21:45:42 peter
  458. * lowercase .INC -> .inc
  459. Revision 1.46 2000/02/28 17:23:57 daniel
  460. * Current work of symtable integration committed. The symtable can be
  461. activated by defining 'newst', but doesn't compile yet. Changes in type
  462. checking and oop are completed. What is left is to write a new
  463. symtablestack and adapt the parser to use it.
  464. Revision 1.45 2000/02/09 13:23:09 peter
  465. * log truncated
  466. Revision 1.44 2000/01/07 01:14:49 peter
  467. * updated copyright to 2000
  468. Revision 1.43 1999/11/06 14:34:32 peter
  469. * truncated log to 20 revs
  470. Revision 1.42 1999/08/05 16:53:28 peter
  471. * V_Fatal=1, all other V_ are also increased
  472. * Check for local procedure when assigning procvar
  473. * fixed comment parsing because directives
  474. * oldtp mode directives better supported
  475. * added some messages to errore.msg
  476. }