OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [a-ztedit.adb] - Blame information for rev 461

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                        GNAT RUN-TIME COMPONENTS                          --
4
--                                                                          --
5
--        A D A . W I D E _ W I D E _ T E X T _ I O . E D I T I N G         --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
10
--                                                                          --
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.                                     --
17
--                                                                          --
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.               --
21
--                                                                          --
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/>.                                          --
26
--                                                                          --
27
-- GNAT was originally developed  by the GNAT team at  New York University. --
28
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with Ada.Strings.Fixed;
33
with Ada.Strings.Wide_Wide_Fixed;
34
 
35
package body Ada.Wide_Wide_Text_IO.Editing is
36
 
37
   package Strings            renames Ada.Strings;
38
   package Strings_Fixed      renames Ada.Strings.Fixed;
39
   package Strings_Wide_Wide_Fixed renames Ada.Strings.Wide_Wide_Fixed;
40
   package Wide_Wide_Text_IO       renames Ada.Wide_Wide_Text_IO;
41
 
42
   -----------------------
43
   -- Local_Subprograms --
44
   -----------------------
45
 
46
   function To_Wide (C : Character) return Wide_Wide_Character;
47
   pragma Inline (To_Wide);
48
   --  Convert Character to corresponding Wide_Wide_Character
49
 
50
   ---------------------
51
   -- Blank_When_Zero --
52
   ---------------------
53
 
54
   function Blank_When_Zero (Pic : Picture) return Boolean is
55
   begin
56
      return Pic.Contents.Original_BWZ;
57
   end Blank_When_Zero;
58
 
59
   --------------------
60
   -- Decimal_Output --
61
   --------------------
62
 
63
   package body Decimal_Output is
64
 
65
      -----------
66
      -- Image --
67
      -----------
68
 
69
      function Image
70
        (Item       : Num;
71
         Pic        : Picture;
72
         Currency   : Wide_Wide_String    := Default_Currency;
73
         Fill       : Wide_Wide_Character := Default_Fill;
74
         Separator  : Wide_Wide_Character := Default_Separator;
75
         Radix_Mark : Wide_Wide_Character := Default_Radix_Mark)
76
         return Wide_Wide_String
77
      is
78
      begin
79
         return Format_Number
80
            (Pic.Contents, Num'Image (Item),
81
             Currency, Fill, Separator, Radix_Mark);
82
      end Image;
83
 
84
      ------------
85
      -- Length --
86
      ------------
87
 
88
      function Length
89
        (Pic      : Picture;
90
         Currency : Wide_Wide_String := Default_Currency) return Natural
91
      is
92
         Picstr     : constant String := Pic_String (Pic);
93
         V_Adjust   : Integer := 0;
94
         Cur_Adjust : Integer := 0;
95
 
96
      begin
97
         --  Check if Picstr has 'V' or '$'
98
 
99
         --  If 'V', then length is 1 less than otherwise
100
 
101
         --  If '$', then length is Currency'Length-1 more than otherwise
102
 
103
         --  This should use the string handling package ???
104
 
105
         for J in Picstr'Range loop
106
            if Picstr (J) = 'V' then
107
               V_Adjust := -1;
108
 
109
            elsif Picstr (J) = '$' then
110
               Cur_Adjust := Currency'Length - 1;
111
            end if;
112
         end loop;
113
 
114
         return Picstr'Length - V_Adjust + Cur_Adjust;
115
      end Length;
116
 
117
      ---------
118
      -- Put --
119
      ---------
120
 
121
      procedure Put
122
        (File       : Wide_Wide_Text_IO.File_Type;
123
         Item       : Num;
124
         Pic        : Picture;
125
         Currency   : Wide_Wide_String    := Default_Currency;
126
         Fill       : Wide_Wide_Character := Default_Fill;
127
         Separator  : Wide_Wide_Character := Default_Separator;
128
         Radix_Mark : Wide_Wide_Character := Default_Radix_Mark)
129
      is
130
      begin
131
         Wide_Wide_Text_IO.Put (File, Image (Item, Pic,
132
                                   Currency, Fill, Separator, Radix_Mark));
133
      end Put;
134
 
135
      procedure Put
136
        (Item       : Num;
137
         Pic        : Picture;
138
         Currency   : Wide_Wide_String    := Default_Currency;
139
         Fill       : Wide_Wide_Character := Default_Fill;
140
         Separator  : Wide_Wide_Character := Default_Separator;
141
         Radix_Mark : Wide_Wide_Character := Default_Radix_Mark)
142
      is
143
      begin
144
         Wide_Wide_Text_IO.Put (Image (Item, Pic,
145
                             Currency, Fill, Separator, Radix_Mark));
146
      end Put;
147
 
148
      procedure Put
149
        (To         : out Wide_Wide_String;
150
         Item       : Num;
151
         Pic        : Picture;
152
         Currency   : Wide_Wide_String    := Default_Currency;
153
         Fill       : Wide_Wide_Character := Default_Fill;
154
         Separator  : Wide_Wide_Character := Default_Separator;
155
         Radix_Mark : Wide_Wide_Character := Default_Radix_Mark)
156
      is
157
         Result : constant Wide_Wide_String :=
158
           Image (Item, Pic, Currency, Fill, Separator, Radix_Mark);
159
 
160
      begin
161
         if Result'Length > To'Length then
162
            raise Wide_Wide_Text_IO.Layout_Error;
163
         else
164
            Strings_Wide_Wide_Fixed.Move (Source => Result, Target => To,
165
                                     Justify => Strings.Right);
166
         end if;
167
      end Put;
168
 
169
      -----------
170
      -- Valid --
171
      -----------
172
 
173
      function Valid
174
        (Item     : Num;
175
         Pic      : Picture;
176
         Currency : Wide_Wide_String := Default_Currency) return Boolean
177
      is
178
      begin
179
         declare
180
            Temp : constant Wide_Wide_String := Image (Item, Pic, Currency);
181
            pragma Warnings (Off, Temp);
182
         begin
183
            return True;
184
         end;
185
 
186
      exception
187
         when Layout_Error => return False;
188
 
189
      end Valid;
190
   end Decimal_Output;
191
 
192
   ------------
193
   -- Expand --
194
   ------------
195
 
196
   function Expand (Picture : String) return String is
197
      Result        : String (1 .. MAX_PICSIZE);
198
      Picture_Index : Integer := Picture'First;
199
      Result_Index  : Integer := Result'First;
200
      Count         : Natural;
201
      Last          : Integer;
202
 
203
   begin
204
      if Picture'Length < 1 then
205
         raise Picture_Error;
206
      end if;
207
 
208
      if Picture (Picture'First) = '(' then
209
         raise Picture_Error;
210
      end if;
211
 
212
      loop
213
         case Picture (Picture_Index) is
214
 
215
            when '(' =>
216
 
217
               --  We now need to scan out the count after a left paren. In
218
               --  the non-wide version we used Integer_IO.Get, but that is
219
               --  not convenient here, since we don't want to drag in normal
220
               --  Text_IO just for this purpose. So we do the scan ourselves,
221
               --  with the normal validity checks.
222
 
223
               Last := Picture_Index + 1;
224
               Count := 0;
225
 
226
               if Picture (Last) not in '0' .. '9' then
227
                  raise Picture_Error;
228
               end if;
229
 
230
               Count := Character'Pos (Picture (Last)) - Character'Pos ('0');
231
               Last := Last + 1;
232
 
233
               loop
234
                  if Last > Picture'Last then
235
                     raise Picture_Error;
236
                  end if;
237
 
238
                  if Picture (Last) = '_' then
239
                     if Picture (Last - 1) = '_' then
240
                        raise Picture_Error;
241
                     end if;
242
 
243
                  elsif Picture (Last) = ')' then
244
                     exit;
245
 
246
                  elsif Picture (Last) not in '0' .. '9' then
247
                     raise Picture_Error;
248
 
249
                  else
250
                     Count := Count * 10
251
                                +  Character'Pos (Picture (Last)) -
252
                                   Character'Pos ('0');
253
                  end if;
254
 
255
                  Last := Last + 1;
256
               end loop;
257
 
258
               --  In what follows note that one copy of the repeated
259
               --  character has already been made, so a count of one is
260
               --  no-op, and a count of zero erases a character.
261
 
262
               for J in 2 .. Count loop
263
                  Result (Result_Index + J - 2) := Picture (Picture_Index - 1);
264
               end loop;
265
 
266
               Result_Index := Result_Index + Count - 1;
267
 
268
               --  Last was a ')' throw it away too
269
 
270
               Picture_Index := Last + 1;
271
 
272
            when ')' =>
273
               raise Picture_Error;
274
 
275
            when others =>
276
               Result (Result_Index) := Picture (Picture_Index);
277
               Picture_Index := Picture_Index + 1;
278
               Result_Index := Result_Index + 1;
279
 
280
         end case;
281
 
282
         exit when Picture_Index > Picture'Last;
283
      end loop;
284
 
285
      return Result (1 .. Result_Index - 1);
286
 
287
   exception
288
      when others =>
289
         raise Picture_Error;
290
   end Expand;
291
 
292
   -------------------
293
   -- Format_Number --
294
   -------------------
295
 
296
   function Format_Number
297
     (Pic                 : Format_Record;
298
      Number              : String;
299
      Currency_Symbol     : Wide_Wide_String;
300
      Fill_Character      : Wide_Wide_Character;
301
      Separator_Character : Wide_Wide_Character;
302
      Radix_Point         : Wide_Wide_Character) return Wide_Wide_String
303
   is
304
      Attrs    : Number_Attributes := Parse_Number_String (Number);
305
      Position : Integer;
306
      Rounded  : String := Number;
307
 
308
      Sign_Position : Integer := Pic.Sign_Position; --  may float.
309
 
310
      Answer       : Wide_Wide_String (1 .. Pic.Picture.Length);
311
      Last         : Integer;
312
      Currency_Pos : Integer := Pic.Start_Currency;
313
 
314
      Dollar : Boolean := False;
315
      --  Overridden immediately if necessary
316
 
317
      Zero : Boolean := True;
318
      --  Set to False when a non-zero digit is output
319
 
320
   begin
321
 
322
      --  If the picture has fewer decimal places than the number, the image
323
      --  must be rounded according to the usual rules.
324
 
325
      if Attrs.Has_Fraction then
326
         declare
327
            R : constant Integer :=
328
              (Attrs.End_Of_Fraction - Attrs.Start_Of_Fraction + 1)
329
                - Pic.Max_Trailing_Digits;
330
            R_Pos : Integer;
331
 
332
         begin
333
            if R > 0 then
334
               R_Pos := Rounded'Length - R;
335
 
336
               if Rounded (R_Pos + 1) > '4' then
337
 
338
                  if Rounded (R_Pos) = '.' then
339
                     R_Pos := R_Pos - 1;
340
                  end if;
341
 
342
                  if Rounded (R_Pos) /= '9' then
343
                     Rounded (R_Pos) := Character'Succ (Rounded (R_Pos));
344
                  else
345
                     Rounded (R_Pos) := '0';
346
                     R_Pos := R_Pos - 1;
347
 
348
                     while R_Pos > 1 loop
349
                        if Rounded (R_Pos) = '.' then
350
                           R_Pos := R_Pos - 1;
351
                        end if;
352
 
353
                        if Rounded (R_Pos) /= '9' then
354
                           Rounded (R_Pos) := Character'Succ (Rounded (R_Pos));
355
                           exit;
356
                        else
357
                           Rounded (R_Pos) := '0';
358
                           R_Pos := R_Pos - 1;
359
                        end if;
360
                     end loop;
361
 
362
                     --  The rounding may add a digit in front. Either the
363
                     --  leading blank or the sign (already captured) can be
364
                     --  overwritten.
365
 
366
                     if R_Pos = 1 then
367
                        Rounded (R_Pos) := '1';
368
                        Attrs.Start_Of_Int := Attrs.Start_Of_Int - 1;
369
                     end if;
370
                  end if;
371
               end if;
372
            end if;
373
         end;
374
      end if;
375
 
376
      for J in Answer'Range loop
377
         Answer (J) := To_Wide (Pic.Picture.Expanded (J));
378
      end loop;
379
 
380
      if Pic.Start_Currency /= Invalid_Position then
381
         Dollar := Answer (Pic.Start_Currency) = '$';
382
      end if;
383
 
384
      --  Fix up "direct inserts" outside the playing field. Set up as one
385
      --  loop to do the beginning, one (reverse) loop to do the end.
386
 
387
      Last := 1;
388
      loop
389
         exit when Last = Pic.Start_Float;
390
         exit when Last = Pic.Radix_Position;
391
         exit when Answer (Last) = '9';
392
 
393
         case Answer (Last) is
394
 
395
            when '_' =>
396
               Answer (Last) := Separator_Character;
397
 
398
            when 'b' =>
399
               Answer (Last) := ' ';
400
 
401
            when others =>
402
               null;
403
 
404
         end case;
405
 
406
         exit when Last = Answer'Last;
407
 
408
         Last := Last + 1;
409
      end loop;
410
 
411
      --  Now for the end...
412
 
413
      for J in reverse Last .. Answer'Last loop
414
         exit when J = Pic.Radix_Position;
415
 
416
         --  Do this test First, Separator_Character can equal Pic.Floater
417
 
418
         if Answer (J) = Pic.Floater then
419
            exit;
420
         end if;
421
 
422
         case Answer (J) is
423
 
424
            when '_' =>
425
               Answer (J) := Separator_Character;
426
 
427
            when 'b' =>
428
               Answer (J) := ' ';
429
 
430
            when '9' =>
431
               exit;
432
 
433
            when others =>
434
               null;
435
 
436
         end case;
437
      end loop;
438
 
439
      --  Non-floating sign
440
 
441
      if Pic.Start_Currency /= -1
442
        and then Answer (Pic.Start_Currency) = '#'
443
        and then Pic.Floater /= '#'
444
      then
445
         if Currency_Symbol'Length >
446
            Pic.End_Currency - Pic.Start_Currency + 1
447
         then
448
            raise Picture_Error;
449
 
450
         elsif Currency_Symbol'Length =
451
            Pic.End_Currency - Pic.Start_Currency + 1
452
         then
453
            Answer (Pic.Start_Currency .. Pic.End_Currency) :=
454
              Currency_Symbol;
455
 
456
         elsif Pic.Radix_Position = Invalid_Position
457
           or else Pic.Start_Currency < Pic.Radix_Position
458
         then
459
            Answer (Pic.Start_Currency .. Pic.End_Currency) :=
460
                                                        (others => ' ');
461
            Answer (Pic.End_Currency - Currency_Symbol'Length + 1 ..
462
                    Pic.End_Currency) := Currency_Symbol;
463
 
464
         else
465
            Answer (Pic.Start_Currency .. Pic.End_Currency) :=
466
                                                        (others => ' ');
467
            Answer (Pic.Start_Currency ..
468
                    Pic.Start_Currency + Currency_Symbol'Length - 1) :=
469
                                                        Currency_Symbol;
470
         end if;
471
      end if;
472
 
473
      --  Fill in leading digits
474
 
475
      if Attrs.End_Of_Int - Attrs.Start_Of_Int + 1 >
476
                                                Pic.Max_Leading_Digits
477
      then
478
         raise Layout_Error;
479
      end if;
480
 
481
      Position :=
482
        (if Pic.Radix_Position = Invalid_Position then Answer'Last
483
         else Pic.Radix_Position - 1);
484
 
485
      for J in reverse Attrs.Start_Of_Int .. Attrs.End_Of_Int loop
486
         while Answer (Position) /= '9'
487
                 and then
488
               Answer (Position) /= Pic.Floater
489
         loop
490
            if Answer (Position) = '_' then
491
               Answer (Position) := Separator_Character;
492
            elsif Answer (Position) = 'b' then
493
               Answer (Position) := ' ';
494
            end if;
495
 
496
            Position := Position - 1;
497
         end loop;
498
 
499
         Answer (Position) := To_Wide (Rounded (J));
500
 
501
         if Rounded (J) /= '0' then
502
            Zero := False;
503
         end if;
504
 
505
         Position := Position - 1;
506
      end loop;
507
 
508
      --  Do lead float
509
 
510
      if Pic.Start_Float = Invalid_Position then
511
 
512
         --  No leading floats, but need to change '9' to '0', '_' to
513
         --  Separator_Character and 'b' to ' '.
514
 
515
         for J in Last .. Position loop
516
 
517
            --  Last set when fixing the "uninteresting" leaders above.
518
            --  Don't duplicate the work.
519
 
520
            if Answer (J) = '9' then
521
               Answer (J) := '0';
522
 
523
            elsif Answer (J) = '_' then
524
               Answer (J) := Separator_Character;
525
 
526
            elsif Answer (J) = 'b' then
527
               Answer (J) := ' ';
528
 
529
            end if;
530
 
531
         end loop;
532
 
533
      elsif Pic.Floater = '<'
534
              or else
535
            Pic.Floater = '+'
536
              or else
537
            Pic.Floater = '-'
538
      then
539
         for J in Pic.End_Float .. Position loop --  May be null range
540
            if Answer (J) = '9' then
541
               Answer (J) := '0';
542
 
543
            elsif Answer (J) = '_' then
544
               Answer (J) := Separator_Character;
545
 
546
            elsif Answer (J) = 'b' then
547
               Answer (J) := ' ';
548
 
549
            end if;
550
         end loop;
551
 
552
         if Position > Pic.End_Float then
553
            Position := Pic.End_Float;
554
         end if;
555
 
556
         for J in Pic.Start_Float .. Position - 1 loop
557
            Answer (J) := ' ';
558
         end loop;
559
 
560
         Answer (Position) := Pic.Floater;
561
         Sign_Position     := Position;
562
 
563
      elsif Pic.Floater = '$' then
564
 
565
         for J in Pic.End_Float .. Position loop --  May be null range
566
            if Answer (J) = '9' then
567
               Answer (J) := '0';
568
 
569
            elsif Answer (J) = '_' then
570
               Answer (J) := ' ';   --  no separator before leftmost digit
571
 
572
            elsif Answer (J) = 'b' then
573
               Answer (J) := ' ';
574
            end if;
575
         end loop;
576
 
577
         if Position > Pic.End_Float then
578
            Position := Pic.End_Float;
579
         end if;
580
 
581
         for J in Pic.Start_Float .. Position - 1 loop
582
            Answer (J) := ' ';
583
         end loop;
584
 
585
         Answer (Position) := Pic.Floater;
586
         Currency_Pos      := Position;
587
 
588
      elsif Pic.Floater = '*' then
589
 
590
         for J in Pic.End_Float .. Position loop --  May be null range
591
            if Answer (J) = '9' then
592
               Answer (J) := '0';
593
 
594
            elsif Answer (J) = '_' then
595
               Answer (J) := Separator_Character;
596
 
597
            elsif Answer (J) = 'b' then
598
               Answer (J) := '*';
599
            end if;
600
         end loop;
601
 
602
         if Position > Pic.End_Float then
603
            Position := Pic.End_Float;
604
         end if;
605
 
606
         for J in Pic.Start_Float .. Position loop
607
            Answer (J) := '*';
608
         end loop;
609
 
610
      else
611
         if Pic.Floater = '#' then
612
            Currency_Pos := Currency_Symbol'Length;
613
         end if;
614
 
615
         for J in reverse Pic.Start_Float .. Position loop
616
            case Answer (J) is
617
 
618
               when '*' =>
619
                  Answer (J) := Fill_Character;
620
 
621
               when 'Z' | 'b' | '/' | '0' =>
622
                  Answer (J) := ' ';
623
 
624
               when '9' =>
625
                  Answer (J) := '0';
626
 
627
               when '.' | 'V' | 'v' | '<' | '$' | '+' | '-' =>
628
                  null;
629
 
630
               when '#' =>
631
                  if Currency_Pos = 0 then
632
                     Answer (J) := ' ';
633
                  else
634
                     Answer (J)   := Currency_Symbol (Currency_Pos);
635
                     Currency_Pos := Currency_Pos - 1;
636
                  end if;
637
 
638
               when '_' =>
639
 
640
                  case Pic.Floater is
641
 
642
                     when '*' =>
643
                        Answer (J) := Fill_Character;
644
 
645
                     when 'Z' | 'b' =>
646
                        Answer (J) := ' ';
647
 
648
                     when '#' =>
649
                        if Currency_Pos = 0 then
650
                           Answer (J) := ' ';
651
 
652
                        else
653
                           Answer (J)   := Currency_Symbol (Currency_Pos);
654
                           Currency_Pos := Currency_Pos - 1;
655
                        end if;
656
 
657
                     when others =>
658
                        null;
659
 
660
                  end case;
661
 
662
               when others =>
663
                  null;
664
 
665
            end case;
666
         end loop;
667
 
668
         if Pic.Floater = '#' and then Currency_Pos /= 0 then
669
            raise Layout_Error;
670
         end if;
671
      end if;
672
 
673
      --  Do sign
674
 
675
      if Sign_Position = Invalid_Position then
676
         if Attrs.Negative then
677
            raise Layout_Error;
678
         end if;
679
 
680
      else
681
         if Attrs.Negative then
682
            case Answer (Sign_Position) is
683
               when 'C' | 'D' | '-' =>
684
                  null;
685
 
686
               when '+' =>
687
                  Answer (Sign_Position) := '-';
688
 
689
               when '<' =>
690
                  Answer (Sign_Position)   := '(';
691
                  Answer (Pic.Second_Sign) := ')';
692
 
693
               when others =>
694
                  raise Picture_Error;
695
 
696
            end case;
697
 
698
         else --  positive
699
 
700
            case Answer (Sign_Position) is
701
 
702
               when '-' =>
703
                  Answer (Sign_Position) := ' ';
704
 
705
               when '<' | 'C' | 'D' =>
706
                  Answer (Sign_Position)   := ' ';
707
                  Answer (Pic.Second_Sign) := ' ';
708
 
709
               when '+' =>
710
                  null;
711
 
712
               when others =>
713
                  raise Picture_Error;
714
 
715
            end case;
716
         end if;
717
      end if;
718
 
719
      --  Fill in trailing digits
720
 
721
      if Pic.Max_Trailing_Digits > 0 then
722
 
723
         if Attrs.Has_Fraction then
724
            Position := Attrs.Start_Of_Fraction;
725
            Last     := Pic.Radix_Position + 1;
726
 
727
            for J in Last .. Answer'Last loop
728
 
729
               if Answer (J) = '9' or else Answer (J) = Pic.Floater then
730
                  Answer (J) := To_Wide (Rounded (Position));
731
 
732
                  if Rounded (Position) /= '0' then
733
                     Zero := False;
734
                  end if;
735
 
736
                  Position := Position + 1;
737
                  Last     := J + 1;
738
 
739
                  --  Used up fraction but remember place in Answer
740
 
741
                  exit when Position > Attrs.End_Of_Fraction;
742
 
743
               elsif Answer (J) = 'b' then
744
                  Answer (J) := ' ';
745
 
746
               elsif Answer (J) = '_' then
747
                  Answer (J) := Separator_Character;
748
 
749
               end if;
750
 
751
               Last := J + 1;
752
            end loop;
753
 
754
            Position := Last;
755
 
756
         else
757
            Position := Pic.Radix_Position + 1;
758
         end if;
759
 
760
         --  Now fill remaining 9's with zeros and _ with separators
761
 
762
         Last := Answer'Last;
763
 
764
         for J in Position .. Last loop
765
            if Answer (J) = '9' then
766
               Answer (J) := '0';
767
 
768
            elsif Answer (J) = Pic.Floater then
769
               Answer (J) := '0';
770
 
771
            elsif Answer (J) = '_' then
772
               Answer (J) := Separator_Character;
773
 
774
            elsif Answer (J) = 'b' then
775
               Answer (J) := ' ';
776
 
777
            end if;
778
         end loop;
779
 
780
         Position := Last + 1;
781
 
782
      else
783
         if Pic.Floater = '#' and then Currency_Pos /= 0 then
784
            raise Layout_Error;
785
         end if;
786
 
787
         --  No trailing digits, but now J may need to stick in a currency
788
         --  symbol or sign.
789
 
790
         Position :=
791
           (if Pic.Start_Currency = Invalid_Position then Answer'Last + 1
792
            else Pic.Start_Currency);
793
      end if;
794
 
795
      for J in Position .. Answer'Last loop
796
         if Pic.Start_Currency /= Invalid_Position and then
797
            Answer (Pic.Start_Currency) = '#' then
798
            Currency_Pos := 1;
799
         end if;
800
 
801
         --  Note: There are some weird cases J can imagine with 'b' or '#'
802
         --  in currency strings where the following code will cause
803
         --  glitches. The trick is to tell when the character in the
804
         --  answer should be checked, and when to look at the original
805
         --  string. Some other time. RIE 11/26/96 ???
806
 
807
         case Answer (J) is
808
            when '*' =>
809
               Answer (J) := Fill_Character;
810
 
811
            when 'b' =>
812
               Answer (J) := ' ';
813
 
814
            when '#' =>
815
               if Currency_Pos > Currency_Symbol'Length then
816
                  Answer (J) := ' ';
817
 
818
               else
819
                  Answer (J)   := Currency_Symbol (Currency_Pos);
820
                  Currency_Pos := Currency_Pos + 1;
821
               end if;
822
 
823
            when '_' =>
824
 
825
               case Pic.Floater is
826
 
827
                  when '*' =>
828
                     Answer (J) := Fill_Character;
829
 
830
                  when 'Z' | 'z' =>
831
                     Answer (J) := ' ';
832
 
833
                  when '#' =>
834
                     if Currency_Pos > Currency_Symbol'Length then
835
                        Answer (J) := ' ';
836
                     else
837
                        Answer (J)   := Currency_Symbol (Currency_Pos);
838
                        Currency_Pos := Currency_Pos + 1;
839
                     end if;
840
 
841
                  when others =>
842
                     null;
843
 
844
               end case;
845
 
846
            when others =>
847
               exit;
848
 
849
         end case;
850
      end loop;
851
 
852
      --  Now get rid of Blank_when_Zero and complete Star fill
853
 
854
      if Zero and then Pic.Blank_When_Zero then
855
 
856
         --  Value is zero, and blank it
857
 
858
         Last := Answer'Last;
859
 
860
         if Dollar then
861
            Last := Last - 1 + Currency_Symbol'Length;
862
         end if;
863
 
864
         if Pic.Radix_Position /= Invalid_Position and then
865
            Answer (Pic.Radix_Position) = 'V' then
866
            Last := Last - 1;
867
         end if;
868
 
869
         return Wide_Wide_String'(1 .. Last => ' ');
870
 
871
      elsif Zero and then Pic.Star_Fill then
872
         Last := Answer'Last;
873
 
874
         if Dollar then
875
            Last := Last - 1 + Currency_Symbol'Length;
876
         end if;
877
 
878
         if Pic.Radix_Position /= Invalid_Position then
879
 
880
            if Answer (Pic.Radix_Position) = 'V' then
881
               Last := Last - 1;
882
 
883
            elsif Dollar then
884
               if Pic.Radix_Position > Pic.Start_Currency then
885
                  return
886
                     Wide_Wide_String'(1 .. Pic.Radix_Position - 1 => '*') &
887
                     Radix_Point &
888
                     Wide_Wide_String'(Pic.Radix_Position + 1 .. Last => '*');
889
 
890
               else
891
                  return
892
                     Wide_Wide_String'
893
                     (1 ..
894
                      Pic.Radix_Position + Currency_Symbol'Length - 2
895
                                             => '*') &
896
                     Radix_Point &
897
                     Wide_Wide_String'
898
                       (Pic.Radix_Position + Currency_Symbol'Length .. Last
899
                                             => '*');
900
               end if;
901
 
902
            else
903
               return
904
                 Wide_Wide_String'(1 .. Pic.Radix_Position - 1 => '*') &
905
                 Radix_Point &
906
                 Wide_Wide_String'(Pic.Radix_Position + 1 .. Last => '*');
907
            end if;
908
         end if;
909
 
910
         return Wide_Wide_String'(1 .. Last => '*');
911
      end if;
912
 
913
      --  This was once a simple return statement, now there are nine
914
      --  different return cases.  Not to mention the five above to deal
915
      --  with zeros.  Why not split things out?
916
 
917
      --  Processing the radix and sign expansion separately
918
      --  would require lots of copying--the string and some of its
919
      --  indicies--without really simplifying the logic.  The cases are:
920
 
921
      --  1) Expand $, replace '.' with Radix_Point
922
      --  2) No currency expansion, replace '.' with Radix_Point
923
      --  3) Expand $, radix blanked
924
      --  4) No currency expansion, radix blanked
925
      --  5) Elide V
926
      --  6) Expand $, Elide V
927
      --  7) Elide V, Expand $ (Two cases depending on order.)
928
      --  8) No radix, expand $
929
      --  9) No radix, no currency expansion
930
 
931
      if Pic.Radix_Position /= Invalid_Position then
932
 
933
         if Answer (Pic.Radix_Position) = '.' then
934
            Answer (Pic.Radix_Position) := Radix_Point;
935
 
936
            if Dollar then
937
 
938
               --  1) Expand $, replace '.' with Radix_Point
939
 
940
               return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
941
                  Answer (Currency_Pos + 1 .. Answer'Last);
942
 
943
            else
944
               --  2) No currency expansion, replace '.' with Radix_Point
945
 
946
               return Answer;
947
            end if;
948
 
949
         elsif Answer (Pic.Radix_Position) = ' ' then --  blanked radix.
950
            if Dollar then
951
 
952
               --  3) Expand $, radix blanked
953
 
954
               return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
955
                 Answer (Currency_Pos + 1 .. Answer'Last);
956
 
957
            else
958
               --  4) No expansion, radix blanked
959
 
960
               return Answer;
961
            end if;
962
 
963
         --  V cases
964
 
965
         else
966
            if not Dollar then
967
 
968
               --  5) Elide V
969
 
970
               return Answer (1 .. Pic.Radix_Position - 1) &
971
                  Answer (Pic.Radix_Position + 1 .. Answer'Last);
972
 
973
            elsif Currency_Pos < Pic.Radix_Position then
974
 
975
               --  6) Expand $, Elide V
976
 
977
               return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
978
                  Answer (Currency_Pos + 1 .. Pic.Radix_Position - 1) &
979
                  Answer (Pic.Radix_Position + 1 .. Answer'Last);
980
 
981
            else
982
               --  7) Elide V, Expand $
983
 
984
               return Answer (1 .. Pic.Radix_Position - 1) &
985
                  Answer (Pic.Radix_Position + 1 .. Currency_Pos - 1) &
986
                  Currency_Symbol &
987
                  Answer (Currency_Pos + 1 .. Answer'Last);
988
            end if;
989
         end if;
990
 
991
      elsif Dollar then
992
 
993
         --  8) No radix, expand $
994
 
995
         return Answer (1 .. Currency_Pos - 1) & Currency_Symbol &
996
            Answer (Currency_Pos + 1 .. Answer'Last);
997
 
998
      else
999
         --  9) No radix, no currency expansion
1000
 
1001
         return Answer;
1002
      end if;
1003
   end Format_Number;
1004
 
1005
   -------------------------
1006
   -- Parse_Number_String --
1007
   -------------------------
1008
 
1009
   function Parse_Number_String (Str : String) return Number_Attributes is
1010
      Answer : Number_Attributes;
1011
 
1012
   begin
1013
      for J in Str'Range loop
1014
         case Str (J) is
1015
 
1016
            when ' ' =>
1017
               null; --  ignore
1018
 
1019
            when '1' .. '9' =>
1020
 
1021
               --  Decide if this is the start of a number.
1022
               --  If so, figure out which one...
1023
 
1024
               if Answer.Has_Fraction then
1025
                  Answer.End_Of_Fraction := J;
1026
               else
1027
                  if Answer.Start_Of_Int = Invalid_Position then
1028
                     --  start integer
1029
                     Answer.Start_Of_Int := J;
1030
                  end if;
1031
                  Answer.End_Of_Int := J;
1032
               end if;
1033
 
1034
            when '0' =>
1035
 
1036
               --  Only count a zero before the decimal point if it follows a
1037
               --  non-zero digit.  After the decimal point, zeros will be
1038
               --  counted if followed by a non-zero digit.
1039
 
1040
               if not Answer.Has_Fraction then
1041
                  if Answer.Start_Of_Int /= Invalid_Position then
1042
                     Answer.End_Of_Int := J;
1043
                  end if;
1044
               end if;
1045
 
1046
            when '-' =>
1047
 
1048
               --  Set negative
1049
 
1050
               Answer.Negative := True;
1051
 
1052
            when '.' =>
1053
 
1054
               --  Close integer, start fraction
1055
 
1056
               if Answer.Has_Fraction then
1057
                  raise Picture_Error;
1058
               end if;
1059
 
1060
               --  Two decimal points is a no-no
1061
 
1062
               Answer.Has_Fraction    := True;
1063
               Answer.End_Of_Fraction := J;
1064
 
1065
               --  Could leave this at Invalid_Position, but this seems the
1066
               --  right way to indicate a null range...
1067
 
1068
               Answer.Start_Of_Fraction := J + 1;
1069
               Answer.End_Of_Int        := J - 1;
1070
 
1071
            when others =>
1072
               raise Picture_Error; -- can this happen? probably not!
1073
         end case;
1074
      end loop;
1075
 
1076
      if Answer.Start_Of_Int = Invalid_Position then
1077
         Answer.Start_Of_Int := Answer.End_Of_Int + 1;
1078
      end if;
1079
 
1080
      --  No significant (intger) digits needs a null range
1081
 
1082
      return Answer;
1083
   end Parse_Number_String;
1084
 
1085
   ----------------
1086
   -- Pic_String --
1087
   ----------------
1088
 
1089
   --  The following ensures that we return B and not b being careful not
1090
   --  to break things which expect lower case b for blank. See CXF3A02.
1091
 
1092
   function Pic_String (Pic : Picture) return String is
1093
      Temp : String (1 .. Pic.Contents.Picture.Length) :=
1094
                              Pic.Contents.Picture.Expanded;
1095
   begin
1096
      for J in Temp'Range loop
1097
         if Temp (J) = 'b' then
1098
            Temp (J) := 'B';
1099
         end if;
1100
      end loop;
1101
 
1102
      return Temp;
1103
   end Pic_String;
1104
 
1105
   ------------------
1106
   -- Precalculate --
1107
   ------------------
1108
 
1109
   procedure Precalculate  (Pic : in out Format_Record) is
1110
 
1111
      Computed_BWZ : Boolean := True;
1112
 
1113
      type Legality is  (Okay, Reject);
1114
      State : Legality := Reject;
1115
      --  Start in reject, which will reject null strings
1116
 
1117
      Index : Pic_Index := Pic.Picture.Expanded'First;
1118
 
1119
      function At_End return Boolean;
1120
      pragma Inline (At_End);
1121
 
1122
      procedure Set_State (L : Legality);
1123
      pragma Inline (Set_State);
1124
 
1125
      function Look return Character;
1126
      pragma Inline (Look);
1127
 
1128
      function Is_Insert return Boolean;
1129
      pragma Inline (Is_Insert);
1130
 
1131
      procedure Skip;
1132
      pragma Inline (Skip);
1133
 
1134
      procedure Trailing_Currency;
1135
      procedure Trailing_Bracket;
1136
      procedure Number_Fraction;
1137
      procedure Number_Completion;
1138
      procedure Number_Fraction_Or_Bracket;
1139
      procedure Number_Fraction_Or_Z_Fill;
1140
      procedure Zero_Suppression;
1141
      procedure Floating_Bracket;
1142
      procedure Number_Fraction_Or_Star_Fill;
1143
      procedure Star_Suppression;
1144
      procedure Number_Fraction_Or_Dollar;
1145
      procedure Leading_Dollar;
1146
      procedure Number_Fraction_Or_Pound;
1147
      procedure Leading_Pound;
1148
      procedure Picture;
1149
      procedure Floating_Plus;
1150
      procedure Floating_Minus;
1151
      procedure Picture_Plus;
1152
      procedure Picture_Minus;
1153
      procedure Picture_Bracket;
1154
      procedure Number;
1155
      procedure Optional_RHS_Sign;
1156
      procedure Picture_String;
1157
 
1158
      ------------
1159
      -- At_End --
1160
      ------------
1161
 
1162
      function At_End return Boolean is
1163
      begin
1164
         return Index > Pic.Picture.Length;
1165
      end At_End;
1166
 
1167
      ----------------------
1168
      -- Floating_Bracket --
1169
      ----------------------
1170
 
1171
      --  Note that Floating_Bracket is only called with an acceptable
1172
      --  prefix. But we don't set Okay, because we must end with a '>'.
1173
 
1174
      procedure Floating_Bracket is
1175
      begin
1176
         Pic.Floater := '<';
1177
         Pic.End_Float := Index;
1178
         Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1179
 
1180
         --  First bracket wasn't counted...
1181
 
1182
         Skip; --  known '<'
1183
 
1184
         loop
1185
            if At_End then
1186
               return;
1187
            end if;
1188
 
1189
            case Look is
1190
 
1191
               when '_' | '0' | '/' =>
1192
                  Pic.End_Float := Index;
1193
                  Skip;
1194
 
1195
               when 'B' | 'b'  =>
1196
                  Pic.End_Float := Index;
1197
                  Pic.Picture.Expanded (Index) := 'b';
1198
                  Skip;
1199
 
1200
               when '<' =>
1201
                  Pic.End_Float := Index;
1202
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1203
                  Skip;
1204
 
1205
               when '9' =>
1206
                  Number_Completion;
1207
 
1208
               when '$' =>
1209
                  Leading_Dollar;
1210
 
1211
               when '#' =>
1212
                  Leading_Pound;
1213
 
1214
               when 'V' | 'v' | '.' =>
1215
                  Pic.Radix_Position := Index;
1216
                  Skip;
1217
                  Number_Fraction_Or_Bracket;
1218
                  return;
1219
 
1220
               when others =>
1221
               return;
1222
            end case;
1223
         end loop;
1224
      end Floating_Bracket;
1225
 
1226
      --------------------
1227
      -- Floating_Minus --
1228
      --------------------
1229
 
1230
      procedure Floating_Minus is
1231
      begin
1232
         loop
1233
            if At_End then
1234
               return;
1235
            end if;
1236
 
1237
            case Look is
1238
               when '_' | '0' | '/' =>
1239
                  Pic.End_Float := Index;
1240
                  Skip;
1241
 
1242
               when 'B' | 'b'  =>
1243
                  Pic.End_Float := Index;
1244
                  Pic.Picture.Expanded (Index) := 'b';
1245
                  Skip;
1246
 
1247
               when '-' =>
1248
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1249
                  Pic.End_Float := Index;
1250
                  Skip;
1251
 
1252
               when '9' =>
1253
                  Number_Completion;
1254
                  return;
1255
 
1256
               when '.' | 'V' | 'v' =>
1257
                  Pic.Radix_Position := Index;
1258
                  Skip; --  Radix
1259
 
1260
                  while Is_Insert loop
1261
                     Skip;
1262
                  end loop;
1263
 
1264
                  if At_End then
1265
                     return;
1266
                  end if;
1267
 
1268
                  if Look = '-' then
1269
                     loop
1270
                        if At_End then
1271
                           return;
1272
                        end if;
1273
 
1274
                        case Look is
1275
 
1276
                           when '-' =>
1277
                              Pic.Max_Trailing_Digits :=
1278
                                Pic.Max_Trailing_Digits + 1;
1279
                              Pic.End_Float := Index;
1280
                              Skip;
1281
 
1282
                           when '_' | '0' | '/' =>
1283
                              Skip;
1284
 
1285
                           when 'B' | 'b'  =>
1286
                              Pic.Picture.Expanded (Index) := 'b';
1287
                              Skip;
1288
 
1289
                           when others =>
1290
                              return;
1291
 
1292
                        end case;
1293
                     end loop;
1294
 
1295
                  else
1296
                     Number_Completion;
1297
                  end if;
1298
 
1299
                  return;
1300
 
1301
               when others =>
1302
                  return;
1303
            end case;
1304
         end loop;
1305
      end Floating_Minus;
1306
 
1307
      -------------------
1308
      -- Floating_Plus --
1309
      -------------------
1310
 
1311
      procedure Floating_Plus is
1312
      begin
1313
         loop
1314
            if At_End then
1315
               return;
1316
            end if;
1317
 
1318
            case Look is
1319
               when '_' | '0' | '/' =>
1320
                  Pic.End_Float := Index;
1321
                  Skip;
1322
 
1323
               when 'B' | 'b'  =>
1324
                  Pic.End_Float := Index;
1325
                  Pic.Picture.Expanded (Index) := 'b';
1326
                  Skip;
1327
 
1328
               when '+' =>
1329
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1330
                  Pic.End_Float := Index;
1331
                  Skip;
1332
 
1333
               when '9' =>
1334
                  Number_Completion;
1335
                  return;
1336
 
1337
               when '.' | 'V' | 'v' =>
1338
                  Pic.Radix_Position := Index;
1339
                  Skip; --  Radix
1340
 
1341
                  while Is_Insert loop
1342
                     Skip;
1343
                  end loop;
1344
 
1345
                  if At_End then
1346
                     return;
1347
                  end if;
1348
 
1349
                  if Look = '+' then
1350
                     loop
1351
                        if At_End then
1352
                           return;
1353
                        end if;
1354
 
1355
                        case Look is
1356
 
1357
                           when '+' =>
1358
                              Pic.Max_Trailing_Digits :=
1359
                                Pic.Max_Trailing_Digits + 1;
1360
                              Pic.End_Float := Index;
1361
                              Skip;
1362
 
1363
                           when '_' | '0' | '/' =>
1364
                              Skip;
1365
 
1366
                           when 'B' | 'b'  =>
1367
                              Pic.Picture.Expanded (Index) := 'b';
1368
                              Skip;
1369
 
1370
                           when others =>
1371
                              return;
1372
 
1373
                        end case;
1374
                     end loop;
1375
 
1376
                  else
1377
                     Number_Completion;
1378
                  end if;
1379
 
1380
                  return;
1381
 
1382
               when others =>
1383
                  return;
1384
 
1385
            end case;
1386
         end loop;
1387
      end Floating_Plus;
1388
 
1389
      ---------------
1390
      -- Is_Insert --
1391
      ---------------
1392
 
1393
      function Is_Insert return Boolean is
1394
      begin
1395
         if At_End then
1396
            return False;
1397
         end if;
1398
 
1399
         case Pic.Picture.Expanded (Index) is
1400
 
1401
            when '_' | '0' | '/' => return True;
1402
 
1403
            when 'B' | 'b' =>
1404
               Pic.Picture.Expanded (Index) := 'b'; --  canonical
1405
               return True;
1406
 
1407
            when others => return False;
1408
         end case;
1409
      end Is_Insert;
1410
 
1411
      --------------------
1412
      -- Leading_Dollar --
1413
      --------------------
1414
 
1415
      --  Note that Leading_Dollar can be called in either State. It will set
1416
      --  state to Okay only if a 9 or (second) is encountered.
1417
 
1418
      --  Also notice the tricky bit with State and Zero_Suppression.
1419
      --  Zero_Suppression is Picture_Error if a '$' or a '9' has been
1420
      --  encountered, exactly the cases where State has been set.
1421
 
1422
      procedure Leading_Dollar is
1423
      begin
1424
         --  Treat as a floating dollar, and unwind otherwise
1425
 
1426
         Pic.Floater := '$';
1427
         Pic.Start_Currency := Index;
1428
         Pic.End_Currency := Index;
1429
         Pic.Start_Float := Index;
1430
         Pic.End_Float := Index;
1431
 
1432
         --  Don't increment Pic.Max_Leading_Digits, we need one "real"
1433
         --  currency place.
1434
 
1435
         Skip; --  known '$'
1436
 
1437
         loop
1438
            if At_End then
1439
               return;
1440
            end if;
1441
 
1442
            case Look is
1443
 
1444
               when '_' | '0' | '/' =>
1445
                  Pic.End_Float := Index;
1446
                  Skip;
1447
 
1448
                  --  A trailing insertion character is not part of the
1449
                  --  floating currency, so need to look ahead.
1450
 
1451
                  if Look /= '$' then
1452
                     Pic.End_Float := Pic.End_Float - 1;
1453
                  end if;
1454
 
1455
               when 'B' | 'b'  =>
1456
                  Pic.End_Float := Index;
1457
                  Pic.Picture.Expanded (Index) := 'b';
1458
                  Skip;
1459
 
1460
               when 'Z' | 'z' =>
1461
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
1462
 
1463
                  if State = Okay then
1464
                     raise Picture_Error;
1465
                  else
1466
                     --  Will overwrite Floater and Start_Float
1467
 
1468
                     Zero_Suppression;
1469
                  end if;
1470
 
1471
               when '*' =>
1472
                  if State = Okay then
1473
                     raise Picture_Error;
1474
                  else
1475
                     --  Will overwrite Floater and Start_Float
1476
 
1477
                     Star_Suppression;
1478
                  end if;
1479
 
1480
               when '$' =>
1481
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1482
                  Pic.End_Float := Index;
1483
                  Pic.End_Currency := Index;
1484
                  Set_State (Okay); Skip;
1485
 
1486
               when '9' =>
1487
                  if State /= Okay then
1488
                     Pic.Floater := '!';
1489
                     Pic.Start_Float := Invalid_Position;
1490
                     Pic.End_Float := Invalid_Position;
1491
                  end if;
1492
 
1493
                  --  A single dollar does not a floating make
1494
 
1495
                  Number_Completion;
1496
                  return;
1497
 
1498
               when 'V' | 'v' | '.' =>
1499
                  if State /= Okay then
1500
                     Pic.Floater := '!';
1501
                     Pic.Start_Float := Invalid_Position;
1502
                     Pic.End_Float := Invalid_Position;
1503
                  end if;
1504
 
1505
                  --  Only one dollar before the sign is okay, but doesn't
1506
                  --  float.
1507
 
1508
                  Pic.Radix_Position := Index;
1509
                  Skip;
1510
                  Number_Fraction_Or_Dollar;
1511
                  return;
1512
 
1513
               when others =>
1514
                  return;
1515
 
1516
            end case;
1517
         end loop;
1518
      end Leading_Dollar;
1519
 
1520
      -------------------
1521
      -- Leading_Pound --
1522
      -------------------
1523
 
1524
      --  This one is complex!  A Leading_Pound can be fixed or floating,
1525
      --  but in some cases the decision has to be deferred until we leave
1526
      --  this procedure.  Also note that Leading_Pound can be called in
1527
      --  either State.
1528
 
1529
      --  It will set state to Okay only if a 9 or (second) # is encountered
1530
 
1531
      --  One Last note:  In ambiguous cases, the currency is treated as
1532
      --  floating unless there is only one '#'.
1533
 
1534
      procedure Leading_Pound is
1535
 
1536
         Inserts : Boolean := False;
1537
         --  Set to True if a '_', '0', '/', 'B', or 'b' is encountered
1538
 
1539
         Must_Float : Boolean := False;
1540
         --  Set to true if a '#' occurs after an insert
1541
 
1542
      begin
1543
         --  Treat as a floating currency. If it isn't, this will be
1544
         --  overwritten later.
1545
 
1546
         Pic.Floater := '#';
1547
 
1548
         Pic.Start_Currency := Index;
1549
         Pic.End_Currency := Index;
1550
         Pic.Start_Float := Index;
1551
         Pic.End_Float := Index;
1552
 
1553
         --  Don't increment Pic.Max_Leading_Digits, we need one "real"
1554
         --  currency place.
1555
 
1556
         Pic.Max_Currency_Digits := 1; --  we've seen one.
1557
 
1558
         Skip; --  known '#'
1559
 
1560
         loop
1561
            if At_End then
1562
               return;
1563
            end if;
1564
 
1565
            case Look is
1566
 
1567
               when '_' | '0' | '/' =>
1568
                  Pic.End_Float := Index;
1569
                  Inserts := True;
1570
                  Skip;
1571
 
1572
               when 'B' | 'b'  =>
1573
                  Pic.Picture.Expanded (Index) := 'b';
1574
                  Pic.End_Float := Index;
1575
                  Inserts := True;
1576
                  Skip;
1577
 
1578
               when 'Z' | 'z' =>
1579
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
1580
 
1581
                  if Must_Float then
1582
                     raise Picture_Error;
1583
                  else
1584
                     Pic.Max_Leading_Digits := 0;
1585
 
1586
                     --  Will overwrite Floater and Start_Float
1587
 
1588
                     Zero_Suppression;
1589
                  end if;
1590
 
1591
               when '*' =>
1592
                  if Must_Float then
1593
                     raise Picture_Error;
1594
                  else
1595
                     Pic.Max_Leading_Digits := 0;
1596
 
1597
                     --  Will overwrite Floater and Start_Float
1598
 
1599
                     Star_Suppression;
1600
                  end if;
1601
 
1602
               when '#' =>
1603
                  if Inserts then
1604
                     Must_Float := True;
1605
                  end if;
1606
 
1607
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1608
                  Pic.End_Float := Index;
1609
                  Pic.End_Currency := Index;
1610
                  Set_State (Okay);
1611
                  Skip;
1612
 
1613
               when '9' =>
1614
                  if State /= Okay then
1615
 
1616
                     --  A single '#' doesn't float
1617
 
1618
                     Pic.Floater := '!';
1619
                     Pic.Start_Float := Invalid_Position;
1620
                     Pic.End_Float := Invalid_Position;
1621
                  end if;
1622
 
1623
                  Number_Completion;
1624
                  return;
1625
 
1626
               when 'V' | 'v' | '.' =>
1627
                  if State /= Okay then
1628
                     Pic.Floater := '!';
1629
                     Pic.Start_Float := Invalid_Position;
1630
                     Pic.End_Float := Invalid_Position;
1631
                  end if;
1632
 
1633
                  --  Only one pound before the sign is okay, but doesn't
1634
                  --  float.
1635
 
1636
                  Pic.Radix_Position := Index;
1637
                  Skip;
1638
                  Number_Fraction_Or_Pound;
1639
                  return;
1640
 
1641
               when others =>
1642
                  return;
1643
            end case;
1644
         end loop;
1645
      end Leading_Pound;
1646
 
1647
      ----------
1648
      -- Look --
1649
      ----------
1650
 
1651
      function Look return Character is
1652
      begin
1653
         if At_End then
1654
            raise Picture_Error;
1655
         end if;
1656
 
1657
         return Pic.Picture.Expanded (Index);
1658
      end Look;
1659
 
1660
      ------------
1661
      -- Number --
1662
      ------------
1663
 
1664
      procedure Number is
1665
      begin
1666
         loop
1667
 
1668
            case Look is
1669
               when '_' | '0' | '/' =>
1670
                  Skip;
1671
 
1672
               when 'B' | 'b'  =>
1673
                  Pic.Picture.Expanded (Index) := 'b';
1674
                  Skip;
1675
 
1676
               when '9' =>
1677
                  Computed_BWZ := False;
1678
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1679
                  Set_State (Okay);
1680
                  Skip;
1681
 
1682
               when '.' | 'V' | 'v' =>
1683
                  Pic.Radix_Position := Index;
1684
                  Skip;
1685
                  Number_Fraction;
1686
                  return;
1687
 
1688
               when others =>
1689
                  return;
1690
 
1691
            end case;
1692
 
1693
            if At_End then
1694
               return;
1695
            end if;
1696
 
1697
            --  Will return in Okay state if a '9' was seen
1698
 
1699
         end loop;
1700
      end Number;
1701
 
1702
      -----------------------
1703
      -- Number_Completion --
1704
      -----------------------
1705
 
1706
      procedure Number_Completion is
1707
      begin
1708
         while not At_End loop
1709
            case Look is
1710
 
1711
               when '_' | '0' | '/' =>
1712
                  Skip;
1713
 
1714
               when 'B' | 'b'  =>
1715
                  Pic.Picture.Expanded (Index) := 'b';
1716
                  Skip;
1717
 
1718
               when '9' =>
1719
                  Computed_BWZ := False;
1720
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
1721
                  Set_State (Okay);
1722
                  Skip;
1723
 
1724
               when 'V' | 'v' | '.' =>
1725
                  Pic.Radix_Position := Index;
1726
                  Skip;
1727
                  Number_Fraction;
1728
                  return;
1729
 
1730
               when others =>
1731
                  return;
1732
            end case;
1733
         end loop;
1734
      end Number_Completion;
1735
 
1736
      ---------------------
1737
      -- Number_Fraction --
1738
      ---------------------
1739
 
1740
      procedure Number_Fraction is
1741
      begin
1742
         --  Note that number fraction can be called in either State.
1743
         --  It will set state to Valid only if a 9 is encountered.
1744
 
1745
         loop
1746
            if At_End then
1747
               return;
1748
            end if;
1749
 
1750
            case Look is
1751
               when '_' | '0' | '/' =>
1752
                  Skip;
1753
 
1754
               when 'B' | 'b'  =>
1755
                  Pic.Picture.Expanded (Index) := 'b';
1756
                  Skip;
1757
 
1758
               when '9' =>
1759
                  Computed_BWZ := False;
1760
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
1761
                  Set_State (Okay); Skip;
1762
 
1763
               when others =>
1764
                  return;
1765
            end case;
1766
         end loop;
1767
      end Number_Fraction;
1768
 
1769
      --------------------------------
1770
      -- Number_Fraction_Or_Bracket --
1771
      --------------------------------
1772
 
1773
      procedure Number_Fraction_Or_Bracket is
1774
      begin
1775
         loop
1776
            if At_End then
1777
               return;
1778
            end if;
1779
 
1780
            case Look is
1781
 
1782
               when '_' | '0' | '/' => Skip;
1783
 
1784
               when 'B' | 'b'  =>
1785
                  Pic.Picture.Expanded (Index) := 'b';
1786
                  Skip;
1787
 
1788
               when '<' =>
1789
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
1790
                  Pic.End_Float := Index;
1791
                  Skip;
1792
 
1793
                  loop
1794
                     if At_End then
1795
                        return;
1796
                     end if;
1797
 
1798
                     case Look is
1799
                        when '_' | '0' | '/' =>
1800
                           Skip;
1801
 
1802
                        when 'B' | 'b'  =>
1803
                           Pic.Picture.Expanded (Index) := 'b';
1804
                           Skip;
1805
 
1806
                        when '<' =>
1807
                           Pic.Max_Trailing_Digits :=
1808
                             Pic.Max_Trailing_Digits + 1;
1809
                           Pic.End_Float := Index;
1810
                           Skip;
1811
 
1812
                        when others =>
1813
                           return;
1814
                     end case;
1815
                  end loop;
1816
 
1817
               when others =>
1818
                  Number_Fraction;
1819
                  return;
1820
            end case;
1821
         end loop;
1822
      end Number_Fraction_Or_Bracket;
1823
 
1824
      -------------------------------
1825
      -- Number_Fraction_Or_Dollar --
1826
      -------------------------------
1827
 
1828
      procedure Number_Fraction_Or_Dollar is
1829
      begin
1830
         loop
1831
            if At_End then
1832
               return;
1833
            end if;
1834
 
1835
            case Look is
1836
               when '_' | '0' | '/' =>
1837
                  Skip;
1838
 
1839
               when 'B' | 'b'  =>
1840
                  Pic.Picture.Expanded (Index) := 'b';
1841
                  Skip;
1842
 
1843
               when '$' =>
1844
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
1845
                  Pic.End_Float := Index;
1846
                  Skip;
1847
 
1848
                  loop
1849
                     if At_End then
1850
                        return;
1851
                     end if;
1852
 
1853
                     case Look is
1854
                        when '_' | '0' | '/' =>
1855
                           Skip;
1856
 
1857
                        when 'B' | 'b'  =>
1858
                           Pic.Picture.Expanded (Index) := 'b';
1859
                           Skip;
1860
 
1861
                        when '$' =>
1862
                           Pic.Max_Trailing_Digits :=
1863
                             Pic.Max_Trailing_Digits + 1;
1864
                           Pic.End_Float := Index;
1865
                           Skip;
1866
 
1867
                        when others =>
1868
                           return;
1869
                     end case;
1870
                  end loop;
1871
 
1872
               when others =>
1873
                  Number_Fraction;
1874
                  return;
1875
            end case;
1876
         end loop;
1877
      end Number_Fraction_Or_Dollar;
1878
 
1879
      ------------------------------
1880
      -- Number_Fraction_Or_Pound --
1881
      ------------------------------
1882
 
1883
      procedure Number_Fraction_Or_Pound is
1884
      begin
1885
         loop
1886
            if At_End then
1887
               return;
1888
            end if;
1889
 
1890
            case Look is
1891
 
1892
               when '_' | '0' | '/' =>
1893
                  Skip;
1894
 
1895
               when 'B' | 'b'  =>
1896
                  Pic.Picture.Expanded (Index) := 'b';
1897
                  Skip;
1898
 
1899
               when '#' =>
1900
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
1901
                  Pic.End_Float := Index;
1902
                  Skip;
1903
 
1904
                  loop
1905
                     if At_End then
1906
                        return;
1907
                     end if;
1908
 
1909
                     case Look is
1910
 
1911
                        when '_' | '0' | '/' =>
1912
                           Skip;
1913
 
1914
                        when 'B' | 'b'  =>
1915
                           Pic.Picture.Expanded (Index) := 'b';
1916
                           Skip;
1917
 
1918
                        when '#' =>
1919
                           Pic.Max_Trailing_Digits :=
1920
                             Pic.Max_Trailing_Digits + 1;
1921
                           Pic.End_Float := Index;
1922
                           Skip;
1923
 
1924
                        when others =>
1925
                           return;
1926
 
1927
                     end case;
1928
                  end loop;
1929
 
1930
               when others =>
1931
                  Number_Fraction;
1932
                  return;
1933
 
1934
            end case;
1935
         end loop;
1936
      end Number_Fraction_Or_Pound;
1937
 
1938
      ----------------------------------
1939
      -- Number_Fraction_Or_Star_Fill --
1940
      ----------------------------------
1941
 
1942
      procedure Number_Fraction_Or_Star_Fill is
1943
      begin
1944
         loop
1945
            if At_End then
1946
               return;
1947
            end if;
1948
 
1949
            case Look is
1950
 
1951
               when '_' | '0' | '/' =>
1952
                  Skip;
1953
 
1954
               when 'B' | 'b'  =>
1955
                  Pic.Picture.Expanded (Index) := 'b';
1956
                  Skip;
1957
 
1958
               when '*' =>
1959
                  Pic.Star_Fill := True;
1960
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
1961
                  Pic.End_Float := Index;
1962
                  Skip;
1963
 
1964
                  loop
1965
                     if At_End then
1966
                        return;
1967
                     end if;
1968
 
1969
                     case Look is
1970
 
1971
                        when '_' | '0' | '/' =>
1972
                           Skip;
1973
 
1974
                        when 'B' | 'b'  =>
1975
                           Pic.Picture.Expanded (Index) := 'b';
1976
                           Skip;
1977
 
1978
                        when '*' =>
1979
                           Pic.Star_Fill := True;
1980
                           Pic.Max_Trailing_Digits :=
1981
                             Pic.Max_Trailing_Digits + 1;
1982
                           Pic.End_Float := Index;
1983
                           Skip;
1984
 
1985
                        when others =>
1986
                           return;
1987
                     end case;
1988
                  end loop;
1989
 
1990
               when others =>
1991
                  Number_Fraction;
1992
                  return;
1993
 
1994
            end case;
1995
         end loop;
1996
      end Number_Fraction_Or_Star_Fill;
1997
 
1998
      -------------------------------
1999
      -- Number_Fraction_Or_Z_Fill --
2000
      -------------------------------
2001
 
2002
      procedure Number_Fraction_Or_Z_Fill is
2003
      begin
2004
         loop
2005
            if At_End then
2006
               return;
2007
            end if;
2008
 
2009
            case Look is
2010
 
2011
               when '_' | '0' | '/' =>
2012
                  Skip;
2013
 
2014
               when 'B' | 'b'  =>
2015
                  Pic.Picture.Expanded (Index) := 'b';
2016
                  Skip;
2017
 
2018
               when 'Z' | 'z' =>
2019
                  Pic.Max_Trailing_Digits := Pic.Max_Trailing_Digits + 1;
2020
                  Pic.End_Float := Index;
2021
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2022
 
2023
                  Skip;
2024
 
2025
                  loop
2026
                     if At_End then
2027
                        return;
2028
                     end if;
2029
 
2030
                     case Look is
2031
 
2032
                        when '_' | '0' | '/' =>
2033
                           Skip;
2034
 
2035
                        when 'B' | 'b'  =>
2036
                           Pic.Picture.Expanded (Index) := 'b';
2037
                           Skip;
2038
 
2039
                        when 'Z' | 'z' =>
2040
                           Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2041
 
2042
                           Pic.Max_Trailing_Digits :=
2043
                             Pic.Max_Trailing_Digits + 1;
2044
                           Pic.End_Float := Index;
2045
                           Skip;
2046
 
2047
                        when others =>
2048
                           return;
2049
                     end case;
2050
                  end loop;
2051
 
2052
               when others =>
2053
                  Number_Fraction;
2054
                  return;
2055
            end case;
2056
         end loop;
2057
      end Number_Fraction_Or_Z_Fill;
2058
 
2059
      -----------------------
2060
      -- Optional_RHS_Sign --
2061
      -----------------------
2062
 
2063
      procedure Optional_RHS_Sign is
2064
      begin
2065
         if At_End then
2066
            return;
2067
         end if;
2068
 
2069
         case Look is
2070
 
2071
            when '+' | '-' =>
2072
               Pic.Sign_Position := Index;
2073
               Skip;
2074
               return;
2075
 
2076
            when 'C' | 'c' =>
2077
               Pic.Sign_Position := Index;
2078
               Pic.Picture.Expanded (Index) := 'C';
2079
               Skip;
2080
 
2081
               if Look = 'R' or else Look = 'r' then
2082
                  Pic.Second_Sign := Index;
2083
                  Pic.Picture.Expanded (Index) := 'R';
2084
                  Skip;
2085
 
2086
               else
2087
                  raise Picture_Error;
2088
               end if;
2089
 
2090
               return;
2091
 
2092
            when 'D' | 'd' =>
2093
               Pic.Sign_Position := Index;
2094
               Pic.Picture.Expanded (Index) := 'D';
2095
               Skip;
2096
 
2097
               if Look = 'B' or else Look = 'b' then
2098
                  Pic.Second_Sign := Index;
2099
                  Pic.Picture.Expanded (Index) := 'B';
2100
                  Skip;
2101
 
2102
               else
2103
                  raise Picture_Error;
2104
               end if;
2105
 
2106
               return;
2107
 
2108
            when '>' =>
2109
               if Pic.Picture.Expanded (Pic.Sign_Position) = '<' then
2110
                  Pic.Second_Sign := Index;
2111
                  Skip;
2112
 
2113
               else
2114
                  raise Picture_Error;
2115
               end if;
2116
 
2117
            when others =>
2118
               return;
2119
 
2120
         end case;
2121
      end Optional_RHS_Sign;
2122
 
2123
      -------------
2124
      -- Picture --
2125
      -------------
2126
 
2127
      --  Note that Picture can be called in either State
2128
 
2129
      --  It will set state to Valid only if a 9 is encountered or floating
2130
      --  currency is called.
2131
 
2132
      procedure Picture is
2133
      begin
2134
         loop
2135
            if At_End then
2136
               return;
2137
            end if;
2138
 
2139
            case Look is
2140
 
2141
               when '_' | '0' | '/' =>
2142
                  Skip;
2143
 
2144
               when 'B' | 'b'  =>
2145
                  Pic.Picture.Expanded (Index) := 'b';
2146
                  Skip;
2147
 
2148
               when '$' =>
2149
                  Leading_Dollar;
2150
                  return;
2151
 
2152
               when '#' =>
2153
                  Leading_Pound;
2154
                  return;
2155
 
2156
               when '9' =>
2157
                  Computed_BWZ := False;
2158
                  Set_State (Okay);
2159
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2160
                  Skip;
2161
 
2162
               when 'V' | 'v' | '.' =>
2163
                  Pic.Radix_Position := Index;
2164
                  Skip;
2165
                  Number_Fraction;
2166
                  Trailing_Currency;
2167
                  return;
2168
 
2169
               when others =>
2170
                  return;
2171
 
2172
            end case;
2173
         end loop;
2174
      end Picture;
2175
 
2176
      ---------------------
2177
      -- Picture_Bracket --
2178
      ---------------------
2179
 
2180
      procedure Picture_Bracket is
2181
      begin
2182
         Pic.Sign_Position := Index;
2183
         Pic.Sign_Position := Index;
2184
 
2185
         --  Treat as a floating sign, and unwind otherwise
2186
 
2187
         Pic.Floater := '<';
2188
         Pic.Start_Float := Index;
2189
         Pic.End_Float := Index;
2190
 
2191
         --  Don't increment Pic.Max_Leading_Digits, we need one "real"
2192
         --  sign place.
2193
 
2194
         Skip; --  Known Bracket
2195
 
2196
         loop
2197
            case Look is
2198
 
2199
               when '_' | '0' | '/' =>
2200
                  Pic.End_Float := Index;
2201
                  Skip;
2202
 
2203
               when 'B' | 'b'  =>
2204
                  Pic.End_Float := Index;
2205
                  Pic.Picture.Expanded (Index) := 'b';
2206
                  Skip;
2207
 
2208
               when '<' =>
2209
                  Set_State (Okay);  --  "<<>" is enough.
2210
                  Floating_Bracket;
2211
                  Trailing_Currency;
2212
                  Trailing_Bracket;
2213
                  return;
2214
 
2215
               when '$' | '#' | '9' | '*' =>
2216
                  if State /= Okay then
2217
                     Pic.Floater := '!';
2218
                     Pic.Start_Float := Invalid_Position;
2219
                     Pic.End_Float := Invalid_Position;
2220
                  end if;
2221
 
2222
                  Picture;
2223
                  Trailing_Bracket;
2224
                  Set_State (Okay);
2225
                  return;
2226
 
2227
               when '.' | 'V' | 'v' =>
2228
                  if State /= Okay then
2229
                     Pic.Floater := '!';
2230
                     Pic.Start_Float := Invalid_Position;
2231
                     Pic.End_Float := Invalid_Position;
2232
                  end if;
2233
 
2234
                  --  Don't assume that state is okay, haven't seen a digit
2235
 
2236
                  Picture;
2237
                  Trailing_Bracket;
2238
                  return;
2239
 
2240
               when others =>
2241
                  raise Picture_Error;
2242
 
2243
            end case;
2244
         end loop;
2245
      end Picture_Bracket;
2246
 
2247
      -------------------
2248
      -- Picture_Minus --
2249
      -------------------
2250
 
2251
      procedure Picture_Minus is
2252
      begin
2253
         Pic.Sign_Position := Index;
2254
 
2255
         --  Treat as a floating sign, and unwind otherwise
2256
 
2257
         Pic.Floater := '-';
2258
         Pic.Start_Float := Index;
2259
         Pic.End_Float := Index;
2260
 
2261
         --  Don't increment Pic.Max_Leading_Digits, we need one "real"
2262
         --  sign place.
2263
 
2264
         Skip; --  Known Minus
2265
 
2266
         loop
2267
            case Look is
2268
 
2269
               when '_' | '0' | '/' =>
2270
                  Pic.End_Float := Index;
2271
                  Skip;
2272
 
2273
               when 'B' | 'b'  =>
2274
                  Pic.End_Float := Index;
2275
                  Pic.Picture.Expanded (Index) := 'b';
2276
                  Skip;
2277
 
2278
               when '-' =>
2279
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2280
                  Pic.End_Float := Index;
2281
                  Skip;
2282
                  Set_State (Okay);  --  "-- " is enough.
2283
                  Floating_Minus;
2284
                  Trailing_Currency;
2285
                  return;
2286
 
2287
               when '$' | '#' | '9' | '*' =>
2288
                  if State /= Okay then
2289
                     Pic.Floater := '!';
2290
                     Pic.Start_Float := Invalid_Position;
2291
                     Pic.End_Float := Invalid_Position;
2292
                  end if;
2293
 
2294
                  Picture;
2295
                  Set_State (Okay);
2296
                  return;
2297
 
2298
               when 'Z' | 'z' =>
2299
 
2300
                  --  Can't have Z and a floating sign
2301
 
2302
                  if State = Okay then
2303
                     Set_State (Reject);
2304
                  end if;
2305
 
2306
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2307
                  Zero_Suppression;
2308
                  Trailing_Currency;
2309
                  Optional_RHS_Sign;
2310
                  return;
2311
 
2312
               when '.' | 'V' | 'v' =>
2313
                  if State /= Okay then
2314
                     Pic.Floater := '!';
2315
                     Pic.Start_Float := Invalid_Position;
2316
                     Pic.End_Float := Invalid_Position;
2317
                  end if;
2318
 
2319
                  --  Don't assume that state is okay, haven't seen a digit
2320
 
2321
                  Picture;
2322
                  return;
2323
 
2324
               when others =>
2325
                  return;
2326
 
2327
            end case;
2328
         end loop;
2329
      end Picture_Minus;
2330
 
2331
      ------------------
2332
      -- Picture_Plus --
2333
      ------------------
2334
 
2335
      procedure Picture_Plus is
2336
      begin
2337
         Pic.Sign_Position := Index;
2338
 
2339
         --  Treat as a floating sign, and unwind otherwise
2340
 
2341
         Pic.Floater := '+';
2342
         Pic.Start_Float := Index;
2343
         Pic.End_Float := Index;
2344
 
2345
         --  Don't increment Pic.Max_Leading_Digits, we need one "real"
2346
         --  sign place.
2347
 
2348
         Skip; --  Known Plus
2349
 
2350
         loop
2351
            case Look is
2352
 
2353
               when '_' | '0' | '/' =>
2354
                  Pic.End_Float := Index;
2355
                  Skip;
2356
 
2357
               when 'B' | 'b'  =>
2358
                  Pic.End_Float := Index;
2359
                  Pic.Picture.Expanded (Index) := 'b';
2360
                  Skip;
2361
 
2362
               when '+' =>
2363
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2364
                  Pic.End_Float := Index;
2365
                  Skip;
2366
                  Set_State (Okay);  --  "++" is enough
2367
                  Floating_Plus;
2368
                  Trailing_Currency;
2369
                  return;
2370
 
2371
               when '$' | '#' | '9' | '*' =>
2372
                  if State /= Okay then
2373
                     Pic.Floater := '!';
2374
                     Pic.Start_Float := Invalid_Position;
2375
                     Pic.End_Float := Invalid_Position;
2376
                  end if;
2377
 
2378
                  Picture;
2379
                  Set_State (Okay);
2380
                  return;
2381
 
2382
               when 'Z' | 'z' =>
2383
                  if State = Okay then
2384
                     Set_State (Reject);
2385
                  end if;
2386
 
2387
                  --  Can't have Z and a floating sign
2388
 
2389
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2390
 
2391
                  --  '+Z' is acceptable
2392
 
2393
                  Set_State (Okay);
2394
 
2395
                  Zero_Suppression;
2396
                  Trailing_Currency;
2397
                  Optional_RHS_Sign;
2398
                  return;
2399
 
2400
               when '.' | 'V' | 'v' =>
2401
                  if State /= Okay then
2402
                     Pic.Floater := '!';
2403
                     Pic.Start_Float := Invalid_Position;
2404
                     Pic.End_Float := Invalid_Position;
2405
                  end if;
2406
 
2407
                  --  Don't assume that state is okay, haven't seen a digit
2408
 
2409
                  Picture;
2410
                  return;
2411
 
2412
               when others =>
2413
                  return;
2414
 
2415
            end case;
2416
         end loop;
2417
      end Picture_Plus;
2418
 
2419
      --------------------
2420
      -- Picture_String --
2421
      --------------------
2422
 
2423
      procedure Picture_String is
2424
      begin
2425
         while Is_Insert loop
2426
            Skip;
2427
         end loop;
2428
 
2429
         case Look is
2430
 
2431
            when '$' | '#' =>
2432
               Picture;
2433
               Optional_RHS_Sign;
2434
 
2435
            when '+' =>
2436
               Picture_Plus;
2437
 
2438
            when '-' =>
2439
               Picture_Minus;
2440
 
2441
            when '<' =>
2442
               Picture_Bracket;
2443
 
2444
            when 'Z' | 'z' =>
2445
               Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2446
               Zero_Suppression;
2447
               Trailing_Currency;
2448
               Optional_RHS_Sign;
2449
 
2450
            when '*' =>
2451
               Star_Suppression;
2452
               Trailing_Currency;
2453
               Optional_RHS_Sign;
2454
 
2455
            when '9' | '.' | 'V' | 'v' =>
2456
               Number;
2457
               Trailing_Currency;
2458
               Optional_RHS_Sign;
2459
 
2460
            when others =>
2461
               raise Picture_Error;
2462
 
2463
         end case;
2464
 
2465
         --  Blank when zero either if the PIC does not contain a '9' or if
2466
         --  requested by the user and no '*'.
2467
 
2468
         Pic.Blank_When_Zero :=
2469
           (Computed_BWZ or else Pic.Blank_When_Zero)
2470
             and then not Pic.Star_Fill;
2471
 
2472
         --  Star fill if '*' and no '9'
2473
 
2474
         Pic.Star_Fill := Pic.Star_Fill and then Computed_BWZ;
2475
 
2476
         if not At_End then
2477
            Set_State (Reject);
2478
         end if;
2479
 
2480
      end Picture_String;
2481
 
2482
      ---------------
2483
      -- Set_State --
2484
      ---------------
2485
 
2486
      procedure Set_State (L : Legality) is
2487
      begin
2488
         State := L;
2489
      end Set_State;
2490
 
2491
      ----------
2492
      -- Skip --
2493
      ----------
2494
 
2495
      procedure Skip is
2496
      begin
2497
         Index := Index + 1;
2498
      end Skip;
2499
 
2500
      ----------------------
2501
      -- Star_Suppression --
2502
      ----------------------
2503
 
2504
      procedure Star_Suppression is
2505
      begin
2506
         Pic.Floater := '*';
2507
         Pic.Start_Float := Index;
2508
         Pic.End_Float := Index;
2509
         Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2510
         Set_State (Okay);
2511
 
2512
         --  Even a single * is a valid picture
2513
 
2514
         Pic.Star_Fill := True;
2515
         Skip; --  Known *
2516
 
2517
         loop
2518
            if At_End then
2519
               return;
2520
            end if;
2521
 
2522
            case Look is
2523
 
2524
               when '_' | '0' | '/' =>
2525
                  Pic.End_Float := Index;
2526
                  Skip;
2527
 
2528
               when 'B' | 'b'  =>
2529
                  Pic.End_Float := Index;
2530
                  Pic.Picture.Expanded (Index) := 'b';
2531
                  Skip;
2532
 
2533
               when '*' =>
2534
                  Pic.End_Float := Index;
2535
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2536
                  Set_State (Okay); Skip;
2537
 
2538
               when '9' =>
2539
                  Set_State (Okay);
2540
                  Number_Completion;
2541
                  return;
2542
 
2543
               when '.' | 'V' | 'v' =>
2544
                  Pic.Radix_Position := Index;
2545
                  Skip;
2546
                  Number_Fraction_Or_Star_Fill;
2547
                  return;
2548
 
2549
               when '#' | '$' =>
2550
                  Trailing_Currency;
2551
                  Set_State (Okay);
2552
                  return;
2553
 
2554
               when others => raise Picture_Error;
2555
            end case;
2556
         end loop;
2557
      end Star_Suppression;
2558
 
2559
      ----------------------
2560
      -- Trailing_Bracket --
2561
      ----------------------
2562
 
2563
      procedure Trailing_Bracket is
2564
      begin
2565
         if Look = '>' then
2566
            Pic.Second_Sign := Index;
2567
            Skip;
2568
         else
2569
            raise Picture_Error;
2570
         end if;
2571
      end Trailing_Bracket;
2572
 
2573
      -----------------------
2574
      -- Trailing_Currency --
2575
      -----------------------
2576
 
2577
      procedure Trailing_Currency is
2578
      begin
2579
         if At_End then
2580
            return;
2581
         end if;
2582
 
2583
         if Look = '$' then
2584
            Pic.Start_Currency := Index;
2585
            Pic.End_Currency := Index;
2586
            Skip;
2587
 
2588
         else
2589
            while not At_End and then Look = '#' loop
2590
               if Pic.Start_Currency = Invalid_Position then
2591
                  Pic.Start_Currency := Index;
2592
               end if;
2593
 
2594
               Pic.End_Currency := Index;
2595
               Skip;
2596
            end loop;
2597
         end if;
2598
 
2599
         loop
2600
            if At_End then
2601
               return;
2602
            end if;
2603
 
2604
            case Look is
2605
               when '_' | '0' | '/' => Skip;
2606
 
2607
               when 'B' | 'b'  =>
2608
                  Pic.Picture.Expanded (Index) := 'b';
2609
                  Skip;
2610
 
2611
               when others => return;
2612
            end case;
2613
         end loop;
2614
      end Trailing_Currency;
2615
 
2616
      ----------------------
2617
      -- Zero_Suppression --
2618
      ----------------------
2619
 
2620
      procedure Zero_Suppression is
2621
      begin
2622
         Pic.Floater := 'Z';
2623
         Pic.Start_Float := Index;
2624
         Pic.End_Float := Index;
2625
         Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2626
         Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2627
 
2628
         Skip; --  Known Z
2629
 
2630
         loop
2631
            --  Even a single Z is a valid picture
2632
 
2633
            if At_End then
2634
               Set_State (Okay);
2635
               return;
2636
            end if;
2637
 
2638
            case Look is
2639
               when '_' | '0' | '/' =>
2640
                  Pic.End_Float := Index;
2641
                  Skip;
2642
 
2643
               when 'B' | 'b'  =>
2644
                  Pic.End_Float := Index;
2645
                  Pic.Picture.Expanded (Index) := 'b';
2646
                  Skip;
2647
 
2648
               when 'Z' | 'z' =>
2649
                  Pic.Picture.Expanded (Index) := 'Z'; -- consistency
2650
 
2651
                  Pic.Max_Leading_Digits := Pic.Max_Leading_Digits + 1;
2652
                  Pic.End_Float := Index;
2653
                  Set_State (Okay);
2654
                  Skip;
2655
 
2656
               when '9' =>
2657
                  Set_State (Okay);
2658
                  Number_Completion;
2659
                  return;
2660
 
2661
               when '.' | 'V' | 'v' =>
2662
                  Pic.Radix_Position := Index;
2663
                  Skip;
2664
                  Number_Fraction_Or_Z_Fill;
2665
                  return;
2666
 
2667
               when '#' | '$' =>
2668
                  Trailing_Currency;
2669
                  Set_State (Okay);
2670
                  return;
2671
 
2672
               when others =>
2673
                  return;
2674
            end case;
2675
         end loop;
2676
      end Zero_Suppression;
2677
 
2678
   --  Start of processing for Precalculate
2679
 
2680
   begin
2681
      Picture_String;
2682
 
2683
      if State = Reject then
2684
         raise Picture_Error;
2685
      end if;
2686
 
2687
   exception
2688
 
2689
      when Constraint_Error =>
2690
 
2691
         --  To deal with special cases like null strings
2692
 
2693
      raise Picture_Error;
2694
 
2695
   end Precalculate;
2696
 
2697
   ----------------
2698
   -- To_Picture --
2699
   ----------------
2700
 
2701
   function To_Picture
2702
     (Pic_String      : String;
2703
      Blank_When_Zero : Boolean := False) return Picture
2704
   is
2705
      Result : Picture;
2706
 
2707
   begin
2708
      declare
2709
         Item : constant String := Expand (Pic_String);
2710
 
2711
      begin
2712
         Result.Contents.Picture         := (Item'Length, Item);
2713
         Result.Contents.Original_BWZ := Blank_When_Zero;
2714
         Result.Contents.Blank_When_Zero := Blank_When_Zero;
2715
         Precalculate (Result.Contents);
2716
         return Result;
2717
      end;
2718
 
2719
   exception
2720
      when others =>
2721
         raise Picture_Error;
2722
 
2723
   end To_Picture;
2724
 
2725
   -------------
2726
   -- To_Wide --
2727
   -------------
2728
 
2729
   function To_Wide (C : Character) return Wide_Wide_Character is
2730
   begin
2731
      return Wide_Wide_Character'Val (Character'Pos (C));
2732
   end To_Wide;
2733
 
2734
   -----------
2735
   -- Valid --
2736
   -----------
2737
 
2738
   function Valid
2739
     (Pic_String      : String;
2740
      Blank_When_Zero : Boolean := False) return Boolean
2741
   is
2742
   begin
2743
      declare
2744
         Expanded_Pic : constant String := Expand (Pic_String);
2745
         --  Raises Picture_Error if Item not well-formed
2746
 
2747
         Format_Rec : Format_Record;
2748
 
2749
      begin
2750
         Format_Rec.Picture := (Expanded_Pic'Length, Expanded_Pic);
2751
         Format_Rec.Blank_When_Zero := Blank_When_Zero;
2752
         Format_Rec.Original_BWZ := Blank_When_Zero;
2753
         Precalculate (Format_Rec);
2754
 
2755
         --  False only if Blank_When_0 is True but the pic string has a '*'
2756
 
2757
         return not Blank_When_Zero
2758
           or else Strings_Fixed.Index (Expanded_Pic, "*") = 0;
2759
      end;
2760
 
2761
   exception
2762
      when others => return False;
2763
   end Valid;
2764
 
2765
end Ada.Wide_Wide_Text_IO.Editing;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.