~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/vmwrtimg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef RCSID
 
2
static char RCSid[] =
 
3
"$Header: d:/cvsroot/tads/tads3/vmwrtimg.cpp,v 1.4 1999/07/11 00:46:59 MJRoberts Exp $";
 
4
#endif
 
5
 
 
6
/* 
 
7
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
 
8
 *   
 
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
 
10
 *   on using and copying this software.  
 
11
 */
 
12
/*
 
13
Name
 
14
  vmwrtimg.cpp - T3 Image File Writer utility functions
 
15
Function
 
16
  Provides functions to write an image file
 
17
Notes
 
18
  
 
19
Modified
 
20
  04/04/99 MJRoberts  - Creation
 
21
*/
 
22
 
 
23
 
 
24
#include <string.h>
 
25
#include <time.h>
 
26
 
 
27
#include "t3std.h"
 
28
#include "vmfile.h"
 
29
#include "vmwrtimg.h"
 
30
#include "vmimage.h"
 
31
 
 
32
/* ------------------------------------------------------------------------ */
 
33
/*
 
34
 *   initialize 
 
35
 */
 
36
CVmImageWriter::CVmImageWriter(CVmFile *fp)
 
37
{
 
38
    /* remember the underlying file */
 
39
    fp_ = fp;
 
40
 
 
41
    /* no block is currently open */
 
42
    block_start_ = 0;
 
43
}
 
44
 
 
45
/*
 
46
 *   delete 
 
47
 */
 
48
CVmImageWriter::~CVmImageWriter()
 
49
{
 
50
}
 
51
 
 
52
/* ------------------------------------------------------------------------ */
 
53
/*
 
54
 *   get the current seek position in the underlying file 
 
55
 */
 
56
long CVmImageWriter::get_pos() const
 
57
{
 
58
    return fp_->get_pos();
 
59
}
 
60
 
 
61
/* ------------------------------------------------------------------------ */
 
62
/*
 
63
 *   Prepare the file - write the header. 
 
64
 */
 
65
void CVmImageWriter::prepare(uint vsn, const char tool_data[4])
 
66
{
 
67
    char buf[32];
 
68
    time_t timer;
 
69
    struct tm *tblock;
 
70
    
 
71
    /* write the signature */
 
72
    fp_->write_bytes(VMIMAGE_SIG, sizeof(VMIMAGE_SIG)-1);
 
73
 
 
74
    /* write the version number */
 
75
    fp_->write_int2(vsn);
 
76
 
 
77
    /* write the 28 reserved bytes, setting all to zero */
 
78
    memset(buf, 0, 28);
 
79
    fp_->write_bytes(buf, 28);
 
80
 
 
81
    /* write the additional 4 bytes reserved for tool use */
 
82
    fp_->write_bytes(tool_data, 4);
 
83
 
 
84
    /* write the compilation timestamp */
 
85
    timer = time(NULL);
 
86
    tblock = localtime(&timer);
 
87
    fp_->write_bytes(asctime(tblock), 24);
 
88
}
 
89
 
 
90
/* ------------------------------------------------------------------------ */
 
91
/*
 
92
 *   Begin a block
 
93
 */
 
94
void CVmImageWriter::begin_block(const char *block_id, int mandatory)
 
95
{
 
96
    char buf[10];
 
97
    uint flags;
 
98
    
 
99
    /* if there's a block currently open, close it */
 
100
    end_block();
 
101
 
 
102
    /* remember the seek location of the start of the block */
 
103
    block_start_ = fp_->get_pos();
 
104
 
 
105
    /* store the type string */
 
106
    memcpy(buf, block_id, 4);
 
107
 
 
108
    /* store four bytes of zeroes as a placeholder for the size */
 
109
    memset(buf+4, 0, 4);
 
110
 
 
111
    /* compute the flags */
 
112
    flags = 0;
 
113
    if (mandatory)
 
114
        flags |= VMIMAGE_DBF_MANDATORY;
 
115
 
 
116
    /* store the flags */
 
117
    oswp2(buf+8, flags);
 
118
 
 
119
    /* write the header */
 
120
    fp_->write_bytes(buf, 10);
 
121
}
 
122
 
 
123
/* ------------------------------------------------------------------------ */
 
124
/*
 
125
 *   End the current block.  If no block is open, this does nothing. 
 
126
 */
 
127
void CVmImageWriter::end_block()
 
128
{
 
129
    long end_pos;
 
130
    uint32 siz;
 
131
    
 
132
    /* if there's no block open, there's nothing we need to do */
 
133
    if (block_start_ == 0)
 
134
        return;
 
135
 
 
136
    /* 
 
137
     *   note the current file position - this will let us compute the
 
138
     *   size of the block, and we'll need to seek back here when we're
 
139
     *   done updating the block header 
 
140
     */
 
141
    end_pos = fp_->get_pos();
 
142
 
 
143
    /*
 
144
     *   Since the block is finished, we can now compute its size.  The
 
145
     *   size of the data block is the end seek position minus the
 
146
     *   starting seek position.  'block_start_' contains the seek
 
147
     *   position of the block header, which takes up ten bytes; we want
 
148
     *   to store the size of the block's data, excluding the header,
 
149
     *   which is (end_pos - block_header_pos - 10).  
 
150
     */
 
151
    siz = (uint32)(end_pos - block_start_ - 10);
 
152
 
 
153
    /* 
 
154
     *   Seek back to the location of the size field in the block header;
 
155
     *   this is four bytes into the block header.  Then, update the size
 
156
     *   field with the size of the block's data.
 
157
     */
 
158
    fp_->set_pos(block_start_ + 4);
 
159
    fp_->write_int4(siz);
 
160
 
 
161
    /* 
 
162
     *   seek back to the end of the block, so we can resume writing data
 
163
     *   following the block 
 
164
     */
 
165
    fp_->set_pos(end_pos);
 
166
 
 
167
    /* the block is now closed, so forget about it */
 
168
    block_start_ = 0;
 
169
}
 
170
 
 
171
/* ------------------------------------------------------------------------ */
 
172
/*
 
173
 *   Write raw bytes to the file 
 
174
 */
 
175
void CVmImageWriter::write_bytes(const char *ptr, uint32 siz)
 
176
{
 
177
    /* write in 64k chunks, to accommodate 16-bit platforms */
 
178
    while (siz != 0)
 
179
    {
 
180
        size_t cur;
 
181
 
 
182
        /* get the next 64k, or the remainder if less than 64k is left */
 
183
        cur = 65535;
 
184
        if (siz < cur)
 
185
            cur = (size_t)siz;
 
186
 
 
187
        /* write this chunk */
 
188
        fp_->write_bytes(ptr, cur);
 
189
 
 
190
        /* advance past this chunk */
 
191
        ptr += cur;
 
192
        siz -= cur;
 
193
    }
 
194
}
 
195
 
 
196
/* ------------------------------------------------------------------------ */
 
197
/*
 
198
 *   Finish the file.  Closes the current block if one is open, and writes
 
199
 *   the end-of-file marker to the file. 
 
200
 */
 
201
void CVmImageWriter::finish()
 
202
{
 
203
    /* if there's a block open, close it */
 
204
    end_block();
 
205
 
 
206
    /* 
 
207
     *   write the EOF block - the block contains no data, so simply begin
 
208
     *   and end it 
 
209
     */
 
210
    begin_block("EOF ", TRUE);
 
211
    end_block();
 
212
}
 
213
 
 
214
/* ------------------------------------------------------------------------ */
 
215
/*
 
216
 *   Write an entrypoint (ENTP) block
 
217
 */
 
218
void CVmImageWriter::write_entrypt(uint32 entry_ofs, size_t method_hdr_size,
 
219
                                   size_t exc_entry_size,
 
220
                                   size_t line_entry_size,
 
221
                                   size_t dbg_hdr_size,
 
222
                                   size_t dbg_lclsym_hdr_size,
 
223
                                   int dbg_vsn_id)
 
224
{
 
225
    char buf[32];
 
226
    
 
227
    /* prepare the block's contents */
 
228
    oswp4(buf, entry_ofs);
 
229
    oswp2(buf+4, method_hdr_size);
 
230
    oswp2(buf+6, exc_entry_size);
 
231
    oswp2(buf+8, line_entry_size);
 
232
    oswp2(buf+10, dbg_hdr_size);
 
233
    oswp2(buf+12, dbg_lclsym_hdr_size);
 
234
    oswp2(buf+14, dbg_vsn_id);
 
235
 
 
236
    /* open the block, write the data, and close the block */
 
237
    begin_block("ENTP", TRUE);
 
238
    fp_->write_bytes(buf, 16);
 
239
    end_block();
 
240
}
 
241
 
 
242
/* ------------------------------------------------------------------------ */
 
243
/*
 
244
 *   Write a function set dependency block
 
245
 */
 
246
void CVmImageWriter::write_func_dep(const char **funcset_names, int count)
 
247
{
 
248
    /* write a FNSD block */
 
249
    write_dep_block("FNSD", funcset_names, count);
 
250
}
 
251
 
 
252
/* ------------------------------------------------------------------------ */
 
253
/*
 
254
 *   begin a metaclass dependency block 
 
255
 */
 
256
void CVmImageWriter::begin_meta_dep(int count)
 
257
{
 
258
    /* begin the dependency block */
 
259
    begin_dep_block("MCLD", count);
 
260
 
 
261
    /* we're not in a property list yet */
 
262
    mcld_propcnt_pos_ = 0;
 
263
}
 
264
 
 
265
/*
 
266
 *   Write a metaclass dependency block 
 
267
 */
 
268
void CVmImageWriter::write_meta_dep(const char **meta_names, int count)
 
269
{
 
270
    /* write a MCLD block */
 
271
    write_dep_block("MCLD", meta_names, count);
 
272
}
 
273
 
 
274
/*
 
275
 *   write a metaclass dependency block item 
 
276
 */
 
277
void CVmImageWriter::write_meta_dep_item(const char *metaclass_name)
 
278
{
 
279
    /* if we didn't end the previous item's property list, end it now */
 
280
    end_meta_prop_list();
 
281
 
 
282
    /* write a placeholder next record offset */
 
283
    mcld_ofs_pos_ = fp_->get_pos();
 
284
    fp_->write_int2(0);
 
285
    
 
286
    /* write the metaclass name */
 
287
    write_dep_block_item(metaclass_name);
 
288
 
 
289
    /* write a placeholder property vector count */
 
290
    mcld_propcnt_pos_ = fp_->get_pos();
 
291
    fp_->write_int2(0);
 
292
 
 
293
    /* write the property record size (2 bytes) */
 
294
    fp_->write_int2(2);
 
295
 
 
296
    /* no properties yet */
 
297
    mcld_prop_cnt_ = 0;
 
298
}
 
299
 
 
300
/*
 
301
 *   write a metaclass dependency property list item 
 
302
 */
 
303
void CVmImageWriter::write_meta_item_prop(uint prop_id)
 
304
{
 
305
    /* write the property ID */
 
306
    fp_->write_int2(prop_id);
 
307
 
 
308
    /* count it */
 
309
    ++mcld_prop_cnt_;
 
310
}
 
311
 
 
312
/*
 
313
 *   end a metaclass prop list 
 
314
 */
 
315
void CVmImageWriter::end_meta_prop_list()
 
316
{
 
317
    /* if we have a count pending, go write it */
 
318
    if (mcld_propcnt_pos_ != 0)
 
319
    {
 
320
        long pos;
 
321
 
 
322
        /* remember the current position */
 
323
        pos = fp_->get_pos();
 
324
 
 
325
        /* go back and write the property count */
 
326
        fp_->set_pos(mcld_propcnt_pos_);
 
327
        fp_->write_int2(mcld_prop_cnt_);
 
328
 
 
329
        /* we no longer have a property count fixup to apply */
 
330
        mcld_propcnt_pos_ = 0;
 
331
 
 
332
        /* go back and write the next-record offset */
 
333
        fp_->set_pos(mcld_ofs_pos_);
 
334
        fp_->write_int2((int)(pos - mcld_ofs_pos_));
 
335
 
 
336
        /* go back to the end of the record */
 
337
        fp_->set_pos(pos);
 
338
    }
 
339
}
 
340
 
 
341
/*
 
342
 *   end a metaclass dependency block 
 
343
 */
 
344
void CVmImageWriter::end_meta_dep()
 
345
{
 
346
    /* end the last metaclass item */
 
347
    end_meta_prop_list();
 
348
    
 
349
    /* end the dependency block */
 
350
    end_dep_block();
 
351
}
 
352
 
 
353
/* ------------------------------------------------------------------------ */
 
354
/*
 
355
 *   Begin a dependency block 
 
356
 */
 
357
void CVmImageWriter::begin_dep_block(const char *block_id, int count)
 
358
{
 
359
    char buf[4];
 
360
    
 
361
    /* open the block */
 
362
    begin_block(block_id, TRUE);
 
363
 
 
364
    /* write the number of entries */
 
365
    oswp2(buf, count);
 
366
    fp_->write_bytes(buf, 2);
 
367
}
 
368
 
 
369
/*
 
370
 *   Write a dependency block item 
 
371
 */
 
372
void CVmImageWriter::write_dep_block_item(const char *nm)
 
373
{
 
374
    size_t len;
 
375
    char buf[4];
 
376
 
 
377
    /* get the length of this name, and truncate to 255 bytes */
 
378
    len = strlen(nm);
 
379
    if (len > 255)
 
380
        len = 255;
 
381
 
 
382
    /* write the length, followed by the name */
 
383
    buf[0] = (char)(uchar)len;
 
384
    fp_->write_bytes(buf, 1);
 
385
    fp_->write_bytes(nm, len);
 
386
}
 
387
 
 
388
/*
 
389
 *   End a dependency block 
 
390
 */
 
391
void CVmImageWriter::end_dep_block()
 
392
{
 
393
    /* end the block */
 
394
    end_block();
 
395
}
 
396
 
 
397
/* ------------------------------------------------------------------------ */
 
398
/*
 
399
 *   Write a generic dependency list block 
 
400
 */
 
401
void CVmImageWriter::write_dep_block(const char *block_id,
 
402
                                     const char **names, int count)
 
403
{
 
404
    /* open the block */
 
405
    begin_dep_block(block_id, count);
 
406
 
 
407
    /* write each entry */
 
408
    for ( ; count > 0 ; ++names, --count)
 
409
        write_dep_block_item(*names);
 
410
 
 
411
    /* end the block */
 
412
    end_dep_block();
 
413
}
 
414
 
 
415
/* ------------------------------------------------------------------------ */
 
416
/*
 
417
 *   Write a constant pool definition block 
 
418
 */
 
419
void CVmImageWriter::write_pool_def(uint pool_id, uint32 page_count,
 
420
                                    uint32 page_size, int mandatory)
 
421
{
 
422
    char buf[16];
 
423
    
 
424
    /* prepare the block's data */
 
425
    oswp2(buf, pool_id);
 
426
    oswp4(buf+2, page_count);
 
427
    oswp4(buf+6, page_size);
 
428
 
 
429
    /* open the block, write the data, and end the block */
 
430
    begin_block("CPDF", mandatory);
 
431
    fp_->write_bytes(buf, 10);
 
432
    end_block();
 
433
}
 
434
 
 
435
/*
 
436
 *   Fix up a pool definition block with the actual page count 
 
437
 */
 
438
void CVmImageWriter::fix_pool_def(long def_seek_ofs, uint32 page_count)
 
439
{
 
440
    long old_pos;
 
441
    char buf[4];
 
442
 
 
443
    /* note the file position at entry */
 
444
    old_pos = fp_->get_pos();
 
445
    
 
446
    /* 
 
447
     *   seek to the original definition block location, plus the size of
 
448
     *   the block header (10 bytes), plus the offset within the block of
 
449
     *   the pool page count (it starts 2 bytes into the block data) 
 
450
     */
 
451
    fp_->set_pos(def_seek_ofs + 10 + 2);
 
452
 
 
453
    /* write the page count */
 
454
    oswp4(buf, page_count);
 
455
    fp_->write_bytes(buf, 4);
 
456
 
 
457
    /* seek back to our location at entry */
 
458
    fp_->set_pos(old_pos);
 
459
}
 
460
 
 
461
 
 
462
/* ------------------------------------------------------------------------ */
 
463
/*
 
464
 *   Write a constant pool page 
 
465
 */
 
466
void CVmImageWriter::write_pool_page(uint pool_id, uint32 page_index,
 
467
                                     const char *page_data,
 
468
                                     uint32 page_data_size, int mandatory,
 
469
                                     uchar xor_mask)
 
470
{
 
471
    char buf[16];
 
472
 
 
473
    /* begin the block */
 
474
    begin_block("CPPG", mandatory);
 
475
 
 
476
    /* prepare the prefix */
 
477
    oswp2(buf, pool_id);
 
478
    oswp4(buf+2, page_index);
 
479
    buf[6] = xor_mask;
 
480
 
 
481
    /* write the prefix */
 
482
    fp_->write_bytes(buf, 7);
 
483
 
 
484
    /* write the page data, XOR'ing the data with the mask byte */
 
485
    xor_and_write_bytes(page_data, page_data_size, xor_mask);
 
486
 
 
487
    /* end the block */
 
488
    end_block();
 
489
}
 
490
 
 
491
/* ------------------------------------------------------------------------ */
 
492
/*
 
493
 *   Begin writing a constant pool page.  This constructs the header and
 
494
 *   prepares for writing the bytes making up the page. 
 
495
 */
 
496
void CVmImageWriter::begin_pool_page(uint pool_id, uint32 page_index,
 
497
                                     int mandatory, uchar xor_mask)
 
498
{
 
499
    char buf[16];
 
500
 
 
501
    /* begin the block */
 
502
    begin_block("CPPG", mandatory);
 
503
 
 
504
    /* prepare the prefix */
 
505
    oswp2(buf, pool_id);
 
506
    oswp4(buf+2, page_index);
 
507
    buf[6] = xor_mask;
 
508
 
 
509
    /* write the prefix */
 
510
    fp_->write_bytes(buf, 7);
 
511
}
 
512
 
 
513
/*
 
514
 *   write bytes to a pool page under construction 
 
515
 */
 
516
void CVmImageWriter::write_pool_page_bytes(const char *buf, uint32 siz,
 
517
                                           uchar xor_mask)
 
518
{
 
519
    /* write the page data, XOR'ing the data with the mask byte */
 
520
    xor_and_write_bytes(buf, siz, xor_mask);
 
521
}
 
522
 
 
523
/*
 
524
 *   XOR and write a block of data - we will XOR each byte of the data
 
525
 *   with the given mask byte before writing it to the file 
 
526
 */
 
527
void CVmImageWriter::xor_and_write_bytes(const char *mem, uint32 siz,
 
528
                                         uchar xor_mask)
 
529
{
 
530
    /* 
 
531
     *   if there's no mask, simply write the data directly - anything XOR
 
532
     *   zero equals the original value
 
533
     */
 
534
    if (xor_mask == 0)
 
535
    {
 
536
        /* write the data to the page */
 
537
        fp_->write_bytes(mem, siz);
 
538
    }
 
539
    else
 
540
    {
 
541
        /* 
 
542
         *   copy the data in chunks into our buffer, XOR it with the
 
543
         *   mask, and write the results 
 
544
         */
 
545
        while (siz != 0)
 
546
        {
 
547
            char buf[1024];
 
548
            size_t cur;
 
549
            size_t rem;
 
550
            char *dst;
 
551
 
 
552
            /* 
 
553
             *   limit this chunk to the buffer size or the remainder of
 
554
             *   the input, whichever is smaller 
 
555
             */
 
556
            cur = sizeof(buf);
 
557
            if (cur > siz)
 
558
                cur = (size_t)siz;
 
559
 
 
560
            /* copy this chunk, xor'ing each byte with the mask */
 
561
            for (dst = buf, rem = cur ; rem != 0 ; --rem, ++dst, ++mem)
 
562
                *dst = *mem ^ xor_mask;
 
563
 
 
564
            /* write out this chunk */
 
565
            fp_->write_bytes(buf, cur);
 
566
 
 
567
            /* subtract this chunk from the length remaining */
 
568
            siz -= cur;
 
569
        }
 
570
    }
 
571
}
 
572
 
 
573
/*
 
574
 *   finish writing a pool page 
 
575
 */
 
576
void CVmImageWriter::end_pool_page()
 
577
{
 
578
    /* end the block */
 
579
    end_block();
 
580
}
 
581
 
 
582
/* ------------------------------------------------------------------------ */
 
583
/*
 
584
 *   Begin a symbolic names block
 
585
 */
 
586
void CVmImageWriter::begin_sym_block()
 
587
{
 
588
    char buf[4];
 
589
 
 
590
    /* begin the block */
 
591
    begin_block("SYMD", FALSE);
 
592
 
 
593
    /* remember where our placeholder goes */
 
594
    symd_prefix_ = fp_->get_pos();
 
595
 
 
596
    /* prepare the placeholder prefix, using a zero count for now */
 
597
    oswp2(buf, 0);
 
598
 
 
599
    /* write the prefix */
 
600
    fp_->write_bytes(buf, 2);
 
601
 
 
602
    /* we haven't written any symbolic name items yet */
 
603
    symd_cnt_ = 0;
 
604
}
 
605
 
 
606
/*
 
607
 *   write a symbolic name for an object ID 
 
608
 */
 
609
void CVmImageWriter::write_sym_item_objid(const char *nm, size_t len,
 
610
                                          ulong obj_id)
 
611
{
 
612
    vm_val_t val;
 
613
 
 
614
    /* set up the object ID value */
 
615
    val.set_obj((vm_obj_id_t)obj_id);
 
616
 
 
617
    /* write it out */
 
618
    write_sym_item(nm, len, &val);
 
619
}
 
620
 
 
621
/*
 
622
 *   write a symbolic name for a property ID 
 
623
 */
 
624
void CVmImageWriter::write_sym_item_propid(const char *nm, size_t len,
 
625
                                           uint prop_id)
 
626
{
 
627
    vm_val_t val;
 
628
 
 
629
    /* set up the property ID value */
 
630
    val.set_propid((vm_prop_id_t)prop_id);
 
631
 
 
632
    /* write it out */
 
633
    write_sym_item(nm, len, &val);
 
634
}
 
635
 
 
636
/*
 
637
 *   write a symbolic name for a function
 
638
 */
 
639
void CVmImageWriter::write_sym_item_func(const char *nm, size_t len,
 
640
                                         ulong code_ofs)
 
641
{
 
642
    vm_val_t val;
 
643
 
 
644
    /* set up the property ID value */
 
645
    val.set_fnptr((pool_ofs_t)code_ofs);
 
646
 
 
647
    /* write it out */
 
648
    write_sym_item(nm, len, &val);
 
649
}
 
650
 
 
651
/*
 
652
 *   write a symbolic name item 
 
653
 */
 
654
void CVmImageWriter::write_sym_item(const char *nm, size_t len,
 
655
                                    const vm_val_t *val)
 
656
{
 
657
    char buf[VMB_DATAHOLDER + 1];
 
658
 
 
659
    /* prepare the data holder in the prefix */
 
660
    vmb_put_dh(buf, val);
 
661
 
 
662
    /* limit the length to 255 bytes */
 
663
    if (len > 255)
 
664
        len = 255;
 
665
 
 
666
    /* add the length to the prefix */
 
667
    buf[VMB_DATAHOLDER] = (char)len;
 
668
 
 
669
    /* write the prefix */
 
670
    fp_->write_bytes(buf, VMB_DATAHOLDER + 1);
 
671
 
 
672
    /* write the string */
 
673
    fp_->write_bytes(nm, len);
 
674
 
 
675
    /* count it */
 
676
    ++symd_cnt_;
 
677
}
 
678
 
 
679
/*
 
680
 *   end a symbolic names block 
 
681
 */
 
682
void CVmImageWriter::end_sym_block()
 
683
{
 
684
    long old_pos;
 
685
    char buf[4];
 
686
    
 
687
    /* end the block */
 
688
    end_block();
 
689
 
 
690
    /* 
 
691
     *   Go back and fix the header with the number of items we wrote.
 
692
     *   First, remember our current position, then seek back to the count
 
693
     *   prefix. 
 
694
     */
 
695
    old_pos = fp_->get_pos();
 
696
    fp_->set_pos(symd_prefix_);
 
697
 
 
698
    /* prepare the prefix, and write it out */
 
699
    oswp2(buf, symd_cnt_);
 
700
    fp_->write_bytes(buf, 2);
 
701
 
 
702
    /* restore the file position */
 
703
    fp_->set_pos(old_pos);
 
704
}
 
705
 
 
706
/* ------------------------------------------------------------------------ */
 
707
/*
 
708
 *   Begin an object static data block
 
709
 */
 
710
void CVmImageWriter::begin_objs_block(uint metaclass_idx, int large_objects,
 
711
                                      int trans)
 
712
{
 
713
    char buf[16];
 
714
    uint flags;
 
715
 
 
716
    /* begin the block */
 
717
    begin_block("OBJS", TRUE);
 
718
 
 
719
    /* prepare the flags */
 
720
    flags = 0;
 
721
    if (large_objects)
 
722
        flags |= 1;
 
723
    if (trans)
 
724
        flags |= 2;
 
725
 
 
726
    /* remember where the prefix goes so we can fix it up later */
 
727
    objs_prefix_ = fp_->get_pos();
 
728
 
 
729
    /* 
 
730
     *   write a placeholder object count, the metaclass dependency table
 
731
     *   index, and the OBJS flags 
 
732
     */
 
733
    oswp2(buf, 0);
 
734
    oswp2(buf + 2, metaclass_idx);
 
735
    oswp2(buf + 4, flags);
 
736
 
 
737
    /* write the prefix */
 
738
    fp_->write_bytes(buf, 6);
 
739
}
 
740
 
 
741
/*
 
742
 *   Write bytes to an OBJS (object static data) block 
 
743
 */
 
744
void CVmImageWriter::write_objs_bytes(const char *buf, uint32 siz)
 
745
{
 
746
    /* write the buffer */
 
747
    fp_->write_bytes(buf, siz);
 
748
}
 
749
 
 
750
/*
 
751
 *   end an object static data block
 
752
 */
 
753
void CVmImageWriter::end_objs_block(uint object_count)
 
754
{
 
755
    long pos;
 
756
 
 
757
    /* remember the current file write position for a moment */
 
758
    pos = fp_->get_pos();
 
759
 
 
760
    /* go back and fix up the object count in the header */
 
761
    fp_->set_pos(objs_prefix_);
 
762
    fp_->write_int2(object_count);
 
763
 
 
764
    /* seek back to the original position */
 
765
    fp_->set_pos(pos);
 
766
    
 
767
    /* end the block */
 
768
    end_block();
 
769
}
 
770
 
 
771
/* ------------------------------------------------------------------------ */
 
772
/*
 
773
 *   SRCF blocks - source file descriptors 
 
774
 */
 
775
 
 
776
/*
 
777
 *   begin a SRCF block 
 
778
 */
 
779
void CVmImageWriter::begin_srcf_block(int count)
 
780
{
 
781
    /* 
 
782
     *   begin the block - SRCF blocks are always optional, since they're
 
783
     *   purely for debugging purposes 
 
784
     */
 
785
    begin_block("SRCF", FALSE);
 
786
 
 
787
    /* write the number of entries */
 
788
    fp_->write_int2(count);
 
789
 
 
790
    /* each source line record is 8 bytes in the current format */
 
791
    fp_->write_int2(8);
 
792
}
 
793
 
 
794
/*
 
795
 *   begin a SRCF file entry 
 
796
 */
 
797
void CVmImageWriter::begin_srcf_entry(int orig_index, const char *fname)
 
798
{
 
799
    size_t len;
 
800
 
 
801
    /* remember where this entry starts, so we can fix up the size later */
 
802
    srcf_entry_pos_ = fp_->get_pos();
 
803
 
 
804
    /* write a placeholder size entry */
 
805
    fp_->write_int4(0);
 
806
    
 
807
    /* write the original index */
 
808
    fp_->write_int2(orig_index);
 
809
 
 
810
    /* write the length of the name */
 
811
    len = get_strlen(fname);
 
812
    fp_->write_int2(len);
 
813
 
 
814
    /* write the filename */
 
815
    fp_->write_bytes(fname, len);
 
816
 
 
817
    /* we have no line record yet, so write a placeholder count */
 
818
    srcf_line_pos_ = fp_->get_pos();
 
819
    fp_->write_int4(0);
 
820
    srcf_line_cnt_ = 0;
 
821
}
 
822
 
 
823
/*
 
824
 *   write a SRCF line record entry 
 
825
 */
 
826
void CVmImageWriter::write_srcf_line_entry(ulong linenum, ulong addr)
 
827
{
 
828
    /* write the line number and address */
 
829
    fp_->write_int4(linenum);
 
830
    fp_->write_int4(addr);
 
831
 
 
832
    /* count it */
 
833
    ++srcf_line_cnt_;
 
834
}
 
835
 
 
836
/*
 
837
 *   end a SRCF file entry 
 
838
 */
 
839
void CVmImageWriter::end_srcf_entry()
 
840
{
 
841
    ulong pos;
 
842
 
 
843
    /* go back and fix up the line record count */
 
844
    pos = fp_->get_pos();
 
845
    fp_->set_pos(srcf_line_pos_);
 
846
    fp_->write_int4(srcf_line_cnt_);
 
847
 
 
848
    /* go back and fix up the total entry size record */
 
849
    fp_->set_pos(srcf_entry_pos_);
 
850
    fp_->write_int4(pos - srcf_entry_pos_);
 
851
 
 
852
    /* seek back to the end of the block */
 
853
    fp_->set_pos(pos);
 
854
 
 
855
}
 
856
 
 
857
/*
 
858
 *   end a SRCF block 
 
859
 */
 
860
void CVmImageWriter::end_srcf_block()
 
861
{
 
862
    /* end the block using the generic mechanism */
 
863
    end_block();
 
864
}
 
865
 
 
866
/* ------------------------------------------------------------------------ */
 
867
/* 
 
868
 *   MACR blocks - global preprocess macro symbol table 
 
869
 */
 
870
 
 
871
/* 
 
872
 *   begin a MACR block 
 
873
 */
 
874
void CVmImageWriter::begin_macr_block()
 
875
{
 
876
    /* 
 
877
     *   write the header - it's an optional block since it's for the
 
878
     *   debugger's use only 
 
879
     */
 
880
    begin_block("MACR", FALSE);
 
881
}
 
882
 
 
883
/*
 
884
 *   end a MACR block 
 
885
 */
 
886
void CVmImageWriter::end_macr_block()
 
887
{
 
888
    /* end the block using the generic mechanism */
 
889
    end_block();
 
890
}
 
891
 
 
892
/* ------------------------------------------------------------------------ */
 
893
/*
 
894
 *   GSYM blocks - global symbol table
 
895
 */
 
896
 
 
897
/*
 
898
 *   begin a GSYM block 
 
899
 */
 
900
void CVmImageWriter::begin_gsym_block()
 
901
{
 
902
    /* 
 
903
     *   begin the block - GSYM blocks are always optional, since they're
 
904
     *   purely for debugging purposes 
 
905
     */
 
906
    begin_block("GSYM", FALSE);
 
907
 
 
908
    /* remember where the prefix goes so we can fix it up later */
 
909
    gsym_prefix_ = fp_->get_pos();
 
910
 
 
911
    /* write a placehodler object count and the metaclass index */
 
912
    fp_->write_int4(0);
 
913
}
 
914
 
 
915
/*
 
916
 *   write a GSYM entry 
 
917
 */
 
918
void CVmImageWriter::write_gsym_entry(const char *sym, size_t sym_len,
 
919
                                      int type_id,
 
920
                                      const char *dat, size_t dat_len)
 
921
{
 
922
    /* 
 
923
     *   write the length of the symbol, length of the extra data, and the
 
924
     *   symbol type 
 
925
     */
 
926
    fp_->write_int2(sym_len);
 
927
    fp_->write_int2(dat_len);
 
928
    fp_->write_int2(type_id);
 
929
 
 
930
    /* write the symbol name */
 
931
    fp_->write_bytes(sym, sym_len);
 
932
 
 
933
    /* write the extra data */
 
934
    fp_->write_bytes(dat, dat_len);
 
935
}
 
936
 
 
937
/*
 
938
 *   end a GSYM block 
 
939
 */
 
940
void CVmImageWriter::end_gsym_block(ulong cnt)
 
941
{
 
942
    long pos;
 
943
 
 
944
    /* remember the current file write position for a moment */
 
945
    pos = fp_->get_pos();
 
946
 
 
947
    /* go back and fix up the count in the header */
 
948
    fp_->set_pos(gsym_prefix_);
 
949
    fp_->write_int4(cnt);
 
950
 
 
951
    /* seek back to the original position */
 
952
    fp_->set_pos(pos);
 
953
    
 
954
    /* end the block using the generic mechanism */
 
955
    end_block();
 
956
}
 
957
 
 
958
/* ------------------------------------------------------------------------ */
 
959
/*
 
960
 *   MHLS blocks - method header list
 
961
 */
 
962
 
 
963
/*
 
964
 *   begin an MHLS block
 
965
 */
 
966
void CVmImageWriter::begin_mhls_block()
 
967
{
 
968
    /* 
 
969
     *   begin the block - MHLS blocks are always optional, since they're
 
970
     *   purely for debugging purposes 
 
971
     */
 
972
    begin_block("MHLS", FALSE);
 
973
 
 
974
    /* remember where the count goes so we can fix it up later */
 
975
    mhls_cnt_pos_ = fp_->get_pos();
 
976
 
 
977
    /* write a placehodler count */
 
978
    fp_->write_int4(0);
 
979
 
 
980
    /* there are no entries yet */
 
981
    mhls_cnt_ = 0;
 
982
}
 
983
 
 
984
/*
 
985
 *   write an MHLS entry 
 
986
 */
 
987
void CVmImageWriter::write_mhls_entry(ulong addr)
 
988
{
 
989
    /* write the address */
 
990
    fp_->write_int4(addr);
 
991
 
 
992
    /* count the entry */
 
993
    ++mhls_cnt_;
 
994
}
 
995
 
 
996
/*
 
997
 *   end an MHLS block 
 
998
 */
 
999
void CVmImageWriter::end_mhls_block()
 
1000
{
 
1001
    long pos;
 
1002
 
 
1003
    /* remember the current file write position for a moment */
 
1004
    pos = fp_->get_pos();
 
1005
 
 
1006
    /* go back and fix up the count in the header */
 
1007
    fp_->set_pos(mhls_cnt_pos_);
 
1008
    fp_->write_int4(mhls_cnt_);
 
1009
 
 
1010
    /* seek back to the original position */
 
1011
    fp_->set_pos(pos);
 
1012
 
 
1013
    /* end the block using the generic mechanism */
 
1014
    end_block();
 
1015
}
 
1016
 
 
1017
/* ------------------------------------------------------------------------ */
 
1018
/*
 
1019
 *   SINI block - static initializer list
 
1020
 */
 
1021
 
 
1022
/*
 
1023
 *   begin an SINI block
 
1024
 */
 
1025
void CVmImageWriter::begin_sini_block(ulong static_cs_ofs, ulong init_cnt)
 
1026
{
 
1027
    /* 
 
1028
     *   begin the block - SINI blocks are mandatory, since the program
 
1029
     *   depends upon static initializers being evaluated immediately
 
1030
     *   after compilation 
 
1031
     */
 
1032
    begin_block("SINI", TRUE);
 
1033
 
 
1034
    /* 
 
1035
     *   write the size of our header (including the size prefix); this
 
1036
     *   serves as a simple versioning flag so we can tell if fields added
 
1037
     *   at a later date are part of a given image file's data or not (if
 
1038
     *   the header is too small to contain them, they're not present) 
 
1039
     */
 
1040
    fp_->write_int4(12);
 
1041
 
 
1042
    /* write the starting static code segment offset */
 
1043
    fp_->write_int4(static_cs_ofs);
 
1044
 
 
1045
    /* write the initializer count */
 
1046
    fp_->write_int4(init_cnt);
 
1047
}
 
1048
 
 
1049
/*
 
1050
 *   end an SINI block 
 
1051
 */
 
1052
void CVmImageWriter::end_sini_block()
 
1053
{
 
1054
    /* end the block using the generic mechanism */
 
1055
    end_block();
 
1056
}
 
1057