cfad47cfa3/tads3/vmwrtimg.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/vmwrtimg.h,v 1.4 1999/07/11 00:46:59 MJRoberts Exp $ */
2
3
/* 
4
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
5
 *   
6
 *   Please see the accompanying license file, LICENSE.TXT, for information
7
 *   on using and copying this software.  
8
 */
9
/*
10
Name
11
  vmwrtimg.h - T3 Image File Writer utility functions
12
Function
13
  
14
Notes
15
  
16
Modified
17
  04/04/99 MJRoberts  - Creation
18
*/
19
20
#ifndef VMWRTIMG_H
21
#define VMWRTIMG_H
22
23
#include "t3std.h"
24
#include "vmtype.h"
25
26
27
class CVmImageWriter
28
{
29
public:
30
    /* create an image writer with a given output file */
31
    CVmImageWriter(class CVmFile *fp);
32
33
    /* delete the image writer */
34
    ~CVmImageWriter();
35
36
    /* get the current seek location in the underlying file */
37
    long get_pos() const;
38
39
    /* 
40
     *   Prepare the file: write out the fixed header information.  This
41
     *   should be called once, before doing any other writing.  'vsn' is
42
     *   the image file version number to store in the file.
43
     */
44
    void prepare(uint vsn, const char tool_data[4]);
45
46
    /*
47
     *   Begin a block with the specified ID (a four-byte string).  Writes
48
     *   the block header, and remembers where the block starts so that
49
     *   the size prefix can be stored when the block is finished.  Blocks
50
     *   cannot be nested; starting a new block automatically ends the
51
     *   previous block.  
52
     */
53
    void begin_block(const char *block_id, int mandatory);
54
55
    /*
56
     *   End the current block. 
57
     */
58
    void end_block();
59
60
    /* write raw bytes to the image file */
61
    void write_bytes(const char *ptr, uint32 siz);
62
63
    /* 
64
     *   Write a complete entrypoint block, given the code offset of the
65
     *   entrypoint and the various table entry sizes.  If a block is in
66
     *   progress, this will terminate it.  
67
     */
68
    void write_entrypt(uint32 entry_ofs, size_t method_header_size,
69
                       size_t exc_entry_size, size_t line_entry_size,
70
                       size_t dbg_hdr_size, size_t dbg_lclsym_hdr_size,
71
                       int dbg_vsn_id);
72
73
    /*
74
     *   Write a complete function set dependency block, given an array of
75
     *   function set names.  If a block is in progress, this will
76
     *   terminate it.
77
     */
78
    void write_func_dep(const char **funcset_names, int count);
79
80
    /*
81
     *   Write a complete metaclass dependency block, given an array of
82
     *   metaclass names.  If a block is in progress, this will terminate
83
     *   it. 
84
     */
85
    void write_meta_dep(const char **metaclass_names, int count);
86
87
    /*
88
     *   Write a metaclass dependency block in pieces.  Call
89
     *   begin_meta_dep() with the number of metaclasses, then call
90
     *   write_meta_dep_item() to write each item, and finally call
91
     *   end_meta_dep() to finish the block.
92
     */
93
    void begin_meta_dep(int count);
94
    void write_meta_dep_item(const char *metaclass_name);
95
    void write_meta_item_prop(uint prop_id);
96
    void end_meta_prop_list();
97
    void end_meta_dep();
98
99
    /*
100
     *   Write a function set dependency block in pieces 
101
     */
102
    void begin_func_dep(int count)
103
        { begin_dep_block("FNSD", count); }
104
    void write_func_dep_item(const char *funcset_name)
105
        { write_dep_block_item(funcset_name); }
106
    void end_func_dep()
107
        { end_dep_block(); }
108
109
    /*
110
     *   Write a constant pool definition block.
111
     */
112
    void write_pool_def(uint pool_id, uint32 page_count, uint32 page_size,
113
                        int mandatory);
114
115
    /*
116
     *   Fix up a constant pool definition block with the actual number of
117
     *   pages.  This can be used, if desired, to wait to determine the
118
     *   actual number of pages in a given constant pool until after
119
     *   writing the pages.  Since the pool definition block must precede
120
     *   the pool's first page block in the image file, it's impossible to
121
     *   wait until after writing all of the pages to write the definition
122
     *   block.  Instead, the caller must write the pool definition block
123
     *   first, using a temporary placeholder value for the page_count (0
124
     *   will suffice), then write the pool pages, then use this to fix up
125
     *   the pool definition block with the actual number of pages.  The
126
     *   caller must note the seek position prior to writing the pool
127
     *   definition block, so that we can seek back to that position to
128
     *   fix up the definition block.
129
     *   
130
     *   Callers need not use this function if they know the actual number
131
     *   of pages in the pool when writing the original pool definition
132
     *   block.  
133
     */
134
    void fix_pool_def(long def_seek_ofs, uint32 page_count);
135
136
    /*
137
     *   Write a constant/code pool page.  This writes the entire page
138
     *   with its header and data in a single operation; this is the
139
     *   easiest way to write a page when the page has been fully
140
     *   constructed in a single memory block in advance.  
141
     */
142
    void write_pool_page(uint pool_id, uint32 page_index,
143
                         const char *page_data, uint32 page_data_size,
144
                         int mandatory, uchar xor_mask);
145
146
    /*
147
     *   Write a constant/code pool page in pieces.  These routines can be
148
     *   used when the data in the page are not contiguous in memory and
149
     *   must be written in pieces.  Start by calling begin_pool_page(),
150
     *   then call write_pool_page_bytes() for each item; the items are
151
     *   written contiguously to the page.  Finish by calling
152
     *   end_pool_page().  
153
     */
154
    void begin_pool_page(uint pool_id, uint32 page_index, int mandatory,
155
                         uchar xor_mask);
156
    void write_pool_page_bytes(const char *buf, uint32 siz, uchar xor_mask);
157
    void end_pool_page();
158
159
    /*
160
     *   Write items in the symbolic names block.  Start with
161
     *   begin_sym_block(), then call the write_sym_item_xxx() functions
162
     *   to write the names.  Finally, call end_sym_block() when done.
163
     */
164
    void begin_sym_block();
165
166
    void write_sym_item_objid(const char *nm, size_t len, ulong obj_id);
167
    void write_sym_item_propid(const char *nm, size_t len, uint prop_id);
168
    void write_sym_item_func(const char *nm, size_t len, ulong code_ofs);
169
    void write_sym_item(const char *nm, size_t nmlen,
170
                        const struct vm_val_t *val);
171
172
    void write_sym_item_objid(const char *nm, ulong obj_id)
173
        { write_sym_item_objid(nm, get_strlen(nm), obj_id); }
174
    void write_sym_item_propid(const char *nm, uint prop_id)
175
        { write_sym_item_propid(nm, get_strlen(nm), prop_id); }
176
    void write_sym_item(const char *nm, const struct vm_val_t *val)
177
        { write_sym_item(nm, get_strlen(nm), val); }
178
179
    void end_sym_block();
180
181
182
    /*
183
     *   Write items in an OBJS (static object data) block.  Start with
184
     *   begin_objs_block(), then call write_objs_bytes() repeatedly to
185
     *   write the bytes.  Finally, call end_objs_block() when done.
186
     *   
187
     *   If the 'large_objects' field is set, the objects in the block use
188
     *   32-bit size fields; otherwise the objects use 16-bit size fields.
189
     *   
190
     *   If 'trans' is true, the objects in this block are transient;
191
     *   otherwise, the objects are non-transient (i.e., persistent).  
192
     */
193
    void begin_objs_block(uint metaclass_idx, int large_objects, int trans);
194
    void write_objs_bytes(const char *buf, uint32 siz);
195
    void end_objs_block(uint object_count);
196
197
    /*
198
     *   Write the items in a SRCF (source file descriptor) block.  Start
199
     *   with begin_srcf_block(), then write the file entries.  For each
200
     *   entry, call begin_src_entry(), then call write_src_line_entry()
201
     *   for each source line debug record, then call end_srcf_entry().
202
     *   Call end_srcf_block() when done with all file entries.  
203
     */
204
    void begin_srcf_block(int count);
205
    void begin_srcf_entry(int orig_index, const char *fname);
206
    void write_srcf_line_entry(ulong linenum, ulong addr);
207
    void end_srcf_entry();
208
    void end_srcf_block();
209
210
    /* 
211
     *   Write the items in a GSYM (global symbol table) block.  Start
212
     *   with begin_gsym_block(), then call write_gsym_entry() repeatedly
213
     *   to write the entries.  Call end_gsym_block() when done. 
214
     */
215
    void begin_gsym_block();
216
    void write_gsym_entry(const char *sym, size_t sym_len,
217
                          int type_id, const char *dat, size_t dat_len);
218
    void end_gsym_block(ulong count);
219
220
    /*
221
     *   Begin MHLS block, write an item, and end the block 
222
     */
223
    void begin_mhls_block();
224
    void write_mhls_entry(ulong code_addr);
225
    void end_mhls_block();
226
227
    /*
228
     *   Begin/end SINI block.  static_cs_ofs is the offset in the code
229
     *   segment of the first static initializer; this is useful in the
230
     *   image file because we can delete all of the code pages starting
231
     *   at this point after pre-initialization is complete.  
232
     */
233
    void begin_sini_block(ulong static_cs_ofs, ulong init_cnt);
234
    void end_sini_block();
235
236
    /* begin/end a MACR (macro symbols) block */
237
    void begin_macr_block();
238
    void end_macr_block();
239
240
    /*
241
     *   Finish the file.  Automatically ends the current block if a block
242
     *   is open, and writes the end-of-file marker. 
243
     */
244
    void finish();
245
246
    /* 
247
     *   get the underlying file object; for some types of blocks, it's
248
     *   simplest for the caller to write the data directly to the underlying
249
     *   file stream without any help from us 
250
     */
251
    class CVmFile *get_fp() const { return fp_; }
252
253
private:
254
    /* write a generic dependency (function set, metaclass) block */
255
    void write_dep_block(const char *block_id, const char **names, int count);
256
257
    /* write a dependency block in pieces */
258
    void begin_dep_block(const char *block_id, int count);
259
    void write_dep_block_item(const char *nm);
260
    void end_dep_block();
261
262
    /* XOR a block of bytes with a mask and write the results to the file */
263
    void xor_and_write_bytes(const char *p, uint32 len, uchar xor_mask);
264
  
265
    /* underlying file */
266
    class CVmFile *fp_;
267
268
    /* 
269
     *   Seek position of start of current block.  If this is zero, no
270
     *   block is currently open. 
271
     */
272
    long block_start_;
273
274
    /* count of symbolic names written so far (for writing SYMD block) */
275
    int symd_cnt_;
276
277
    /* location of metaclass entry next-record offset */
278
    long mcld_ofs_pos_;
279
280
    /* location of metaclass property list count prefix */
281
    long mcld_propcnt_pos_;
282
283
    /* count of properties writeen in a metaclass prop list so far */
284
    int mcld_prop_cnt_;
285
286
    /* seek location of SYMD count prefix, for fixing up at end of block */
287
    long symd_prefix_;
288
289
    /* seek location of OBJS count prefix, for fixup up at end of block */
290
    long objs_prefix_;
291
292
    /* seek location of GSYM count prefix, for fixup at end of block */
293
    long gsym_prefix_;
294
295
    /* start of current SRCF file entry */
296
    long srcf_entry_pos_;
297
298
    /* count of SRCF line entries */
299
    long srcf_line_cnt_;
300
301
    /* position of SRCF line entry for the current file */
302
    long srcf_line_pos_;
303
304
    /* position of MHLS block count entry, and MHLS entry count so far */
305
    long mhls_cnt_pos_;
306
    ulong mhls_cnt_;
307
};
308
309
#endif /* VMWRTIMG_H */
310