1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . W I D E _ W I D E _ T E X T _ I O . G E N E R I C _ A U X --
9 -- Copyright (C) 1992-2023, 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
.Wide_Wide_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 Is_Blank
(C
: Character) return Boolean is
94 return C
= ' ' or else C
= ASCII
.HT
;
104 Ptr
: in out Integer;
106 Loaded
: out Boolean)
111 if File
.Before_Wide_Wide_Character
then
118 if ch
= Character'Pos (Char
) then
119 Store_Char
(File
, ch
, Buf
, Ptr
);
131 Ptr
: in out Integer;
137 if File
.Before_Wide_Wide_Character
then
143 if ch
= Character'Pos (Char
) then
144 Store_Char
(File
, ch
, Buf
, Ptr
);
154 Ptr
: in out Integer;
157 Loaded
: out Boolean)
162 if File
.Before_Wide_Wide_Character
then
169 if ch
= Character'Pos (Char1
)
170 or else ch
= Character'Pos (Char2
)
172 Store_Char
(File
, ch
, Buf
, Ptr
);
184 Ptr
: in out Integer;
191 if File
.Before_Wide_Wide_Character
then
197 if ch
= Character'Pos (Char1
)
198 or else ch
= Character'Pos (Char2
)
200 Store_Char
(File
, ch
, Buf
, Ptr
);
211 procedure Load_Digits
214 Ptr
: in out Integer;
215 Loaded
: out Boolean)
218 After_Digit
: Boolean;
221 if File
.Before_Wide_Wide_Character
then
228 if ch
not in Character'Pos ('0') .. Character'Pos ('9') then
236 Store_Char
(File
, ch
, Buf
, Ptr
);
239 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
242 elsif ch
= Character'Pos ('_') and then After_Digit
then
243 After_Digit
:= False;
255 procedure Load_Digits
258 Ptr
: in out Integer)
261 After_Digit
: Boolean;
264 if File
.Before_Wide_Wide_Character
then
270 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
274 Store_Char
(File
, ch
, Buf
, Ptr
);
277 if ch
in Character'Pos ('0') .. Character'Pos ('9') then
280 elsif ch
= Character'Pos ('_') and then After_Digit
then
281 After_Digit
:= False;
293 --------------------------
294 -- Load_Extended_Digits --
295 --------------------------
297 procedure Load_Extended_Digits
300 Ptr
: in out Integer;
301 Loaded
: out Boolean)
304 After_Digit
: Boolean := False;
307 if File
.Before_Wide_Wide_Character
then
317 if ch
in Character'Pos ('0') .. Character'Pos ('9')
319 ch
in Character'Pos ('a') .. Character'Pos ('f')
321 ch
in Character'Pos ('A') .. Character'Pos ('F')
325 elsif ch
= Character'Pos ('_') and then After_Digit
then
326 After_Digit
:= False;
332 Store_Char
(File
, ch
, Buf
, Ptr
);
338 end Load_Extended_Digits
;
340 procedure Load_Extended_Digits
343 Ptr
: in out Integer)
347 Load_Extended_Digits
(File
, Buf
, Ptr
, Junk
);
348 end Load_Extended_Digits
;
354 procedure Load_Integer
357 Ptr
: in out Natural)
365 -- Note: it is a bit strange to allow a minus sign here, but it seems
366 -- consistent with the general behavior expected by the ACVC tests
367 -- which is to scan past junk and then signal data error, see ACVC
368 -- test CE3704F, case (6), which is for signed integer exponents,
369 -- which seems a similar case.
371 Load
(File
, Buf
, Ptr
, '+', '-');
372 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
376 -- Deal with based literal. We recognize either the standard '#' or
377 -- the allowed alternative replacement ':' (see RM J.2(3)).
379 Load
(File
, Buf
, Ptr
, '#', ':', Loaded
);
383 Load_Extended_Digits
(File
, Buf
, Ptr
);
384 Load
(File
, Buf
, Ptr
, Buf
(Hash_Loc
));
387 -- Deal with exponent
389 Load
(File
, Buf
, Ptr
, 'E', 'e', Loaded
);
393 -- Note: it is strange to allow a minus sign, since the syntax
394 -- does not, but that is what ACVC test CE3704F, case (6) wants
395 -- for the signed case, and there seems no good reason to treat
396 -- exponents differently for the signed and unsigned cases.
398 Load
(File
, Buf
, Ptr
, '+', '-');
399 Load_Digits
(File
, Buf
, Ptr
);
411 Ptr
: in out Natural)
416 -- Skip initial blanks and load possible sign
419 Load
(File
, Buf
, Ptr
, '+', '-');
423 Load
(File
, Buf
, Ptr
, '.', Loaded
);
426 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
428 -- Hopeless junk if no digits loaded
434 -- Otherwise must have digits to start
437 Load_Digits
(File
, Buf
, Ptr
, Loaded
);
439 -- Hopeless junk if no digits loaded
445 -- Deal with based case. We recognize either the standard '#' or the
446 -- allowed alternative replacement ':' (see RM J.2(3)).
448 Load
(File
, Buf
, Ptr
, '#', ':', Loaded
);
454 Load
(File
, Buf
, Ptr
, '.', Loaded
);
457 Load_Extended_Digits
(File
, Buf
, Ptr
);
458 Load
(File
, Buf
, Ptr
, '#', ':');
460 -- Case of nnn#xxx.[xxx]# or nnn#xxx#
463 Load_Extended_Digits
(File
, Buf
, Ptr
);
464 Load
(File
, Buf
, Ptr
, '.', Loaded
);
467 Load_Extended_Digits
(File
, Buf
, Ptr
);
470 -- As usual, it seems strange to allow mixed base characters,
471 -- but that is what ACVC tests expect, see CE3804M, case (3).
473 Load
(File
, Buf
, Ptr
, '#', ':');
476 -- Case of nnn.[nnn] or nnn
479 -- Prevent the potential processing of '.' in cases where the
480 -- initial digits have a trailing underscore.
482 if Buf
(Ptr
) = '_' then
486 Load
(File
, Buf
, Ptr
, '.', Loaded
);
489 Load_Digits
(File
, Buf
, Ptr
);
494 -- Deal with exponent
496 Load
(File
, Buf
, Ptr
, 'E', 'e', Loaded
);
499 Load
(File
, Buf
, Ptr
, '+', '-');
500 Load_Digits
(File
, Buf
, Ptr
);
508 procedure Load_Skip
(File
: File_Type
) is
512 FIO
.Check_Read_Status
(AP
(File
));
514 -- We need to explicitly test for the case of being before a wide
515 -- character (greater than 16#7F#). Since no such character can
516 -- ever legitimately be a valid numeric character, we can
517 -- immediately signal Data_Error.
519 if File
.Before_Wide_Wide_Character
then
523 -- Otherwise loop till we find a non-blank character (note that as
524 -- usual in Wide_Wide_Text_IO, blank includes horizontal tab). Note that
525 -- Get_Character deals with Before_LM/Before_LM_PM flags appropriately.
528 Get_Character
(File
, C
);
529 exit when not Is_Blank
(C
);
532 Ungetc
(Character'Pos (C
), File
);
533 File
.Col
:= File
.Col
- 1;
544 Ptr
: in out Integer)
547 WC
: Wide_Wide_Character
;
549 Bad_Wide_Wide_C
: Boolean := False;
550 -- Set True if one of the characters read is not in range of type
551 -- Character. This is always a Data_Error, but we do not signal it
552 -- right away, since we have to read the full number of characters.
555 FIO
.Check_Read_Status
(AP
(File
));
557 -- If we are immediately before a line mark, then we have no characters.
558 -- This is always a data error, so we may as well raise it right away.
560 if File
.Before_LM
then
564 for J
in 1 .. Width
loop
565 if File
.Before_Wide_Wide_Character
then
566 Bad_Wide_Wide_C
:= True;
567 Store_Char
(File
, 0, Buf
, Ptr
);
568 File
.Before_Wide_Wide_Character
:= False;
581 WC
:= Get_Wide_Wide_Char
(Character'Val (ch
), File
);
582 ch
:= Wide_Wide_Character
'Pos (WC
);
585 Bad_Wide_Wide_C
:= True;
589 Store_Char
(File
, ch
, Buf
, Ptr
);
594 if Bad_Wide_Wide_C
then
604 procedure Put_Item
(File
: File_Type
; Str
: String) is
606 Check_On_One_Line
(File
, Str
'Length);
608 for J
in Str
'Range loop
609 Put
(File
, Wide_Wide_Character
'Val (Character'Pos (Str
(J
))));
621 Ptr
: in out Integer)
624 File
.Col
:= File
.Col
+ 1;
626 if Ptr
= Buf
'Last then
630 Buf
(Ptr
) := Character'Val (ch
);
638 procedure String_Skip
(Str
: String; Ptr
: out Integer) is
640 -- Routines calling String_Skip malfunction if Str'Last = Positive'Last.
641 -- It's too much trouble to make this silly case work, so we just raise
642 -- Program_Error with an appropriate message. We raise Program_Error
643 -- rather than Constraint_Error because we don't want this case to be
644 -- converted to Data_Error.
646 if Str
'Last = Positive'Last then
647 raise Program_Error
with
648 "string upper bound is Positive'Last, not supported";
651 -- Normal case where Str'Last < Positive'Last
656 if Ptr
> Str
'Last then
659 elsif not Is_Blank
(Str
(Ptr
)) then
672 procedure Ungetc
(ch
: int
; File
: File_Type
) is
675 if ungetc
(ch
, File
.Stream
) = EOF
then
681 end Ada
.Wide_Wide_Text_IO
.Generic_Aux
;