~ubuntu-branches/ubuntu/jaunty/adacontrol/jaunty

« back to all changes in this revision

Viewing changes to src/framework-reports.adb

  • Committer: Bazaar Package Importer
  • Author(s): Ludovic Brenta
  • Date: 2008-04-27 15:25:59 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080427152559-qrlic533a1x02flu
Tags: 1.8r8-1

* New upstream version.
* debian/adacontrol.gpr: delete; use upstream's project file instead.
* patches/build.patch: patch upstream's project file to change Object_Dir
  and Exec_Dir.
* Build-depend on asis 2007 and gnat-4.3.
* Add support for mips, mipsel and ppc64.
* Build and provide ptree.
* ptree.1: new.
* adactl.1: update; new options and rules are available.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
-- Ada
33
33
with
 
34
  Ada.Exceptions,
34
35
  Ada.Characters.Handling,
35
36
  Ada.Strings.Wide_Fixed,
36
37
  Ada.Wide_Text_IO;
37
38
 
38
39
-- Adalog
39
40
with
 
41
  Linear_Queue,
40
42
  Utilities;
41
43
 
42
44
-- Adactl
48
50
 
49
51
   CSV_Separator : constant array (Output_Format range CSV..CSVX) of Wide_Character := (',', ';');
50
52
 
51
 
   Not_Found   : constant             := 0;
52
 
   Adactl_Mark : constant Wide_String := "##";
53
 
   Adactl_Tag  : constant Wide_String := "--" & Adactl_Mark;
 
53
   Not_Found : constant := 0;
54
54
 
55
55
   Error_Count   : Natural := 0;
56
56
   Warning_Count : Natural := 0;
57
57
 
58
58
   Uncheckable_Used   : array (Uncheckable_Consequence) of Boolean := (others => False);
59
 
   Uncheckable_Types  : array (Uncheckable_Consequence) of Rule_Types;
 
59
   Uncheckable_Types  : array (Uncheckable_Consequence) of Control_Kinds;
60
60
   Uncheckable_Labels : array (Uncheckable_Consequence) of Ada.Strings.Wide_Unbounded.Unbounded_Wide_String;
 
61
   type False_Positive_Info (Len : Positive) is
 
62
      record
 
63
         Loc : Location;
 
64
         Msg : Wide_String (1 .. Len);
 
65
      end record;
 
66
   package False_Positive_List is new Linear_Queue (False_Positive_Info);
 
67
   package False_Positive_Map  is new Binary_Map (Unbounded_Wide_String, False_Positive_List.Queue);
 
68
   False_Positive_Messages : False_Positive_Map.Map;
 
69
   -- The above map maps Rule Id's to a list of delayed false positive messages
 
70
   -- See Uncheckable.
61
71
 
62
72
   package Counters is new Binary_Map (Unbounded_Wide_String, Natural);
63
73
   Rule_Counter   : Counters.Map;
64
 
   Stats_Counters : array (Rule_Types) of Counters.Map;
 
74
   Stats_Counters : array (Control_Kinds) of Counters.Map;
 
75
   -- Note on the management of stat counters:
 
76
   -- An entry in each map of Stats_Counters is added by Rule_Manager (Init_Stats)
 
77
   -- when a new control is added. This is necessary to know about rules that were
 
78
   -- not triggered at all.
 
79
   -- However, this does not guarantee that every rule is present in the map, because
 
80
   -- of Uncheckable, which does not follow the normal naming scheme of rules.
 
81
   -- Therefore, a default value must still be provided when fetching from those maps.
65
82
 
66
83
   -----------
67
84
   -- Reset --
78
95
   -- Update --
79
96
   ------------
80
97
 
81
 
   procedure Update (Rule_Id     : in     Wide_String;
82
 
                     Rule_Label  : in     Wide_String;
 
98
   procedure Update (Id          : in     Wide_String;
 
99
                     Label       : in     Wide_String;
83
100
                     Line        : in     Wide_String;
84
101
                     Single_Line : in     Boolean;
85
102
                     Active      : in out Boolean) is
86
103
      use Utilities, Ada.Strings.Wide_Fixed;
87
104
 
88
 
      Pos : Natural := Index (Line, Adactl_Tag);
 
105
      Mark1 : constant Wide_String := "--" & To_Wide_String (Adactl_Tag1);
 
106
      Mark2 : constant Wide_String := To_Wide_String (Adactl_Tag2);
 
107
      Pos   : Natural := Index (Line, Mark1);
89
108
 
90
109
      function Next_Word return Wide_String is
91
110
         Quoted : Boolean;
97
116
               return "";
98
117
            elsif Line (Start) <= ' ' then
99
118
               Start := Start+1;
100
 
            elsif Start <= Line'Last - Adactl_Mark'Length + 1
101
 
              and then Line (Start .. Start + Adactl_Mark'Length -1) = Adactl_Mark
 
119
            elsif Start <= Line'Last - Mark2'Length + 1
 
120
              and then Line (Start .. Start + Mark2'Length -1) = Mark2
102
121
            then
103
122
               return "";
104
123
            else
123
142
            else
124
143
               exit when Stop > Line'Last;
125
144
               exit when Line (Stop) <= ' ';
 
145
               exit when Line (Stop) = '#';
126
146
            end if;
127
147
            Stop := Stop + 1;
128
148
         end loop;
140
160
      if Pos = Not_Found then
141
161
         return;
142
162
      end if;
143
 
      Pos := Pos + Adactl_Tag'Length;
 
163
      Pos := Pos + Mark1'Length;
144
164
 
145
165
      if Next_Word /= "RULE" then
146
166
         return;
184
204
               Current : constant Wide_String := Next_Word;
185
205
            begin
186
206
               exit when Current = "";
187
 
               if        Current = To_Upper (Rule_Id)
188
 
                 or else Current = To_Upper (Rule_Label)
 
207
               if        Current = To_Upper (Id)
 
208
                 or else Current = To_Upper (Label)
189
209
                 or else Current = "ALL"
190
210
               then
191
211
                  Active := Activity;
200
220
      -- Active does not change
201
221
   end Update;
202
222
 
 
223
   -----------
 
224
   -- "and" --
 
225
   -----------
 
226
 
 
227
   function "and" (Left, Right : Wide_String) return Wide_String is
 
228
   begin
 
229
      case Format_Option is
 
230
         when Gnat | Source=>
 
231
            return Left & ": " & Right;
 
232
         when CSV | CSVX =>
 
233
            return Left & CSV_Separator (Format_Option) & Right;
 
234
         when None =>
 
235
            return Left & CSV_Separator (CSVX) & Right;
 
236
      end case;
 
237
   end "and";
 
238
 
 
239
   ----------------
 
240
   -- Raw_Report --
 
241
   ----------------
 
242
 
 
243
   procedure Raw_Report (Message : Wide_String) is
 
244
      use Ada.Wide_Text_IO;
 
245
   begin
 
246
      Put_Line (Message);
 
247
   end Raw_Report;
 
248
 
203
249
   ------------
204
250
   -- Report --
205
251
   ------------
206
252
 
207
 
   procedure Report (Rule_Id    : in Wide_String;
208
 
                     Rule_Label : in Wide_String;
209
 
                     Rule_Type  : in Rule_Types;
210
 
                     Loc        : in Location;
211
 
                     Msg        : in Wide_String) is
 
253
   procedure Report (Rule_Id   : in Wide_String;
 
254
                     Ctl_Label : in Wide_String;
 
255
                     Ctl_Kind  : in Control_Kinds;
 
256
                     Loc       : in Location;
 
257
                     Msg       : in Wide_String)
 
258
   is
 
259
      -- This one is the "true" Report procedure, i.e. the other Report procedure is just
 
260
      -- a front-end to this one.
212
261
      use Utilities, Adactl_Options;
213
262
 
214
 
      Label     : constant Wide_String := Choose (Rule_Label, Otherwise => Rule_Id);
 
263
      Label     : constant Wide_String := Choose (Ctl_Label, Otherwise => Rule_Id);
215
264
      Line      : Wide_String (1..1024);
216
265
      Line_Last : Natural := 0;
217
266
 
219
268
         use Ada.Wide_Text_IO;
220
269
 
221
270
         function Quote (Item : Wide_String) return Wide_String is
222
 
            use Ada.Strings.Wide_Fixed;
223
271
            Result : Wide_String (Item'First .. Item'Last + Ada.Strings.Wide_Fixed.Count (Item, """") + 2);
224
272
            Index  : Positive;
225
273
         begin
240
288
         end Quote;
241
289
 
242
290
         Current_Col : Ada.Wide_Text_IO.Count;
243
 
      begin
 
291
      begin   -- Issue_Message
 
292
         if Just_Created then
 
293
            Just_Created := False;
 
294
            case Format_Option is
 
295
               when CSV | CSVX =>
 
296
                  Put ("Location");
 
297
                  Put (CSV_Separator (Format_Option));
 
298
                  Put ("Type");
 
299
                  Put (CSV_Separator (Format_Option));
 
300
                  Put ("Label");
 
301
                  Put (CSV_Separator (Format_Option));
 
302
                  Put ("Rule");
 
303
                  Put (CSV_Separator (Format_Option));
 
304
                  Put ("Message");
 
305
                  New_Line;
 
306
               when others =>
 
307
                  null;
 
308
            end case;
 
309
         end if;
 
310
 
244
311
         case Format_Option is
245
312
            when Gnat =>
246
313
               if Loc /= Null_Location then
262
329
               Put (CSV_Separator (Format_Option));
263
330
               Put (Title);
264
331
               Put (CSV_Separator (Format_Option));
265
 
               Put (Choose (Rule_Label, Otherwise => """"""));
 
332
               Put (Choose (Ctl_Label, Otherwise => """"""));
266
333
               Put (CSV_Separator (Format_Option));
267
334
               Put (Rule_Id);
268
335
               Put (CSV_Separator (Format_Option));
269
336
               Put (Quote (Msg));
270
337
               New_Line;
271
338
            when Source =>
272
 
               if Loc /= Null_Location then
 
339
               if Loc = Null_Location then
 
340
                  Put (Line (1 .. Line_Last));
 
341
               else
273
342
                  Put (Image (Loc));
274
343
                  Put (": ");
 
344
                  Current_Col := Col (Current_Output);
 
345
                  Put (Line (1 .. Line_Last));
 
346
                  New_Line;
 
347
                  Set_Col (Current_Col + Ada.Wide_Text_IO.Count (Get_First_Column (Loc)) - 1);
 
348
                  Put ("! ");
275
349
               end if;
276
 
               Current_Col := Col (Current_Output);
277
 
               Put (Line (1 .. Line_Last));
278
 
               New_Line;
279
 
               Set_Col (Current_Col + Ada.Wide_Text_IO.Count (Get_First_Column (Loc)) - 1);
280
 
               Put ("! ");
281
350
               Put (Title);
282
351
               Put (": ");
283
352
               Put (Label);
284
353
               Put (": ");
285
354
               Put (Msg);
286
355
               New_Line;
 
356
            when None =>
 
357
               null;
287
358
         end case;
288
359
      end Issue_Message;
289
360
 
290
 
      use Counters;
 
361
      use Ada.Exceptions;
 
362
      use Counters, False_Positive_Map;
291
363
      Active : Boolean := True;
292
364
 
293
365
   begin
294
 
      if not Ignore_Option or Format_Option = Source then
 
366
      if Error_Count = Max_Errors or Error_Count + Warning_Count = Max_Messages then
 
367
         -- This can happen for finalization messages after the run has been previously cancelled
 
368
         -- due to too many errors/messages
 
369
         return;
 
370
      end if;
 
371
 
 
372
      -- Output delayed false positive messages for this rule
 
373
      -- There can be such messages only if Uncheckable has been activated
 
374
      if Is_Present (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id)) then
 
375
         declare
 
376
            use False_Positive_List;
 
377
            Message_Queue : constant Queue  := Fetch (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id));
 
378
            Current       : Cursor := First (Message_Queue);
 
379
         begin
 
380
            -- Delete entry in map here to avoid infinite recursion
 
381
            -- There is no problem, since Queues are controlled, the queue will be released when
 
382
            -- exiting the block.
 
383
            Delete (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id));
 
384
            while Has_Element (Current) loop
 
385
               declare
 
386
                  Mess_Info : constant False_Positive_Info := Fetch (Current);
 
387
               begin
 
388
                  Report (Rule_Id,
 
389
                          To_Wide_String (Uncheckable_Labels (False_Positive)),
 
390
                          Uncheckable_Types  (False_Positive),
 
391
                          Mess_Info.Loc,
 
392
                          Mess_Info.Msg);
 
393
               end;
 
394
               Current := Next (Current);
 
395
            end loop;
 
396
         end;
 
397
      end if;
 
398
 
 
399
      if Format_Option = Source
 
400
        or (Format_Option /= None and not Ignore_Option)
 
401
      then
295
402
         declare
296
403
            use Ada.Characters.Handling, Ada.Wide_Text_IO;
297
 
            File : File_Type;
 
404
            Source_File : File_Type;
298
405
         begin
299
 
            Open (File,
 
406
            Open (Source_File,
300
407
                  In_File,
301
408
                  To_String (Get_File_Name (Loc)),
302
409
                  Form => Implementation_Options.Form_Parameters);
303
410
 
304
411
            for I in Natural range 1 .. Get_First_Line (Loc) - 1 loop
305
 
               Get_Line (File, Line, Line_Last);
 
412
               Get_Line (Source_File, Line, Line_Last);
306
413
               if not Ignore_Option then
307
 
                  Update (Rule_Id, Rule_Label, Line (Line'First .. Line_Last), Single_Line => False, Active => Active);
 
414
                  Update (Rule_Id, Ctl_Label, Line (Line'First .. Line_Last), Single_Line => False, Active => Active);
308
415
               end if;
309
416
            end loop;
310
417
 
311
 
            Get_Line (File, Line, Line_Last);
 
418
            Get_Line (Source_File, Line, Line_Last);
312
419
            if not Ignore_Option then
313
 
               Update (Rule_Id, Rule_Label, Line (Line'First .. Line_Last), Single_Line => True, Active => Active);
 
420
               Update (Rule_Id, Ctl_Label, Line (Line'First .. Line_Last), Single_Line => True, Active => Active);
314
421
            end if;
315
422
 
316
 
            Close (File);
 
423
            Close (Source_File);
317
424
         exception
318
425
            when Name_Error =>
319
426
               -- if file is not found ???,
320
427
               -- consider that rule is active
321
428
               null;
322
429
            when others =>
323
 
               if Is_Open (File) then
324
 
                  Close (File);
 
430
               if Is_Open (Source_File) then
 
431
                  Close (Source_File);
325
432
               end if;
326
433
               raise;
327
434
         end;
330
437
      -- Here, Line is the good source line
331
438
 
332
439
      if Active then
333
 
         case Rule_Type is
 
440
         case Ctl_Kind is
334
441
            when Check =>
335
442
               Error_Count := Error_Count + 1;
 
443
 
336
444
               Issue_Message ("Error");
337
445
            when Search =>
338
446
               if Warning_As_Error_Option then
353
461
         if Stats_Level >= Nulls_Only then
354
462
            declare
355
463
               Key : constant Unbounded_Wide_String := To_Unbounded_Wide_String (Rule_Id
356
 
                                                                                   & Choose (Rule_Label = "",
 
464
                                                                                   & Choose (Ctl_Label = "",
357
465
                                                                                             "",
358
 
                                                                                             "." & Rule_Label));
 
466
                                                                                             "." & Ctl_Label));
359
467
            begin
360
 
               Add (Stats_Counters (Rule_Type), Key, Fetch (Stats_Counters (Rule_Type), Key) + 1);
 
468
               Add (Stats_Counters (Ctl_Kind), Key, Fetch (Stats_Counters (Ctl_Kind), Key, Default_Value => 0) + 1);
361
469
            end;
362
470
         end if;
 
471
 
 
472
         if Error_Count = Max_Errors then
 
473
            Raise_Exception (Cancellation'Identity, Message => "too many errors");
 
474
         elsif Error_Count + Warning_Count = Max_Messages then
 
475
            Raise_Exception (Cancellation'Identity, Message => "too many messages");
 
476
         end if;
363
477
      end if;
364
478
   end Report;
365
479
 
367
481
   -- Report --
368
482
   ------------
369
483
 
370
 
   procedure Report (Rule_Id    : in Wide_String;
 
484
   procedure Report (Rule_Id     : in Wide_String;
371
485
                     Context    : in Root_Context'Class;
372
486
                     Loc        : in Location;
373
487
                     Msg        : in Wide_String;
383
497
      begin
384
498
         if not Count_Only then
385
499
            Report (Rule_Id,
386
 
                    To_Wide_String (Basic_Context.Rule_Label),
387
 
                    Basic_Context.Rule_Type,
 
500
                    To_Wide_String (Basic_Context.Ctl_Label),
 
501
                    Basic_Context.Ctl_Kind,
388
502
                    Loc,
389
503
                    Msg);
390
504
         end if;
403
517
   -- Uncheckable --
404
518
   -----------------
405
519
 
406
 
   Risk_Message : constant array (Uncheckable_Consequence) of Wide_String (1 .. 8)
407
 
     := ("positive", "negative");
408
 
 
409
520
   procedure Uncheckable (Rule_Id : in Wide_String;
410
521
                          Risk    : in Uncheckable_Consequence;
411
522
                          Loc     : in Location;
412
523
                          Msg     : in Wide_String)
413
524
   is
414
525
      use Utilities;
415
 
      Rule_Label : constant Wide_String := To_Wide_String (Uncheckable_Labels (Risk));
 
526
      Label : constant Wide_String := To_Wide_String (Uncheckable_Labels (Risk));
416
527
   begin
417
528
      if Uncheckable_Used (Risk) then
418
 
         Report (Rule_Id,
419
 
                 Rule_Label,
420
 
                 Uncheckable_Types  (Risk),
421
 
                 Loc,
422
 
                 Choose (Rule_Label /= "", "in rule " & Rule_Id & ": ", "")
423
 
                   & "Possible false " & Risk_Message (Risk) & ": " & Msg);
 
529
         case Risk is
 
530
            when False_Negative =>
 
531
               Report (Rule_Id,
 
532
                       Label,
 
533
                       Uncheckable_Types  (Risk),
 
534
                       Loc,
 
535
                       Choose (Label /= "", "in rule " & Rule_Id & ": ", "")
 
536
                       & "Possible false negative: " & Msg);
 
537
            when False_Positive =>
 
538
               -- False positive messages are delayed until the next call to Report from the
 
539
               -- same rule. Therefore, false positive messages will not appear if there are
 
540
               -- no messages from the rule at all.
 
541
               declare
 
542
                  use False_Positive_List, False_Positive_Map;
 
543
                  Rule_Queue : Queue := Fetch (False_Positive_Messages,
 
544
                                               To_Unbounded_Wide_String (Rule_Id),
 
545
                                               Default_Value => Empty_Queue);
 
546
                  Full_Msg : constant Wide_String := Choose (Label /= "", "in rule " & Rule_Id & ": ", "")
 
547
                                                     & "Possible false positive: " & Msg;
 
548
               begin
 
549
                  Append (Rule_Queue, (Full_Msg'Length,
 
550
                                       Loc,
 
551
                                       Full_Msg));
 
552
                  Add (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id), Rule_Queue);
 
553
               end;
 
554
         end case;
424
555
      end if;
425
556
   end Uncheckable;
426
557
 
429
560
   -----------------------
430
561
 
431
562
   procedure Reset_Uncheckable is
 
563
      use False_Positive_Map;
432
564
   begin
433
565
      Uncheckable_Used := (others => False);
 
566
      Clear (False_Positive_Messages);
434
567
   end Reset_Uncheckable;
435
568
 
436
569
   ---------------------
437
570
   -- Set_Uncheckable --
438
571
   ---------------------
439
572
 
440
 
   procedure Set_Uncheckable (Risk : Uncheckable_Consequence; Rule_Type : Rule_Types; Label : Wide_String) is
 
573
   procedure Set_Uncheckable (Risk     : Uncheckable_Consequence;
 
574
                              Ctl_Kind : Control_Kinds;
 
575
                              Label    : Wide_String)
 
576
   is
441
577
   begin
442
578
      Uncheckable_Used   (Risk) := True;
443
 
      Uncheckable_Types  (Risk) := Rule_Type;
 
579
      Uncheckable_Types  (Risk) := Ctl_Kind;
444
580
      Uncheckable_Labels (Risk) := To_Unbounded_Wide_String (Label);
445
581
   end Set_Uncheckable;
446
582
 
466
602
   -- Init_Counts --
467
603
   -----------------
468
604
 
469
 
   procedure Init_Counts (Rule_Id : Wide_String; Rule_Label : Wide_String) is
 
605
   procedure Init_Counts (Rule : Wide_String; Label : Wide_String) is
470
606
      use Counters, Utilities;
471
607
 
472
 
      Label : constant Wide_String := Choose (Rule_Label, Otherwise => Rule_Id);
 
608
      Good_Label : constant Wide_String := Choose (Label, Otherwise => Rule);
473
609
   begin
474
 
      Add (Rule_Counter, To_Unbounded_Wide_String (Label), 0);
 
610
      Add (Rule_Counter, To_Unbounded_Wide_String (Good_Label), 0);
475
611
  end Init_Counts;
476
612
 
477
613
   -------------------
479
615
   -------------------
480
616
 
481
617
   procedure Report_Counts is
482
 
      use Counters, Utilities, Ada.Wide_Text_IO;
 
618
      use Counters, Ada.Wide_Text_IO;
483
619
 
484
620
      procedure Report_One_Count (Key : in Unbounded_Wide_String; Counter_Value : in out Natural) is
 
621
         use Utilities;
485
622
      begin
486
 
         Put (To_Wide_String (Key));
487
 
         case Format_Option is
488
 
            when Gnat | Source=>
489
 
               Put (": ");
490
 
            when CSV | CSVX =>
491
 
               Put (CSV_Separator (Format_Option));
492
 
         end case;
493
 
         Put (Integer_Img (Counter_Value));
494
 
         New_Line;
 
623
         Raw_Report (To_Wide_String (Key) and Integer_Img (Counter_Value));
495
624
      end Report_One_Count;
496
625
 
497
626
      procedure Report_All_Counts is new Iterate (Report_One_Count);
498
627
   begin
499
 
      if Is_Empty (Rule_Counter) then
 
628
      if Is_Empty (Rule_Counter) or Format_Option = None then
500
629
         return;
501
630
      end if;
502
631
 
513
642
      use Counters;
514
643
   begin
515
644
      Clear (Rule_Counter);
516
 
      for R in Rule_Types loop
 
645
      for R in Control_Kinds loop
517
646
         Clear (Stats_Counters (R));
518
647
      end loop;
519
648
   end Clear_All;
529
658
      Error_Count   := 0;
530
659
      Reset (Rule_Counter);
531
660
 
532
 
      for R in Rule_Types loop
 
661
      for R in Control_Kinds loop
533
662
         Reset (Stats_Counters (R));
534
663
      end loop;
535
664
   end Reset;
543
672
      use Counters, Utilities;
544
673
      Key : constant Unbounded_Wide_String := To_Unbounded_Wide_String (Rule & Choose (Label = "", "", "." & Label));
545
674
   begin
546
 
      for R in Rule_Types loop
 
675
      for R in Control_Kinds loop
547
676
        Add (Stats_Counters (R), Key, 0);
548
677
      end loop;
549
678
   end Init_Stats;
570
699
      Check_Delete (Rule_Counter);
571
700
      -- TBSL: delete entries whose name is a label associated to the rule
572
701
 
573
 
      for R in Rule_Types loop
 
702
      for R in Control_Kinds loop
574
703
         Check_Delete (Stats_Counters (R));
575
704
      end loop;
576
705
   end Clear;
589
718
         Wide_Key        : Wide_String := To_Wide_String (Key);
590
719
         Dot_Found       : Boolean     := False;
591
720
      begin
592
 
         for R in Rule_Types range Rule_Types'Succ (Rule_Types'First) .. Rule_Types'Last loop
593
 
            Triggered_Count := Triggered_Count + Fetch (Stats_Counters (R), Key);
 
721
         for R in Control_Kinds range Control_Kinds'Succ (Control_Kinds'First) .. Control_Kinds'Last loop
 
722
            Triggered_Count := Triggered_Count + Fetch (Stats_Counters (R), Key, Default_Value => 0);
594
723
         end loop;
595
724
 
596
725
         if Triggered_Count = 0 or else Stats_Level = Full then
597
726
            case Format_Option is
598
 
               when Gnat | Source=>
 
727
               when Gnat | Source | None =>
599
728
                  Put (Wide_Key);
 
729
                  Put (": ");
600
730
                  if Triggered_Count = 0 then
601
731
                     Put ("not triggered");
602
732
                  else
603
 
                     Put (To_Title (Rule_Types'Wide_Image (Rule_Types'First)));
 
733
                     Put (To_Title (Control_Kinds'Wide_Image (Control_Kinds'First)));
604
734
                     Put (": ");
605
735
                     Put (Integer_Img (Counter_Value));
606
736
 
607
 
                     for R in Rule_Types range Rule_Types'Succ (Rule_Types'First) .. Rule_Types'Last loop
 
737
                     for R in Control_Kinds range Control_Kinds'Succ (Control_Kinds'First) .. Control_Kinds'Last loop
608
738
                        Put (", ");
609
 
                        Put (To_Title (Rule_Types'Wide_Image (R)));
 
739
                        Put (To_Title (Control_Kinds'Wide_Image (R)));
610
740
                        Put(": ");
611
 
                        Put (Integer_Img (Fetch (Stats_Counters (R), Key)));
 
741
                        Put (Integer_Img (Fetch (Stats_Counters (R), Key, Default_Value => 0)));
612
742
                     end loop;
613
743
                  end if;
614
744
               when CSV | CSVX =>
626
756
                     Put (CSV_Separator (Format_Option));
627
757
                  end if;
628
758
 
629
 
                  for R in Rule_Types loop
 
759
                  for R in Control_Kinds loop
630
760
                     Put (CSV_Separator (Format_Option));
631
 
                     Put (Integer_Img (Fetch (Stats_Counters (R), Key)));
 
761
                     Put (Integer_Img (Fetch (Stats_Counters (R), Key, Default_Value => 0)));
632
762
                  end loop;
633
763
            end case;
634
764
            New_Line;
636
766
      end Report_One_Stat;
637
767
 
638
768
      procedure Report_All_Stats is new Iterate (Report_One_Stat);
 
769
      use Utilities;
639
770
   begin
640
771
      if Stats_Level = None then
641
772
         return;
645
776
         New_Line;
646
777
         Put_Line ("Rules usage statistics:");
647
778
         case Format_Option is
648
 
            when Gnat | Source=>
 
779
            when Gnat | Source | None =>
649
780
               null;
650
781
            when CSV | CSVX =>
651
782
               Put_Line ("Rule"
654
785
                           & CSV_Separator (Format_Option) & "Search"
655
786
                           & CSV_Separator (Format_Option) & "Count");
656
787
         end case;
657
 
         Report_All_Stats (Stats_Counters (Rule_Types'First));
 
788
         Report_All_Stats (Stats_Counters (Control_Kinds'First));
658
789
      end if;
659
790
 
660
791
      if Stats_Level >= General then
661
792
         New_Line;
662
 
         Put ("Issued messages: Errors =" & Natural'Wide_Image (Nb_Errors));
663
 
         Put (", Warnings =" & Natural'Wide_Image (Nb_Warnings));
 
793
         Put ("Issued messages: Errors = " & Integer_Img (Nb_Errors));
 
794
         Put (", Warnings = " & Integer_Img (Nb_Warnings));
664
795
         New_Line;
665
796
      end if;
666
797
   end Report_Stats;
667
 
 
668
 
   ---------------------
669
 
   -- Report_Counters --
670
 
   ---------------------
671
 
 
672
 
   procedure Report_Counters is
673
 
   begin
674
 
      Report_Counts;
675
 
      Report_Stats;
676
 
   end Report_Counters;
677
798
end Framework.Reports;