1 ------------------------------------------------------------------------------
3 -- GNAT SYSTEM UTILITIES --
9 -- Copyright (C) 2003-2013, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 ------------------------------------------------------------------------------
23 -- This utility is used to process the source of gnat_ugn.texi to make a
24 -- version suitable for running through standard Texinfo processor. It is
25 -- invoked as follows:
27 -- xgnatugn <target> <in-file> <word-list> [ <out-file> [ <warnings> ] ]
29 -- 1. <target> is the target type of the manual, which is one of:
31 -- unw Unix and Windows platforms
34 -- 2. <in-file> is the file name of the Texinfo file to be
37 -- 3. <word-list> is the name of the word list file. This file is used for
38 -- rewriting the VMS edition. Each line contains a word mapping: The source
39 -- word in the first column, the target word in the second column. The
40 -- columns are separated by a '^' character. When preprocessing for VMS, the
41 -- first word is replaced with the second. (Words consist of letters,
42 -- digits, and the four characters "?-_~". A sequence of multiple words can
43 -- be replaced if they are listed in the first column, separated by a single
44 -- space character. If multiple words are to be replaced, there must be a
45 -- replacement for each prefix.)
47 -- 4. <out-file> (optional) is the name of the output file. It defaults to
48 -- gnat_ugn_unw.texi or gnat_ugn_vms.texi, depending on the target.
50 -- 5. <warnings> (optional, and allowed only if <out-file> is explicit)
51 -- can be any string. If present, it indicates that warning messages are
52 -- to be output to Standard_Error. If absent, no warning messages are
55 -- The following steps are performed:
59 -- Any occurrences of ^alpha^beta^ are replaced by beta. The sequence
60 -- must fit on a single line, and there can only be one occurrence on a
63 -- Any occurrences of a word in the Ug_Words list are replaced by the
64 -- appropriate vms equivalents. Note that replacements do not occur
65 -- within ^alpha^beta^ sequences.
67 -- Any occurrence of [filename].extension, where extension one of the
70 -- "o", "ads", "adb", "ali", "ada", "atb", "ats", "adc", "c"
72 -- replaced by the appropriate VMS names (all upper case with .o
73 -- replaced .OBJ). Note that replacements do not occur within
74 -- ^alpha^beta^ sequences.
78 -- Any occurrences of ^alpha^beta^ are replaced by alpha. The sequence
79 -- must fit on a single line.
83 -- The sequence ^^^ is replaced by a single ^. This escape sequence
84 -- must be used if the literal character ^ is to appear in the
85 -- output. A line containing this escape sequence may not also contain
86 -- a ^alpha^beta^ sequence.
88 with Ada
.Command_Line
; use Ada
.Command_Line
;
89 with Ada
.Strings
; use Ada
.Strings
;
90 with Ada
.Strings
.Fixed
; use Ada
.Strings
.Fixed
;
91 with Ada
.Strings
.Unbounded
; use Ada
.Strings
.Unbounded
;
92 with Ada
.Strings
.Maps
; use Ada
.Strings
.Maps
;
93 with Ada
.Strings
.Maps
.Constants
; use Ada
.Strings
.Maps
.Constants
;
94 with Ada
.Streams
.Stream_IO
; use Ada
.Streams
.Stream_IO
;
95 with Ada
.Text_IO
; use Ada
.Text_IO
;
97 with GNAT
.Spitbol
; use GNAT
.Spitbol
;
98 with GNAT
.Spitbol
.Table_VString
; use GNAT
.Spitbol
.Table_VString
;
100 procedure Xgnatugn
is
103 -- Print usage information. Invoked if an invalid command line is
106 subtype Sfile
is Ada
.Streams
.Stream_IO
.File_Type
;
109 -- The preprocessed output is written to this file
111 type Input_File
is record
113 Data
: Ada
.Text_IO
.File_Type
;
116 -- Records information on an input file. Name and Line are used
117 -- in error messages, Line is updated automatically by Get_Line.
119 function Get_Line
(Input
: access Input_File
) return String;
120 -- Returns a line from Input and performs the necessary
121 -- line-oriented checks (length, character set, trailing spaces).
123 procedure Put_Line
(F
: Sfile
; S
: String);
124 -- Local version of Put_Line ensures Unix style line endings
126 First_Time
: Boolean := True;
127 Number_Of_Warnings
: Natural := 0;
128 Number_Of_Errors
: Natural := 0;
129 Warnings_Enabled
: Boolean;
133 At_Character
: Natural;
138 -- Prints a message reporting an error on line Input.Line. If
139 -- At_Character is not 0, indicate the exact character at which
144 At_Character
: Natural;
147 Dictionary_File
: aliased Input_File
;
148 procedure Read_Dictionary_File
;
149 -- Dictionary_File is opened using the name given on the command
150 -- line. It contains the replacements for the Ug_Words list.
151 -- Read_Dictionary_File reads Dictionary_File and fills the
154 Source_File
: aliased Input_File
;
155 procedure Process_Source_File
;
156 -- Source_File is opened using the name given on the command line.
157 -- It contains the Texinfo source code. Process_Source_File
158 -- performs the necessary replacements.
160 type Flag_Type
is (UNW
, VMS
, FSFEDITION
, PROEDITION
, GPLEDITION
);
161 -- The flags permitted in @ifset or @ifclear commands:
163 -- Targets for preprocessing
164 -- UNW (Unix and Windows) or VMS
166 -- Editions of the manual
167 -- FSFEDITION, PROEDITION, or GPLEDITION
169 -- Conditional commands for target are processed by xgnatugn
171 -- Conditional commands for edition are passed through unchanged
173 subtype Target_Type
is Flag_Type
range UNW
.. VMS
;
175 Target
: Target_Type
;
176 -- The Target variable is initialized using the command line
178 Valid_Characters
: constant Character_Set
:= To_Set
(Span
=> (' ', '~'));
179 -- This array controls which characters are permitted in the input
180 -- file (after line breaks have been removed). Valid characters
181 -- are all printable ASCII characters and the space character.
183 Word_Characters
: constant Character_Set
:=
185 (('0', '9'), ('a', 'z'), ('A', 'Z')))
187 -- The characters which are permitted in words. Other (valid)
188 -- characters are assumed to be delimiters between words. Note that
189 -- this set has to include all characters of the source words of the
190 -- Ug_Words dictionary.
192 Reject_Trailing_Spaces
: constant Boolean := True;
193 -- Controls whether Xgnatug rejects superfluous space characters
194 -- at the end of lines.
196 Maximum_Line_Length
: constant Positive := 79;
197 Fatal_Line_Length_Limit
: constant Positive := 5000;
198 Fatal_Line_Length
: exception;
199 -- If Maximum_Line_Length is exceeded in an input file, an error
200 -- message is printed. If Fatal_Line_Length is exceeded,
201 -- execution terminates with a Fatal_Line_Length exception.
203 VMS_Escape_Character
: constant Character := '^';
204 -- The character used to mark VMS alternatives (^alpha^beta^)
206 Extensions
: GNAT
.Spitbol
.Table_VString
.Table
(20);
207 procedure Initialize_Extensions
;
208 -- This table records extensions and their replacement for
209 -- rewriting filenames in the VMS version of the manual.
211 function Is_Extension
(Extension
: String) return Boolean;
212 function Get_Replacement_Extension
(Extension
: String) return String;
213 -- These functions query the replacement table. Is_Extension
214 -- checks if the given string is a known extension.
215 -- Get_Replacement returns the replacement extension.
217 Ug_Words
: GNAT
.Spitbol
.Table_VString
.Table
(200);
218 function Is_Known_Word
(Word
: String) return Boolean;
219 function Get_Replacement_Word
(Word
: String) return String;
220 -- The Ug_Words table lists replacement words for the VMS version
221 -- of the manual. Is_Known_Word and Get_Replacement_Word query
222 -- this table. The table is filled using Read_Dictionary_File.
224 function Rewrite_Source_Line
(Line
: String) return String;
225 -- This subprogram takes a line and rewrites it according to Target.
226 -- It relies on information in Source_File to generate error messages.
234 Put_Line
(Standard_Error
,
235 "usage: xgnatugn TARGET SOURCE DICTIONARY [OUTFILE [WARNINGS]]");
237 Put_Line
(Standard_Error
, "TARGET is one of:");
239 for T
in Target_Type
'Range loop
240 Put_Line
(Standard_Error
, " " & Target_Type
'Image (T
));
244 Put_Line
(Standard_Error
, "SOURCE is the source file to process.");
246 Put_Line
(Standard_Error
, "DICTIONARY is the name of a file "
247 & "that contains word replacements");
248 Put_Line
(Standard_Error
, "for the VMS version.");
250 Put_Line
(Standard_Error
,
251 "OUT-FILE, if present, is the output file to be created;");
252 Put_Line
(Standard_Error
,
253 "If OUT-FILE is absent, the output file is either " &
254 "gnat_ugn_unw.texi, ");
255 Put_Line
(Standard_Error
,
256 "or gnat_ugn_vms.texi, depending on TARGET.");
258 Put_Line
(Standard_Error
,
259 "WARNINGS, if present, is any string;");
260 Put_Line
(Standard_Error
,
261 "it will result in warning messages (e.g., line too long))");
262 Put_Line
(Standard_Error
,
263 "being output to Standard_Error.");
270 function Get_Line
(Input
: access Input_File
) return String is
271 Line_Buffer
: String (1 .. Fatal_Line_Length_Limit
);
275 Input
.Line
:= Input
.Line
+ 1;
276 Get_Line
(Input
.Data
, Line_Buffer
, Last
);
278 if Last
= Line_Buffer
'Last then
279 Error
(Input
.all, "line exceeds fatal line length limit");
280 raise Fatal_Line_Length
;
284 Line
: String renames Line_Buffer
(Line_Buffer
'First .. Last
);
287 for J
in Line
'Range loop
288 if not Is_In
(Line
(J
), Valid_Characters
) then
289 Error
(Input
.all, J
, "invalid character");
294 if Line
'Length > Maximum_Line_Length
then
295 Warning
(Input
.all, Maximum_Line_Length
+ 1, "line too long");
298 if Reject_Trailing_Spaces
299 and then Line
'Length > 0
300 and then Line
(Line
'Last) = ' '
302 Error
(Input
.all, Line
'Last, "trailing space character");
305 return Trim
(Line
, Right
);
313 procedure Put_Line
(F
: Sfile
; S
: String) is
315 String'Write (Stream
(F
), S
);
316 Character'Write (Stream
(F
), ASCII
.LF
);
328 Error
(Input
, 0, Message
);
333 At_Character
: Natural;
336 Line_Image
: constant String := Integer'Image (Input
.Line
);
337 At_Character_Image
: constant String := Integer'Image (At_Character
);
338 -- These variables are required because we have to drop the leading
342 Number_Of_Errors
:= Number_Of_Errors
+ 1;
344 if At_Character
> 0 then
345 Put_Line
(Standard_Error
,
347 & Line_Image
(Line_Image
'First + 1 .. Line_Image
'Last) & ':'
348 & At_Character_Image
(At_Character_Image
'First + 1
349 .. At_Character_Image
'Last)
353 Put_Line
(Standard_Error
,
355 & Line_Image
(Line_Image
'First + 1 .. Line_Image
'Last)
367 At_Character
: Natural;
370 Line_Image
: constant String := Integer'Image (Input
.Line
);
371 At_Character_Image
: constant String := Integer'Image (At_Character
);
372 -- These variables are required because we have to drop the leading
376 if not Warnings_Enabled
then
380 Number_Of_Warnings
:= Number_Of_Warnings
+ 1;
382 if At_Character
> 0 then
383 Put_Line
(Standard_Error
,
385 & Line_Image
(Line_Image
'First + 1 .. Line_Image
'Last) & ':'
386 & At_Character_Image
(At_Character_Image
'First + 1
387 .. At_Character_Image
'Last)
391 Put_Line
(Standard_Error
,
393 & Line_Image
(Line_Image
'First + 1 .. Line_Image
'Last)
399 --------------------------
400 -- Read_Dictionary_File --
401 --------------------------
403 procedure Read_Dictionary_File
is
405 while not End_Of_File
(Dictionary_File
.Data
) loop
407 Line
: constant String :=
408 Get_Line
(Dictionary_File
'Access);
409 Split
: constant Natural :=
410 Index
(Line
, (1 => VMS_Escape_Character
));
413 if Line
'Length = 0 then
414 Error
(Dictionary_File
, "empty line in dictionary file");
416 elsif Line
(Line
'First) = ' ' then
417 Error
(Dictionary_File
, 1, "line starts with space character");
420 Error
(Dictionary_File
, "line does not contain "
421 & VMS_Escape_Character
& " character");
424 Source
: constant String :=
425 Trim
(Line
(1 .. Split
- 1), Both
);
426 Target
: constant String :=
427 Trim
(Line
(Split
+ 1 .. Line
'Last), Both
);
429 Two_Spaces
: constant Natural := Index
(Source
, " ");
431 Non_Word_Character
: constant Natural :=
438 if Two_Spaces
/= 0 then
439 Error
(Dictionary_File
, Two_Spaces
,
440 "multiple space characters in source word");
443 if Non_Word_Character
/= 0 then
444 Error
(Dictionary_File
, Non_Word_Character
,
445 "illegal character in source word");
448 if Source
'Length = 0 then
449 Error
(Dictionary_File
, "source is empty");
451 elsif Target
'Length = 0 then
452 Error
(Dictionary_File
, "target is empty");
455 Set
(Ug_Words
, Source
, V
(Target
));
457 -- Ensure that if Source is a sequence of words
458 -- "WORD1 WORD2 ...", we already have a mapping for
461 for J
in Source
'Range loop
462 if Source
(J
) = ' ' then
464 Prefix
: String renames
465 Source
(Source
'First .. J
- 1);
467 if not Is_Known_Word
(Prefix
) then
468 Error
(Dictionary_File
,
470 & "' not known at this point");
480 end Read_Dictionary_File
;
482 -------------------------
483 -- Rewrite_Source_Line --
484 -------------------------
486 function Rewrite_Source_Line
(Line
: String) return String is
488 -- We use a simple lexer to split the line into tokens:
490 -- Word consisting entirely of Word_Characters
491 -- VMS_Alternative ^alpha^beta^ replacement (but not ^^^)
492 -- Space a space character
493 -- Other everything else (sequence of non-word characters)
494 -- VMS_Error incomplete VMS alternative
495 -- End_Of_Line no more characters on this line
497 -- A sequence of three VMS_Escape_Characters is automatically
498 -- collapsed to an Other token.
500 type Token_Span
is record
501 First
, Last
: Positive;
503 -- The character range covered by a token in Line
505 type Token_Kind
is (End_Of_Line
, Word
, Other
,
506 VMS_Alternative
, VMS_Error
);
507 type Token_Record
(Kind
: Token_Kind
:= End_Of_Line
) is record
512 when VMS_Alternative
=>
513 Non_VMS
, VMS
: Token_Span
;
514 when VMS_Error | End_Of_Line
=>
519 Input_Position
: Positive := Line
'First;
520 Token
: Token_Record
;
521 -- The position of the next character to be processed by Next_Token
523 procedure Next_Token
;
524 -- Returns the next token in Line, starting at Input_Position
526 Rewritten_Line
: VString
;
527 -- Collects the line as it is rewritten
529 procedure Rewrite_Word
;
530 -- The current token is assumed to be a Word. When processing the VMS
531 -- version of the manual, additional tokens are gathered to check if
532 -- we have a file name or a sequence of known words.
534 procedure Maybe_Rewrite_Extension
;
535 -- The current token is assumed to be Other. When processing the VMS
536 -- version of the manual and the token represents a single dot ".",
537 -- the following word is rewritten according to the rules for
540 VMS_Token_Seen
: Boolean := False;
541 -- This is set to true if a VMS_Alternative has been encountered, or a
548 procedure Next_Token
is
549 Remaining_Line
: String renames Line
(Input_Position
.. Line
'Last);
550 Last_Character
: Natural;
553 if Remaining_Line
'Length = 0 then
554 Token
:= (End_Of_Line
, Remaining_Line
'First);
558 -- ^alpha^beta^, the VMS_Alternative case
560 if Remaining_Line
(Remaining_Line
'First) = VMS_Escape_Character
then
562 VMS_Second_Character
, VMS_Third_Character
: Natural;
565 if VMS_Token_Seen
then
566 Error
(Source_File
, Remaining_Line
'First,
567 "multiple " & VMS_Escape_Character
568 & " characters on a single line");
570 VMS_Token_Seen
:= True;
573 -- Find the second and third escape character. If one of
574 -- them is not present, generate an error token.
576 VMS_Second_Character
:=
577 Index
(Remaining_Line
(Remaining_Line
'First + 1
578 .. Remaining_Line
'Last),
579 (1 => VMS_Escape_Character
));
581 if VMS_Second_Character
= 0 then
582 Input_Position
:= Remaining_Line
'Last + 1;
583 Token
:= (VMS_Error
, Remaining_Line
'First);
587 VMS_Third_Character
:=
588 Index
(Remaining_Line
(VMS_Second_Character
+ 1
589 .. Remaining_Line
'Last),
590 (1 => VMS_Escape_Character
));
592 if VMS_Third_Character
= 0 then
593 Input_Position
:= Remaining_Line
'Last + 1;
594 Token
:= (VMS_Error
, Remaining_Line
'First);
598 -- Consume all the characters we are about to include in
601 Input_Position
:= VMS_Third_Character
+ 1;
603 -- Check if we are in a ^^^ situation, and return an Other
604 -- token in this case.
606 if Remaining_Line
'First + 1 = VMS_Second_Character
607 and then Remaining_Line
'First + 2 = VMS_Third_Character
609 Token
:= (Other
, Remaining_Line
'First,
610 (Remaining_Line
'First, Remaining_Line
'First));
614 Token
:= (VMS_Alternative
, Remaining_Line
'First,
615 (Remaining_Line
'First + 1, VMS_Second_Character
- 1),
616 (VMS_Second_Character
+ 1, VMS_Third_Character
- 1));
621 -- The Word case. Search for characters not in Word_Characters.
622 -- We have found a word if the first non-word character is not
623 -- the first character in Remaining_Line, i.e. if Remaining_Line
624 -- starts with a word character.
626 Last_Character
:= Index
(Remaining_Line
, Word_Characters
, Outside
);
627 if Last_Character
/= Remaining_Line
'First then
629 -- If we haven't found a character which is not in
630 -- Word_Characters, all remaining characters are part of the
631 -- current Word token.
633 if Last_Character
= 0 then
634 Last_Character
:= Remaining_Line
'Last + 1;
637 Input_Position
:= Last_Character
;
638 Token
:= (Word
, Remaining_Line
'First,
639 (Remaining_Line
'First, Last_Character
- 1));
643 -- Remaining characters are in the Other category. To speed
644 -- up processing, we collect them together if there are several
647 Input_Position
:= Last_Character
+ 1;
649 Remaining_Line
'First,
650 (Remaining_Line
'First, Last_Character
));
657 procedure Rewrite_Word
is
659 renames Line
(Token
.Span
.First
.. Token
.Span
.Last
);
662 -- We do not perform any error checking below, so we can just skip
663 -- all processing for the non-VMS version.
665 if Target
/= VMS
then
666 Append
(Rewritten_Line
, First_Word
);
671 if Is_Known_Word
(First_Word
) then
673 -- If we have a word from the dictionary, we look for the
674 -- longest possible sequence we can rewrite.
677 Seq
: Token_Span
:= Token
.Span
;
678 Lost_Space
: Boolean := False;
683 if Token
.Kind
= Other
684 and then Line
(Token
.Span
.First
.. Token
.Span
.Last
) = " "
688 if Token
.Kind
/= Word
689 or else not Is_Known_Word
(Line
(Seq
.First
692 -- When we reach this point, the following conditions
695 -- Seq is a known word
697 -- The previous token was a space character
699 -- Seq extended to the current token is not a
706 -- Extend Seq to cover the current (known) word
708 Seq
.Last
:= Token
.Span
.Last
;
713 -- When we reach this point, the following conditions
716 -- Seq is a known word
718 -- The previous token was a word
720 -- The current token is not a space character.
726 -- Rewrite Seq, and add the lost space if necessary
728 Append
(Rewritten_Line
,
729 Get_Replacement_Word
(Line
(Seq
.First
.. Seq
.Last
)));
731 Append
(Rewritten_Line
, ' ');
734 -- The unknown token will be processed during the
735 -- next iteration of the main loop.
742 if Token
.Kind
= Other
743 and then Line
(Token
.Span
.First
.. Token
.Span
.Last
) = "."
745 -- Deal with extensions
750 Is_Extension
(Line
(Token
.Span
.First
.. Token
.Span
.Last
))
752 -- We have discovered a file extension. Convert the file
753 -- name to upper case.
755 Append
(Rewritten_Line
,
756 Translate
(First_Word
, Upper_Case_Map
) & '.');
757 Append
(Rewritten_Line
,
758 Get_Replacement_Extension
759 (Line
(Token
.Span
.First
.. Token
.Span
.Last
)));
762 -- We already have: Word ".", followed by an unknown token
764 Append
(Rewritten_Line
, First_Word
& '.');
766 -- The unknown token will be processed during the next
767 -- iteration of the main loop.
771 -- We have an unknown Word, followed by an unknown token.
772 -- The unknown token will be processed by the outer loop.
774 Append
(Rewritten_Line
, First_Word
);
778 -----------------------------
779 -- Maybe_Rewrite_Extension --
780 -----------------------------
782 procedure Maybe_Rewrite_Extension
is
784 -- Again, we need no special processing in the non-VMS case
787 and then Line
(Token
.Span
.First
.. Token
.Span
.Last
) = "."
789 -- This extension is not preceded by a word, otherwise
790 -- Rewrite_Word would have handled it.
795 and then Is_Extension
(Line
(Token
.Span
.First
798 Append
(Rewritten_Line
, '.' & Get_Replacement_Extension
799 (Line
(Token
.Span
.First
.. Token
.Span
.Last
)));
802 Append
(Rewritten_Line
, '.');
806 Append
(Rewritten_Line
, Line
(Token
.Span
.First
807 .. Token
.Span
.Last
));
810 end Maybe_Rewrite_Extension
;
812 -- Start of processing for Process_Source_Line
815 -- The following parser recognizes the following special token
818 -- Word "." Word rewrite as file name if second word is extension
819 -- Word " " Word rewrite as a single word using Ug_Words table
831 Maybe_Rewrite_Extension
;
833 when VMS_Alternative
=>
835 Append
(Rewritten_Line
, Line
(Token
.VMS
.First
838 Append
(Rewritten_Line
, Line
(Token
.Non_VMS
.First
839 .. Token
.Non_VMS
.Last
));
845 Error
(Source_File
, Token
.First
, "invalid VMS alternative");
850 return S
(Rewritten_Line
);
851 end Rewrite_Source_Line
;
853 -------------------------
854 -- Process_Source_File --
855 -------------------------
857 procedure Process_Source_File
is
859 while not End_Of_File
(Source_File
.Data
) loop
861 Line
: constant String := Get_Line
(Source_File
'Access);
863 Rewritten
: constant String := Rewrite_Source_Line
(Line
);
864 -- We unconditionally rewrite the line so that we can check the
865 -- syntax of all lines, and not only those which are actually
866 -- included in the output.
870 and then Line
'Length > 3 and then Line
(1 .. 3) = "@if"
872 Put_Line
(Output_File
, "@set " & Argument
(1));
876 Put_Line
(Output_File
, Rewritten
);
879 end Process_Source_File
;
881 ---------------------------
882 -- Initialize_Extensions --
883 ---------------------------
885 procedure Initialize_Extensions
is
887 procedure Add
(Extension
: String);
888 -- Adds an extension which is replaced with itself (in upper case)
890 procedure Add
(Extension
, Replacement
: String);
891 -- Adds an extension with a custom replacement
897 procedure Add
(Extension
: String) is
899 Add
(Extension
, Translate
(Extension
, Upper_Case_Map
));
902 procedure Add
(Extension
, Replacement
: String) is
904 Set
(Extensions
, Extension
, V
(Replacement
));
907 -- Start of processing for Initialize_Extensions
910 -- To avoid performance degradation, increase the constant in the
911 -- definition of Extensions above if you add more extensions here.
922 end Initialize_Extensions
;
928 function Is_Extension
(Extension
: String) return Boolean is
930 return Present
(Extensions
, Extension
);
933 -------------------------------
934 -- Get_Replacement_Extension --
935 -------------------------------
937 function Get_Replacement_Extension
(Extension
: String) return String is
939 return S
(Get
(Extensions
, Extension
));
940 end Get_Replacement_Extension
;
946 function Is_Known_Word
(Word
: String) return Boolean is
948 return Present
(Ug_Words
, Word
);
951 --------------------------
952 -- Get_Replacement_Word --
953 --------------------------
955 function Get_Replacement_Word
(Word
: String) return String is
957 return S
(Get
(Ug_Words
, Word
));
958 end Get_Replacement_Word
;
960 -- Start of processing for Xgnatugn
962 Valid_Command_Line
: Boolean;
963 Output_File_Name
: VString
;
966 Initialize_Extensions
;
967 Valid_Command_Line
:= Argument_Count
in 3 .. 5;
969 -- First argument: Target
971 if Valid_Command_Line
then
973 Target
:= Flag_Type
'Value (Argument
(1));
975 if not Target
'Valid then
976 Valid_Command_Line
:= False;
980 when Constraint_Error
=>
981 Valid_Command_Line
:= False;
985 -- Second argument: Source_File
987 if Valid_Command_Line
then
989 Source_File
.Name
:= V
(Argument
(2));
990 Open
(Source_File
.Data
, In_File
, Argument
(2));
993 when Ada
.Text_IO
.Name_Error
=>
994 Valid_Command_Line
:= False;
998 -- Third argument: Dictionary_File
1000 if Valid_Command_Line
then
1002 Dictionary_File
.Name
:= V
(Argument
(3));
1003 Open
(Dictionary_File
.Data
, In_File
, Argument
(3));
1006 when Ada
.Text_IO
.Name_Error
=>
1007 Valid_Command_Line
:= False;
1011 -- Fourth argument: Output_File
1013 if Valid_Command_Line
then
1014 if Argument_Count
in 4 .. 5 then
1015 Output_File_Name
:= V
(Argument
(4));
1019 Output_File_Name
:= V
("gnat_ugn_unw.texi");
1021 Output_File_Name
:= V
("gnat_ugn_vms.texi");
1025 Warnings_Enabled
:= Argument_Count
= 5;
1028 Create
(Output_File
, Out_File
, S
(Output_File_Name
));
1031 when Ada
.Text_IO
.Name_Error | Ada
.Text_IO
.Use_Error
=>
1032 Valid_Command_Line
:= False;
1036 if not Valid_Command_Line
then
1038 Set_Exit_Status
(Failure
);
1041 Read_Dictionary_File
;
1042 Close
(Dictionary_File
.Data
);
1044 -- Main processing starts here
1046 Process_Source_File
;
1047 Close
(Output_File
);
1048 Close
(Source_File
.Data
);
1050 New_Line
(Standard_Error
);
1052 if Number_Of_Warnings
= 0 then
1053 Put_Line
(Standard_Error
, " NO Warnings");
1056 Put
(Standard_Error
, Integer'Image (Number_Of_Warnings
));
1057 Put
(Standard_Error
, " Warning");
1059 if Number_Of_Warnings
> 1 then
1060 Put
(Standard_Error
, "s");
1063 New_Line
(Standard_Error
);
1066 if Number_Of_Errors
= 0 then
1067 Put_Line
(Standard_Error
, " NO Errors");
1070 Put
(Standard_Error
, Integer'Image (Number_Of_Errors
));
1071 Put
(Standard_Error
, " Error");
1073 if Number_Of_Errors
> 1 then
1074 Put
(Standard_Error
, "s");
1077 New_Line
(Standard_Error
);
1080 if Number_Of_Errors
/= 0 then
1081 Set_Exit_Status
(Failure
);
1083 Set_Exit_Status
(Success
);