1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 2000-2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
34 ------------------------------------------------------------------------------
36 with Ada
.Exceptions
; use Ada
.Exceptions
;
38 package body SFN_Scan
is
41 -- Allow easy access to control character definitions
43 type String_Ptr
is access String;
46 -- Points to the gnat.adc input file
49 -- Subscript of next character to process in S
52 -- Current line number
54 Start_Of_Line
: Natural;
55 -- Subscript of first character at start of current line
57 ----------------------
58 -- Local Procedures --
59 ----------------------
61 function Acquire_String
(B
: Natural; E
: Natural) return String;
62 -- This function takes a string scanned out by Scan_String, strips
63 -- the enclosing quote characters and any internal doubled quote
64 -- characters, and returns the result as a String. The arguments
65 -- B and E are as returned from a call to Scan_String. The lower
66 -- bound of the string returned is always 1.
68 function Acquire_Unit_Name
return String;
69 -- Skips white space, and then scans and returns a unit name. The
70 -- unit name is cased exactly as it appears in the source file.
71 -- The terminating character must be white space, or a comma or
72 -- a right parenthesis or end of file.
74 function At_EOF
return Boolean;
75 pragma Inline
(At_EOF
);
76 -- Returns True if at end of file, False if not. Note that this
77 -- function does NOT skip white space, so P is always unchanged.
79 procedure Check_Not_At_EOF
;
80 pragma Inline
(Check_Not_At_EOF
);
81 -- Skips past white space if any, and then raises Error if at
82 -- end of file. Otherwise returns with P skipped past whitespace.
84 function Check_File_Type
return Character;
85 -- Skips white space if any, and then looks for any of the tokens
86 -- Spec_File_Name, Body_File_Name, or Subunit_File_Name. If one
87 -- of these is found then the value returned is 's', 'b' or 'u'
88 -- respectively, and P is bumped past the token. If none of
89 -- these tokens is found, then P is unchanged (except for
90 -- possible skip of white space), and a space is returned.
92 function Check_Token
(T
: String) return Boolean;
93 -- Skips white space if any, and then checks if the string at the
94 -- current location matches the given string T, and the character
95 -- immediately following is non-alphabetic, non-numeric. If so,
96 -- P is stepped past the token, and True is returned. If not,
97 -- P is unchanged (except for possibly skipping past whitespace),
98 -- and False is returned. S may contain only lower-case letters
101 procedure Error
(Err
: String);
102 -- Called if an error is detected. Raises Syntax_Error_In_GNAT_ADC
103 -- with a message of the form gnat.adc:line:col: xxx, where xxx is
104 -- the string Err passed as a parameter.
106 procedure Require_Token
(T
: String);
107 -- Skips white space if any, and then requires the given string
108 -- to be present. If it is, the P is stepped past it, otherwise
109 -- Error is raised, since this is a syntax error. Require_Token
110 -- is used only for sequences of special characters, so there
111 -- is no issue of terminators, or casing of letters.
113 procedure Scan_String
(B
: out Natural; E
: out Natural);
114 -- Skips white space if any, then requires that a double quote
115 -- or percent be present (start of string). Raises error if
116 -- neither of these two characters is found. Otherwise scans
117 -- out the string, and returns with P pointing past the
118 -- closing quote and S (B .. E) contains the characters of the
119 -- string (including the enclosing quotes, with internal quotes
120 -- still doubled). Raises Error if the string is malformed.
123 -- Skips P past any white space characters (end of line
124 -- characters, spaces, comments, horizontal tab characters).
130 function Acquire_String
(B
: Natural; E
: Natural) return String is
131 Str
: String (1 .. E
- B
- 1);
132 Q
: constant Character := S
(B
);
143 if S
(Ptr
) = Q
and then S
(Ptr
+ 1) = Q
then
153 -----------------------
154 -- Acquire_Unit_Name --
155 -----------------------
157 function Acquire_Unit_Name
return String is
164 while not At_EOF
loop
165 exit when S
(P
) not in '0' .. '9'
166 and then S
(P
) /= '.'
167 and then S
(P
) /= '_'
168 and then not (S
(P
) = '[' and then S
(P
+ 1) = '"')
169 and then not (S
(P
) = '"' and then S
(P
- 1) = '[')
170 and then not (S
(P
) = '"' and then S
(P
+ 1) = ']')
171 and then not (S
(P
) = ']' and then S
(P
- 1) = '"')
172 and then S
(P
) < 'A';
177 Error
("null unit name");
180 return S
(B
.. P
- 1);
181 end Acquire_Unit_Name
;
187 function At_EOF
return Boolean is
192 ---------------------
193 -- Check_File_Type --
194 ---------------------
196 function Check_File_Type
return Character is
198 if Check_Token
("spec_file_name") then
200 elsif Check_Token
("body_file_name") then
202 elsif Check_Token
("subunit_file_name") then
209 ----------------------
210 -- Check_Not_At_EOF --
211 ----------------------
213 procedure Check_Not_At_EOF
is
218 Error
("unexpected end of file");
222 end Check_Not_At_EOF
;
228 function Check_Token
(T
: String) return Boolean is
236 for K
in T
'Range loop
244 if C
in 'A' .. 'Z' then
245 C
:= Character'Val (Character'Pos (C
) +
246 (Character'Pos ('a') - Character'Pos ('A')));
264 or else C
in 'a' .. 'z'
265 or else C
in 'A' .. 'Z'
266 or else C
> Character'Val (127)
280 procedure Error
(Err
: String) is
284 M
: String (1 .. 80);
285 -- Buffer used to build resulting error msg
288 -- Pointer to last set location in M
290 procedure Add_Nat
(N
: Natural);
291 -- Add chars of integer to error msg buffer
293 procedure Add_Nat
(N
: Natural) is
300 M
(LM
) := Character'Val (N
mod 10 + Character'Pos ('0'));
303 -- Start of processing for Error
306 M
(1 .. 9) := "gnat.adc:";
312 -- Determine column number
314 for X
in Start_Of_Line
.. P
loop
318 C
:= (C
+ 7) / 8 * 8;
328 M
(LM
+ 1 .. LM
+ Err
'Length) := Err
;
329 LM
:= LM
+ Err
'Length;
331 Raise_Exception
(Syntax_Error_In_GNAT_ADC
'Identity, M
(1 .. LM
));
338 procedure Require_Token
(T
: String) is
345 for J
in T
'Range loop
347 if At_EOF
or else S
(P
) /= T
(J
) then
349 S
: String (1 .. T
'Length + 10);
352 S
(1 .. 9) := "missing """;
353 S
(10 .. T
'Length + 9) := T
;
354 S
(T
'Length + 10) := '"';
365 ----------------------
366 -- Scan_SFN_Pragmas --
367 ----------------------
369 procedure Scan_SFN_Pragmas
371 SFN_Ptr
: Set_File_Name_Ptr
;
372 SFNP_Ptr
: Set_File_Name_Pattern_Ptr
)
380 S
:= Source
'Unrestricted_Access;
384 -- Loop through pragmas in file
386 Main_Scan_Loop
: loop
388 exit Main_Scan_Loop
when At_EOF
;
390 -- Error if something other than pragma
392 if not Check_Token
("pragma") then
393 Error
("non pragma encountered");
396 -- Source_File_Name pragma case
398 if Check_Token
("source_file_name") then
401 Typ
:= Check_File_Type
;
403 -- First format, with unit name first
406 if Check_Token
("unit_name") then
407 Require_Token
("=>");
411 U
: constant String := Acquire_Unit_Name
;
415 Typ
:= Check_File_Type
;
417 if Typ
/= 's' and then Typ
/= 'b' then
418 Error
("bad pragma");
421 Require_Token
("=>");
425 F
: constant String := Acquire_String
(B
, E
);
430 SFN_Ptr
.all (Typ
, U
, F
);
434 -- Second format with pattern string
437 Require_Token
("=>");
441 Pat
: constant String := Acquire_String
(B
, E
);
445 -- Check exactly one asterisk
447 for J
in Pat
'Range loop
448 if Pat
(J
) = '*' then
454 Error
("** not allowed");
461 -- Loop to scan out Casing or Dot_Replacement parameters
465 exit when S
(P
) = ')';
468 if Check_Token
("casing") then
469 Require_Token
("=>");
472 Error
("duplicate casing argument");
473 elsif Check_Token
("lowercase") then
475 elsif Check_Token
("uppercase") then
477 elsif Check_Token
("mixedcase") then
480 Error
("invalid casing argument");
483 elsif Check_Token
("dot_replacement") then
484 Require_Token
("=>");
487 Error
("duplicate dot_replacement");
493 Error
("invalid argument");
505 SFNP_Ptr
.all (Pat
, Typ
, ".", Cas
);
509 Dot
: constant String := Acquire_String
(B
, E
);
512 SFNP_Ptr
.all (Pat
, Typ
, Dot
, Cas
);
518 -- Some other pragma, scan to semicolon at end of pragma
522 exit Main_Scan_Loop
when At_EOF
;
523 exit Skip_Loop
when S
(P
) = ';';
525 if S
(P
) = '"' or else S
(P
) = '%' then
532 -- We successfuly skipped to semicolon, so skip past it
536 end loop Main_Scan_Loop
;
540 Cursor
:= P
- S
'First + 1;
542 end Scan_SFN_Pragmas
;
548 procedure Scan_String
(B
: out Natural; E
: out Natural) is
556 elsif S
(P
) = '%' then
559 Error
("bad string");
563 -- Scan out the string, B points to first char
569 if At_EOF
or else S
(P
) = LF
or else S
(P
) = CR
then
570 Error
("missing string quote");
572 elsif S
(P
) = HT
then
573 Error
("tab character in string");
575 elsif S
(P
) /= Q
then
583 -- Check for doubled quote
585 if not At_EOF
and then S
(P
) = Q
then
588 -- Otherwise this is the terminating quote
604 WS_Scan
: while not At_EOF
loop
607 -- End of physical line
610 Line_Num
:= Line_Num
+ 1;
614 and then (S
(P
) = CR
or else S
(P
) = LF
)
616 Line_Num
:= Line_Num
+ 1;
622 -- All other cases of white space characters
624 when ' ' | FF | VT | HT
=>
633 Error
("bad comment");
635 elsif S
(P
) = '-' then
638 while not At_EOF
loop
640 when CR | LF | FF | VT
=>