1 /*********************************************************************
3 Gazelle: a system for building fast, reusable parsers
7 This file contains routines for reading files in Bitcode format.
8 It is a stream interface -- the stream keeps only one record in
9 memory at a time, and is designed to have a very small memory
12 Copyright (c) 2007 Joshua Haberman. See LICENSE for details.
14 *********************************************************************/
16 #include "bc_read_stream.h"
18 #define OP_ENCODING_FIXED 1
19 #define OP_ENCODING_VBR 2
20 #define OP_ENCODING_ARRAY 3
21 #define OP_ENCODING_CHAR6 4
23 #define ABBREV_ID_END_BLOCK 0
24 #define ABBREV_ID_ENTER_SUBBLOCK 1
25 #define ABBREV_ID_DEFINE_ABBREV 2
26 #define ABBREV_ID_UNABBREV_RECORD 3
28 #define STDBLOCK_BLOCKINFO 0
30 #define BLOCKINFO_BLOCK_SETBID 1
32 #define RESIZE_ARRAY_IF_NECESSARY(ptr, size, desired_size) \
33 if(size < desired_size) \
36 ptr = realloc(ptr, size*sizeof(*ptr)); \
45 int num_abbreviations
;
46 int size_abbreviations
;
47 struct blockinfo_abbrev
{
49 struct abbrev_operand
*operands
;
53 struct stream_stack_entry
56 struct block_metadata
{
64 int first_operand_offset
;
78 long long literal_value
;
80 unsigned char encoding
;
93 /* Values for the stream */
101 struct stream_stack_entry
*old_block_metadata
;
103 /* Values for the current block */
106 struct stream_stack_entry
*block_metadata
;
107 struct blockinfo
*blockinfo
;
109 /* Values for the current record */
110 enum RecordType record_type
;
112 /* - for data records */
114 int current_record_size
;
115 int current_record_offset
;
117 uint64_t *record_buf
;
119 /* - for StartBlock records */
123 /* - for DefineAbbrev records */
124 int record_size_abbrev
;
125 int record_num_abbrev
;
126 struct abbrev_operand
*record_abbrev_operands
;
129 /* The stream stack */
130 int stream_stack_size
;
131 int stream_stack_len
;
132 struct stream_stack_entry
*stream_stack
;
134 int abbrev_operands_size
;
135 int abbrev_operands_len
;
136 struct abbrev_operand
*abbrev_operands
;
138 /* Data about blockinfo records we have encountered */
141 struct blockinfo
*blockinfos
;
145 void print_abbrev(struct abbrev_operand *operands, int num_operands)
147 printf("Abbrev: num_operands=%d\n", num_operands);
148 for(int i = 0; i < num_operands; i++)
150 struct abbrev_operand *o = &operands[i];
151 if(o->type == Literal)
153 printf(" Literal value: %llu\n", o->o.literal_value);
155 else if(o->type == EncodingInfo)
157 printf(" EncodingInfo: encoding=%u, value=%d\n", o->o.encoding_info.encoding,
158 o->o.encoding_info.value);
163 void dump_stack(struct bc_read_stream *s)
165 printf("Stream stack: %d entries\n", s->stream_stack_len);
166 for(int i = 0; i < s->stream_stack_len; i++)
169 struct stream_stack_entry *e = &s->stream_stack[i];
170 if(e->type == Abbreviation)
172 print_abbrev(s->abbrev_operands + e->e.abbrev.first_operand_offset, e->e.abbrev.num_operands);
174 else if(e->type == BlockMetadata)
176 printf("BlockMetadata: abbrev_len=%d, block_id=%d\n", e->e.block_metadata.abbrev_len,
177 e->e.block_metadata.block_id);
182 void dump_blockinfo(struct blockinfo *bi)
186 printf("Blockinfo! BlockID: %u, Abbrevs:\n", bi->block_id);
187 for(int i = 0; i < bi->num_abbreviations; i++)
188 print_abbrev(bi->abbreviations[i].operands, bi->abbreviations[i].num_operands);
193 static int refill_next_bits(struct bc_read_stream
*stream
);
194 struct bc_read_stream
*bc_read_stream_init();
196 struct bc_read_stream
*bc_rs_open_mem(const char *data
)
198 struct bc_read_stream
*stream
= bc_read_stream_init();
199 stream
->inmem
= (unsigned char *)data
;
200 refill_next_bits(stream
);
204 struct bc_read_stream
*bc_rs_open_file(const char *filename
)
206 FILE *infile
= fopen(filename
, "r");
214 int ret
= fread(magic
, 4, 1, infile
);
215 if(ret
< 1 || magic
[0] != 'B' || magic
[1] != 'C')
221 struct bc_read_stream
*stream
= bc_read_stream_init();
222 stream
->infile
= infile
;
223 refill_next_bits(stream
);
227 struct bc_read_stream
*bc_read_stream_init()
229 /* TODO: give the application a way to get the app-specific magic number */
231 struct bc_read_stream
*stream
= malloc(sizeof(*stream
));
232 stream
->infile
= NULL
;
233 stream
->stream_err
= 0;
235 stream
->next_bits
= 0;
236 stream
->num_next_bits
= 0;
237 stream
->stream_offset
= 0;
239 stream
->abbrev_len
= 2; /* its initial value according to the spec */
240 stream
->num_abbrevs
= 0;
242 stream
->stream_stack_size
= 8; /* enough for a few levels of nesting and a few abbrevs */
243 stream
->stream_stack
= malloc(stream
->stream_stack_size
*sizeof(*stream
->stream_stack
));
245 /* we create an outermose stack frame -- this exists mostly to store
246 * the abbrev length of the outermost scope, and to store a bogus
247 * block_id so that we'll never find a blockinfo for the outer scope */
248 stream
->stream_stack_len
= 1;
249 stream
->block_metadata
= &stream
->stream_stack
[0];
250 stream
->block_metadata
->type
= BlockMetadata
;
251 stream
->block_metadata
->e
.block_metadata
.abbrev_len
= stream
->abbrev_len
;
252 stream
->block_metadata
->e
.block_metadata
.block_id
= -1;
254 stream
->record_type
= DataRecord
; /* anything besides Eof */
256 stream
->abbrev_operands_size
= 8;
257 stream
->abbrev_operands_len
= 0;
258 stream
->abbrev_operands
= malloc(stream
->abbrev_operands_size
*sizeof(*stream
->abbrev_operands
));
260 stream
->blockinfo_size
= 8;
261 stream
->blockinfo_len
= 0;
262 stream
->blockinfos
= malloc(stream
->blockinfo_size
*sizeof(*stream
->blockinfos
));
264 stream
->record_buf_size
= 8;
265 stream
->record_buf
= malloc(stream
->record_buf_size
*sizeof(*stream
->record_buf
));
267 stream
->record_size_abbrev
= 8;
268 stream
->record_abbrev_operands
= malloc(stream
->record_size_abbrev
*sizeof(*stream
->record_abbrev_operands
));
273 void bc_rs_close_stream(struct bc_read_stream
*stream
)
275 free(stream
->record_abbrev_operands
);
276 free(stream
->record_buf
);
277 free(stream
->abbrev_operands
);
278 free(stream
->stream_stack
);
280 for(int i
= 0; i
< stream
->blockinfo_len
; i
++)
282 for(int j
= 0; j
< stream
->blockinfos
[i
].num_abbreviations
; j
++)
284 free(stream
->blockinfos
[i
].abbreviations
[j
].operands
);
286 free(stream
->blockinfos
[i
].abbreviations
);
288 free(stream
->blockinfos
);
291 fclose(stream
->infile
);
295 uint64_t bc_rs_read_64(struct bc_read_stream
*stream
, int i
)
297 if(i
> stream
->current_record_size
)
299 stream
->stream_err
|= BITCODE_ERR_NO_SUCH_VALUE
;
304 return stream
->record_buf
[i
];
309 #define GETTER_FUNC(type, bits) \
310 type bc_rs_read_ ## bits (struct bc_read_stream *stream, int i) \
312 uint64_t val = bc_rs_read_64(stream, i); \
313 if(stream->record_buf[i] > ((1ULL << bits) - 1)) \
315 stream->stream_err |= BITCODE_ERR_VALUE_TOO_LARGE; \
324 GETTER_FUNC(uint8_t, 8)
325 GETTER_FUNC(uint16_t, 16)
326 GETTER_FUNC(uint32_t, 32)
328 #define NEXT_GETTER_FUNC(type, bits) \
329 type bc_rs_read_next_ ## bits (struct bc_read_stream *stream) \
331 return bc_rs_read_ ## bits(stream, stream->current_record_offset++); \
334 NEXT_GETTER_FUNC(uint8_t, 8)
335 NEXT_GETTER_FUNC(uint16_t, 16)
336 NEXT_GETTER_FUNC(uint32_t, 32)
337 NEXT_GETTER_FUNC(uint64_t, 64)
339 static int refill_next_bits(struct bc_read_stream
*stream
)
341 unsigned char buf
[4];
343 stream
->stream_offset
+= 4;
347 int ret
= fread(buf
, 4, 1, stream
->infile
);
350 //if(feof(stream->infile))
351 // stream->record_type = Eof;
353 if(ferror(stream
->infile
))
354 stream
->stream_err
|= BITCODE_ERR_IO
;
361 memcpy(buf
, stream
->inmem
+ stream
->stream_offset
, 4);
364 stream
->next_bits
= buf
[0] | (buf
[1] << 8) | (buf
[2] << 16) | (buf
[3] << 24);
365 stream
->num_next_bits
= 32;
370 #define LOW_BITS(bitfield, num_bits) (bitfield & (~0U >> (32-num_bits)))
372 static uint32_t read_fixed(struct bc_read_stream
*stream
, int num_bits
)
376 if(stream
->num_next_bits
>= num_bits
)
378 /* next_bits already contains all the bits we need -- take them */
379 ret
= LOW_BITS(stream
->next_bits
, num_bits
);
380 stream
->next_bits
>>= num_bits
;
381 stream
->num_next_bits
-= num_bits
;
385 /* we need all of next_bits, and then some */
386 ret
= stream
->next_bits
;
387 int bits_filled
= stream
->num_next_bits
;
388 int bits_left
= num_bits
- bits_filled
;
390 if(refill_next_bits(stream
) < 0) return 0;
392 /* take bits_left bits from the next_bits */
393 ret
|= LOW_BITS(stream
->next_bits
, bits_left
) << bits_filled
;
396 stream
->next_bits
>>= bits_left
;
398 stream
->next_bits
= 0;
400 stream
->num_next_bits
-= bits_left
;
403 if(stream
->num_next_bits
== 0)
405 /* We could defer this, but doing it now makes our stream_offset more accurate */
406 refill_next_bits(stream
);
412 static uint64_t read_fixed_64(struct bc_read_stream
*stream
, int num_bits
)
416 return read_fixed(stream
, num_bits
);
420 uint64_t ret
= read_fixed(stream
, 32);
421 return ret
| ((uint64_t)read_fixed(stream
, num_bits
-32) << 32);
425 static uint64_t read_vbr_64(struct bc_read_stream
*stream
, int bits
)
429 int continuation_bit
= 1 << (bits
-1);
430 int value_bits
= continuation_bit
- 1;
434 uint32_t next_bits
= read_fixed(stream
, bits
);
435 continues
= next_bits
& continuation_bit
;
436 val
|= (next_bits
& value_bits
) << read_bits
;
443 static uint32_t read_vbr(struct bc_read_stream
*stream
, int bits
)
445 uint64_t val
= read_vbr_64(stream
, bits
);
448 stream
->stream_err
|= BITCODE_ERR_CORRUPT_INPUT
;
453 return (uint32_t)val
;
457 static uint8_t decode_char6(int num
)
459 if(num
< 26) return 'a' + num
;
460 else if(num
< 52) return 'A' + (num
-26);
461 else if(num
< 62) return '0' + (num
-52);
462 else if(num
< 63) return '.';
466 /* This can handle any abbreviated type except for arrays */
467 static uint64_t read_abbrev_value(struct bc_read_stream
*stream
, struct abbrev_operand
*op
)
469 if(op
->type
== Literal
)
470 return op
->o
.literal_value
;
473 switch(op
->o
.encoding_info
.encoding
) {
474 case OP_ENCODING_FIXED
:
475 return read_fixed_64(stream
, op
->o
.encoding_info
.value
);
476 case OP_ENCODING_VBR
:
477 return read_vbr_64(stream
, op
->o
.encoding_info
.value
);
478 case OP_ENCODING_CHAR6
:
479 return decode_char6(read_fixed(stream
, 6));
481 stream
->stream_err
|= BITCODE_ERR_INTERNAL
;
487 static void append_value(struct bc_read_stream
*stream
, uint64_t val
)
489 RESIZE_ARRAY_IF_NECESSARY(stream
->record_buf
, stream
->record_buf_size
, stream
->current_record_size
+1);
490 stream
->record_buf
[stream
->current_record_size
++] = val
;
493 static void read_user_abbreviated_record(struct bc_read_stream
*stream
,
494 struct abbrev_operand
*ops
,
497 stream
->current_record_size
= 0;
499 for(int i
= 0; i
< num_operands
; i
++)
501 struct abbrev_operand
*op
= &ops
[i
];
503 if(op
->type
== EncodingInfo
&& op
->o
.encoding_info
.encoding
== OP_ENCODING_ARRAY
)
505 int num_elements
= read_vbr(stream
, 6);
507 for(int j
= 0; j
< num_elements
; j
++)
508 append_value(stream
, read_abbrev_value(stream
, &ops
[i
]));
512 uint64_t val
= read_abbrev_value(stream
, &ops
[i
]);
515 stream
->record_id
= val
;
519 append_value(stream
, val
);
525 static int read_abbrev_op(struct bc_read_stream
*stream
, struct abbrev_operand
*o
, int array_ok
)
527 int is_literal
= read_fixed(stream
, 1);
531 o
->o
.literal_value
= read_vbr(stream
, 8);
535 o
->type
= EncodingInfo
;
536 o
->o
.encoding_info
.encoding
= read_fixed(stream
, 3);
537 switch(o
->o
.encoding_info
.encoding
)
539 case OP_ENCODING_FIXED
:
540 case OP_ENCODING_VBR
:
541 o
->o
.encoding_info
.value
= read_vbr(stream
, 5);
544 case OP_ENCODING_ARRAY
:
545 if(!array_ok
) return -1;
548 case OP_ENCODING_CHAR6
:
556 void align_32_bits(struct bc_read_stream
*stream
)
558 if(stream
->num_next_bits
!= 32)
559 refill_next_bits(stream
);
562 struct blockinfo
*find_blockinfo(struct bc_read_stream
*stream
, int block_id
)
564 for(int i
= 0; i
< stream
->blockinfo_len
; i
++)
565 if(stream
->blockinfos
[i
].block_id
== block_id
)
566 return &stream
->blockinfos
[i
];
571 struct blockinfo
*find_or_create_blockinfo(struct bc_read_stream
*stream
, int block_id
)
573 struct blockinfo
*bi
= find_blockinfo(stream
, block_id
);
581 RESIZE_ARRAY_IF_NECESSARY(stream
->blockinfos
, stream
->blockinfo_size
, stream
->blockinfo_len
+1);
583 struct blockinfo
*new_bi
= &stream
->blockinfos
[stream
->blockinfo_len
++];
585 new_bi
->block_id
= block_id
;
586 new_bi
->num_abbreviations
= 0;
587 new_bi
->size_abbreviations
= 8;
588 new_bi
->abbreviations
= malloc(new_bi
->size_abbreviations
* sizeof(*new_bi
->abbreviations
));
594 static void pop_stack_frame(struct bc_read_stream
*stream
)
596 stream
->stream_stack_len
= stream
->block_metadata
- stream
->stream_stack
;
597 if(stream
->stream_stack_len
== 0)
599 stream
->record_type
= Eof
;
603 stream
->num_abbrevs
= 0;
604 stream
->block_metadata
--;
605 while(stream
->block_metadata
->type
== Abbreviation
)
607 stream
->num_abbrevs
++;
608 stream
->block_metadata
--;
611 stream
->abbrev_len
= stream
->block_metadata
->e
.block_metadata
.abbrev_len
;
612 stream
->block_id
= stream
->block_metadata
->e
.block_metadata
.block_id
;
613 stream
->blockinfo
= find_blockinfo(stream
, stream
->block_id
);
617 void bc_rs_next_record(struct bc_read_stream
*stream
)
619 /* don't attempt to read past eof */
620 if(stream
->record_type
== Eof
) return;
622 int abbrev_id
= read_fixed(stream
, stream
->abbrev_len
);
623 stream
->current_record_offset
= 0;
626 case ABBREV_ID_END_BLOCK
:
627 stream
->record_type
= EndBlock
;
628 stream
->old_block_metadata
= stream
->block_metadata
;
630 align_32_bits(stream
);
631 pop_stack_frame(stream
);
635 case ABBREV_ID_ENTER_SUBBLOCK
:
636 stream
->block_id
= read_vbr(stream
, 8);
637 stream
->abbrev_len
= read_vbr(stream
, 4);
638 align_32_bits(stream
);
639 stream
->block_len
= read_fixed(stream
, 32);
640 stream
->record_type
= StartBlock
;
642 RESIZE_ARRAY_IF_NECESSARY(stream
->stream_stack
, stream
->stream_stack_size
,
643 stream
->stream_stack_len
+1);
645 stream
->block_metadata
= &stream
->stream_stack
[stream
->stream_stack_len
++];
646 stream
->block_metadata
->type
= BlockMetadata
;
647 stream
->block_metadata
->e
.block_metadata
.block_id
= stream
->block_id
;
648 stream
->block_metadata
->e
.block_metadata
.abbrev_len
= stream
->abbrev_len
;
649 stream
->block_metadata
->e
.block_metadata
.block_offset
= stream
->stream_offset
;
650 stream
->block_metadata
->e
.block_metadata
.block_len
= stream
->block_len
;
652 //printf("++ Entering block id=%d, offset=%d\n", stream->block_id, stream->stream_offset);
654 stream
->blockinfo
= find_or_create_blockinfo(stream
, stream
->block_id
);
657 case ABBREV_ID_DEFINE_ABBREV
:
658 stream
->record_type
= DefineAbbrev
;
659 stream
->record_num_abbrev
= read_vbr(stream
, 5);
661 RESIZE_ARRAY_IF_NECESSARY(stream
->record_abbrev_operands
, stream
->record_size_abbrev
,
662 stream
->record_num_abbrev
);
664 for(int i
= 0; i
< stream
->record_num_abbrev
; i
++)
666 read_abbrev_op(stream
, &stream
->record_abbrev_operands
[i
], 0);
671 case ABBREV_ID_UNABBREV_RECORD
:
672 stream
->record_type
= DataRecord
;
673 stream
->record_id
= read_vbr(stream
, 6);
675 stream
->current_record_size
= read_vbr(stream
, 6);
677 RESIZE_ARRAY_IF_NECESSARY(stream
->record_buf
, stream
->record_buf_size
,
678 stream
->current_record_size
+1);
680 for(int i
= 0; i
< stream
->current_record_size
; i
++)
681 stream
->record_buf
[i
] = read_vbr(stream
, 6);
686 /* This must be a user-defined abbreviation. It could come from the
687 * blockinfo-defined abbreviations or abbreviations defined in this
689 stream
->record_type
= DataRecord
;
690 int user_abbrev_id
= abbrev_id
- 4;
691 int num_blockinfo_abbrevs
= stream
->blockinfo
? stream
->blockinfo
->num_abbreviations
: 0;
692 int block_abbrev_id
= user_abbrev_id
- num_blockinfo_abbrevs
;
693 if(user_abbrev_id
< num_blockinfo_abbrevs
)
695 struct blockinfo_abbrev
*a
= &stream
->blockinfo
->abbreviations
[user_abbrev_id
];
696 read_user_abbreviated_record(stream
, a
->operands
, a
->num_operands
);
698 else if(block_abbrev_id
< stream
->num_abbrevs
)
700 struct stream_stack_entry
*e
= stream
->block_metadata
+ block_abbrev_id
+ 1;
701 struct abbrev_operand
*o
= stream
->abbrev_operands
+ e
->e
.abbrev
.first_operand_offset
;
702 read_user_abbreviated_record(stream
, o
, e
->e
.abbrev
.num_operands
);
706 stream
->stream_err
|= BITCODE_ERR_CORRUPT_INPUT
;
713 struct record_info
bc_rs_next_data_record(struct bc_read_stream
*stream
)
717 bc_rs_next_record(stream
);
719 if(stream
->record_type
== DefineAbbrev
)
721 int num_ops
= stream
->record_num_abbrev
;
723 RESIZE_ARRAY_IF_NECESSARY(stream
->stream_stack
, stream
->stream_stack_size
,
724 stream
->stream_stack_len
+1);
725 RESIZE_ARRAY_IF_NECESSARY(stream
->abbrev_operands
, stream
->abbrev_operands_size
,
726 stream
->abbrev_operands_len
+num_ops
+1);
728 struct stream_stack_entry
*e
= &stream
->stream_stack
[stream
->stream_stack_len
++];
729 e
->type
= Abbreviation
;
730 e
->e
.abbrev
.first_operand_offset
= stream
->abbrev_operands_len
;
731 e
->e
.abbrev
.num_operands
= num_ops
;
732 struct abbrev_operand
*abbrev_operands
= &stream
->abbrev_operands
[stream
->abbrev_operands_len
];
733 stream
->abbrev_operands_len
+= num_ops
;
735 for(int i
= 0; i
< num_ops
; i
++)
736 abbrev_operands
[i
] = stream
->record_abbrev_operands
[i
];
738 stream
->num_abbrevs
++;
740 else if(stream
->record_type
== StartBlock
&& stream
->block_id
== STDBLOCK_BLOCKINFO
)
742 /* The first record must be a SETBID record */
743 bc_rs_next_record(stream
);
744 struct blockinfo
*bi
= NULL
;
748 if(stream
->record_type
== EndBlock
)
752 else if(stream
->record_type
== Err
|| stream
->record_type
== Eof
)
754 struct record_info ri
;
755 ri
.record_type
= stream
->record_type
;
759 else if(stream
->record_type
== DataRecord
)
761 if(stream
->record_id
== BLOCKINFO_BLOCK_SETBID
)
763 if(stream
->current_record_size
!= 1)
766 stream
->stream_err
|= BITCODE_ERR_CORRUPT_INPUT
;
768 bi
= find_or_create_blockinfo(stream
, stream
->record_buf
[0]);
771 else if(stream
->record_type
== DefineAbbrev
)
777 stream
->stream_err
|= BITCODE_ERR_CORRUPT_INPUT
;
780 RESIZE_ARRAY_IF_NECESSARY(bi
->abbreviations
,
781 bi
->size_abbreviations
, bi
->num_abbreviations
+1);
783 struct blockinfo_abbrev
*abbrev
= &bi
->abbreviations
[bi
->num_abbreviations
++];
784 abbrev
->num_operands
= stream
->record_num_abbrev
;
785 abbrev
->operands
= malloc(sizeof(*abbrev
->operands
) * abbrev
->num_operands
);
786 for(int i
= 0; i
< abbrev
->num_operands
; i
++)
787 abbrev
->operands
[i
] = stream
->record_abbrev_operands
[i
];
790 bc_rs_next_record(stream
);
796 struct record_info ri
;
797 ri
.record_type
= stream
->record_type
;
800 if(ri
.record_type
== StartBlock
) ri
.id
= stream
->block_id
;
801 else if(ri
.record_type
== DataRecord
) ri
.id
= stream
->record_id
;
808 int bc_rs_get_error(struct bc_read_stream
*stream
)
810 return stream
->stream_err
;
813 int bc_rs_get_record_size(struct bc_read_stream
*stream
)
815 return stream
->current_record_size
;
818 int bc_rs_get_remaining_record_size(struct bc_read_stream
*stream
)
820 return stream
->current_record_size
- stream
->current_record_offset
;
823 void bc_rs_skip_block(struct bc_read_stream
*stream
)
825 int offset
= stream
->block_metadata
->e
.block_metadata
.block_offset
+
826 (stream
->block_metadata
->e
.block_metadata
.block_len
* 4);
829 fseek(stream
->infile
, offset
, SEEK_SET
);
831 stream
->stream_offset
= offset
-4;
832 refill_next_bits(stream
);
833 pop_stack_frame(stream
);
836 void bc_rs_rewind_block(struct bc_read_stream
*stream
)
838 if(stream
->record_type
== EndBlock
)
840 stream
->num_abbrevs
= stream
->old_block_metadata
- stream
->block_metadata
- 1;
841 stream
->block_metadata
= stream
->old_block_metadata
;
842 stream
->abbrev_len
= stream
->block_metadata
->e
.block_metadata
.abbrev_len
;
843 stream
->block_id
= stream
->block_metadata
->e
.block_metadata
.block_id
;
844 stream
->blockinfo
= find_or_create_blockinfo(stream
, stream
->block_id
);
845 stream
->stream_stack_len
= stream
->block_metadata
- stream
->stream_stack
+ 1;
848 int offset
= stream
->block_metadata
->e
.block_metadata
.block_offset
;
851 fseek(stream
->infile
, offset
, SEEK_SET
);
853 stream
->stream_offset
= offset
-4;
854 refill_next_bits(stream
);
855 align_32_bits(stream
);
860 * c-file-style: "bsd"
862 * indent-tabs-mode: nil