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