Subversion Repositories tendra.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 7u83 1
		A Public Domain Tool for producing TDF
2
		-------------------------------------
3
 
4
1. Introduction
5
 
6
The basic idea is to produce the TDF bit encoding using language
7
constructions directly related to the TDF constructors given in the
8
specification document. These constructions have been produced
9
automatically from the document and so updating them in view of further
10
revisions of TDF is a relatively painless exercise. 
11
 
12
There are macros for all of the non-primitive constructors with
13
names given by prefixing the constructor name with o_ ; eg to output the
14
EXP make_top, you simply call the macro o_make_top. A constructor with a
15
number of parameters will correspond to a macro with that number of
16
parameters. The expansion of the macro will check that each parameter
17
outputs the correct TDF SORT.
18
 
19
There are also procedures for outputing primitive SORTS; eg out_tdfbool(b)
20
outputs b as as a TDFBOOL. I have only provided output procedures
21
for primitive SORTs which have simple representations in C eg
22
out_tdfint32(x) outputs the 32 bit integer x as a TDFINT.
23
 
24
To give a flavour of the intended use of the tool, in order to produce
25
the TDF for an assignment, one does:
26
 	o_assign(LHS, RHS)
27
where LHS and RHS are pieces of code which will output the EXPs for the
28
source and destination of the assignment. For example, LHS for a simple
29
variable as destination could be:
30
	o_obtain_tag(o_make_tag(out_tdfint32(A)))
31
where A is the number chosen by the compiler for the variable. Of course,
32
it is unlikely that a compiler would do this directly. LHS will usually be
33
some conditional code which might choose this expansion from its analysis
34
of the program being compiled. Both LHS and RHS (in common with all the
35
parameters of the o_ macros) are statements (not expessions!) whose
36
sequencing is controlled by the macro.
37
 
38
The expansion of o_assign (see encodings.h) is: 
39
#define o_assign(p_arg1,p_arg2)\
40
{  out_basic_int(e_assign, 7);\
41
 p_arg1; ASSERT_SORT(s_exp); \
42
 p_arg2; ASSERT_SORT(s_exp); \
43
SET_RSORT(s_exp);\
44
}
45
The encoding for the EXP assign (ie 6)is given by e_assign (in enc_nos.h)
46
while s_exp (also in enc_nos.h) is a number chosen to represent the sort of
47
an EXP. The procedure out_basic_int (in PD_streams.c) is the most primitive
48
output routine. The macros ASSERT_SORT and SET_RSORT are defined in
49
asserts.h and used to implement the SORT checking.
50
 
51
 
52
2. Stream Mechanisms
53
 
54
The TDF encoding is constructed in streams, represented by the type TDF
55
given in PD_streams.h. 
56
 
57
Each of the output macros and procedures operate on one of these streams
58
given by TDF * current_TDF. For example, the out_basic_int(e_assign, 7) in
59
o_assign above will add 7 bits to current_TDF to encode e_assign.
60
 
61
We have:
62
	typedef struct { Chunk * first; Chunk * last;
63
			 unsigned int no; unsigned int sort;} TDF;
64
The no and sort fields are used to provide the SORT checking mechanism. The
65
first field points to the start of current stream given by a list of
66
Chunks; the last field is the final Chunk in this list, ie the one where the
67
next bits of output will go.
68
 
69
A Chunk is given by:
70
typedef struct chunk_struct
71
		{ struct chunk_struct *next;
72
		  short int usage;
73
		  unsigned char offst; unsigned char aligned;
74
     		  unsigned char data[DATA_SIZE];
75
		} Chunk;
76
The output bits will go into the data field where usage ( <= DATA_SIZE ) is
77
the index of the next character to be written to and offst is the bit
78
position within this character starting from the most significant end (ie
79
offst=0 => no bits written yet into character). The next field is the next
80
Chunk in the stream, terminated by (Chunk*)0; if the the next field is 0
81
then this Chunk will be pointed to be the last field of the corresponding
82
TDF structure.
83
 
84
The a non-zero aligned field indicates that the start of the chunk data must be 
85
on a byte boundary in the final CAPSULE.
86
 
87
Note that the initial Chunks of a stream may not be completely filled; ie
88
usage can less than DATA_SIZE (and offst need no be zero) for any Chunk in
89
the chain.
90
 
91
I have not provided any routines for compressing the Chunks into a
92
contiguous area of mainstore; however the routine make_tdf_file will output
93
a TDF stream to a file. If the contents of the TDF stream is a CAPSULE then
94
this would be a .j file.
95
 
96
 
97
3. Creating and changing streams.
98
 
99
It is usually necessary to have several streams of TDF being produced at
100
the same time. For example, tagdef and tagdec UNITs are often conveniently
101
constructed in parallel; for example, there would usually be at least one
102
for each UNIT being produced in the CAPSULE being compiled. We simply
103
change the  stream in current_TDF. For some constructions,  the macros
104
given below are very convenient - in any case the same pattern should be
105
used.
106
 
107
To create a new stream of output in a variable of type TDF , use the macro
108
NEW_STREAM given in PD_streams.h:
109
 
110
#define NEW_STREAM(ptrtoTDF, make_stream)\
111
{ TDF * hold_;\
112
  hold_ = current_TDF;\
113
  current_TDF = ptrtoTDF;\
114
  current_TDF->first = current_TDF->last = create_chunk();\
115
  make_stream;\
116
  current_TDF = hold_;\
117
}	
118
 
119
Here ptrtoTDF is some TDF* where the new stream is to be produced and
120
make_stream is code to produce the bits of the stream. NEW_STREAM will park
121
the current stream while the new stream is being produced, re-instating it
122
after it is finished. For example:
123
	TDF new_stream;
124
	NEW_STREAM( & new_stream, o_make_top)
125
will produce a stream containing make_top in new_stream, leaving the
126
current stream unchanged. To add more to new_stream later, one would do:
127
	CONT_STREAM( & new_stream, more_bits)
128
 
129
Notice that NEW_STREAM(x,y) is just the same as:
130
	CONT_STREAM(x, 
131
		current_TDF->first = current_TDF->last = create_chunk(); y)
132
 
133
 
134
Having constructed a new stream, it can be appended onto the current stream
135
using the procedure: 
136
	void append_TDF(TDF * tdf, Bool free_it)
137
Here, free_it says whether the Chunks of tdf can be freed and reused. For
138
example, append_tdf( & new_stream, 1) will append new_stream onto
139
current_TDF, allowing the Chunks of new_stream to be resused (see
140
create_chunk and free_chunk in PD_streams.c). The variable new_stream can
141
then only be used as another output stream using NEW_STREAM.
142
If one wished to copy new_stream onto the end of the current stream leaving
143
its Chunks intact, use free_it = 0.
144
 
145
A similar, more specialised, method of appending is given by:
146
	void append_bytestream(TDF * tdf, Bool free_it)
147
which makes tdf into a BYTESTREAM and appends it onto current_TDF. This
148
would only be used for encoding a UNIT.
149
 
150
 
151
4. Encodings
152
 
153
The encoding macros of those construction which have encoding numbers
154
output the encoding number for the construction in the number of bits
155
appropriate to its SORT using:
156
	void out_basic_int(long num, int bts)
157
num is output to current_TDF in bts bits. This is the most primitive output
158
routine and all the others use it, eg out_tdfint32 does the appropriate
159
number of out_basic_int(oct_digit, 4).
160
 
161
The encoding numbers of each construction given by the o_ macros in
162
encodings.h may be found in enc_nos.h
163
 
164
The parameters of a construction are output after the encoding number, so
165
that many constructions are sequences of encoding numbers and the encodings
166
of primitive sorts, implicitly bracketed by the signatures of the
167
constructions involved.
168
 
169
There are five procedures provided to give primitive encodings in
170
PD_streams.c:
171
 void out_tdfint32(unsigned long n);
172
 	- outputs n as a TDFINT - assumes long is 32 bits.
173
 void out_extendable_int(unsigned long num, unsigned int bts);
174
 	- outputs num as extentable encoding in bts bits (see spec 7.3.3)
175
 void out_tdfbool(Bool b);
176
 	- outputs b as a TDFBOOL
177
 void out_tdfstring_bytes (unsigned char * s, unsigned int k,
178
 					unsigned int n);
179
 	- outputs s as a TDFSTRING with k elements of size k bits.
180
 void out_tdfident_bytes (unsigned char * s)
181
 	- outputs s as a TDFIDENT, putting in the appropriate alignments
182
 	necessary.
183
Other will be required for total generality; for example, it will become
184
necessary to create TDFINTs of size greater than 32 bits.
185
 
186
A procedure which can output a TDF stream (usually it would be a complete
187
CAPSULE - a .j file) is given by:
188
  void make_tdf_file(TDF * s, FILE * out_file)
189
This is in mke_tdf_file.c
190
 
191
 
192
 
193
5. LISTs and OPTIONs
194
 
195
Many of the TDF constructors have LIST parameters with special encoding
196
giving the number of elements in the LIST. The o_ macros take account of
197
these by invoking the macro TDF_LIST. With the use of the LIST_ELEM macro,
198
the number of elements are counted as they are output and used to provide
199
the prefix of the encoding of the LIST. For example, a sequence S1; S2; S3
200
would be encoded: 
201
	o_sequence( {LIST_ELEM(S1); LIST_ELEM(S2)}, S3)
202
The SORT checking is not foolproof here; in a LIST there must be no output
203
other than that in the parameter of a LIST_ELEM. In the above example, the
204
SORTS of S1 and S2 will be checked to see that they are EXPs, but there is
205
no check to see that nothing has been output between LIST_ELEM(S1) and
206
LIST_ELEM(S2).
207
 
208
The mechanism for this is quite simple. The macro call of TDF_LIST in
209
o_sequence (for example) creates a new stream into which the list elements
210
will be output; each LIST_ELEM will increment the no field of the stream;
211
the final number will be output to the original stream and the new stream
212
appended to it.
213
 
214
A similar mechanism is used for OPTIONal parameters. This time the o_ macro
215
invokes TDF_OPTION and the actual parameter has the choice of either
216
outputing nothing or something of the correct SORT using the OPTION macro.
217
For example, a procedure application has an optional var_param parameter;
218
with a empty option we have:
219
	o_apply_proc(Shape, Proc, Pars, {})
220
while with a real var_param V:
221
	o_apply_proc(Shape, Proc, Pars, OPTION(V))
222
 
223
 
224
6. BITSTREAMs
225
 
226
Most of the constructors which use BITSTREAMs are handled transparently by
227
their o_ macros. For example, a shape_cond would be encoded:
228
	o_shape_cond(C, S1, S2)
229
where S1 and S2 simply output SHAPEs normally. The _cond constructors all
230
invoke the macro TDF_COND which provides new streams for both E1 and E2.
231
The number of bits in each is computed using:
232
	long bits_in_TDF(TDF *tdf); 
233
and give the prefix TDFINT for the bitstreams required by the _cond
234
construction.
235
 
236
Similarly all the _apply_token constructors work in the same fashion, this
237
time using the TOK_APP macro. Here, of course, there is no SORT check
238
possible on the parameter applied to the token. An EXP token, T,  with two
239
parameters, P1 and P2,is applied using: o_exp_apply_token(T, {P1; P2}) ie
240
the token parameters are simply output sequentially.
241
 
242
The other BITSTREAMs are all derived from token_definition which is rather
243
peculiar in that the SORT of the body parameter depends on its result_sort
244
parameter. The o_token_definition macro is to be found in PD_streams.h
245
rather than in encodings.h and its SORT is described as s_bitstream rather
246
than s_token_definition as one might expect. Otherwise, it can used in the
247
same way as the other o_ macros. Note that the SORT of the body parameter
248
is not checked to be consistent with its result_sort parameter.  
249
 
250
 
251
7. Summary
252
 
253
Files:
254
	encodings.h
255
	  - contains all the o_ macros except for o_token_definition.
256
	enc_nos.h
257
	  - contains the e_ encoding numbers an s_ sort numbers.
258
	PD_streams.h
259
	  - declares the stream procedures, the primitive encodings and the 
260
	    stream changing and creation macros, together with
261
	    o_token_definition.		
262
	PD_streams.c
263
	  - defines the stream procedures and primitive encodings.
264
	asserts.h
265
	  - defines the macros which control the SORT checking;
266
	    can be modified to eliminate SORT checking.
267
	proto_def.h
268
	  - defines the macro proto to allow prototypes in declarations.
269
 
270
All output will be directed at: 
271
	TDF * current_TDF;
272
 
273
Primitive encoding procedures:
274
	void out_basic_int(unsigned long num, unsigned int bts);
275
	void out_extendable_int(unsigned long num, unsigned int bts);
276
	void out_tdfint32(unsigned long n);
277
	void out_tdfstring_bytes(unsigned char * s, unsigned int k,
278
 					unsigned int n);
279
	void out_tdfbool(Bool b);
280
 
281
Stream handling procedures:
282
	void append_TDF(TDF * tdf, Bool free_it);
283
	void append_bytestream(TDF *tdf, Bool free_it);	
284
	long bits_in_TDF(TDF *tdf);
285
 
286
Chunk handling procedures:
287
	Chunk * create_chunk();
288
	void free_chunk(Chunk * x);
289
 
290
Stream macros:
291
	NEW_STREAM(ptrtoTDF, make_stream)
292
	CONT_STREAM(ptrtoTDF, make_stream)
293
   These are used by the o_ macros:
294
   	TDF_COND(code_, sort_, exp_, arg1, arg2)
295
   	TDF_LIST(x, sort_)
296
   	   - an actual x parameter will contain only LIST_ELEM(...)s
297
   	TDF_OPTION(x, sort_)
298
   	   - an actual x parameter will have no output or one OPTION(...) 
299
   	TOK_APP(num_, sort_, tok_, pars_)
300
 
301
 
302
 
303
8. Appendix
304
 
305
There are four other files included which may be useful. They are:
306
	decodings.c
307
	  - contains d_X procedures, where X is a TDF non-primitive SORT;
308
	    when used with readstream.c, the d_ procedures will give a
309
	    diagnostic print of TDF in the above stream format. 
310
	readstream.c
311
	  - defines the primitive decoding and printing for stream format.
312
	readstream.h
313
	  - declares the primitive decodings.
314
	mke_tdf_file.c
315
	  - usually used to output the completed CAPSULE as a .j file.	   	   	
316
 
317
		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318
 
319
Please direct any comments or complaints to:
320
	Ian Currie, DRA, Malvern
321
	E-mail: currie@uk.mod.hermes