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-wtedit.adb] - Blame information for rev 473

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

powered by: WebSVN 2.1.0

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