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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [tree_io.adb] - Blame information for rev 749

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

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                              T R E E _ I O                               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009  Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNAT was originally developed  by the GNAT team at  New York University. --
28
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with Debug;  use Debug;
33
with Output; use Output;
34
with Unchecked_Conversion;
35
 
36
package body Tree_IO is
37
   Debug_Flag_Tree : Boolean := False;
38
   --  Debug flag for debug output from tree read/write
39
 
40
   -------------------------------------------
41
   -- Compression Scheme Used for Tree File --
42
   -------------------------------------------
43
 
44
   --  We don't just write the data directly, but instead do a mild form
45
   --  of compression, since we expect lots of compressible zeroes and
46
   --  blanks. The compression scheme is as follows:
47
 
48
   --    00nnnnnn followed by nnnnnn bytes (non compressed data)
49
   --    01nnnnnn indicates nnnnnn binary zero bytes
50
   --    10nnnnnn indicates nnnnnn ASCII space bytes
51
   --    11nnnnnn bbbbbbbb indicates nnnnnnnn occurrences of byte bbbbbbbb
52
 
53
   --  Since we expect many zeroes in trees, and many spaces in sources,
54
   --  this compression should be reasonably efficient. We can put in
55
   --  something better later on.
56
 
57
   --  Note that this compression applies to the Write_Tree_Data and
58
   --  Read_Tree_Data calls, not to the calls to read and write single
59
   --  scalar values, which are written in memory format without any
60
   --  compression.
61
 
62
   C_Noncomp : constant := 2#00_000000#;
63
   C_Zeros   : constant := 2#01_000000#;
64
   C_Spaces  : constant := 2#10_000000#;
65
   C_Repeat  : constant := 2#11_000000#;
66
   --  Codes for compression sequences
67
 
68
   Max_Count : constant := 63;
69
   --  Maximum data length for one compression sequence
70
 
71
   --  The above compression scheme applies only to data written with the
72
   --  Tree_Write routine and read with Tree_Read. Data written using the
73
   --  Tree_Write_Char or Tree_Write_Int routines and read using the
74
   --  corresponding input routines is not compressed.
75
 
76
   type Int_Bytes is array (1 .. 4) of Byte;
77
   for Int_Bytes'Size use 32;
78
 
79
   function To_Int_Bytes is new Unchecked_Conversion (Int, Int_Bytes);
80
   function To_Int       is new Unchecked_Conversion (Int_Bytes, Int);
81
 
82
   ----------------------
83
   -- Global Variables --
84
   ----------------------
85
 
86
   Tree_FD : File_Descriptor;
87
   --  File descriptor for tree
88
 
89
   Buflen : constant Int := 8_192;
90
   --  Length of buffer for read and write file data
91
 
92
   Buf : array (Pos range 1 .. Buflen) of Byte;
93
   --  Read/write file data buffer
94
 
95
   Bufn : Nat;
96
   --  Number of bytes read/written from/to buffer
97
 
98
   Buft : Nat;
99
   --  Total number of bytes in input buffer containing valid data. Used only
100
   --  for input operations. There is data left to be processed in the buffer
101
   --  if Buft > Bufn. A value of zero for Buft means that the buffer is empty.
102
 
103
   -----------------------
104
   -- Local Subprograms --
105
   -----------------------
106
 
107
   procedure Read_Buffer;
108
   --  Reads data into buffer, setting Bufn appropriately
109
 
110
   function Read_Byte return Byte;
111
   pragma Inline (Read_Byte);
112
   --  Returns next byte from input file, raises Tree_Format_Error if none left
113
 
114
   procedure Write_Buffer;
115
   --  Writes out current buffer contents
116
 
117
   procedure Write_Byte (B : Byte);
118
   pragma Inline (Write_Byte);
119
   --  Write one byte to output buffer, checking for buffer-full condition
120
 
121
   -----------------
122
   -- Read_Buffer --
123
   -----------------
124
 
125
   procedure Read_Buffer is
126
   begin
127
      Buft := Int (Read (Tree_FD, Buf (1)'Address, Integer (Buflen)));
128
 
129
      if Buft = 0 then
130
         raise Tree_Format_Error;
131
      else
132
         Bufn := 0;
133
      end if;
134
   end Read_Buffer;
135
 
136
   ---------------
137
   -- Read_Byte --
138
   ---------------
139
 
140
   function Read_Byte return Byte is
141
   begin
142
      if Bufn = Buft then
143
         Read_Buffer;
144
      end if;
145
 
146
      Bufn := Bufn + 1;
147
      return Buf (Bufn);
148
   end Read_Byte;
149
 
150
   --------------------
151
   -- Tree_Read_Bool --
152
   --------------------
153
 
154
   procedure Tree_Read_Bool (B : out Boolean) is
155
   begin
156
      B := Boolean'Val (Read_Byte);
157
 
158
      if Debug_Flag_Tree then
159
         if B then
160
            Write_Str ("True");
161
         else
162
            Write_Str ("False");
163
         end if;
164
 
165
         Write_Eol;
166
      end if;
167
   end Tree_Read_Bool;
168
 
169
   --------------------
170
   -- Tree_Read_Char --
171
   --------------------
172
 
173
   procedure Tree_Read_Char (C : out Character) is
174
   begin
175
      C := Character'Val (Read_Byte);
176
 
177
      if Debug_Flag_Tree then
178
         Write_Str ("==> transmitting Character = ");
179
         Write_Char (C);
180
         Write_Eol;
181
      end if;
182
   end Tree_Read_Char;
183
 
184
   --------------------
185
   -- Tree_Read_Data --
186
   --------------------
187
 
188
   procedure Tree_Read_Data (Addr : Address; Length : Int) is
189
 
190
      type S is array (Pos) of Byte;
191
      --  This is a big array, for which we have to suppress the warning
192
 
193
      type SP is access all S;
194
 
195
      function To_SP is new Unchecked_Conversion (Address, SP);
196
 
197
      Data : constant SP := To_SP (Addr);
198
      --  Data buffer to be read as an indexable array of bytes
199
 
200
      OP : Pos := 1;
201
      --  Pointer to next byte of data buffer to be read into
202
 
203
      B : Byte;
204
      C : Byte;
205
      L : Int;
206
 
207
   begin
208
      if Debug_Flag_Tree then
209
         Write_Str ("==> transmitting ");
210
         Write_Int (Length);
211
         Write_Str (" data bytes");
212
         Write_Eol;
213
      end if;
214
 
215
      --  Verify data length
216
 
217
      Tree_Read_Int (L);
218
 
219
      if L /= Length then
220
         Write_Str ("==> transmitting, expected ");
221
         Write_Int (Length);
222
         Write_Str (" bytes, found length = ");
223
         Write_Int (L);
224
         Write_Eol;
225
         raise Tree_Format_Error;
226
      end if;
227
 
228
      --  Loop to read data
229
 
230
      while OP <= Length loop
231
 
232
         --  Get compression control character
233
 
234
         B := Read_Byte;
235
         C := B and 2#00_111111#;
236
         B := B and 2#11_000000#;
237
 
238
         --  Non-repeat case
239
 
240
         if B = C_Noncomp then
241
            if Debug_Flag_Tree then
242
               Write_Str ("==>    uncompressed:  ");
243
               Write_Int (Int (C));
244
               Write_Str (", starting at ");
245
               Write_Int (OP);
246
               Write_Eol;
247
            end if;
248
 
249
            for J in 1 .. C loop
250
               Data (OP) := Read_Byte;
251
               OP := OP + 1;
252
            end loop;
253
 
254
         --  Repeated zeroes
255
 
256
         elsif B = C_Zeros then
257
            if Debug_Flag_Tree then
258
               Write_Str ("==>    zeroes:        ");
259
               Write_Int (Int (C));
260
               Write_Str (", starting at ");
261
               Write_Int (OP);
262
               Write_Eol;
263
            end if;
264
 
265
            for J in 1 .. C loop
266
               Data (OP) := 0;
267
               OP := OP + 1;
268
            end loop;
269
 
270
         --  Repeated spaces
271
 
272
         elsif B = C_Spaces then
273
            if Debug_Flag_Tree then
274
               Write_Str ("==>    spaces:        ");
275
               Write_Int (Int (C));
276
               Write_Str (", starting at ");
277
               Write_Int (OP);
278
               Write_Eol;
279
            end if;
280
 
281
            for J in 1 .. C loop
282
               Data (OP) := Character'Pos (' ');
283
               OP := OP + 1;
284
            end loop;
285
 
286
         --  Specified repeated character
287
 
288
         else -- B = C_Repeat
289
            B := Read_Byte;
290
 
291
            if Debug_Flag_Tree then
292
               Write_Str ("==>    other char:    ");
293
               Write_Int (Int (C));
294
               Write_Str (" (");
295
               Write_Int (Int (B));
296
               Write_Char (')');
297
               Write_Str (", starting at ");
298
               Write_Int (OP);
299
               Write_Eol;
300
            end if;
301
 
302
            for J in 1 .. C loop
303
               Data (OP) := B;
304
               OP := OP + 1;
305
            end loop;
306
         end if;
307
      end loop;
308
 
309
      --  At end of loop, data item must be exactly filled
310
 
311
      if OP /= Length + 1 then
312
         raise Tree_Format_Error;
313
      end if;
314
 
315
   end Tree_Read_Data;
316
 
317
   --------------------------
318
   -- Tree_Read_Initialize --
319
   --------------------------
320
 
321
   procedure Tree_Read_Initialize (Desc : File_Descriptor) is
322
   begin
323
      Buft := 0;
324
      Bufn := 0;
325
      Tree_FD := Desc;
326
      Debug_Flag_Tree := Debug_Flag_5;
327
   end Tree_Read_Initialize;
328
 
329
   -------------------
330
   -- Tree_Read_Int --
331
   -------------------
332
 
333
   procedure Tree_Read_Int (N : out Int) is
334
      N_Bytes : Int_Bytes;
335
 
336
   begin
337
      for J in 1 .. 4 loop
338
         N_Bytes (J) := Read_Byte;
339
      end loop;
340
 
341
      N := To_Int (N_Bytes);
342
 
343
      if Debug_Flag_Tree then
344
         Write_Str ("==> transmitting Int = ");
345
         Write_Int (N);
346
         Write_Eol;
347
      end if;
348
   end Tree_Read_Int;
349
 
350
   -------------------
351
   -- Tree_Read_Str --
352
   -------------------
353
 
354
   procedure Tree_Read_Str (S : out String_Ptr) is
355
      N : Nat;
356
 
357
   begin
358
      Tree_Read_Int (N);
359
      S := new String (1 .. Natural (N));
360
      Tree_Read_Data (S.all (1)'Address, N);
361
   end Tree_Read_Str;
362
 
363
   -------------------------
364
   -- Tree_Read_Terminate --
365
   -------------------------
366
 
367
   procedure Tree_Read_Terminate is
368
   begin
369
      --  Must be at end of input buffer, so we should get Tree_Format_Error
370
      --  if we try to read one more byte, if not, we have a format error.
371
 
372
      declare
373
         B : Byte;
374
         pragma Warnings (Off, B);
375
 
376
      begin
377
         B := Read_Byte;
378
 
379
      exception
380
         when Tree_Format_Error => return;
381
      end;
382
 
383
      raise Tree_Format_Error;
384
   end Tree_Read_Terminate;
385
 
386
   ---------------------
387
   -- Tree_Write_Bool --
388
   ---------------------
389
 
390
   procedure Tree_Write_Bool (B : Boolean) is
391
   begin
392
      if Debug_Flag_Tree then
393
         Write_Str ("==> transmitting Boolean = ");
394
 
395
         if B then
396
            Write_Str ("True");
397
         else
398
            Write_Str ("False");
399
         end if;
400
 
401
         Write_Eol;
402
      end if;
403
 
404
      Write_Byte (Boolean'Pos (B));
405
   end Tree_Write_Bool;
406
 
407
   ---------------------
408
   -- Tree_Write_Char --
409
   ---------------------
410
 
411
   procedure Tree_Write_Char (C : Character) is
412
   begin
413
      if Debug_Flag_Tree then
414
         Write_Str ("==> transmitting Character = ");
415
         Write_Char (C);
416
         Write_Eol;
417
      end if;
418
 
419
      Write_Byte (Character'Pos (C));
420
   end Tree_Write_Char;
421
 
422
   ---------------------
423
   -- Tree_Write_Data --
424
   ---------------------
425
 
426
   procedure Tree_Write_Data (Addr : Address; Length : Int) is
427
 
428
      type S is array (Pos) of Byte;
429
      --  This is a big array, for which we have to suppress the warning
430
 
431
      type SP is access all S;
432
 
433
      function To_SP is new Unchecked_Conversion (Address, SP);
434
 
435
      Data : constant SP := To_SP (Addr);
436
      --  Pointer to data to be written, converted to array type
437
 
438
      IP : Pos := 1;
439
      --  Input buffer pointer, next byte to be processed
440
 
441
      NC : Nat range 0 .. Max_Count := 0;
442
      --  Number of bytes of non-compressible sequence
443
 
444
      C  : Byte;
445
 
446
      procedure Write_Non_Compressed_Sequence;
447
      --  Output currently collected sequence of non-compressible data
448
 
449
      -----------------------------------
450
      -- Write_Non_Compressed_Sequence --
451
      -----------------------------------
452
 
453
      procedure Write_Non_Compressed_Sequence is
454
      begin
455
         if NC > 0 then
456
            Write_Byte (C_Noncomp + Byte (NC));
457
 
458
            if Debug_Flag_Tree then
459
               Write_Str ("==>    uncompressed:  ");
460
               Write_Int (NC);
461
               Write_Str (", starting at ");
462
               Write_Int (IP - NC);
463
               Write_Eol;
464
            end if;
465
 
466
            for J in reverse 1 .. NC loop
467
               Write_Byte (Data (IP - J));
468
            end loop;
469
 
470
            NC := 0;
471
         end if;
472
      end Write_Non_Compressed_Sequence;
473
 
474
   --  Start of processing for Tree_Write_Data
475
 
476
   begin
477
      if Debug_Flag_Tree then
478
         Write_Str ("==> transmitting ");
479
         Write_Int (Length);
480
         Write_Str (" data bytes");
481
         Write_Eol;
482
      end if;
483
 
484
      --  We write the count at the start, so that we can check it on
485
      --  the corresponding read to make sure that reads and writes match
486
 
487
      Tree_Write_Int (Length);
488
 
489
      --  Conversion loop
490
      --    IP is index of next input character
491
      --    NC is number of non-compressible bytes saved up
492
 
493
      loop
494
         --  If input is completely processed, then we are all done
495
 
496
         if IP > Length then
497
            Write_Non_Compressed_Sequence;
498
            return;
499
         end if;
500
 
501
         --  Test for compressible sequence, must be at least three identical
502
         --  bytes in a row to be worthwhile compressing.
503
 
504
         if IP + 2 <= Length
505
           and then Data (IP) = Data (IP + 1)
506
           and then Data (IP) = Data (IP + 2)
507
         then
508
            Write_Non_Compressed_Sequence;
509
 
510
            --  Count length of new compression sequence
511
 
512
            C := 3;
513
            IP := IP + 3;
514
 
515
            while IP < Length
516
              and then Data (IP) = Data (IP - 1)
517
              and then C < Max_Count
518
            loop
519
               C := C + 1;
520
               IP := IP + 1;
521
            end loop;
522
 
523
            --  Output compression sequence
524
 
525
            if Data (IP - 1) = 0 then
526
               if Debug_Flag_Tree then
527
                  Write_Str ("==>    zeroes:        ");
528
                  Write_Int (Int (C));
529
                  Write_Str (", starting at ");
530
                  Write_Int (IP - Int (C));
531
                  Write_Eol;
532
               end if;
533
 
534
               Write_Byte (C_Zeros + C);
535
 
536
            elsif Data (IP - 1) = Character'Pos (' ') then
537
               if Debug_Flag_Tree then
538
                  Write_Str ("==>    spaces:        ");
539
                  Write_Int (Int (C));
540
                  Write_Str (", starting at ");
541
                  Write_Int (IP - Int (C));
542
                  Write_Eol;
543
               end if;
544
 
545
               Write_Byte (C_Spaces + C);
546
 
547
            else
548
               if Debug_Flag_Tree then
549
                  Write_Str ("==>    other char:    ");
550
                  Write_Int (Int (C));
551
                  Write_Str (" (");
552
                  Write_Int (Int (Data (IP - 1)));
553
                  Write_Char (')');
554
                  Write_Str (", starting at ");
555
                  Write_Int (IP - Int (C));
556
                  Write_Eol;
557
               end if;
558
 
559
               Write_Byte (C_Repeat + C);
560
               Write_Byte (Data (IP - 1));
561
            end if;
562
 
563
         --  No compression possible here
564
 
565
         else
566
            --  Output non-compressed sequence if at maximum length
567
 
568
            if NC = Max_Count then
569
               Write_Non_Compressed_Sequence;
570
            end if;
571
 
572
            NC := NC + 1;
573
            IP := IP + 1;
574
         end if;
575
      end loop;
576
 
577
   end Tree_Write_Data;
578
 
579
   ---------------------------
580
   -- Tree_Write_Initialize --
581
   ---------------------------
582
 
583
   procedure Tree_Write_Initialize (Desc : File_Descriptor) is
584
   begin
585
      Bufn := 0;
586
      Tree_FD := Desc;
587
      Set_Standard_Error;
588
      Debug_Flag_Tree := Debug_Flag_5;
589
   end Tree_Write_Initialize;
590
 
591
   --------------------
592
   -- Tree_Write_Int --
593
   --------------------
594
 
595
   procedure Tree_Write_Int (N : Int) is
596
      N_Bytes : constant Int_Bytes := To_Int_Bytes (N);
597
 
598
   begin
599
      if Debug_Flag_Tree then
600
         Write_Str ("==> transmitting Int = ");
601
         Write_Int (N);
602
         Write_Eol;
603
      end if;
604
 
605
      for J in 1 .. 4 loop
606
         Write_Byte (N_Bytes (J));
607
      end loop;
608
   end Tree_Write_Int;
609
 
610
   --------------------
611
   -- Tree_Write_Str --
612
   --------------------
613
 
614
   procedure Tree_Write_Str (S : String_Ptr) is
615
   begin
616
      Tree_Write_Int (S'Length);
617
      Tree_Write_Data (S (1)'Address, S'Length);
618
   end Tree_Write_Str;
619
 
620
   --------------------------
621
   -- Tree_Write_Terminate --
622
   --------------------------
623
 
624
   procedure Tree_Write_Terminate is
625
   begin
626
      if Bufn > 0 then
627
         Write_Buffer;
628
      end if;
629
   end Tree_Write_Terminate;
630
 
631
   ------------------
632
   -- Write_Buffer --
633
   ------------------
634
 
635
   procedure Write_Buffer is
636
   begin
637
      if Integer (Bufn) = Write (Tree_FD, Buf'Address, Integer (Bufn)) then
638
         Bufn := 0;
639
 
640
      else
641
         Set_Standard_Error;
642
         Write_Str ("fatal error: disk full");
643
         OS_Exit (2);
644
      end if;
645
   end Write_Buffer;
646
 
647
   ----------------
648
   -- Write_Byte --
649
   ----------------
650
 
651
   procedure Write_Byte (B : Byte) is
652
   begin
653
      Bufn := Bufn + 1;
654
      Buf (Bufn) := B;
655
 
656
      if Bufn = Buflen then
657
         Write_Buffer;
658
      end if;
659
   end Write_Byte;
660
 
661
end Tree_IO;

powered by: WebSVN 2.1.0

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