1 /*
2 Copyright (C) 2011-2015, Parrot Foundation.
3 
4 =head1 NAME
5 
6 src/packfile/segments.c - Segment Handling Routines
7 
8 =head1 DESCRIPTION
9 
10 Functions in this file represent behaviors for different PackFile segments.
11 
12 =cut
13 
14 */
15 
16 /* HEADERIZER HFILE: include/parrot/packfile.h */
17 
18 #include "parrot/parrot.h"
19 #include "pf_private.h"
20 #include "pmc/pmc_parrotlibrary.h"
21 #include "segments.str"
22 
23 /* HEADERIZER BEGIN: static */
24 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
25 
26 static void annotations_destroy(PARROT_INTERP,
27     ARGMOD(PackFile_Segment *seg))
28         __attribute__nonnull__(1)
29         __attribute__nonnull__(2)
30         FUNC_MODIFIES(*seg);
31 
32 static void annotations_dump(PARROT_INTERP,
33     ARGIN(const PackFile_Segment *seg))
34         __attribute__nonnull__(1)
35         __attribute__nonnull__(2);
36 
37 PARROT_CANNOT_RETURN_NULL
38 static PackFile_Segment * annotations_new(PARROT_INTERP)
39         __attribute__nonnull__(1);
40 
41 PARROT_WARN_UNUSED_RESULT
42 PARROT_CANNOT_RETURN_NULL
43 static opcode_t * annotations_pack(PARROT_INTERP,
44     ARGIN(PackFile_Segment *seg),
45     ARGOUT(opcode_t *cursor))
46         __attribute__nonnull__(2)
47         __attribute__nonnull__(3)
48         FUNC_MODIFIES(*cursor);
49 
50 PARROT_WARN_UNUSED_RESULT
51 PARROT_PURE_FUNCTION
52 static size_t annotations_packed_size(PARROT_INTERP,
53     ARGMOD(PackFile_Segment *seg))
54         __attribute__nonnull__(2)
55         FUNC_MODIFIES(*seg);
56 
57 PARROT_CANNOT_RETURN_NULL
58 static const opcode_t * annotations_unpack(PARROT_INTERP,
59     ARGMOD(PackFile_Segment *seg),
60     ARGIN(const opcode_t *cursor))
61         __attribute__nonnull__(1)
62         __attribute__nonnull__(2)
63         __attribute__nonnull__(3)
64         FUNC_MODIFIES(*seg);
65 
66 static void byte_code_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
67         __attribute__nonnull__(1)
68         __attribute__nonnull__(2)
69         FUNC_MODIFIES(*self);
70 
71 PARROT_WARN_UNUSED_RESULT
72 PARROT_CANNOT_RETURN_NULL
73 static PackFile_Segment * byte_code_new(PARROT_INTERP)
74         __attribute__nonnull__(1);
75 
76 PARROT_WARN_UNUSED_RESULT
77 PARROT_CANNOT_RETURN_NULL
78 static opcode_t * byte_code_pack(PARROT_INTERP,
79     ARGMOD(PackFile_Segment *self),
80     ARGOUT(opcode_t *cursor))
81         __attribute__nonnull__(2)
82         __attribute__nonnull__(3)
83         FUNC_MODIFIES(*self)
84         FUNC_MODIFIES(*cursor);
85 
86 PARROT_WARN_UNUSED_RESULT
87 PARROT_PURE_FUNCTION
88 static size_t byte_code_packed_size(PARROT_INTERP,
89     ARGMOD(PackFile_Segment *self))
90         __attribute__nonnull__(2)
91         FUNC_MODIFIES(*self);
92 
93 PARROT_WARN_UNUSED_RESULT
94 PARROT_CANNOT_RETURN_NULL
95 static const opcode_t * byte_code_unpack(PARROT_INTERP,
96     ARGMOD(PackFile_Segment *self),
97     ARGIN(const opcode_t *cursor))
98         __attribute__nonnull__(1)
99         __attribute__nonnull__(2)
100         __attribute__nonnull__(3)
101         FUNC_MODIFIES(*self);
102 
103 static void const_clear(PARROT_INTERP, ARGMOD(PackFile_ConstTable *self))
104         __attribute__nonnull__(1)
105         __attribute__nonnull__(2)
106         FUNC_MODIFIES(*self);
107 
108 static void const_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
109         __attribute__nonnull__(1)
110         __attribute__nonnull__(2)
111         FUNC_MODIFIES(*self);
112 
113 PARROT_MALLOC
114 PARROT_CANNOT_RETURN_NULL
115 static PackFile_Segment * const_new(PARROT_INTERP)
116         __attribute__nonnull__(1);
117 
118 PARROT_WARN_UNUSED_RESULT
119 PARROT_CAN_RETURN_NULL
120 static const opcode_t * const_unpack(PARROT_INTERP,
121     ARGMOD(PackFile_Segment *seg),
122     ARGIN(const opcode_t *cursor))
123         __attribute__nonnull__(1)
124         __attribute__nonnull__(2)
125         __attribute__nonnull__(3)
126         FUNC_MODIFIES(*seg);
127 
128 PARROT_WARN_UNUSED_RESULT
129 PARROT_CANNOT_RETURN_NULL
130 static PMC * const_unpack_pmc(PARROT_INTERP,
131     ARGIN(PackFile_ConstTable *constt),
132     ARGIN(const opcode_t **cursor))
133         __attribute__nonnull__(1)
134         __attribute__nonnull__(2)
135         __attribute__nonnull__(3);
136 
137 static void default_destroy(PARROT_INTERP,
138     ARGFREE_NOTNULL(PackFile_Segment *self))
139         __attribute__nonnull__(1)
140         __attribute__nonnull__(2);
141 
142 static void default_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
143         __attribute__nonnull__(1)
144         __attribute__nonnull__(2);
145 
146 PARROT_WARN_UNUSED_RESULT
147 PARROT_CANNOT_RETURN_NULL
148 static opcode_t * default_pack(
149     ARGIN(const PackFile_Segment *self),
150     ARGOUT(opcode_t *dest))
151         __attribute__nonnull__(1)
152         __attribute__nonnull__(2)
153         FUNC_MODIFIES(*dest);
154 
155 PARROT_PURE_FUNCTION
156 PARROT_WARN_UNUSED_RESULT
157 static size_t default_packed_size(ARGIN(const PackFile_Segment *self))
158         __attribute__nonnull__(1);
159 
160 PARROT_WARN_UNUSED_RESULT
161 PARROT_CAN_RETURN_NULL
162 static const opcode_t * default_unpack(PARROT_INTERP,
163     ARGMOD(PackFile_Segment *self),
164     ARGIN(const opcode_t *cursor))
165         __attribute__nonnull__(1)
166         __attribute__nonnull__(2)
167         __attribute__nonnull__(3)
168         FUNC_MODIFIES(*self);
169 
170 static void directory_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
171         __attribute__nonnull__(1)
172         __attribute__nonnull__(2)
173         FUNC_MODIFIES(*self);
174 
175 static void directory_dump(PARROT_INTERP,
176     ARGIN(const PackFile_Segment *self))
177         __attribute__nonnull__(1)
178         __attribute__nonnull__(2);
179 
180 PARROT_WARN_UNUSED_RESULT
181 PARROT_CANNOT_RETURN_NULL
182 static PackFile_Segment * directory_new(PARROT_INTERP)
183         __attribute__nonnull__(1);
184 
185 PARROT_WARN_UNUSED_RESULT
186 PARROT_CANNOT_RETURN_NULL
187 static opcode_t * directory_pack(PARROT_INTERP,
188     ARGMOD(PackFile_Segment *self),
189     ARGOUT(opcode_t *cursor))
190         __attribute__nonnull__(1)
191         __attribute__nonnull__(2)
192         __attribute__nonnull__(3)
193         FUNC_MODIFIES(*self)
194         FUNC_MODIFIES(*cursor);
195 
196 PARROT_WARN_UNUSED_RESULT
197 static size_t directory_packed_size(PARROT_INTERP,
198     ARGMOD(PackFile_Segment *self))
199         __attribute__nonnull__(1)
200         __attribute__nonnull__(2)
201         FUNC_MODIFIES(*self);
202 
203 PARROT_CAN_RETURN_NULL
204 PARROT_WARN_UNUSED_RESULT
205 static const opcode_t * directory_unpack(PARROT_INTERP,
206     ARGMOD(PackFile_Segment *segp),
207     ARGIN(const opcode_t *cursor))
208         __attribute__nonnull__(1)
209         __attribute__nonnull__(2)
210         __attribute__nonnull__(3)
211         FUNC_MODIFIES(*segp);
212 
213 static void make_code_pointers(ARGMOD(PackFile_Segment *seg))
214         __attribute__nonnull__(1)
215         FUNC_MODIFIES(*seg);
216 
217 static void pf_debug_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
218         __attribute__nonnull__(1)
219         __attribute__nonnull__(2)
220         FUNC_MODIFIES(*self);
221 
222 static void pf_debug_dump(PARROT_INTERP,
223     ARGIN(const PackFile_Segment *self))
224         __attribute__nonnull__(1)
225         __attribute__nonnull__(2);
226 
227 PARROT_WARN_UNUSED_RESULT
228 PARROT_CANNOT_RETURN_NULL
229 static PackFile_Segment * pf_debug_new(PARROT_INTERP)
230         __attribute__nonnull__(1);
231 
232 PARROT_WARN_UNUSED_RESULT
233 PARROT_CANNOT_RETURN_NULL
234 static opcode_t * pf_debug_pack(PARROT_INTERP,
235     ARGMOD(PackFile_Segment *self),
236     ARGOUT(opcode_t *cursor))
237         __attribute__nonnull__(1)
238         __attribute__nonnull__(2)
239         __attribute__nonnull__(3)
240         FUNC_MODIFIES(*self)
241         FUNC_MODIFIES(*cursor);
242 
243 static size_t pf_debug_packed_size(PARROT_INTERP,
244     ARGMOD(PackFile_Segment *self))
245         __attribute__nonnull__(2)
246         FUNC_MODIFIES(*self);
247 
248 PARROT_WARN_UNUSED_RESULT
249 PARROT_CANNOT_RETURN_NULL
250 static const opcode_t * pf_debug_unpack(PARROT_INTERP,
251     ARGMOD(PackFile_Segment *self),
252     ARGIN(const opcode_t *cursor))
253         __attribute__nonnull__(1)
254         __attribute__nonnull__(2)
255         __attribute__nonnull__(3)
256         FUNC_MODIFIES(*self);
257 
258 static void pf_register_funcs(
259     ARGMOD(PackFile *pf),
260     UINTVAL type,
261     const PackFile_funcs funcs)
262         __attribute__nonnull__(1)
263         FUNC_MODIFIES(*pf);
264 
265 static void segment_init(
266     ARGOUT(PackFile_Segment *self),
267     ARGIN(PackFile *pf),
268     ARGIN(STRING *name))
269         __attribute__nonnull__(1)
270         __attribute__nonnull__(2)
271         __attribute__nonnull__(3)
272         FUNC_MODIFIES(*self);
273 
274 PARROT_WARN_UNUSED_RESULT
275 PARROT_CANNOT_RETURN_NULL
276 static PackFile_Segment * segment_new(PARROT_INTERP)
277         __attribute__nonnull__(1);
278 
279 static void sort_segs(ARGMOD(PackFile_Directory *dir))
280         __attribute__nonnull__(1)
281         FUNC_MODIFIES(*dir);
282 
283 #define ASSERT_ARGS_annotations_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
284        PARROT_ASSERT_ARG(interp) \
285     , PARROT_ASSERT_ARG(seg))
286 #define ASSERT_ARGS_annotations_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
287        PARROT_ASSERT_ARG(interp) \
288     , PARROT_ASSERT_ARG(seg))
289 #define ASSERT_ARGS_annotations_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
290        PARROT_ASSERT_ARG(interp))
291 #define ASSERT_ARGS_annotations_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
292        PARROT_ASSERT_ARG(seg) \
293     , PARROT_ASSERT_ARG(cursor))
294 #define ASSERT_ARGS_annotations_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
295        PARROT_ASSERT_ARG(seg))
296 #define ASSERT_ARGS_annotations_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
297        PARROT_ASSERT_ARG(interp) \
298     , PARROT_ASSERT_ARG(seg) \
299     , PARROT_ASSERT_ARG(cursor))
300 #define ASSERT_ARGS_byte_code_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
301        PARROT_ASSERT_ARG(interp) \
302     , PARROT_ASSERT_ARG(self))
303 #define ASSERT_ARGS_byte_code_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
304        PARROT_ASSERT_ARG(interp))
305 #define ASSERT_ARGS_byte_code_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
306        PARROT_ASSERT_ARG(self) \
307     , PARROT_ASSERT_ARG(cursor))
308 #define ASSERT_ARGS_byte_code_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
309        PARROT_ASSERT_ARG(self))
310 #define ASSERT_ARGS_byte_code_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
311        PARROT_ASSERT_ARG(interp) \
312     , PARROT_ASSERT_ARG(self) \
313     , PARROT_ASSERT_ARG(cursor))
314 #define ASSERT_ARGS_const_clear __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
315        PARROT_ASSERT_ARG(interp) \
316     , PARROT_ASSERT_ARG(self))
317 #define ASSERT_ARGS_const_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
318        PARROT_ASSERT_ARG(interp) \
319     , PARROT_ASSERT_ARG(self))
320 #define ASSERT_ARGS_const_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
321        PARROT_ASSERT_ARG(interp))
322 #define ASSERT_ARGS_const_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
323        PARROT_ASSERT_ARG(interp) \
324     , PARROT_ASSERT_ARG(seg) \
325     , PARROT_ASSERT_ARG(cursor))
326 #define ASSERT_ARGS_const_unpack_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
327        PARROT_ASSERT_ARG(interp) \
328     , PARROT_ASSERT_ARG(constt) \
329     , PARROT_ASSERT_ARG(cursor))
330 #define ASSERT_ARGS_default_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
331        PARROT_ASSERT_ARG(interp) \
332     , PARROT_ASSERT_ARG(self))
333 #define ASSERT_ARGS_default_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
334        PARROT_ASSERT_ARG(interp) \
335     , PARROT_ASSERT_ARG(self))
336 #define ASSERT_ARGS_default_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
337        PARROT_ASSERT_ARG(self) \
338     , PARROT_ASSERT_ARG(dest))
339 #define ASSERT_ARGS_default_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
340        PARROT_ASSERT_ARG(self))
341 #define ASSERT_ARGS_default_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
342        PARROT_ASSERT_ARG(interp) \
343     , PARROT_ASSERT_ARG(self) \
344     , PARROT_ASSERT_ARG(cursor))
345 #define ASSERT_ARGS_directory_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
346        PARROT_ASSERT_ARG(interp) \
347     , PARROT_ASSERT_ARG(self))
348 #define ASSERT_ARGS_directory_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
349        PARROT_ASSERT_ARG(interp) \
350     , PARROT_ASSERT_ARG(self))
351 #define ASSERT_ARGS_directory_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
352        PARROT_ASSERT_ARG(interp))
353 #define ASSERT_ARGS_directory_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
354        PARROT_ASSERT_ARG(interp) \
355     , PARROT_ASSERT_ARG(self) \
356     , PARROT_ASSERT_ARG(cursor))
357 #define ASSERT_ARGS_directory_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
358        PARROT_ASSERT_ARG(interp) \
359     , PARROT_ASSERT_ARG(self))
360 #define ASSERT_ARGS_directory_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
361        PARROT_ASSERT_ARG(interp) \
362     , PARROT_ASSERT_ARG(segp) \
363     , PARROT_ASSERT_ARG(cursor))
364 #define ASSERT_ARGS_make_code_pointers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
365        PARROT_ASSERT_ARG(seg))
366 #define ASSERT_ARGS_pf_debug_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
367        PARROT_ASSERT_ARG(interp) \
368     , PARROT_ASSERT_ARG(self))
369 #define ASSERT_ARGS_pf_debug_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
370        PARROT_ASSERT_ARG(interp) \
371     , PARROT_ASSERT_ARG(self))
372 #define ASSERT_ARGS_pf_debug_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
373        PARROT_ASSERT_ARG(interp))
374 #define ASSERT_ARGS_pf_debug_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
375        PARROT_ASSERT_ARG(interp) \
376     , PARROT_ASSERT_ARG(self) \
377     , PARROT_ASSERT_ARG(cursor))
378 #define ASSERT_ARGS_pf_debug_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
379        PARROT_ASSERT_ARG(self))
380 #define ASSERT_ARGS_pf_debug_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
381        PARROT_ASSERT_ARG(interp) \
382     , PARROT_ASSERT_ARG(self) \
383     , PARROT_ASSERT_ARG(cursor))
384 #define ASSERT_ARGS_pf_register_funcs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
385        PARROT_ASSERT_ARG(pf))
386 #define ASSERT_ARGS_segment_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
387        PARROT_ASSERT_ARG(self) \
388     , PARROT_ASSERT_ARG(pf) \
389     , PARROT_ASSERT_ARG(name))
390 #define ASSERT_ARGS_segment_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
391        PARROT_ASSERT_ARG(interp))
392 #define ASSERT_ARGS_sort_segs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
393        PARROT_ASSERT_ARG(dir))
394 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
395 /* HEADERIZER END: static */
396 
397 
398 /*
399 
400 =head2 PackFile Segment Functions
401 
402 =over 4
403 
404 =item C<INTVAL Parrot_pf_map_segments(PARROT_INTERP, const PackFile_Directory
405 *dir, PackFile_map_segments_func_t callback, void *user_data)>
406 
407 Calls the callback function C<callback> for each segment in the directory
408 C<dir> called. The pointer C<user_data> is included in each call.
409 
410 If a callback returns non-zero, segment processing stops, returning this value.
411 
412 =cut
413 
414 */
415 
416 PARROT_EXPORT
417 INTVAL
Parrot_pf_map_segments(PARROT_INTERP,ARGIN (const PackFile_Directory * dir),PackFile_map_segments_func_t callback,ARGIN_NULLOK (void * user_data))418 Parrot_pf_map_segments(PARROT_INTERP, ARGIN(const PackFile_Directory *dir),
419                        PackFile_map_segments_func_t callback,
420                        ARGIN_NULLOK(void *user_data))
421 {
422     ASSERT_ARGS(Parrot_pf_map_segments)
423     size_t i;
424 
425     for (i = 0; i < dir->num_segments; ++i) {
426         const INTVAL ret = callback(interp, dir->segments[i], user_data);
427         if (ret)
428             return ret;
429     }
430 
431     return 0;
432 }
433 
434 /*
435 
436 =item C<INTVAL PackFile_map_segments(PARROT_INTERP, const PackFile_Directory
437 *dir, PackFile_map_segments_func_t callback, void *user_data)>
438 
439 Deprecated: This function should not be exposed as a part of the public API.
440 See TT #2140 for details.
441 
442 =cut
443 
444 */
445 
446 PARROT_EXPORT
447 PARROT_DEPRECATED
448 INTVAL
PackFile_map_segments(PARROT_INTERP,ARGIN (const PackFile_Directory * dir),PackFile_map_segments_func_t callback,ARGIN_NULLOK (void * user_data))449 PackFile_map_segments(PARROT_INTERP, ARGIN(const PackFile_Directory *dir),
450                        PackFile_map_segments_func_t callback,
451                        ARGIN_NULLOK(void *user_data))
452 {
453     ASSERT_ARGS(PackFile_map_segments)
454     return Parrot_pf_map_segments(interp, dir, callback, user_data);
455 }
456 
457 /*
458 
459 =item C<void Parrot_pf_add_segment(PARROT_INTERP, PackFile_Directory *dir,
460 PackFile_Segment *seg)>
461 
462 Adds the Segment C<seg> to the directory C<dir>.  The PackFile becomes the
463 owner of the segment; it gets destroyed when the PackFile does.
464 
465 =cut
466 
467 */
468 
469 PARROT_EXPORT
470 void
Parrot_pf_add_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),ARGMOD (PackFile_Segment * seg))471 Parrot_pf_add_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
472         ARGMOD(PackFile_Segment *seg))
473 {
474     ASSERT_ARGS(Parrot_pf_add_segment)
475     dir->segments = mem_gc_realloc_n_typed_zeroed(interp, dir->segments,
476             dir->num_segments + 1, dir->num_segments, PackFile_Segment *);
477     dir->segments[dir->num_segments] = seg;
478     ++dir->num_segments;
479     seg->dir = dir;
480 
481     return;
482 }
483 
484 /*
485 
486 =item C<void PackFile_add_segment(PARROT_INTERP, PackFile_Directory *dir,
487 PackFile_Segment *seg)>
488 
489 Deprecated: Use C<Parrot_pf_add_segment> instead. TT #2140, GH #1170
490 
491 =cut
492 
493 */
494 
495 PARROT_EXPORT
496 PARROT_DEPRECATED
497 void
PackFile_add_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),ARGMOD (PackFile_Segment * seg))498 PackFile_add_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
499         ARGMOD(PackFile_Segment *seg))
500 {
501     ASSERT_ARGS(PackFile_add_segment)
502     Parrot_pf_add_segment(interp, dir, seg);
503 }
504 
505 /*
506 
507 =item C<PackFile_Segment * Parrot_pf_find_segment(PARROT_INTERP,
508 PackFile_Directory *dir, const STRING *name, int sub_dir)>
509 
510 Finds the segment with the name C<name> in the C<PackFile_Directory> if
511 C<sub_dir> is true, searches directories recursively.  The returned segment is
512 still owned by the C<PackFile>.
513 
514 =cut
515 
516 */
517 
518 PARROT_EXPORT
519 PARROT_WARN_UNUSED_RESULT
520 PARROT_CAN_RETURN_NULL
521 PackFile_Segment *
Parrot_pf_find_segment(PARROT_INTERP,ARGIN_NULLOK (PackFile_Directory * dir),ARGIN (const STRING * name),int sub_dir)522 Parrot_pf_find_segment(PARROT_INTERP, ARGIN_NULLOK(PackFile_Directory *dir),
523     ARGIN(const STRING *name), int sub_dir)
524 {
525     ASSERT_ARGS(Parrot_pf_find_segment)
526     size_t i;
527 
528     if (!dir)
529         return NULL;
530 
531     for (i = 0; i < dir->num_segments; ++i) {
532         PackFile_Segment *seg = dir->segments[i];
533 
534         if (!seg)
535             continue;
536 
537         if (STRING_equal(interp, seg->name, name))
538             return seg;
539 
540         if (sub_dir && seg->type == PF_DIR_SEG) {
541             seg = Parrot_pf_find_segment(interp,
542                     (PackFile_Directory *)seg, name, sub_dir);
543 
544             if (seg)
545                 return seg;
546         }
547     }
548 
549     return NULL;
550 }
551 
552 /*
553 
554 =item C<PackFile_Segment * PackFile_find_segment(PARROT_INTERP,
555 PackFile_Directory *dir, const STRING *name, int sub_dir)>
556 
557 Finds the segment with the name C<name> in the C<PackFile_Directory> if
558 C<sub_dir> is true, searches directories recursively.  The returned segment is
559 still owned by the C<PackFile>.
560 
561 Deprecated: Use C<Parrot_pf_find_segment> instead.
562 
563 =cut
564 
565 */
566 
567 PARROT_EXPORT
568 PARROT_WARN_UNUSED_RESULT
569 PARROT_CAN_RETURN_NULL
570 PARROT_DEPRECATED
571 PackFile_Segment *
PackFile_find_segment(PARROT_INTERP,ARGIN_NULLOK (PackFile_Directory * dir),ARGIN (const STRING * name),int sub_dir)572 PackFile_find_segment(PARROT_INTERP, ARGIN_NULLOK(PackFile_Directory *dir),
573     ARGIN(const STRING *name), int sub_dir)
574 {
575     ASSERT_ARGS(PackFile_find_segment)
576     return Parrot_pf_find_segment(interp, dir, name, sub_dir);
577 }
578 
579 /*
580 
581 =back
582 
583 =head2 Private PackFile Segment Methods
584 
585 =over 4
586 
587 =item C<static void const_clear(PARROT_INTERP, PackFile_ConstTable *self)>
588 
589 Clear the C<PackFile_ConstTable> C<self>.
590 
591 =cut
592 
593 */
594 
595 static void
const_clear(PARROT_INTERP,ARGMOD (PackFile_ConstTable * self))596 const_clear(PARROT_INTERP, ARGMOD(PackFile_ConstTable *self))
597 {
598     ASSERT_ARGS(const_clear)
599 
600     if (self->num.constants) {
601         mem_gc_free(interp, self->num.constants);
602         self->num.constants = NULL;
603     }
604 
605     if (self->str.constants) {
606         mem_gc_free(interp, self->str.constants);
607         self->str.constants = NULL;
608     }
609 
610     if (self->pmc.constants) {
611         mem_gc_free(interp, self->pmc.constants);
612         self->pmc.constants = NULL;
613     }
614 
615     if (self->string_hash) {
616         Parrot_hash_destroy(interp, self->string_hash);
617         self->string_hash = NULL;
618     }
619 
620     if (self->tag_map) {
621         mem_gc_free(interp, self->tag_map);
622         self->ntags = 0;
623     }
624 
625     return;
626 }
627 
628 
629 /*
630 
631 =item C<static const opcode_t * const_unpack(PARROT_INTERP, PackFile_Segment
632 *seg, const opcode_t *cursor)>
633 
634 Unpacks a PackFile ConstTable from a block of memory. The format is:
635 
636   opcode_t const_count
637   *  constants
638 
639 Returns cursor if everything is OK, else zero (0).
640 
641 =cut
642 
643 */
644 
645 PARROT_WARN_UNUSED_RESULT
646 PARROT_CAN_RETURN_NULL
647 static const opcode_t *
const_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * seg),ARGIN (const opcode_t * cursor))648 const_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *seg),
649              ARGIN(const opcode_t *cursor))
650 {
651     ASSERT_ARGS(const_unpack)
652     STRING              * const sub_str = CONST_STRING(interp, "Sub");
653     PackFile_ConstTable * const self    = (PackFile_ConstTable *)seg;
654     PackFile            * const pf      = seg->pf;
655     opcode_t                    i;
656 
657     const_clear(interp, self);
658 
659     self->num.const_count = PF_fetch_opcode(pf, &cursor);
660     self->str.const_count = PF_fetch_opcode(pf, &cursor);
661     self->pmc.const_count = PF_fetch_opcode(pf, &cursor);
662 
663     if (self->num.const_count) {
664         self->num.constants = mem_gc_allocate_n_zeroed_typed(interp,
665                                     self->num.const_count, FLOATVAL);
666         if (!self->num.constants)
667             goto err;
668     }
669 
670     if (self->str.const_count) {
671         self->str.constants = mem_gc_allocate_n_zeroed_typed(interp,
672                                     self->str.const_count, STRING *);
673         if (!self->str.constants)
674             goto err;
675     }
676 
677     if (self->pmc.const_count) {
678         self->pmc.constants = mem_gc_allocate_n_zeroed_typed(interp,
679                                     self->pmc.const_count, PMC *);
680         if (!self->pmc.constants)
681             goto err;
682     }
683 
684     for (i = 0; i < self->num.const_count; i++)
685         self->num.constants[i] = PF_fetch_number(pf, &cursor);
686 
687     for (i = 0; i < self->str.const_count; i++)
688         self->str.constants[i] = PF_fetch_string(interp, pf, &cursor);
689 
690     for (i = 0; i < self->pmc.const_count; i++)
691         self->pmc.constants[i] = const_unpack_pmc(interp, self, &cursor);
692 
693     for (i = 0; i < self->pmc.const_count; i++) {
694         /* XXX unpack returned the lists of all objects in the object graph
695          * must dereference the first object into the constant slot */
696         PMC      * const pmc  = self->pmc.constants[i]
697                               = VTABLE_get_pmc_keyed_int(interp, self->pmc.constants[i], 0);
698 
699         PObj_is_shared_SET(pmc); /* packfile constants will be shared among threads */
700 
701         /* magically place subs into namespace stashes
702          * XXX make this explicit with :load subs in PBC */
703         if (VTABLE_isa(interp, pmc, sub_str))
704             Parrot_ns_store_sub(interp, pmc);
705     }
706 
707     self->ntags = PF_fetch_opcode(pf, &cursor);
708     self->tag_map = mem_gc_allocate_n_zeroed_typed(interp, self->ntags, PackFile_ConstTagPair);
709     for (i = 0; i < self->ntags; i++) {
710         self->tag_map[i].tag_idx   = PF_fetch_opcode(pf, &cursor);
711         self->tag_map[i].const_idx = PF_fetch_opcode(pf, &cursor);
712     }
713 
714     return cursor;
715 
716   err:
717     Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_ALLOCATION_ERROR,
718         "const_unpack: Could not allocate memory for array");
719 }
720 
721 
722 /*
723 
724 =item C<static PackFile_Segment * const_new(PARROT_INTERP)>
725 
726 Returns a new C<PackFile_ConstTable> segment.
727 
728 =cut
729 
730 */
731 
732 PARROT_MALLOC
733 PARROT_CANNOT_RETURN_NULL
734 static PackFile_Segment *
const_new(PARROT_INTERP)735 const_new(PARROT_INTERP)
736 {
737     ASSERT_ARGS(const_new)
738     PackFile_ConstTable * const const_table =
739             mem_gc_allocate_zeroed_typed(interp, PackFile_ConstTable);
740 
741     return (PackFile_Segment *)const_table;
742 }
743 
744 
745 /*
746 
747 =item C<static void const_destroy(PARROT_INTERP, PackFile_Segment *self)>
748 
749 Destroys the C<PackFile_ConstTable> C<self>.
750 
751 =cut
752 
753 */
754 
755 static void
const_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))756 const_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
757 {
758     ASSERT_ARGS(const_destroy)
759     PackFile_ConstTable * const ct = (PackFile_ConstTable *)self;
760     const_clear(interp, ct);
761 }
762 
763 
764 /*
765 
766 =item C<static PMC * const_unpack_pmc(PARROT_INTERP, PackFile_ConstTable
767 *constt, const opcode_t **cursor)>
768 
769 Unpacks a constant PMC.
770 
771 =cut
772 
773 */
774 
775 PARROT_WARN_UNUSED_RESULT
776 PARROT_CANNOT_RETURN_NULL
777 static PMC *
const_unpack_pmc(PARROT_INTERP,ARGIN (PackFile_ConstTable * constt),ARGIN (const opcode_t ** cursor))778 const_unpack_pmc(PARROT_INTERP, ARGIN(PackFile_ConstTable *constt),
779         ARGIN(const opcode_t **cursor))
780 {
781     ASSERT_ARGS(const_unpack_pmc)
782     PackFile * const pf         = constt->base.pf;
783     PMC             *pmc;
784     /* thawing the PMC needs the real packfile in place */
785     PackFile_ByteCode * const cs_save = interp->code;
786     interp->code                      = pf->cur_cs;
787     pmc                               = Parrot_thaw_pbc(interp, constt, cursor);
788     /* restore code */
789     interp->code = cs_save;
790 
791     return pmc;
792 }
793 
794 
795 /*
796 
797 =item C<static PackFile_Segment * annotations_new(PARROT_INTERP)>
798 
799 Creates a new annotations segment structure.
800 
801 =cut
802 
803 */
804 
805 PARROT_CANNOT_RETURN_NULL
806 static PackFile_Segment *
annotations_new(PARROT_INTERP)807 annotations_new(PARROT_INTERP)
808 {
809     ASSERT_ARGS(annotations_new)
810     /* Allocate annotations structure; create it all zeroed, and we will
811      * allocate memory for each of the arrays on demand. */
812     PackFile_Annotations * const seg = mem_gc_allocate_zeroed_typed(interp,
813             PackFile_Annotations);
814     return (PackFile_Segment *) seg;
815 }
816 
817 /*
818 
819 =item C<static void annotations_destroy(PARROT_INTERP, PackFile_Segment *seg)>
820 
821 Frees all memory associated with an annotations segment.
822 
823 =cut
824 
825 */
826 
827 static void
annotations_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * seg))828 annotations_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *seg))
829 {
830     ASSERT_ARGS(annotations_destroy)
831     PackFile_Annotations * const self = (PackFile_Annotations *)seg;
832 
833     /* Free any keys. */
834     if (self->keys)
835         mem_gc_free(interp, self->keys);
836 
837     self->keys    = NULL;
838 }
839 
840 
841 /*
842 
843 =item C<static size_t annotations_packed_size(PARROT_INTERP, PackFile_Segment
844 *seg)>
845 
846 Computes the number of opcode_ts needed to store the passed annotations
847 segment.
848 
849 =cut
850 
851 */
852 
853 PARROT_WARN_UNUSED_RESULT
854 PARROT_PURE_FUNCTION
855 static size_t
annotations_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * seg))856 annotations_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *seg))
857 {
858     ASSERT_ARGS(annotations_packed_size)
859     const PackFile_Annotations * const self = (PackFile_Annotations *)seg;
860     return 1 + self->num_keys * 4;  /* keys and key count */
861 }
862 
863 
864 /*
865 
866 =item C<static opcode_t * annotations_pack(PARROT_INTERP, PackFile_Segment *seg,
867 opcode_t *cursor)>
868 
869 Packs this segment into bytecode.
870 
871 =cut
872 
873 */
874 
875 PARROT_WARN_UNUSED_RESULT
876 PARROT_CANNOT_RETURN_NULL
877 static opcode_t *
annotations_pack(SHIM_INTERP,ARGIN (PackFile_Segment * seg),ARGOUT (opcode_t * cursor))878 annotations_pack(SHIM_INTERP, ARGIN(PackFile_Segment *seg),
879         ARGOUT(opcode_t *cursor))
880 {
881     ASSERT_ARGS(annotations_pack)
882     const PackFile_Annotations * const self = (PackFile_Annotations *)seg;
883     INTVAL i;
884 
885     /* Write key count and any keys. */
886     *cursor++ = self->num_keys;
887 
888     for (i = 0; i < self->num_keys; ++i) {
889         const PackFile_Annotations_Key * const key = self->keys + i;
890         *cursor++ = key->name;
891         *cursor++ = key->type;
892         *cursor++ = key->start;
893         *cursor++ = key->len;
894     }
895 
896     return cursor;
897 }
898 
899 
900 /*
901 
902 =item C<static const opcode_t * annotations_unpack(PARROT_INTERP,
903 PackFile_Segment *seg, const opcode_t *cursor)>
904 
905 Unpacks this segment from the bytecode.
906 
907 =cut
908 
909 */
910 
911 PARROT_CANNOT_RETURN_NULL
912 static const opcode_t *
annotations_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * seg),ARGIN (const opcode_t * cursor))913 annotations_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *seg),
914         ARGIN(const opcode_t *cursor))
915 {
916     ASSERT_ARGS(annotations_unpack)
917     PackFile_Annotations * const self = (PackFile_Annotations *)seg;
918     PackFile_ByteCode    *code;
919     STRING               *code_name;
920     INTVAL               i, str_len;
921 
922     /* Unpack keys. */
923     self->num_keys = PF_fetch_opcode(seg->pf, &cursor);
924 
925     self->keys     = mem_gc_allocate_n_zeroed_typed(interp,
926             self->num_keys, PackFile_Annotations_Key);
927 
928     for (i = 0; i < self->num_keys; ++i) {
929         PackFile_Annotations_Key * const key = self->keys + i;
930         key->name  = PF_fetch_opcode(seg->pf, &cursor);
931         key->type  = (pf_ann_key_type_t)PF_fetch_opcode(seg->pf, &cursor);
932         key->start = PF_fetch_opcode(seg->pf, &cursor);
933         key->len   = PF_fetch_opcode(seg->pf, &cursor);
934     }
935 
936     /* Need to associate this segment with the applicable code segment. */
937     str_len     = Parrot_str_length(interp, self->base.name);
938     code_name   = STRING_substr(interp, self->base.name, 0, str_len - 4);
939     code        = (PackFile_ByteCode *)Parrot_pf_find_segment(interp,
940                                 self->base.dir, code_name, 0);
941 
942     if (!code || code->base.type != PF_BYTEC_SEG) {
943         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
944             "Code '%s' not found for annotations segment '%s'",
945             code_name, self->base.name);
946     }
947 
948     self->code        = code;
949     code->annotations = self;
950 
951     return cursor;
952 }
953 
954 
955 /*
956 
957 =item C<static void annotations_dump(PARROT_INTERP, const PackFile_Segment
958 *seg)>
959 
960 Produces a dump of the annotations segment.
961 
962 =cut
963 
964 */
965 
966 static void
annotations_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * seg))967 annotations_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *seg))
968 {
969     ASSERT_ARGS(annotations_dump)
970     const PackFile_Annotations * const self = (const PackFile_Annotations *)seg;
971     INTVAL                      i;
972     size_t                      j;
973 
974     default_dump_header(interp, (const PackFile_Segment *)self);
975 
976     /* Dump keys. */
977     Parrot_io_printf(interp, "\n  [\n");
978     for (i = 0; i < self->num_keys; ++i) {
979         const PackFile_Annotations_Key * const key = &self->keys[i];
980         const size_t                       key_end = key->start + key->len;
981         Parrot_io_printf(interp, "    #"INTVAL_FMT"\n    [\n", i);
982         Parrot_io_printf(interp, "        NAME => %Ss\n",
983                 self->code->const_table->str.constants[key->name]);
984         Parrot_io_printf(interp, "        TYPE => %s\n",
985                 key->type == PF_ANNOTATION_KEY_TYPE_INT ? "integer" :
986                 key->type == PF_ANNOTATION_KEY_TYPE_STR ? "string" :
987                 key->type == PF_ANNOTATION_KEY_TYPE_PMC ? "pmc" :
988                 "<ERROR>");
989         for (j = key->start; j < key_end; j++) {
990             Parrot_io_printf(interp, "      [\n");
991             Parrot_io_printf(interp, "          BYTECODE_OFFSET => %ld\n",
992                     self->base.data[j * 2 + ANN_ENTRY_OFF]);
993             Parrot_io_printf(interp, "          VALUE => %ld\n",
994                     self->base.data[j * 2 + ANN_ENTRY_VAL]);
995             Parrot_io_printf(interp, "      ],\n");
996         }
997         Parrot_io_printf(interp, "    ],\n");
998     }
999 
1000     Parrot_io_printf(interp, "  ],\n");
1001     Parrot_io_printf(interp, "],\n");
1002 }
1003 
1004 /*
1005 
1006 =item C<static void pf_register_funcs(PackFile *pf, UINTVAL type, const
1007 PackFile_funcs funcs)>
1008 
1009 Registers the C<pack>/C<unpack>/... functions for a packfile type.
1010 
1011 =cut
1012 
1013 */
1014 
1015 static void
pf_register_funcs(ARGMOD (PackFile * pf),UINTVAL type,const PackFile_funcs funcs)1016 pf_register_funcs(ARGMOD(PackFile *pf), UINTVAL type,
1017                         const PackFile_funcs funcs)
1018 {
1019     ASSERT_ARGS(pf_register_funcs)
1020     pf->PackFuncs[type] = funcs;
1021 }
1022 
1023 
1024 /*
1025 
1026 =item C<static const opcode_t * default_unpack(PARROT_INTERP, PackFile_Segment
1027 *self, const opcode_t *cursor)>
1028 
1029 Unpacks a PackFile given a cursor into PBC.  This is the default unpack.
1030 
1031 =cut
1032 
1033 */
1034 
1035 PARROT_WARN_UNUSED_RESULT
1036 PARROT_CAN_RETURN_NULL
1037 static const opcode_t *
default_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1038 default_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
1039 {
1040     ASSERT_ARGS(default_unpack)
1041     DECL_CONST_CAST_OF(opcode_t);
1042 
1043     self->op_count = PF_fetch_opcode(self->pf, &cursor);
1044     self->itype    = PF_fetch_opcode(self->pf, &cursor);
1045     self->id       = PF_fetch_opcode(self->pf, &cursor);
1046     self->size     = PF_fetch_opcode(self->pf, &cursor);
1047 
1048     if (self->size == 0)
1049         return cursor;
1050 
1051     /* if the packfile is mmap()ed just point to it if we don't
1052      * need any fetch transforms */
1053     if (self->pf->is_mmap_ped
1054     && !self->pf->need_endianize
1055     && !self->pf->need_wordsize) {
1056         self->data  = PARROT_const_cast(opcode_t *, cursor);
1057         cursor     += self->size;
1058         return cursor;
1059     }
1060 
1061     /* else allocate mem */
1062     self->data = mem_gc_allocate_n_typed(interp, self->size, opcode_t);
1063 
1064     if (!self->data) {
1065         Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_ALLOCATION_ERROR,
1066             "PackFile_unpack: Unable to allocate data memory");
1067     }
1068 
1069     if (!self->pf->need_endianize && !self->pf->need_wordsize) {
1070         memcpy(self->data, cursor, self->size * sizeof (opcode_t));
1071         cursor += self->size;
1072     }
1073     else {
1074         int i;
1075         for (i = 0; i < (int)self->size; i++)
1076             self->data[i] = PF_fetch_opcode(self->pf, &cursor);
1077     }
1078 
1079     return cursor;
1080 }
1081 
1082 
1083 /*
1084 
1085 =item C<void default_dump_header(PARROT_INTERP, const PackFile_Segment *self)>
1086 
1087 Dumps the header of a given PackFile_Segment.
1088 
1089 =cut
1090 
1091 */
1092 
1093 void
default_dump_header(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1094 default_dump_header(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1095 {
1096     ASSERT_ARGS(default_dump_header)
1097     Parrot_io_printf(interp, "%Ss => [ # offs 0x%x(%d)",
1098             self->name, (int)self->file_offset, (int)self->file_offset);
1099     Parrot_io_printf(interp, " = op_count %d, itype %d, id %d, size %d, ...",
1100             (int)self->op_count, (int)self->itype,
1101             (int)self->id, (int)self->size);
1102 }
1103 
1104 
1105 /*
1106 
1107 =item C<static void default_dump(PARROT_INTERP, const PackFile_Segment *self)>
1108 
1109 Dumps a PackFile_Segment.
1110 
1111 =cut
1112 
1113 */
1114 
1115 static void
default_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1116 default_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1117 {
1118     ASSERT_ARGS(default_dump)
1119     size_t i = self->data ? 0: self->file_offset + SEGMENT_HEADER_SIZE;
1120 
1121     default_dump_header(interp, self);
1122 
1123     if (i % 8)
1124         Parrot_io_printf(interp, "\n %04x:  ", (int) i);
1125 
1126     for (; i < (self->data ? self->size :
1127             self->file_offset + self->op_count); ++i) {
1128 
1129         if (i % 8 == 0)
1130             Parrot_io_printf(interp, "\n %04x:  ", (int) i);
1131 
1132         Parrot_io_printf(interp, "%08lx ", (unsigned long)
1133                 (self->data ? self->data[i] : self->pf->src[i]));
1134     }
1135 
1136     Parrot_io_printf(interp, "\n]\n");
1137 }
1138 
1139 
1140 /*
1141 
1142 =item C<void pf_register_standard_funcs(PackFile *pf)>
1143 
1144 Registers a PackFile's functions; called from within C<Parrot_pf_new()>.
1145 
1146 =cut
1147 
1148 */
1149 
1150 void
pf_register_standard_funcs(ARGMOD (PackFile * pf))1151 pf_register_standard_funcs(ARGMOD(PackFile *pf))
1152 {
1153     ASSERT_ARGS(pf_register_standard_funcs)
1154 
1155     static const PackFile_funcs dirf = {
1156         directory_new,
1157         directory_destroy,
1158         directory_packed_size,
1159         directory_pack,
1160         directory_unpack,
1161         directory_dump
1162     };
1163 
1164     static const PackFile_funcs defaultf = {
1165         segment_new,
1166         (PackFile_Segment_destroy_func_t)     NULL,
1167         (PackFile_Segment_packed_size_func_t) NULL,
1168         (PackFile_Segment_pack_func_t)        NULL,
1169         (PackFile_Segment_unpack_func_t)      NULL,
1170         default_dump
1171     };
1172 
1173     static const PackFile_funcs constf = {
1174         const_new,
1175         const_destroy,
1176         Parrot_pf_ConstTable_pack_size,
1177         Parrot_pf_ConstTable_pack,
1178         const_unpack,
1179         default_dump
1180     };
1181 
1182     static const PackFile_funcs bytef = {
1183         byte_code_new,
1184         byte_code_destroy,
1185         byte_code_packed_size,
1186         byte_code_pack,
1187         byte_code_unpack,
1188         default_dump
1189     };
1190 
1191     static const PackFile_funcs debugf = {
1192         pf_debug_new,
1193         pf_debug_destroy,
1194         pf_debug_packed_size,
1195         pf_debug_pack,
1196         pf_debug_unpack,
1197         pf_debug_dump
1198     };
1199 
1200     static const PackFile_funcs annotationf = {
1201         annotations_new,
1202         annotations_destroy,
1203         annotations_packed_size,
1204         annotations_pack,
1205         annotations_unpack,
1206         annotations_dump
1207     };
1208 
1209     pf_register_funcs(pf, PF_DIR_SEG,         dirf);
1210     pf_register_funcs(pf, PF_UNKNOWN_SEG,     defaultf);
1211     pf_register_funcs(pf, PF_CONST_SEG,       constf);
1212     pf_register_funcs(pf, PF_BYTEC_SEG,       bytef);
1213     pf_register_funcs(pf, PF_DEBUG_SEG,       debugf);
1214     pf_register_funcs(pf, PF_ANNOTATIONS_SEG, annotationf);
1215 
1216     return;
1217 }
1218 
1219 
1220 /*
1221 
1222 =back
1223 
1224 =head2 PackFile Segment Methods
1225 
1226 =over 4
1227 
1228 =item C<PackFile_Segment * Parrot_pf_new_segment(PARROT_INTERP,
1229 PackFile_Directory *dir, UINTVAL type, STRING *name, int add)>
1230 
1231 Creates a new segment in the given PackFile_Directory of the given C<type> with
1232 the given C<name>.  If C<add> is true, adds the segment to the directory.
1233 
1234 =cut
1235 
1236 */
1237 
1238 PARROT_EXPORT
1239 PARROT_WARN_UNUSED_RESULT
1240 PARROT_CANNOT_RETURN_NULL
1241 PackFile_Segment *
Parrot_pf_new_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),UINTVAL type,ARGIN (STRING * name),int add)1242 Parrot_pf_new_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
1243         UINTVAL type, ARGIN(STRING *name), int add)
1244 {
1245     ASSERT_ARGS(Parrot_pf_new_segment)
1246     PackFile * const                  pf  = dir->base.pf;
1247     const PackFile_Segment_new_func_t f   = pf->PackFuncs[type].new_seg;
1248     PackFile_Segment * const          seg = (f)(interp);
1249 
1250     segment_init(seg, pf, name);
1251     seg->type = type;
1252 
1253     if (add)
1254         Parrot_pf_add_segment(interp, dir, seg);
1255 
1256     return seg;
1257 }
1258 
1259 /*
1260 
1261 =item C<PackFile_Segment * PackFile_Segment_new_seg(PARROT_INTERP,
1262 PackFile_Directory *dir, UINTVAL type, STRING *name, int add)>
1263 
1264 Deprecated: Use C<Parrot_pf_new_segment> instead. GH #1122
1265 
1266 =cut
1267 
1268 */
1269 
1270 PARROT_EXPORT
1271 PARROT_DEPRECATED
1272 PARROT_WARN_UNUSED_RESULT
1273 PARROT_CANNOT_RETURN_NULL
1274 PackFile_Segment *
PackFile_Segment_new_seg(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),UINTVAL type,ARGIN (STRING * name),int add)1275 PackFile_Segment_new_seg(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
1276         UINTVAL type, ARGIN(STRING *name), int add)
1277 {
1278     ASSERT_ARGS(PackFile_Segment_new_seg)
1279     return Parrot_pf_new_segment(interp, dir, type, name, add);
1280 }
1281 
1282 /*
1283 
1284 =item C<void Parrot_pf_destroy_segment(PARROT_INTERP, PackFile_Segment *self)>
1285 
1286 Destroys the given PackFile_Segment.
1287 
1288 =cut
1289 
1290 */
1291 
1292 PARROT_EXPORT
1293 void
Parrot_pf_destroy_segment(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1294 Parrot_pf_destroy_segment(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1295 {
1296     ASSERT_ARGS(Parrot_pf_destroy_segment)
1297     const PackFile_Segment_destroy_func_t f =
1298         self->pf->PackFuncs[self->type].destroy;
1299 
1300     if (f)
1301         (f)(interp, self);
1302 
1303     /* destroy self after specific */
1304     default_destroy(interp, self);
1305 }
1306 
1307 /*
1308 
1309 =item C<void PackFile_Segment_destroy(PARROT_INTERP, PackFile_Segment *self)>
1310 
1311 Deprecated: Use C<Parrot_pf_destroy_segment> instead. See TT #2140
1312 
1313 =cut
1314 
1315 */
1316 
1317 PARROT_EXPORT
1318 PARROT_DEPRECATED
1319 void
PackFile_Segment_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1320 PackFile_Segment_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1321 {
1322     ASSERT_ARGS(PackFile_Segment_destroy)
1323     Parrot_pf_destroy_segment(interp, self);
1324 }
1325 
1326 /*
1327 
1328 =item C<size_t pf_segment_packed_size(PARROT_INTERP, PackFile_Segment *self)>
1329 
1330 Returns the size of the given segment, when packed, taking into account padding
1331 and alignment.
1332 
1333 =cut
1334 
1335 */
1336 
1337 size_t
pf_segment_packed_size(PARROT_INTERP,ARGIN (PackFile_Segment * self))1338 pf_segment_packed_size(PARROT_INTERP, ARGIN(PackFile_Segment *self))
1339 {
1340     ASSERT_ARGS(pf_segment_packed_size)
1341     size_t size                           = default_packed_size(self);
1342     const size_t align                    = 16 / sizeof (opcode_t);
1343     PackFile_Segment_packed_size_func_t f =
1344         self->pf->PackFuncs[self->type].packed_size;
1345 
1346     if (f)
1347         size += (f)(interp, self);
1348 
1349     /* pad/align it */
1350     if (align && size % align)
1351         size += (align - size % align);
1352 
1353     return size;
1354 }
1355 
1356 /*
1357 
1358 =item C<size_t PackFile_Segment_packed_size(PARROT_INTERP, PackFile_Segment
1359 *self)>
1360 
1361 Deprecated: Use C<pf_segment_packed_size> instead. Will not be exported anymore.
1362 See TT #2140
1363 
1364 =cut
1365 
1366 */
1367 
1368 PARROT_EXPORT
1369 PARROT_DEPRECATED
1370 size_t
PackFile_Segment_packed_size(PARROT_INTERP,ARGIN (PackFile_Segment * self))1371 PackFile_Segment_packed_size(PARROT_INTERP, ARGIN(PackFile_Segment *self))
1372 {
1373     ASSERT_ARGS(PackFile_Segment_packed_size)
1374     return pf_segment_packed_size(interp, self);
1375 }
1376 
1377 /*
1378 
1379 =item C<opcode_t * pf_segment_pack(PARROT_INTERP, PackFile_Segment *self,
1380 opcode_t *cursor)>
1381 
1382 Packs a PackFile_Segment, returning a cursor to the start of the results.
1383 
1384 =cut
1385 
1386 */
1387 
1388 PARROT_WARN_UNUSED_RESULT
1389 PARROT_CANNOT_RETURN_NULL
1390 opcode_t *
pf_segment_pack(PARROT_INTERP,ARGIN (PackFile_Segment * self),ARGIN (opcode_t * cursor))1391 pf_segment_pack(PARROT_INTERP, ARGIN(PackFile_Segment *self),
1392                 ARGIN(opcode_t *cursor))
1393 {
1394     ASSERT_ARGS(pf_segment_pack)
1395     /*const size_t align             = 16 / sizeof (opcode_t);*/
1396     PackFile_Segment_pack_func_t f =
1397         self->pf->PackFuncs[self->type].pack;
1398     opcode_t * old_cursor;          /* Used for filling padding with 0 */
1399 
1400     cursor = default_pack(self, cursor);
1401 
1402     if (f)
1403         cursor = (f)(interp, self, cursor);
1404 
1405     old_cursor = cursor;
1406     ALIGN_16(self->pf, cursor);
1407     /* fill padding with zeros */
1408     while (old_cursor != cursor)
1409         *old_cursor++ = 0;
1410 
1411     /*if (align && (cursor - self->pf->src) % align)
1412       cursor += align - (cursor - self->pf->src) % align;*/
1413 
1414     return cursor;
1415 }
1416 
1417 /*
1418 
1419 =item C<opcode_t * PackFile_Segment_pack(PARROT_INTERP, PackFile_Segment *self,
1420 opcode_t *cursor)>
1421 
1422 Deprecated: Use C<pf_segment_pack> instead. Will not be exported anymore.
1423 See GH #1122
1424 
1425 =cut
1426 
1427 */
1428 
1429 PARROT_EXPORT
1430 PARROT_DEPRECATED
1431 PARROT_WARN_UNUSED_RESULT
1432 PARROT_CANNOT_RETURN_NULL
1433 opcode_t *
PackFile_Segment_pack(PARROT_INTERP,ARGIN (PackFile_Segment * self),ARGIN (opcode_t * cursor))1434 PackFile_Segment_pack(PARROT_INTERP, ARGIN(PackFile_Segment *self),
1435         ARGIN(opcode_t *cursor))
1436 {
1437     ASSERT_ARGS(PackFile_Segment_pack)
1438     return pf_segment_pack(interp, self, cursor);
1439 }
1440 
1441 /*
1442 
1443 =item C<const opcode_t * pf_segment_unpack(PARROT_INTERP, PackFile_Segment
1444 *self, const opcode_t *cursor)>
1445 
1446 Unpacks a PackFile_Segment, returning a cursor to the results on success and
1447 NULL otherwise.
1448 
1449 All these functions call the related C<default_*> function.
1450 
1451 If a special is defined this gets called after.
1452 
1453 =cut
1454 
1455 */
1456 
1457 PARROT_WARN_UNUSED_RESULT
1458 PARROT_CAN_RETURN_NULL
1459 const opcode_t *
pf_segment_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1460 pf_segment_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self),
1461         ARGIN(const opcode_t *cursor))
1462 {
1463     ASSERT_ARGS(pf_segment_unpack)
1464     PackFile_Segment_unpack_func_t f = self->pf->PackFuncs[self->type].unpack;
1465     int offs;
1466     cursor = default_unpack(interp, self, cursor);
1467 
1468     if (!cursor)
1469         return NULL;
1470 
1471     if (f) {
1472         cursor = (f)(interp, self, cursor);
1473         if (!cursor)
1474             return NULL;
1475     }
1476 
1477     offs = OFFS(self->pf, cursor);
1478     offs += PAD_16_B(offs);
1479     cursor = self->pf->src + offs/(sizeof (opcode_t));
1480     return cursor;
1481 }
1482 
1483 /*
1484 
1485 =item C<const opcode_t * PackFile_Segment_unpack(PARROT_INTERP, PackFile_Segment
1486 *self, const opcode_t *cursor)>
1487 
1488 Deprecated: Use C<pf_segment_unpack> instead. Will not be exported anymore. See TT #2140
1489 See GH #1122
1490 
1491 =cut
1492 
1493 */
1494 
1495 PARROT_EXPORT
1496 PARROT_DEPRECATED
1497 PARROT_WARN_UNUSED_RESULT
1498 PARROT_CAN_RETURN_NULL
1499 const opcode_t *
PackFile_Segment_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1500 PackFile_Segment_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self),
1501         ARGIN(const opcode_t *cursor))
1502 {
1503     ASSERT_ARGS(PackFile_Segment_unpack)
1504     return pf_segment_unpack(interp, self, cursor);
1505 }
1506 
1507 /*
1508 
1509 =item C<void Parrot_pf_dump_segment(PARROT_INTERP, const PackFile_Segment
1510 *self)>
1511 
1512 Dumps the packfile segment C<self>.
1513 
1514 =cut
1515 
1516 */
1517 
1518 PARROT_EXPORT
1519 void
Parrot_pf_dump_segment(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1520 Parrot_pf_dump_segment(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1521 {
1522     ASSERT_ARGS(Parrot_pf_dump_segment)
1523     self->pf->PackFuncs[self->type].dump(interp, self);
1524 }
1525 
1526 /*
1527 
1528 =item C<void PackFile_Segment_dump(PARROT_INTERP, const PackFile_Segment *self)>
1529 
1530 Dumps the segment C<self>.
1531 
1532 Deprecated: Will not be exported anymore. GH #1170
1533 
1534 =cut
1535 
1536 */
1537 
1538 PARROT_EXPORT
1539 PARROT_DEPRECATED
1540 void
PackFile_Segment_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1541 PackFile_Segment_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1542 {
1543     ASSERT_ARGS(PackFile_Segment_dump)
1544     self->pf->PackFuncs[self->type].dump(interp, self);
1545 }
1546 
1547 /*
1548 
1549 =back
1550 
1551 =head2 Standard Directory Functions
1552 
1553 =over 4
1554 
1555 =item C<static PackFile_Segment * directory_new(PARROT_INTERP)>
1556 
1557 Returns a new C<PackFile_Directory> cast as a C<PackFile_Segment>.
1558 
1559 =cut
1560 
1561 */
1562 
1563 PARROT_WARN_UNUSED_RESULT
1564 PARROT_CANNOT_RETURN_NULL
1565 static PackFile_Segment *
directory_new(PARROT_INTERP)1566 directory_new(PARROT_INTERP)
1567 {
1568     ASSERT_ARGS(directory_new)
1569 
1570     return (PackFile_Segment *)mem_gc_allocate_zeroed_typed(interp, PackFile_Directory);
1571 }
1572 
1573 
1574 /*
1575 
1576 =item C<static void directory_dump(PARROT_INTERP, const PackFile_Segment *self)>
1577 
1578 Dumps the directory C<self>.
1579 
1580 =cut
1581 
1582 */
1583 
1584 static void
directory_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1585 directory_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1586 {
1587     ASSERT_ARGS(directory_dump)
1588     const PackFile_Directory * const dir = (const PackFile_Directory *) self;
1589     size_t i;
1590 
1591     default_dump_header(interp, self);
1592 
1593     Parrot_io_printf(interp, "\n\t# "SIZE_FMT" segments\n", dir->num_segments);
1594 
1595     for (i = 0; i < dir->num_segments; ++i) {
1596         const PackFile_Segment * const seg = dir->segments[i];
1597 
1598         Parrot_io_printf(interp,
1599                 "\ttype %d\t%Ss\t", (int)seg->type, seg->name);
1600 
1601         Parrot_io_printf(interp,
1602                 " offs 0x%lx(0x%lx)\top_count %ld\n",
1603                 seg->file_offset,
1604                 seg->file_offset * sizeof (opcode_t),
1605                 seg->op_count);
1606     }
1607 
1608     Parrot_io_printf(interp, "]\n");
1609 
1610     for (i = 0; i < dir->num_segments; ++i)
1611         Parrot_pf_dump_segment(interp, dir->segments[i]);
1612 }
1613 
1614 
1615 /*
1616 
1617 =item C<static const opcode_t * directory_unpack(PARROT_INTERP, PackFile_Segment
1618 *segp, const opcode_t *cursor)>
1619 
1620 Unpacks the directory from the provided cursor.
1621 
1622 =cut
1623 
1624 */
1625 
1626 PARROT_CAN_RETURN_NULL
1627 PARROT_WARN_UNUSED_RESULT
1628 static const opcode_t *
directory_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * segp),ARGIN (const opcode_t * cursor))1629 directory_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *segp), ARGIN(const opcode_t *cursor))
1630 {
1631     ASSERT_ARGS(directory_unpack)
1632     PackFile_Directory * const dir = (PackFile_Directory *)segp;
1633     PackFile           * const pf  = dir->base.pf;
1634     const opcode_t            *pos;
1635     size_t                     i;
1636     int                        offs;
1637 
1638     PARROT_ASSERT(pf);
1639     dir->num_segments = PF_fetch_opcode(pf, &cursor);
1640     dir->segments = mem_gc_allocate_n_zeroed_typed(interp,
1641             dir->num_segments, PackFile_Segment *);
1642 
1643     for (i = 0; i < dir->num_segments; ++i) {
1644         PackFile_Segment *seg;
1645         STRING           *name;
1646         size_t            opcode;
1647 
1648         /* get type */
1649         UINTVAL type = PF_fetch_opcode(pf, &cursor);
1650         if (type >= PF_MAX_SEG)
1651             type = PF_UNKNOWN_SEG;
1652 
1653         /* get name */
1654         name = PF_fetch_string(interp, pf, &cursor);
1655 
1656         /* create it */
1657         seg  = Parrot_pf_new_segment(interp, dir, type, name, 0);
1658         seg->file_offset = PF_fetch_opcode(pf, &cursor);
1659         seg->op_count    = PF_fetch_opcode(pf, &cursor);
1660 
1661         if (pf->need_wordsize) {
1662 #if OPCODE_T_SIZE == 8
1663             if (pf->header->wordsize == 4)
1664                 pos = pf->src + seg->file_offset / 2;
1665 #else
1666             if (pf->header->wordsize == 8)
1667                 pos = pf->src + seg->file_offset * 2;
1668 #endif
1669             else {
1670                 fprintf(stderr, "directory_unpack failed: invalid wordsize %d\n",
1671                         (int)pf->header->wordsize);
1672                 return NULL;
1673             }
1674         }
1675         else
1676             pos = pf->src + seg->file_offset;
1677 
1678         opcode = PF_fetch_opcode(pf, &pos);
1679 
1680         if (seg->op_count != opcode) {
1681             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
1682                 "%Ss: Size in directory %d doesn't match size %d "
1683                 "at offset 0x%x", seg->name, (int)seg->op_count,
1684                 (int)opcode, (int)seg->file_offset);
1685         }
1686 
1687         if (i) {
1688             PackFile_Segment *last = dir->segments[i - 1];
1689             if (last->file_offset + last->op_count != seg->file_offset)
1690                 fprintf(stderr, "section: sections are not back to back\n");
1691         }
1692 
1693         make_code_pointers(seg);
1694 
1695         /* store the segment */
1696         dir->segments[i] = seg;
1697         seg->dir         = dir;
1698     }
1699 
1700     offs = OFFS(pf, cursor);
1701     offs += PAD_16_B(offs);
1702     cursor = pf->src + offs/(sizeof (opcode_t));
1703 
1704     /* and now unpack contents of dir */
1705     for (i = 0; cursor && i < dir->num_segments; ++i) {
1706         const opcode_t * const csave = cursor;
1707 
1708         /* check len again */
1709         const size_t tmp = PF_fetch_opcode(pf, &cursor);
1710 
1711         /* keep gcc -O silent */
1712         size_t delta = 0;
1713 
1714         cursor = csave;
1715         pos    = pf_segment_unpack(interp, dir->segments[i], cursor);
1716 
1717         if (!pos) {
1718             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
1719                 "PackFile_unpack segment '%Ss' failed", dir->segments[i]->name);
1720         }
1721 
1722         /* FIXME bug on 64bit reading 32bit lurking here! TT #254 */
1723         if (pf->need_wordsize) {
1724 #if OPCODE_T_SIZE == 8
1725             if (pf->header->wordsize == 4)
1726                 delta = (pos - cursor) * 2;
1727 #else
1728             if (pf->header->wordsize == 8)
1729                 delta = (pos - cursor) / 2;
1730 #endif
1731         }
1732         else
1733             delta = pos - cursor;
1734 
1735         if (delta != tmp || dir->segments[i]->op_count != tmp)
1736             Parrot_io_eprintf(interp, "PackFile_unpack segment '%Ss' directory length %d "
1737                     "length in file %d needed %d for unpack\n",
1738                     dir->segments[i]->name,
1739                     (int)dir->segments[i]->op_count, (int)tmp,
1740                     (int)delta);
1741         cursor = pos;
1742     }
1743 
1744     return cursor;
1745 }
1746 
1747 
1748 /*
1749 
1750 =item C<static void directory_destroy(PARROT_INTERP, PackFile_Segment *self)>
1751 
1752 Destroys the directory.
1753 
1754 =cut
1755 
1756 */
1757 
1758 static void
directory_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1759 directory_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1760 {
1761     ASSERT_ARGS(directory_destroy)
1762     PackFile_Directory * const dir = (PackFile_Directory *)self;
1763     size_t i;
1764 
1765     for (i = 0; i < dir->num_segments; ++i) {
1766         PackFile_Segment * const segment = dir->segments[i];
1767         /* Prevent repeated destruction */
1768         dir->segments[i] = NULL;
1769 
1770         if (segment && segment != self)
1771             Parrot_pf_destroy_segment(interp, segment);
1772     }
1773 
1774     if (dir->segments) {
1775         mem_gc_free(interp, dir->segments);
1776         dir->segments     = NULL;
1777         dir->num_segments = 0;
1778     }
1779 }
1780 
1781 /*
1782 
1783 =item C<static void sort_segs(PackFile_Directory *dir)>
1784 
1785 Sorts the segments in C<dir>.
1786 
1787 =cut
1788 
1789 */
1790 
1791 static void
sort_segs(ARGMOD (PackFile_Directory * dir))1792 sort_segs(ARGMOD(PackFile_Directory *dir))
1793 {
1794     ASSERT_ARGS(sort_segs)
1795     const size_t      num_segs = dir->num_segments;
1796     PackFile_Segment *seg      = dir->segments[0];
1797 
1798     if (seg->type != PF_BYTEC_SEG) {
1799         size_t i;
1800 
1801         for (i = 1; i < num_segs; ++i) {
1802             PackFile_Segment * const s2 = dir->segments[i];
1803             if (s2->type == PF_BYTEC_SEG) {
1804                 dir->segments[0] = s2;
1805                 dir->segments[i] = seg;
1806                 break;
1807             }
1808         }
1809     }
1810 
1811 
1812     /* XXX
1813      * Temporary? hack to put ConstantTable in front of other segments.
1814      * This is useful for Annotations because we ensure that constants used
1815      * for keys already available during unpack.
1816      */
1817     seg = dir->segments[1];
1818 
1819     if (seg->type != PF_CONST_SEG) {
1820         size_t i;
1821 
1822         for (i = 3; i < num_segs; ++i) {
1823             PackFile_Segment * const s2 = dir->segments[i];
1824             if (s2->type == PF_CONST_SEG) {
1825                 dir->segments[2] = s2;
1826                 dir->segments[i] = seg;
1827                 break;
1828             }
1829         }
1830     }
1831 }
1832 
1833 
1834 /*
1835 
1836 =item C<static size_t directory_packed_size(PARROT_INTERP, PackFile_Segment
1837 *self)>
1838 
1839 Returns the size of the directory minus the value returned by
1840 C<default_packed_size()>.
1841 
1842 =cut
1843 
1844 */
1845 
1846 PARROT_WARN_UNUSED_RESULT
1847 static size_t
directory_packed_size(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1848 directory_packed_size(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1849 {
1850     ASSERT_ARGS(directory_packed_size)
1851     PackFile_Directory * const dir   = (PackFile_Directory *)self;
1852     const size_t               align = 16 / sizeof (opcode_t);
1853     size_t size, i;
1854 
1855     /* need bytecode, fixup, other segs ... */
1856     sort_segs(dir);
1857 
1858     /* number of segments + default, we need it for the offsets */
1859     size = 1 + default_packed_size(self);
1860 
1861     for (i = 0; i < dir->num_segments; ++i) {
1862         /* type, offset, size */
1863         size += 3;
1864         size += PF_size_string(dir->segments[i]->name);
1865     }
1866 
1867     /* pad/align it */
1868     if (align && size % align)
1869         size += (align - size % align);
1870 
1871     for (i = 0; i < dir->num_segments; ++i) {
1872         size_t seg_size;
1873 
1874         dir->segments[i]->file_offset = size + self->file_offset;
1875         seg_size = pf_segment_packed_size(interp, dir->segments[i]);
1876         dir->segments[i]->op_count    = seg_size;
1877         size += seg_size;
1878     }
1879 
1880     self->op_count = size;
1881 
1882     /* subtract default, it is added in PackFile_Segment_packed_size */
1883     return size - default_packed_size(self);
1884 }
1885 
1886 
1887 /*
1888 
1889 =item C<static opcode_t * directory_pack(PARROT_INTERP, PackFile_Segment *self,
1890 opcode_t *cursor)>
1891 
1892 Packs the directory C<self>, using the given cursor.
1893 
1894 =cut
1895 
1896 */
1897 
1898 PARROT_WARN_UNUSED_RESULT
1899 PARROT_CANNOT_RETURN_NULL
1900 static opcode_t *
directory_pack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))1901 directory_pack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
1902 {
1903     ASSERT_ARGS(directory_pack)
1904     PackFile_Directory * const dir      = (PackFile_Directory *)self;
1905     const size_t               num_segs = dir->num_segments;
1906     /*const size_t               align    = 16/sizeof (opcode_t);*/
1907     size_t i;
1908     PackFile           * const pf       = self->pf;
1909     opcode_t                 * old_cursor;  /* Used for filling padding with 0 */
1910 
1911     *cursor++ = num_segs;
1912 
1913     for (i = 0; i < num_segs; i++) {
1914         const PackFile_Segment * const seg = dir->segments[i];
1915 
1916         *cursor++ = seg->type;
1917         cursor = PF_store_string(cursor, seg->name);
1918         *cursor++ = seg->file_offset;
1919         *cursor++ = seg->op_count;
1920     }
1921 
1922     old_cursor = cursor;
1923     ALIGN_16(pf, cursor);
1924     /* fill padding with zeros */
1925     while (old_cursor != cursor)
1926         *old_cursor++ = 0;
1927 
1928     /*if (align && (cursor - self->pf->src) % align)
1929       cursor += align - (cursor - self->pf->src) % align;*/
1930 
1931     /* now pack all segments into new format */
1932     for (i = 0; i < dir->num_segments; ++i) {
1933         PackFile_Segment * const seg = dir->segments[i];
1934         cursor = pf_segment_pack(interp, seg, cursor);
1935     }
1936 
1937     return cursor;
1938 }
1939 
1940 
1941 /*
1942 
1943 =back
1944 
1945 =head2 C<PackFile_Segment> Functions
1946 
1947 =over 4
1948 
1949 =item C<static void segment_init(PackFile_Segment *self, PackFile *pf, STRING
1950 *name)>
1951 
1952 Initializes the segment C<self> with the provided PackFile and the given name.
1953 Note that this duplicates the given name.
1954 
1955 =cut
1956 
1957 */
1958 
1959 static void
segment_init(ARGOUT (PackFile_Segment * self),ARGIN (PackFile * pf),ARGIN (STRING * name))1960 segment_init(ARGOUT(PackFile_Segment *self), ARGIN(PackFile *pf),
1961         ARGIN(STRING *name))
1962 {
1963     ASSERT_ARGS(segment_init)
1964     self->pf          = pf;
1965     self->type        = PF_UNKNOWN_SEG;
1966     self->file_offset = 0;
1967     self->op_count    = 0;
1968     self->itype       = 0;
1969     self->size        = 0;
1970     self->data        = NULL;
1971     self->id          = 0;
1972     self->name        = name;
1973 }
1974 
1975 
1976 /*
1977 
1978 =item C<static PackFile_Segment * segment_new(PARROT_INTERP)>
1979 
1980 Creates a new default segment section for a packfile.
1981 
1982 =cut
1983 
1984 */
1985 
1986 PARROT_WARN_UNUSED_RESULT
1987 PARROT_CANNOT_RETURN_NULL
1988 static PackFile_Segment *
segment_new(PARROT_INTERP)1989 segment_new(PARROT_INTERP)
1990 {
1991     ASSERT_ARGS(segment_new)
1992     PackFile_Segment * const seg = mem_gc_allocate_zeroed_typed(interp, PackFile_Segment);
1993 
1994     return seg;
1995 }
1996 
1997 /*
1998 
1999 =item C<PackFile_Segment * PackFile_Segment_new(PARROT_INTERP)>
2000 
2001 Creates a new default section.
2002 
2003 Deprecated: Will not be exported anymore.
2004 
2005 =cut
2006 
2007 */
2008 
2009 PARROT_EXPORT
2010 PARROT_DEPRECATED
2011 PARROT_WARN_UNUSED_RESULT
2012 PARROT_CANNOT_RETURN_NULL
2013 PackFile_Segment *
PackFile_Segment_new(PARROT_INTERP)2014 PackFile_Segment_new(PARROT_INTERP)
2015 {
2016     ASSERT_ARGS(PackFile_Segment_new)
2017     PackFile_Segment * const seg = mem_gc_allocate_zeroed_typed(interp, PackFile_Segment);
2018 
2019     return seg;
2020 }
2021 
2022 /*
2023 
2024 =back
2025 
2026 =head2 Default Function Implementations
2027 
2028 The default functions are called before the segment specific functions
2029 and can read a block of C<opcode_t> data.
2030 
2031 =over 4
2032 
2033 =item C<static void default_destroy(PARROT_INTERP, PackFile_Segment *self)>
2034 
2035 The default destroy function.  Destroys a PackFile_Segment.
2036 
2037 =cut
2038 
2039 */
2040 
2041 static void
default_destroy(PARROT_INTERP,ARGFREE_NOTNULL (PackFile_Segment * self))2042 default_destroy(PARROT_INTERP, ARGFREE_NOTNULL(PackFile_Segment *self))
2043 {
2044     ASSERT_ARGS(default_destroy)
2045     if (!self->pf->is_mmap_ped && self->data) {
2046         mem_gc_free(interp, self->data);
2047         self->data = NULL;
2048     }
2049 
2050     mem_gc_free(interp, self);
2051 }
2052 
2053 
2054 /*
2055 
2056 =item C<static size_t default_packed_size(const PackFile_Segment *self)>
2057 
2058 Returns the default size of the segment C<self>.
2059 
2060 =cut
2061 
2062 */
2063 
2064 PARROT_PURE_FUNCTION
2065 PARROT_WARN_UNUSED_RESULT
2066 static size_t
default_packed_size(ARGIN (const PackFile_Segment * self))2067 default_packed_size(ARGIN(const PackFile_Segment *self))
2068 {
2069     ASSERT_ARGS(default_packed_size)
2070     return SEGMENT_HEADER_SIZE + self->size;
2071 }
2072 
2073 
2074 /*
2075 
2076 =item C<static opcode_t * default_pack(const PackFile_Segment *self, opcode_t
2077 *dest)>
2078 
2079 Performs the default pack.
2080 
2081 =cut
2082 
2083 */
2084 
2085 PARROT_WARN_UNUSED_RESULT
2086 PARROT_CANNOT_RETURN_NULL
2087 static opcode_t *
default_pack(ARGIN (const PackFile_Segment * self),ARGOUT (opcode_t * dest))2088 default_pack(ARGIN(const PackFile_Segment *self), ARGOUT(opcode_t *dest))
2089 {
2090     ASSERT_ARGS(default_pack)
2091     *dest++ = self->op_count;
2092     *dest++ = self->itype;
2093     *dest++ = self->id;
2094     *dest++ = self->size;
2095 
2096     if (self->size)
2097         STRUCT_COPY_N(dest, self->data, self->size);
2098 
2099     return dest + self->size;
2100 }
2101 
2102 /*
2103 
2104 =back
2105 
2106 =head2 ByteCode
2107 
2108 =over 4
2109 
2110 =item C<static void byte_code_destroy(PARROT_INTERP, PackFile_Segment *self)>
2111 
2112 Destroys the C<PackFile_ByteCode> segment C<self>.
2113 
2114 =cut
2115 
2116 */
2117 
2118 static void
byte_code_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))2119 byte_code_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
2120 {
2121     ASSERT_ARGS(byte_code_destroy)
2122     PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2123 
2124     if (byte_code->op_func_table)
2125         mem_gc_free(interp, byte_code->op_func_table);
2126     if (byte_code->op_info_table)
2127         mem_gc_free(interp, byte_code->op_info_table);
2128     if (byte_code->op_mapping.libs) {
2129         const opcode_t n_libs = byte_code->op_mapping.n_libs;
2130         opcode_t i;
2131 
2132         for (i = 0; i < n_libs; i++) {
2133             mem_gc_free(interp, byte_code->op_mapping.libs[i].table_ops);
2134             mem_gc_free(interp, byte_code->op_mapping.libs[i].lib_ops);
2135         }
2136 
2137         mem_gc_free(interp, byte_code->op_mapping.libs);
2138     }
2139 
2140     if (byte_code->libdeps)
2141         mem_gc_free(interp, byte_code->libdeps);
2142 
2143     if (byte_code->annotations)
2144         annotations_destroy(interp, (PackFile_Segment *)byte_code->annotations);
2145 
2146     byte_code->annotations     = NULL;
2147     byte_code->const_table     = NULL;
2148     byte_code->debugs          = NULL;
2149     byte_code->op_func_table   = NULL;
2150     byte_code->op_info_table   = NULL;
2151     byte_code->op_mapping.libs = NULL;
2152     byte_code->libdeps         = NULL;
2153 }
2154 
2155 
2156 /*
2157 
2158 =item C<static PackFile_Segment * byte_code_new(PARROT_INTERP)>
2159 
2160 Creates a new C<PackFile_ByteCode> segment.
2161 
2162 =cut
2163 
2164 */
2165 
2166 PARROT_WARN_UNUSED_RESULT
2167 PARROT_CANNOT_RETURN_NULL
2168 static PackFile_Segment *
byte_code_new(PARROT_INTERP)2169 byte_code_new(PARROT_INTERP)
2170 {
2171     ASSERT_ARGS(byte_code_new)
2172     PackFile_ByteCode * const byte_code = mem_gc_allocate_zeroed_typed(interp, PackFile_ByteCode);
2173     byte_code->main_sub          = -1;
2174 
2175     return (PackFile_Segment *) byte_code;
2176 }
2177 
2178 /*
2179 
2180 =item C<static size_t byte_code_packed_size(PARROT_INTERP, PackFile_Segment
2181 *self)>
2182 
2183 Computes the size in multiples of C<opcode_t> required to store the passed
2184 C<PackFile_ByteCode>.
2185 
2186 =cut
2187 
2188 */
2189 
2190 PARROT_WARN_UNUSED_RESULT
2191 PARROT_PURE_FUNCTION
2192 static size_t
byte_code_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * self))2193 byte_code_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *self))
2194 {
2195     ASSERT_ARGS(byte_code_packed_size)
2196     PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2197     size_t size;
2198     int i;
2199     unsigned int u;
2200 
2201     size = 4; /* main_sub + op_count + n_libs + n_libdeps*/
2202 
2203     for (u = 0; u < byte_code->n_libdeps; u++)
2204         size += PF_size_string(byte_code->libdeps[u]);
2205 
2206     for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2207         PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2208 
2209         /* dynoplib data */
2210         size += PF_size_cstring(entry->lib->name);
2211         size += 2; /* bc_major + bc_minor */
2212 
2213         /* op entries */
2214         size += 1;                /* n_ops */
2215         size += entry->n_ops * 2; /* lib_ops and table_ops */
2216     }
2217 
2218     return size;
2219 }
2220 
2221 /*
2222 
2223 =item C<static opcode_t * byte_code_pack(PARROT_INTERP, PackFile_Segment *self,
2224 opcode_t *cursor)>
2225 
2226 Stores the passed C<PackFile_ByteCode> segment in bytecode.
2227 
2228 =cut
2229 
2230 */
2231 
2232 PARROT_WARN_UNUSED_RESULT
2233 PARROT_CANNOT_RETURN_NULL
2234 static opcode_t *
byte_code_pack(SHIM_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))2235 byte_code_pack(SHIM_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
2236 {
2237     ASSERT_ARGS(byte_code_pack)
2238     const PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2239     int i;
2240     unsigned int u;
2241 
2242     *cursor++ = byte_code->main_sub;
2243 
2244     *cursor++ = byte_code->n_libdeps;
2245     *cursor++ = byte_code->op_count;
2246     *cursor++ = byte_code->op_mapping.n_libs;
2247 
2248     for (u = 0; u < byte_code->n_libdeps; u++)
2249         cursor = PF_store_string(cursor, byte_code->libdeps[u]);
2250 
2251     for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2252         int j;
2253 
2254         PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2255 
2256         /* dynoplib data */
2257         cursor    = PF_store_cstring(cursor, entry->lib->name);
2258         *cursor++ = entry->lib->bc_major_version;
2259         *cursor++ = entry->lib->bc_minor_version;
2260 
2261         /* op entries */
2262         *cursor++ = entry->n_ops;
2263         for (j = 0; j < entry->n_ops; j++) {
2264             *cursor++ = entry->table_ops[j];
2265             *cursor++ = entry->lib_ops[j];
2266         }
2267     }
2268 
2269     return cursor;
2270 }
2271 
2272 /*
2273 
2274 =item C<static const opcode_t * byte_code_unpack(PARROT_INTERP, PackFile_Segment
2275 *self, const opcode_t *cursor)>
2276 
2277 Unpacks a bytecode segment into the passed C<PackFile_ByteCode>.
2278 
2279 =cut
2280 
2281 */
2282 
2283 PARROT_WARN_UNUSED_RESULT
2284 PARROT_CANNOT_RETURN_NULL
2285 static const opcode_t *
byte_code_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))2286 byte_code_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
2287 {
2288     ASSERT_ARGS(byte_code_unpack)
2289     PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2290     int i;
2291     unsigned int u;
2292     size_t total_ops = 0;
2293 
2294     byte_code->main_sub          = PF_fetch_opcode(self->pf, &cursor);
2295 
2296     byte_code->n_libdeps         = PF_fetch_opcode(self->pf, &cursor);
2297     byte_code->libdeps           = mem_gc_allocate_n_zeroed_typed(interp,
2298                                         byte_code->n_libdeps, STRING *);
2299 
2300     byte_code->op_count          = PF_fetch_opcode(self->pf, &cursor);
2301     byte_code->op_func_table     = mem_gc_allocate_n_zeroed_typed(interp,
2302                                         byte_code->op_count, op_func_t);
2303     byte_code->op_info_table     = mem_gc_allocate_n_zeroed_typed(interp,
2304                                         byte_code->op_count, op_info_t *);
2305 
2306 
2307     byte_code->op_mapping.n_libs = PF_fetch_opcode(self->pf, &cursor);
2308     byte_code->op_mapping.libs   = mem_gc_allocate_n_zeroed_typed(interp,
2309                                     byte_code->op_mapping.n_libs,
2310                                     PackFile_ByteCode_OpMappingEntry);
2311 
2312     for (u = 0; u < byte_code->n_libdeps; u++) {
2313         STRING * const libname = PF_fetch_string(interp, self->pf, &cursor);
2314         PMC    * const lib_pmc = Parrot_dyn_load_lib(interp, libname, NULL);
2315         byte_code->libdeps[u] = libname;
2316         UNUSED(lib_pmc);
2317     }
2318 
2319     for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2320         PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2321 
2322         /* dynoplib data */
2323         {
2324             char * const    lib_name = PF_fetch_cstring(interp, self->pf, &cursor);
2325             const opcode_t  bc_major = PF_fetch_opcode(self->pf, &cursor);
2326             const opcode_t  bc_minor = PF_fetch_opcode(self->pf, &cursor);
2327 
2328             /* XXX
2329              * broken encapsulation => should make this data easier to access somehow
2330              */
2331             if (STREQ(lib_name, PARROT_CORE_OPLIB_NAME)) {
2332                 entry->lib = PARROT_CORE_OPLIB_INIT(interp, 1);
2333             }
2334             else {
2335                 PMC * const lib_pmc = Parrot_dyn_load_lib(interp,
2336                                                 Parrot_str_new(interp, lib_name, 0),
2337                                                 NULL);
2338                 typedef op_lib_t *(*oplib_init_t)(PARROT_INTERP, long init);
2339                 void *oplib_init;
2340                 oplib_init_t fn;
2341                 if (!VTABLE_get_bool(interp, lib_pmc))
2342                     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR,
2343                         "Could not load oplib `%s'", lib_name);
2344                 GETATTR_ParrotLibrary_oplib_init(interp, lib_pmc, oplib_init);
2345                 fn = (oplib_init_t)D2FPTR(oplib_init);
2346                 entry->lib = fn(interp, 1);
2347             }
2348 
2349 
2350             mem_gc_free(interp, lib_name);
2351 
2352             if (entry->lib->bc_major_version != bc_major
2353              || entry->lib->bc_minor_version != bc_minor)
2354                 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR,
2355                     "Incompatible versions of `%s' bytecode, possibly due to "
2356                     "loading bytecode generated by an old version of Parrot. "
2357                     "Found %d.%d but loaded %d.%d",
2358                     entry->lib->name, bc_major, bc_minor,
2359                     entry->lib->bc_major_version, entry->lib->bc_minor_version);
2360         }
2361 
2362         /* op entries */
2363         {
2364             int       j;
2365             total_ops += entry->n_ops = PF_fetch_opcode(self->pf, &cursor);
2366 
2367             entry->table_ops = mem_gc_allocate_n_zeroed_typed(interp,
2368                                     entry->n_ops, opcode_t);
2369             entry->lib_ops   = mem_gc_allocate_n_zeroed_typed(interp,
2370                                     entry->n_ops, opcode_t);
2371 
2372             for (j = 0; j < entry->n_ops; j++) {
2373                 opcode_t idx = PF_fetch_opcode(self->pf, &cursor);
2374                 opcode_t op  = PF_fetch_opcode(self->pf, &cursor);
2375 
2376                 if (0 > op || op >= entry->lib->op_count)
2377                     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2378                         "opcode index out of bounds on library `%s'. Found %d, expected 0 to %d",
2379                         entry->lib->name, op, entry->lib->op_count - 1);
2380 
2381                 if (0 > idx || (size_t)idx >= byte_code->op_count)
2382                     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2383                         "op table index out of bounds for entry from library `%s'."
2384                         " Found %d, expected 0 to %d",
2385                         entry->lib->name, idx, byte_code->op_count - 1);
2386 
2387                 if (byte_code->op_func_table[idx])
2388                     Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_MALFORMED_PACKFILE,
2389                         "duplicate entries in optable");
2390 
2391                 entry->table_ops[j]           = idx;
2392                 entry->lib_ops[j]             = op;
2393                 byte_code->op_func_table[idx] = entry->lib->op_func_table[op];
2394                 byte_code->op_info_table[idx] = &entry->lib->op_info_table[op];
2395             }
2396         }
2397     }
2398 
2399     if (total_ops != byte_code->op_count)
2400         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2401             "wrong number of ops decoded for optable. Decoded %d, but expected %d",
2402             total_ops, byte_code->op_count);
2403 
2404     return cursor;
2405 }
2406 
2407 /*
2408 
2409 =back
2410 
2411 =head2 Debug Info
2412 
2413 =over 4
2414 
2415 =item C<static void pf_debug_destroy(PARROT_INTERP, PackFile_Segment *self)>
2416 
2417 Destroys the C<PackFile_Debug> segment C<self>.
2418 
2419 =cut
2420 
2421 */
2422 
2423 static void
pf_debug_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))2424 pf_debug_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
2425 {
2426     ASSERT_ARGS(pf_debug_destroy)
2427     PackFile_Debug * const debug = (PackFile_Debug *) self;
2428 
2429     /* Free mappings pointer array. */
2430     mem_gc_free(interp, debug->mappings);
2431     debug->mappings     = NULL;
2432     debug->num_mappings = 0;
2433 }
2434 
2435 
2436 /*
2437 
2438 =item C<static PackFile_Segment * pf_debug_new(PARROT_INTERP)>
2439 
2440 Creates and returns a new C<PackFile_Debug> segment.
2441 
2442 =cut
2443 
2444 */
2445 
2446 PARROT_WARN_UNUSED_RESULT
2447 PARROT_CANNOT_RETURN_NULL
2448 static PackFile_Segment *
pf_debug_new(PARROT_INTERP)2449 pf_debug_new(PARROT_INTERP)
2450 {
2451     ASSERT_ARGS(pf_debug_new)
2452     PackFile_Debug * const debug = mem_gc_allocate_zeroed_typed(interp, PackFile_Debug);
2453 
2454     /* don't create initial mappings here; they'll get overwritten later */
2455 
2456     return (PackFile_Segment *)debug;
2457 }
2458 
2459 
2460 /*
2461 
2462 =item C<static size_t pf_debug_packed_size(PARROT_INTERP, PackFile_Segment
2463 *self)>
2464 
2465 Returns the size of the C<PackFile_Debug> segment's filename in C<opcode_t>
2466 units.
2467 
2468 =cut
2469 
2470 */
2471 
2472 static size_t
pf_debug_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * self))2473 pf_debug_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *self))
2474 {
2475     ASSERT_ARGS(pf_debug_packed_size)
2476     PackFile_Debug * const debug = (PackFile_Debug *)self;
2477 
2478     return (debug->num_mappings*2) + 1;
2479 }
2480 
2481 
2482 /*
2483 
2484 =item C<static opcode_t * pf_debug_pack(PARROT_INTERP, PackFile_Segment *self,
2485 opcode_t *cursor)>
2486 
2487 Packs the debug segment, using the given cursor.
2488 
2489 =cut
2490 
2491 */
2492 
2493 PARROT_WARN_UNUSED_RESULT
2494 PARROT_CANNOT_RETURN_NULL
2495 static opcode_t *
pf_debug_pack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))2496 pf_debug_pack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
2497 {
2498     ASSERT_ARGS(pf_debug_pack)
2499     PackFile_Debug * const debug = (PackFile_Debug *)self;
2500     const              int n     = debug->num_mappings;
2501     int i;
2502 
2503     if (n > 0 && debug->mappings == NULL)
2504         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2505                                     "No mappings but non zero num mappings(%I)", n);
2506 
2507     /* Store number of mappings. */
2508     *cursor++ = n;
2509 
2510     /* Now store each mapping. */
2511     for (i = 0; i < n; ++i) {
2512         /* Bytecode offset and filename. */
2513         *cursor++ = debug->mappings[i].offset;
2514         *cursor++ = debug->mappings[i].filename;
2515     }
2516 
2517     return cursor;
2518 }
2519 
2520 
2521 /*
2522 
2523 =item C<static const opcode_t * pf_debug_unpack(PARROT_INTERP, PackFile_Segment
2524 *self, const opcode_t *cursor)>
2525 
2526 Unpacks a debug segment into a PackFile_Debug structure, given the cursor.
2527 
2528 =cut
2529 
2530 */
2531 
2532 PARROT_WARN_UNUSED_RESULT
2533 PARROT_CANNOT_RETURN_NULL
2534 static const opcode_t *
pf_debug_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))2535 pf_debug_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
2536 {
2537     ASSERT_ARGS(pf_debug_unpack)
2538     PackFile_Debug * const debug = (PackFile_Debug *)self;
2539     PackFile_ByteCode     *code;
2540     int                    i;
2541 
2542     /* For some reason, we store the source file name in the segment
2543        name. So we can't find the bytecode seg without knowing the filename.
2544        But with the new scheme we can have many file names. For now, just
2545        base this on the name of the debug segment. */
2546     STRING *code_name;
2547     size_t str_len;
2548 
2549     /* Number of mappings. */
2550     debug->num_mappings = PF_fetch_opcode(self->pf, &cursor);
2551 
2552     /* Allocate space for mappings vector. */
2553     debug->mappings = mem_gc_allocate_n_zeroed_typed(interp,
2554             debug->num_mappings, PackFile_DebugFilenameMapping);
2555 
2556     /* Read in each mapping. */
2557     for (i = 0; i < debug->num_mappings; ++i) {
2558         /* Get offset and filename type. */
2559         debug->mappings[i].offset   = PF_fetch_opcode(self->pf, &cursor);
2560         debug->mappings[i].filename = PF_fetch_opcode(self->pf, &cursor);
2561     }
2562 
2563     /* find seg e.g. CODE_DB => CODE and attach it */
2564     str_len     = Parrot_str_length(interp, debug->base.name);
2565     code_name   = STRING_substr(interp, debug->base.name, 0, str_len - 3);
2566     code        = (PackFile_ByteCode *)Parrot_pf_find_segment(interp, self->dir, code_name, 0);
2567 
2568     if (!code || code->base.type != PF_BYTEC_SEG) {
2569         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2570             "Code '%Ss' not found for debug segment '%Ss'",
2571             code_name, self->name);
2572     }
2573 
2574     code->debugs = debug;
2575     debug->code  = code;
2576 
2577     return cursor;
2578 }
2579 
2580 
2581 /*
2582 
2583 =item C<static void pf_debug_dump(PARROT_INTERP, const PackFile_Segment *self)>
2584 
2585 Dumps a debug segment to a human readable form.
2586 
2587 =cut
2588 
2589 */
2590 
2591 static void
pf_debug_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))2592 pf_debug_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
2593 {
2594     ASSERT_ARGS(pf_debug_dump)
2595     const PackFile_Debug * const debug = (const PackFile_Debug *)self;
2596 
2597     opcode_t i;
2598 
2599     default_dump_header(interp, self);
2600 
2601     Parrot_io_printf(interp, "\n  mappings => [\n");
2602     for (i = 0; i < debug->num_mappings; ++i) {
2603         Parrot_io_printf(interp, "    #%ld\n    [\n", i);
2604         Parrot_io_printf(interp, "        OFFSET => %ld,\n",
2605                    debug->mappings[i].offset);
2606         Parrot_io_printf(interp, "        FILENAME => %Ss\n",
2607                 debug->code->const_table->str.constants[debug->mappings[i].filename]);
2608         Parrot_io_printf(interp, "    ],\n");
2609     }
2610 
2611     Parrot_io_printf(interp, "  ]\n");
2612 }
2613 
2614 /*
2615 
2616 =item C<static void make_code_pointers(PackFile_Segment *seg)>
2617 
2618 Makes compact/shorthand pointers.
2619 
2620 The first segments read are the default segments.
2621 
2622 =cut
2623 
2624 */
2625 
2626 static void
make_code_pointers(ARGMOD (PackFile_Segment * seg))2627 make_code_pointers(ARGMOD(PackFile_Segment *seg))
2628 {
2629     ASSERT_ARGS(make_code_pointers)
2630     PackFile * const pf = seg->pf;
2631 
2632     switch (seg->type) {
2633       case PF_BYTEC_SEG:
2634         if (!pf->cur_cs)
2635             pf->cur_cs = (PackFile_ByteCode *)seg;
2636         break;
2637       case PF_CONST_SEG:
2638         if (!pf->cur_cs->const_table) {
2639             pf->cur_cs->const_table       = (PackFile_ConstTable *)seg;
2640             pf->cur_cs->const_table->code = pf->cur_cs;
2641         }
2642         break;
2643       case PF_UNKNOWN_SEG:
2644         break;
2645       case PF_DEBUG_SEG:
2646         pf->cur_cs->debugs       = (PackFile_Debug *)seg;
2647         pf->cur_cs->debugs->code = pf->cur_cs;
2648         break;
2649       default:
2650         break;
2651     }
2652 }
2653 
2654 /*
2655 
2656 =back
2657 
2658 =cut
2659 
2660 */
2661 
2662 /*
2663  * Local variables:
2664  *   c-file-style: "parrot"
2665  * End:
2666  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
2667  */
2668