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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [a-teioed.adb] - Blame information for rev 750

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

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

powered by: WebSVN 2.1.0

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