127
148
procedure Compile is
128
use Rules_Manager, Framework.Language.Commands, Ada.IO_Exceptions;
149
use Rules_Manager, Framework.Language.Commands, Framework.Reports, Ada.IO_Exceptions, Ada.Characters.Handling;
151
procedure Process_Error (Occur : Ada.Exceptions.Exception_Occurrence) is
154
User_Message ("Error in rule: " & To_Wide_String (Exception_Message (Occur)));
155
Rule_Error_Occurred := True;
156
-- Ignore till next semi-colon (or Eof)
158
case Current_Token.Kind is
166
Next_Token (No_Delay => True);
169
-- Encountered bad characters => Ignore
130
176
-- Set up initial token
133
while Current_Token.Kind /= EoF loop
134
Last_Was_Go := False;
136
if Current_Token.Kind /= Name then
137
Syntax_Error ("Command or label expected", Current_Token.Position);
140
case Current_Token.Key is
143
Add_Use ("", Check, Get_Rule_Name);
148
if Current_Token.Kind /= Name then
149
Syntax_Error ("""all"", ""counts"", or Rule name expected", Current_Token.Position);
152
if Current_Token.Key = Key_All then
159
Command (Current_Token.Text (1 .. Current_Token.Length), Clear);
161
exit when Current_Token.Kind /= Comma;
163
if Current_Token.Kind /= Name then
164
Syntax_Error ("Rule name expected", Current_Token.Position);
172
Add_Use ("", Count, Get_Rule_Name);
184
if Current_Token.Kind = Semi_Colon then
187
User_Message ("Commands:");
189
User_Message ("Rules:");
192
elsif Current_Token.Kind = Name and then Current_Token.Key = Key_All then
199
-- The simpler solution is to provide help messages as rule names are parsed,
200
-- but this gives unpleasant behaviour in interactive mode when there is a
201
-- syntax error. Therefore, we first accumulate names, then give all helps.
203
Rule_Names : array (1 .. Number_Of_Rules) of Unbounded_Wide_String;
178
Next_Token (No_Delay => True);
179
-- No_Delay is true to get the error here if there is a parse error in the first token
181
when Occur : others =>
182
Process_Error (Occur);
185
while Current_Token.Kind /= Eof loop
187
Last_Was_Go := False;
189
if Current_Token.Kind /= Name then
190
Syntax_Error ("Command or label expected", Current_Token.Position);
193
case Current_Token.Key is
196
Add_Use ("", Check, Get_Rule_Name);
201
if Current_Token.Kind /= Name then
202
Syntax_Error ("""all"" or Rule name expected", Current_Token.Position);
205
if Current_Token.Key = Key_All then
213
Command (Current_Token.Text (1 .. Current_Token.Length), Clear);
215
exit when Current_Token.Kind /= Comma;
207
217
if Current_Token.Kind /= Name then
208
218
Syntax_Error ("Rule name expected", Current_Token.Position);
210
if Inx = Rule_Names'Last then
211
-- This can happen only if the user specified the same rule
212
-- several times, and listed more names than there are rules.
213
-- Extremely unlikely in practice, but not a reason for not being careful...
214
Syntax_Error ("Too many rule names in ""Help"" command", Current_Token.Position);
217
Rule_Names (Inx) := To_Unbounded_Wide_String (Current_Token.Text
218
(1 .. Current_Token.Length));
220
exit when Current_Token.Kind /= Comma;
225
for I in 1 .. Inx loop
226
Help (To_Wide_String (Rule_Names (I)));
233
Ruler.Inhibit (Get_Rule_Name);
237
Next_Token (Force_String => True);
238
if Current_Token.Kind /= Name then
239
Syntax_Error ("Message expected", Current_Token.Position);
242
Mess : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
257
Add_Use ("", Search, Get_Rule_Name);
263
Option : constant Wide_String := To_Upper (Current_Token.Text (1 .. Current_Token.Length));
267
if Option = "OUTPUT" then
268
Next_Token (Force_String => True);
269
if Current_Token.Kind /= Name then
270
Syntax_Error ("File name expected", Current_Token.Position);
226
Add_Use ("", Count, Get_Rule_Name);
238
if Current_Token.Kind = Semi_Colon then
241
User_Message ("Commands:");
243
User_Message ("Rules:");
246
elsif Current_Token.Kind = Name and then Current_Token.Key = Key_All then
253
-- The simpler solution is to provide help messages as rule names are parsed,
254
-- but this gives unpleasant behaviour in interactive mode when there is a
255
-- syntax error. Therefore, we first accumulate names, then give all helps.
273
Output : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
257
Rule_Names : array (Rules_Count range 1 .. Number_Of_Rules) of Unbounded_Wide_String;
258
Inx : Rules_Count := 0;
261
if Current_Token.Kind /= Name then
262
Syntax_Error ("Rule name expected", Current_Token.Position);
264
if Inx = Rule_Names'Last then
265
-- This can happen only if the user specified the same rule
266
-- several times, and listed more names than there are rules.
267
-- Extremely unlikely in practice, but not a reason for not being careful...
268
Syntax_Error ("Too many rule names in ""Help"" command", Current_Token.Position);
271
Rule_Names (Inx) := To_Unbounded_Wide_String (Current_Token.Text
272
(1 .. Current_Token.Length));
274
exit when Current_Token.Kind /= Comma;
278
for I in Rules_Count range 1 .. Inx loop
279
Help (To_Wide_String (Rule_Names (I)));
282
-- Note: Close command *after* providing help, since in case of errors
283
-- we assume that the command is not yet closed (see handler)
278
Set_Output_Command (Output);
283
if Is_String (Current_Token, "ON") then
285
elsif Is_String (Current_Token, "OFF") then
288
Syntax_Error ("""on"" or ""off"" expected", Current_Token.Position);
291
if Option = "VERBOSE" then
292
Verbose_Option := State;
293
elsif Option = "DEBUG" then
294
Debug_Option := State;
295
elsif Option = "IGNORE" then
296
Ignore_Option := True;
298
Syntax_Error ("Unrecognised parameter: """ & Option &'"', Current_Token.Position);
306
Next_Token (Force_String => True);
307
if Current_Token.Kind /= Name then
308
Syntax_Error ("Expect file name after ""Source""", Current_Token.Position);
312
Source : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
313
Source_Pos : constant Location := Current_Token.Position;
318
Source_Command (Source);
321
Syntax_Error ("Sourced file " & Source & " not found", Source_Pos);
325
| Profile_Keys -- Profile keys and "not" allowed as labels
330
Label : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
333
if Current_Token.Kind /= Colon then
334
Syntax_Error ("Unknown command " & Label, Current_Token.Position);
337
if Current_Token.Kind /= Name then
338
Syntax_Error ("Unexpected element after label", Current_Token.Position);
341
case Current_Token.Key is
344
Add_Use (Label, Check, Get_Rule_Name);
347
Add_Use (Label, Search, Get_Rule_Name);
350
Add_Use (Label, Count, Get_Rule_Name);
352
Syntax_Error ("Only ""Check"", ""Search"", or ""Count"" allowed after label",
353
Current_Token.Position);
291
Inhibit_Command (Get_Rule_Name (Allow_All => True));
295
Next_Token (Force_String => True);
296
if Current_Token.Kind /= Name then
297
Syntax_Error ("Message expected", Current_Token.Position);
300
Mess : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
315
Add_Use ("", Search, Get_Rule_Name);
321
Option : constant Wide_String := To_Upper (Current_Token.Text (1 .. Current_Token.Length));
325
if Option = "FORMAT" then
327
if Current_Token.Kind /= Name then
328
Syntax_Error ("Format name expected", Current_Token.Position);
331
Format : constant Wide_String := To_Upper (Current_Token.Text (1 .. Current_Token.Length));
336
Set_Format_Command (Format);
339
elsif Option = "OUTPUT" then
340
Next_Token (Force_String => True);
341
if Current_Token.Kind /= Name then
342
Syntax_Error ("File name expected", Current_Token.Position);
345
Output : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
350
Set_Output_Command (Output);
353
elsif Option = "STATISTICS" then
355
if Current_Token.Kind /= Integer_Value
356
or else Current_Token.Value not in 0 .. Stats_Levels'Pos (Stats_Levels'Last)
358
Syntax_Error ("Statistics level expected (0 .."
359
& Integer'Wide_Image (Stats_Levels'Pos (Stats_Levels'Last))
361
Current_Token.Position);
363
Stats_Level := Stats_Levels'Val (Current_Token.Value);
367
elsif Option = "TRACE" then
368
Next_Token (Force_String => True);
369
if Current_Token.Kind /= Name then
370
Syntax_Error ("File name expected", Current_Token.Position);
373
Trace : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
378
Set_Trace_Command (Trace);
383
if Is_String (Current_Token, "ON") then
385
elsif Is_String (Current_Token, "OFF") then
388
Syntax_Error ("""on"" or ""off"" expected", Current_Token.Position);
391
if Option = "VERBOSE" then
392
Verbose_Option := State;
393
elsif Option = "DEBUG" then
394
Debug_Option := State;
395
elsif Option = "IGNORE" then
396
Ignore_Option := True;
397
elsif Option = "WARNING" then
398
Skip_Warning_Option := not State;
400
Syntax_Error ("Unrecognised parameter: """ & Option &'"', Current_Token.Position);
408
Next_Token (Force_String => True);
409
if Current_Token.Kind /= Name then
410
Syntax_Error ("Expect file name after ""Source""", Current_Token.Position);
414
Source : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
415
Source_Pos : constant Location := Current_Token.Position;
418
Source_Command (Source);
423
Syntax_Error ("Sourced file " & Source & " not found", Source_Pos);
427
| Profile_Keys -- Profile keys and "not" allowed as labels
432
Label : constant Wide_String := Current_Token.Text (1 .. Current_Token.Length);
435
if Current_Token.Kind /= Colon then
436
Syntax_Error ("Unknown command " & Label, Current_Token.Position);
439
if Current_Token.Kind /= Name then
440
Syntax_Error ("Unexpected element after label", Current_Token.Position);
443
case Current_Token.Key is
446
Add_Use (Label, Check, Get_Rule_Name);
449
Add_Use (Label, Search, Get_Rule_Name);
452
Add_Use (Label, Count, Get_Rule_Name);
454
Syntax_Error ("Only ""Check"", ""Search"", or ""Count"" allowed after label",
455
Current_Token.Position);
461
when Occur : Utilities.User_Error =>
462
Process_Error (Occur);
680
850
end Get_Modifier;
682
------------------------
683
-- Get_Flag_Parameter --
684
------------------------
852
-----------------------------
853
-- Get_Enumerated_Modifier --
854
-----------------------------
686
function Get_Flag_Parameter return Flags is
856
function Get_Enumerated_Modifier
857
(Default : in Index := Index'First;
858
Prefix : in Wide_String := "")
688
if not In_Parameters then
689
Failure ("Get_Flag_Parameter called when not in parameters");
692
862
if Current_Token.Kind = Name then
694
To_Compare : constant Wide_String := To_Upper (Prefix &
695
Current_Token.Text (1 .. Current_Token.Length));
697
for Key in Flags loop
698
if To_Compare = Flags'Wide_Image (Key) then
699
if Allow_Any and then Key = Flags'First then
700
-- Oops, the user specified the special value
701
Syntax_Error ("Not a valid parameter: " & Current_Token.Text (1 .. Current_Token.Length),
702
Current_Token.Position);
863
for Idx in Index loop
865
To_Upper (Prefix & Current_Token.Text (1..Current_Token.Length)) =
866
To_Upper (Index'Wide_Image (Idx))
874
end Get_Enumerated_Modifier;
881
package body Flag_Utilities is
883
------------------------
884
-- Get_Flag_Parameter --
885
------------------------
887
function Get_Flag_Parameter (Allow_Any : Boolean) return Flags is
889
if not In_Parameters then
890
Failure ("Get_Flag_Parameter called when not in parameters");
893
if Current_Token.Kind = Name then
895
To_Compare : constant Wide_String := To_Upper (Prefix &
896
Current_Token.Text (1 .. Current_Token.Length));
898
for Key in Flags loop
899
if To_Compare = Flags'Wide_Image (Key) then
900
if Allow_Any and then Key = Flags'First then
901
-- Oops, the user specified the special value
902
Syntax_Error ("Not a valid parameter: " & Current_Token.Text (1 .. Current_Token.Length),
903
Current_Token.Position);
713
-- Here: not a Name, or unrecognized keyword
715
-- Keep the current token
719
Syntax_Error ("Keyword expected, use option -h <rule name> for a list of allowable keywords",
720
Current_Token.Position);
721
end Get_Flag_Parameter;
914
-- Here: not a Name, or unrecognized keyword
916
-- Keep the current token
920
if Current_Token.Kind = Name then
921
Syntax_Error ("Unknown keyword """
922
& Current_Token.Text (1 .. Current_Token.Length)
923
& """, use option -h <rule name> for a list of allowable keywords",
924
Current_Token.Position);
926
Syntax_Error ("Keyword expected, use option -h <rule name> for a list of allowable keywords",
927
Current_Token.Position);
929
end Get_Flag_Parameter;
935
function Image (Item : Flags) return Wide_String is
936
Img : constant Wide_String := To_Lower (Flags'Wide_Image (Item));
939
return Img (Prefix'Length+1 .. Img'Last);
946
procedure Help_On_Flags (Header : Wide_String := "";
947
Footer : Wide_String := "";
948
Extra_Value : Wide_String := "")
950
-- Pretty print of values of flags.
951
-- Values are arranged in columns.
952
-- The number of columns is computed assuming that each column is True_Width wide,
953
-- except for the first one that can contain Extra_Value if provided.
954
-- then the actual width is adjusted to what is actually needed, to make it prettier
955
-- looking. More sophisticated optimization would be overkill.
956
Display_Width : constant := 79;
957
True_Width : constant Natural := Flags'Width - Prefix'Length;
958
Buffer : Wide_String (1..Display_Width);
960
Nb_Col : constant Natural := 1 + (Display_Width - Header'Length
961
- Natural'Max (True_Width, Extra_Value'Length) - 3 -- Width of 1st col
962
) / (True_Width + 3); -- 3 => " | "
963
Col_Widthes : array (1 .. Nb_Col) of Natural := (1 => Extra_Value'Length, others => 0);
964
Current_Col : Natural;
970
Img : constant Wide_String := Image (I);
972
if Img'Length > Col_Widthes (Current_Col) then
973
Col_Widthes (Current_Col) := Img'Length;
975
if Current_Col = Nb_Col then
978
Current_Col := Current_Col + 1;
983
Buffer := (others => ' ');
984
Buffer (1 .. Header'Length) := Header;
985
Index := Header'Length;
988
if Extra_Value = "" then
989
First_Flag := Flags'First;
991
Index := Index + 1; -- Add space
992
Buffer (Index + 1 .. Index + Extra_Value'Length) := Extra_Value;
993
Index := Index + Col_Widthes (Current_Col) + 1;
995
Buffer (Index + 1) := '|';
999
User_Message (Buffer (1 .. Index));
1001
Buffer := (others => ' ');
1002
Index := Header'Length;
1007
-- Gnat warns about Constraint_Error being raised by the following statement
1008
-- when instantiated with a Flag type that has only one value.
1009
-- But in this case, Extra_Value must be "", so it is OK.
1010
pragma Warnings (Off);
1011
First_Flag := Flags'Succ (Flags'First);
1012
pragma Warnings (On);
1015
for I in Flags range First_Flag .. Flags'Last loop
1017
Img : constant Wide_String := Image (I);
1019
Index := Index + 1; -- Add space
1021
Buffer (Index + 1 .. Index + Img'Length) := Img;
1022
if I = Flags'Last then
1023
Index := Index + Img'Length;
1024
User_Message (Buffer (1 .. Index));
1027
Index := Index + Col_Widthes (Current_Col) + 1;
1030
Buffer (Index + 1) := '|';
1033
if Current_Col = Nb_Col then
1034
User_Message (Buffer (1 .. Index));
1036
Buffer := (others => ' ');
1037
Index := Header'Length;
1039
Current_Col := Current_Col + 1;
1044
if Footer /= "" then
1045
User_Message ((1..Header'Length + 1 => ' ') & Footer);
723
1050
------------------
724
1051
-- Adjust_Image --