This file is indexed.

/usr/share/ada/adainclude/gmpada/gnu_multiple_precision-aux.adb is in libgmpada3-dev 0.0.20120331-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
--    GMPAda, binding to the Ada Language for the GNU MultiPrecision library.
--    Copyright (C) 2007-2011 Nicolas Boulenguez <nicolas.boulenguez@free.fr>
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program is distributed in the hope that it will be useful,
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--    GNU General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.

with Ada.IO_Exceptions;
with Ada.Unchecked_Deallocation;

package body GNU_Multiple_Precision.Aux is

   type Char_Array_Access is access char_array;
   procedure Free is new Ada.Unchecked_Deallocation (char_array,
                                                     Char_Array_Access);
   --  Since we will allocate huge buffers, we have to allocate on the
   --  heap to avoid stack overflow.

   function Is_Digit (Item : Character;
                      Base : int)
                     return Boolean
   is
   begin
      case Item is
         when '0' .. '9' =>
            return Character'Pos (Item) - Character'Pos ('0') < Base;
         when 'A' .. 'F' =>
            return Character'Pos (Item) - Character'Pos ('A') + 10 < Base;
         when 'a' .. 'f' =>
            return Character'Pos (Item) - Character'Pos ('a') + 10 < Base;
         when others =>
            return False;
      end case;
   end Is_Digit;

   function Is_Blank (Item : Character) return Boolean
   is
   begin
      return Item = ' ' or Item = ASCII.HT;
   end Is_Blank;

   procedure Put
     (Put_Character : access procedure (Item : in Character);
      Item          : in Mpz_T;
      Width         : in Natural;
      Base          : in Integer)
   is
      Buffer   : Char_Array_Access
        := new char_array (0 .. Mpz_Sizeinbase (Item, int (Base)) + 1);
      Length   : size_t
        := Buffer'Last - 2; --  no sign and mpz_sizeinbase overestimated
      Negative : Boolean;
   begin
      Mpz_Get_Str (Buffer.all, int (Base), Item);
      Negative := To_Ada (Buffer.all (0)) = '-';
      while Buffer.all (Length) /= nul loop
         Length := Length + 1;
      end loop;
      case Base is
         when 2 .. 9 =>
            for I in Natural (Length) + 4 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
            Put_Character.all (Character'Val (Base + Character'Pos ('0')));
            Put_Character.all ('#');
         when 10 =>
            for I in Natural (Length) + 1 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
         when 11 .. 16 =>
            for I in Natural (Length) + 5 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
            Put_Character.all ('1');
            Put_Character.all (Character'Val
                                 (Base - 10 + Character'Pos ('0')));
            Put_Character.all ('#');
         when others =>
            null;
            pragma Assert (False);
      end case;
      if Negative then
         for I in 1 .. Length - 1 loop
            Put_Character.all (To_Ada (Buffer.all (I)));
         end loop;
      else
         for I in 0 .. Length - 1 loop
            Put_Character.all (To_Ada (Buffer.all (I)));
         end loop;
      end if;
      if Base /= 10 then
         Put_Character.all ('#');
      end if;
      Free (Buffer);
   exception
      when others =>
         Free (Buffer);
         raise;
   end Put;

   procedure Put
     (Put_Character : access procedure (Item : in Character);
      Item          : in Mpq_T;
      Width         : in Natural;
      Base          : in Integer)
   is
      Buffer : Char_Array_Access := new char_array
        (0 .. Mpz_Sizeinbase (Mpq_Numref (Item).all, int (Base))
         + Mpz_Sizeinbase (Mpq_Denref (Item).all, int (Base)) + 2);
      Length : size_t := Buffer'Last - 4;
      --  no sign, no slash and both mpz_sizeinbase overestimated
      Negative : Boolean;
   begin
      Mpq_Get_Str (Buffer.all, int (Base), Item);
      Negative := To_Ada (Buffer.all (0)) = '-';
      while Buffer.all (Length) /= nul loop
         Length := Length + 1;
      end loop;
      case Base is
         when 2 .. 9 =>
            for I in Natural (Length) + 4 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
            Put_Character.all (Character'Val (Base + Character'Pos ('0')));
            Put_Character.all ('#');
         when 10 =>
            for I in Natural (Length) + 1 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
         when 11 .. 16 =>
            for I in Natural (Length) + 5 .. Width loop
               Put_Character.all (' ');
            end loop;
            if Negative then Put_Character.all ('-'); end if;
            Put_Character.all ('1');
            Put_Character.all (Character'Val
                                 (Base - 10 + Character'Pos ('0')));
            Put_Character.all ('#');
         when others =>
            null;
            pragma Assert (False);
      end case;
      if Negative then
         for I in 1 .. Length - 1 loop
            Put_Character.all (To_Ada (Buffer.all (I)));
         end loop;
      else
         for I in 0 .. Length - 1 loop
            Put_Character.all (To_Ada (Buffer.all (I)));
         end loop;
      end if;
      if Base /= 10 then
         Put_Character.all ('#');
      end if;
      Free (Buffer);
   exception
      when others =>
         Free (Buffer);
         raise;
   end Put;

   procedure Put
     (Put_Character : access procedure (Item : in Character);
      Item          : in Mpf_T;
      Fore          : in Natural;
      Aft           : in Natural;
      Exp           : in Natural)
   is
      Actual_Fore : constant Natural := Natural'Max (1, Fore);
      Actual_Aft  : constant Natural := Natural'Max (1, Aft);
      Next_In     : size_t := 1;
      Exponent    : Mp_Exp_T;
      procedure Copy (Buffer : in char_array);
      procedure Blank_And_Sign (Buffer      : in char_array;
                                Filled_Fore : in Natural);
      pragma Inline (Copy);
      procedure Copy (Buffer : in char_array)
      is
      begin
         if Buffer (Next_In) = nul then
            Put_Character.all ('0');
         else
            pragma Assert (To_Ada (Buffer (Next_In)) in '0' .. '9'
                           or To_Ada (Buffer (Next_In)) = '-');
            Put_Character.all (To_Ada (Buffer (Next_In)));
            Next_In := Next_In + 1;
         end if;
      end Copy;
      procedure Blank_And_Sign (Buffer      : in char_array;
                                Filled_Fore : in Natural)
      is
      begin
         if Buffer (Buffer'First) = To_C ('-') then
            for I in Filled_Fore + 2 .. Actual_Fore loop
               Put_Character.all (' ');
            end loop;
            Copy (Buffer);
         else
            for I in Filled_Fore + 1 .. Actual_Fore loop
               Put_Character.all (' ');
            end loop;
         end if;
      end Blank_And_Sign;
   begin
      if Exp > 0 then
         declare
            Buffer : Char_Array_Access
              := new char_array (1 .. size_t (Actual_Fore + Actual_Aft) + 2);
            --  2 for sign and nul
         begin
            Mpf_Get_Str (Buffer.all, Exponent, 10, Buffer'Length - 2, Item);
            Blank_And_Sign (Buffer.all, 1);
            if Buffer.all (Next_In) /= nul then
               Exponent := Exponent - 1;
            end if;
            Copy (Buffer.all);
            Put_Character.all ('.');
            for I in 1 .. Actual_Aft loop Copy (Buffer.all); end loop;
            Put_Character.all ('E');
            declare
               E_Img : String := Mp_Exp_T'Image (Exponent);
            begin
               if Exponent >= 0 then E_Img (1) := '+'; end if;
               Put_Character.all (E_Img (1));
               for I in E_Img'Length + 1 .. Exp loop
                  Put_Character.all ('0');
               end loop;
               for I in 2 .. E_Img'Last loop
                  Put_Character.all (E_Img (I));
               end loop;
            end;
            Free (Buffer);
         exception
            when others =>
               Free (Buffer);
               raise;
         end;
      else
         declare
            --  Say d = # decimal digits and b = # binary digits
            --  10^{d-1} \leqslant Arg < 10^d
            --  \ln Arg < d\ln 10 \leqslant \ln Arg + \ln 10
            --  \ln Arg < b\ln 2  \leqslant \ln Arg + \ln 2
            --  d \leqslant \frac{\ln Arg}{\ln 10} + 1
            --            < b\frac{\ln 2}{\ln 10} + 1 < b / 3 + 1
            N_Digits : constant unsigned_long
              := unsigned_long'Max (1, Mpf_Get_Prec (Item) / 3);
            --  We want to be sure to ask at least one digit, no C
            --  allocated-string.
            Buffer : Char_Array_Access
              := new char_array (1 .. size_t (N_Digits) + 2); --  sign nul
         begin
            Mpf_Get_Str (Buffer.all, Exponent, 10, Buffer'Length - 2, Item);
            if Exponent > 0 then
               Blank_And_Sign (Buffer.all, Natural (Exponent));
               for I in 1 .. Exponent loop Copy (Buffer.all); end loop;
               Put_Character.all ('.');
               for I in 1 .. Actual_Aft loop Copy (Buffer.all); end loop;
            else
               Exponent := -Exponent;
               Blank_And_Sign (Buffer.all, 1);
               Put_Character.all ('0');
               Put_Character.all ('.');
               if Mp_Exp_T (Actual_Aft) <= Exponent then
                  for I in 1 .. Actual_Aft loop
                     Put_Character.all ('0');
                  end loop;
               else
                  for I in 1 .. Exponent loop
                     Put_Character.all ('0');
                  end loop;
                  for I in Exponent + 1 .. Mp_Exp_T (Actual_Aft) loop
                     Copy (Buffer.all);
                  end loop;
               end if;
            end if;
            Free (Buffer);
         exception
            when others =>
               Free (Buffer);
               raise;
         end;
      end if;
   end Put;

   package body Generic_Scan is

      procedure Blanks_And_Sign (Buffer   : in out char_array;
                                 Next_Out : in out size_t);

      procedure Scan_Based_Numeral
        (Action : access procedure;     --  Consuming a digit
         Base   : in     int);
      procedure Copy (Buffer   : in out char_array;
                      Next_Out : in out size_t);
      procedure Copy_Numeral (Buffer    : in out char_array;
                              Next_Out  : in out size_t;
                              Dot_Seen  :    out Boolean;
                              Base      : in     int;
                              Allow_Dot : in     Boolean);
      procedure Copy_Literal (Buffer      : in out char_array;
                              Next_Out    : in out size_t;
                              Base        :    out int;
                              Allow_Float : in     Boolean);

      procedure Blanks_And_Sign (Buffer   : in out char_array;
                                 Next_Out : in out size_t)
      is
      begin
         while Is_Blank (Next) loop
            Consume;
         end loop;
         if Next = '+' then
            Consume;
         elsif Next = '-' then
            Copy (Buffer, Next_Out);
         end if;
      end Blanks_And_Sign;

      procedure Scan_Based_Numeral
        (Action : access procedure; --  Consuming a digit
         Base   : in int)
      is
         Digit_Is_Mandatory : Boolean := True;
      begin
         loop
            if Is_Digit (Next, Base) then
               Action.all;
               Digit_Is_Mandatory := False;
            elsif Digit_Is_Mandatory then
               raise Ada.IO_Exceptions.Data_Error;
            elsif Next = '_' then
               Digit_Is_Mandatory := True;
               Consume;
            else
               return;
            end if;
         end loop;
      end Scan_Based_Numeral;

      pragma Inline (Copy);
      procedure Copy (Buffer   : in out char_array;
                      Next_Out : in out size_t)
      is
      begin
         Buffer (Next_Out) := To_C (Next);
         Next_Out := Next_Out + 1;
         Consume;
      end Copy;

      procedure Copy_Numeral
        (Buffer    : in out char_array;
         Next_Out  : in out size_t;
         Dot_Seen  :    out Boolean;
         Base      : in     int;
         Allow_Dot : in     Boolean)
      is
         procedure Action;
         procedure Action is begin Copy (Buffer, Next_Out); end Action;
      begin
         Dot_Seen := False;
         if Allow_Dot and Next = '.' then
            Copy (Buffer, Next_Out);
            Dot_Seen := True;
         end if;
         Scan_Based_Numeral (Action'Access, Base);
         if Allow_Dot and not Dot_Seen and Next = '.' then
            Copy (Buffer, Next_Out);
            Dot_Seen := True;
            if Is_Digit (Next, Base) then
               Scan_Based_Numeral (Action'Access, Base);
            end if;
         end if;
      end Copy_Numeral;

      procedure Copy_Literal
        (Buffer      : in out char_array;
         Next_Out    : in out size_t;
         Base        :    out int;
         Allow_Float : in     Boolean)
      is
         Start    : constant size_t := Next_Out;
         Dot_Seen : Boolean;
      begin
         Copy_Numeral (Buffer, Next_Out, Dot_Seen, 10,
                       Allow_Dot => Allow_Float);
         if Next /= '#' or Dot_Seen then
            Base := 10;
         else
            Consume;
            Base := 0;
            for I in Start .. Next_Out - 1 loop
               Base := Base * 10
                 + char'Pos (Buffer (I)) - char'Pos (To_C ('0'));
               if Base > 16 then raise Ada.IO_Exceptions.Data_Error; end if;
               --  Check it before an overflow occurs.
            end loop;
            if Base < 2 then raise Ada.IO_Exceptions.Data_Error; end if;
            Next_Out := Start;
            Copy_Numeral (Buffer, Next_Out, Dot_Seen, Base,
                          Allow_Dot => Allow_Float);
            if Next /= '#' then
               raise Ada.IO_Exceptions.Data_Error;
            end if;
            Consume;
         end if;
      end Copy_Literal;

      procedure Get_Mpz_T (Item  : in out Mpz_T;
                           Width : in     Natural)
      is
         Buffer    : Char_Array_Access
           := new char_array (1 .. size_t (Width) + 1); --  Keep space for nul.
         Next_Out  : size_t := Buffer'First;
         Base, Ret : int;
         Exponent  : unsigned_long := 0;
         Temp      : Mpz_T;
         procedure Action;
         procedure Action is begin
            Exponent := Exponent * 10
              + Character'Pos (Next) - Character'Pos ('0');
            Consume;
         end Action;
      begin
         Blanks_And_Sign (Buffer.all, Next_Out);
         Copy_Literal (Buffer.all, Next_Out, Base, Allow_Float => False);
         Buffer.all (Next_Out) := nul;
         Mpz_Set_Str (Ret, Item, Buffer.all, Base);
         pragma Assert (Ret = 0);
         if Next = 'E' or Next = 'e' then
            Consume;
            if Next = '+' then Consume; end if;
            Scan_Based_Numeral (Action'Access, 10);
            Mpz_Init (Temp);
            Mpz_Ui_Pow_Ui (Temp, 10, Exponent);
            pragma Warnings
              (Off,
               "writable actual for ""Rop"" overlaps with actual for ""Op1""");
            Mpz_Mul (Item, Item, Temp);
            pragma Warnings
              (On,
               "writable actual for ""Rop"" overlaps with actual for ""Op1""");
            Mpz_Clear (Temp);
         end if;
         Free (Buffer);
      exception
         when others =>
            Free (Buffer);
            raise;
      end Get_Mpz_T;

      procedure Get_Mpf_T (Item  : in out Mpf_T;
                           Width : in     Natural)
      is
         Buffer    : Char_Array_Access
           := new char_array (1 .. size_t (Width) + 1); --  Keep space for nul.
         Next_Out  : size_t := Buffer'First;
         Base, Ret : int;
         Dot_Seen  : Boolean;
      begin
         Blanks_And_Sign (Buffer.all, Next_Out);
         Copy_Literal (Buffer.all, Next_Out, Base, Allow_Float => True);
         if Next = 'E' or Next = 'e' then
            Consume;
            Buffer.all (Next_Out) := To_C ('@');
            Next_Out := Next_Out + 1;
            if Next = '+' then
               Consume;
            elsif Next = '-' then
               Copy (Buffer.all, Next_Out);
            end if;
            Copy_Numeral (Buffer.all, Next_Out, Dot_Seen, 10,
                          Allow_Dot => False);
         end if;
         Buffer.all (Next_Out) := nul;
         Mpf_Set_Str (Ret, Item, Buffer.all, -Base);
         pragma Assert (Ret = 0);
         Free (Buffer);
      exception
         when others =>
            Free (Buffer);
            raise;
      end Get_Mpf_T;

   end Generic_Scan;

end GNU_Multiple_Precision.Aux;