1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . T E X T _ I O . G E N E R I C _ A U X --
9 -- Copyright (C) 1992-2024, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Interfaces
.C_Streams
; use Interfaces
.C_Streams
;
34 with System
.File_Control_Block
;
36 package body Ada
.Text_IO
.Generic_Aux
is
38 package FIO
renames System
.File_IO
;
39 package FCB
renames System
.File_Control_Block
;
40 subtype AP
is FCB
.AFCB_Ptr
;
42 ------------------------
43 -- Check_End_Of_Field --
44 ------------------------
46 procedure Check_End_Of_Field
60 for J
in Ptr
.. Stop
loop
61 if not Is_Blank
(Buf
(J
)) then
66 end Check_End_Of_Field
;
68 -----------------------
69 -- Check_On_One_Line --
70 -----------------------
72 procedure Check_On_One_Line
77 FIO
.Check_Write_Status
(AP
(File
));
79 if File
.Line_Length
/= 0 then
80 if Count
(Length
) > File
.Line_Length
then
82 elsif File
.Col
+ Count
(Length
) > File
.Line_Length
+ 1 then
86 end Check_On_One_Line
;
92 function Getc
(File
: File_Type
) return int
is
96 ch
:= fgetc
(File
.Stream
);
98 if ch
= EOF
and then ferror
(File
.Stream
) /= 0 then
109 function Is_Blank
(C
: Character) return Boolean is
111 return C
= ' ' or else C
= ASCII
.HT
;
121 Ptr
: in out Integer;
123 Loaded
: out Boolean)
130 if ch
= Character'Pos (Char
) then
131 Store_Char
(File
, ch
, Buf
, Ptr
);
142 Ptr
: in out Integer;
150 if ch
= Character'Pos (Char
) then
151 Store_Char
(File
, ch
, Buf
, Ptr
);
160 Ptr
: in out Integer;
163 Loaded
: out Boolean)
170 if ch
= Character'Pos (Char1
) or else ch
= Character'Pos (Char2
) then
171 Store_Char
(File
, ch
, Buf
, Ptr
);
182 Ptr
: in out Integer;
191 if ch
= Character'Pos (Char1
) or else ch
= Character'Pos (Char2
) then
192 Store_Char
(File
, ch
, Buf
, Ptr
);
202 procedure Load_Digits
205 Ptr
: in out Integer;
206 Loaded
: out Boolean)
209 After_Digit
: Boolean;
214 if ch
not in Character'Pos ('0') .. Character'Pos ('9') then
222 Store_Char
(File
, ch
, Buf
, Ptr
);
225 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
228 elsif ch
= Character'Pos ('_') and then After_Digit
then
229 After_Digit
:= False;
240 procedure Load_Digits
243 Ptr
: in out Integer)
246 After_Digit
: Boolean;
251 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
255 Store_Char
(File
, ch
, Buf
, Ptr
);
258 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
261 elsif ch
= Character'Pos ('_') and then After_Digit
then
262 After_Digit
:= False;
273 --------------------------
274 -- Load_Extended_Digits --
275 --------------------------
277 procedure Load_Extended_Digits
280 Ptr
: in out Integer;
281 Loaded
: out Boolean)
284 After_Digit
: Boolean := False;
292 if ch
in Character'Pos ('0') .. Character'Pos ('9')
294 ch
in Character'Pos ('a') .. Character'Pos ('f')
296 ch
in Character'Pos ('A') .. Character'Pos ('F')
300 elsif ch
= Character'Pos ('_') and then After_Digit
then
301 After_Digit
:= False;
307 Store_Char
(File
, ch
, Buf
, Ptr
);
312 end Load_Extended_Digits
;
314 procedure Load_Extended_Digits
317 Ptr
: in out Integer)
321 Load_Extended_Digits
(File
, Buf
, Ptr
, Junk
);
322 end Load_Extended_Digits
;
328 procedure Load_Integer
331 Ptr
: in out Natural)
339 -- Note: it is a bit strange to allow a minus sign here, but it seems
340 -- consistent with the general behavior expected by the ACVC tests
341 -- which is to scan past junk and then signal data error, see ACVC
342 -- test CE3704F, case (6), which is for signed integer exponents,
343 -- which seems a similar case.
345 Load
(File
, Buf
, Ptr
, '+', '-');
346 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
350 -- Deal with based literal. We recognize either the standard '#' or
351 -- the allowed alternative replacement ':' (see RM J.2(3)).
353 Load
(File
, Buf
, Ptr
, '#', ':', Loaded
);
357 Load_Extended_Digits
(File
, Buf
, Ptr
);
358 Load
(File
, Buf
, Ptr
, Buf
(Hash_Loc
));
361 -- Deal with exponent
363 Load
(File
, Buf
, Ptr
, 'E', 'e', Loaded
);
367 -- Note: it is strange to allow a minus sign, since the syntax
368 -- does not, but that is what ACVC test CE3704F, case (6) wants
369 -- for the signed case, and there seems no good reason to treat
370 -- exponents differently for the signed and unsigned cases.
372 Load
(File
, Buf
, Ptr
, '+', '-');
373 Load_Digits
(File
, Buf
, Ptr
);
385 Ptr
: in out Natural)
390 -- Skip initial blanks, and load possible sign
393 Load
(File
, Buf
, Ptr
, '+', '-');
397 Load
(File
, Buf
, Ptr
, '.', Loaded
);
400 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
402 -- Hopeless junk if no digits loaded
408 -- Otherwise must have digits to start
411 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
413 -- Hopeless junk if no digits loaded
419 -- Based cases. We recognize either the standard '#' or the
420 -- allowed alternative replacement ':' (see RM J.2(3)).
422 Load
(File
, Buf
, Ptr
, '#', ':', Loaded
);
428 Load
(File
, Buf
, Ptr
, '.', Loaded
);
431 Load_Extended_Digits
(File
, Buf
, Ptr
);
432 Load
(File
, Buf
, Ptr
, '#', ':');
434 -- Case of nnn#xxx.[xxx]# or nnn#xxx#
437 Load_Extended_Digits
(File
, Buf
, Ptr
);
438 Load
(File
, Buf
, Ptr
, '.', Loaded
);
441 Load_Extended_Digits
(File
, Buf
, Ptr
);
444 -- As usual, it seems strange to allow mixed base characters,
445 -- but that is what ACVC tests expect, see CE3804M, case (3).
447 Load
(File
, Buf
, Ptr
, '#', ':');
450 -- Case of nnn.[nnn] or nnn
453 -- Prevent the potential processing of '.' in cases where the
454 -- initial digits have a trailing underscore.
456 if Buf
(Ptr
) = '_' then
460 Load
(File
, Buf
, Ptr
, '.', Loaded
);
463 Load_Digits
(File
, Buf
, Ptr
);
468 -- Deal with exponent
470 Load
(File
, Buf
, Ptr
, 'E', 'e', Loaded
);
473 Load
(File
, Buf
, Ptr
, '+', '-');
474 Load_Digits
(File
, Buf
, Ptr
);
482 procedure Load_Skip
(File
: File_Type
) is
486 FIO
.Check_Read_Status
(AP
(File
));
488 -- Loop till we find a non-blank character (note that as usual in
489 -- Text_IO, blank includes horizontal tab). Note that Get deals with
490 -- the Before_LM and Before_LM_PM flags appropriately.
494 exit when not Is_Blank
(C
);
497 Ungetc
(Character'Pos (C
), File
);
498 File
.Col
:= File
.Col
- 1;
509 Ptr
: in out Integer)
514 FIO
.Check_Read_Status
(AP
(File
));
516 -- If we are immediately before a line mark, then we have no characters.
517 -- This is always a data error, so we may as well raise it right away.
519 if File
.Before_LM
then
523 for J
in 1 .. Width
loop
534 Store_Char
(File
, ch
, Buf
, Ptr
);
544 function Nextc
(File
: File_Type
) return int
is
548 ch
:= fgetc
(File
.Stream
);
551 if ferror
(File
.Stream
) /= 0 then
567 procedure Put_Item
(File
: File_Type
; Str
: String) is
569 Check_On_One_Line
(File
, Str
'Length);
581 Ptr
: in out Integer)
584 File
.Col
:= File
.Col
+ 1;
586 if Ptr
< Buf
'Last then
590 Buf
(Ptr
) := Character'Val (ch
);
597 procedure String_Skip
(Str
: String; Ptr
: out Integer) is
599 -- Routines calling String_Skip malfunction if Str'Last = Positive'Last.
600 -- It's too much trouble to make this silly case work, so we just raise
601 -- Program_Error with an appropriate message. We raise Program_Error
602 -- rather than Constraint_Error because we don't want this case to be
603 -- converted to Data_Error.
605 if Str
'Last = Positive'Last then
606 raise Program_Error
with
607 "string upper bound is Positive'Last, not supported";
610 -- Normal case where Str'Last < Positive'Last
615 if Ptr
> Str
'Last then
618 elsif not Is_Blank
(Str
(Ptr
)) then
631 procedure Ungetc
(ch
: int
; File
: File_Type
) is
634 if ungetc
(ch
, File
.Stream
) = EOF
then
640 end Ada
.Text_IO
.Generic_Aux
;