summaryrefslogtreecommitdiff
path: root/include/mach/flick_mach3_glue.h
blob: 7deb6203a7e99af9ed53f4bd5ccf7e7bce7fecc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* 
 * Copyright (c) 1995 The University of Utah and
 * the Computer Systems Laboratory at the University of Utah (CSL).
 * All rights reserved.
 *
 * Permission to use, copy, modify and distribute this software is hereby
 * granted provided that (1) source code retains these copyright, permission,
 * and disclaimer notices, and (2) redistributions including binaries
 * reproduce the notices in supporting documentation, and (3) all advertising
 * materials mentioning features or use of this software display the following
 * acknowledgement: ``This product includes software developed by the
 * Computer Systems Laboratory at the University of Utah.''
 *
 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
 * improvements that they make and grant CSL redistribution rights.
 *
 *      Author: Bryan Ford, University of Utah CSL
 */
/*
 * Glue for the Flick's Mach 3 backend.  (Flick := Flexible IDL Compiler Kit.)
 * This file is included from every stub source code (.c) file generated by that backend.
 * Stubs are built primarily out of invocations of these macros.
 */
#ifndef _MACH_FLICK_MACH3_GLUE_H_
#define _MACH_FLICK_MACH3_GLUE_H_

#include <stdlib.h>
#include <string.h>
#include <mach/flick_mach3.h>


/*** Internal Flick data types ***/

/* Each client stub allocates one of these on its stack first thing,
   and holds all the important generic state throughout RPC processing.  */
struct flick_mach3_rpc_desc
{
	/* This is initially set to point to init_buf,
	   but is dynamically re-allocated if more space is needed.  */
	char *msg_buf;
	vm_size_t msg_buf_size;

	/* Before calling flick_mach3_rpc(),
	   the client stub sets this to the offset of the end of the data it marshaled.
	   It always starts marshaling at offset 4*4, to leave room for a mach_msg_header
	   (which is actually 6*4 bytes, but overwrites the 2*4-byte marshaled IDL ID).  */
	vm_size_t send_end_ofs;

	/* flick_mach3_rpc() sets these to the offset of the data to unmarshal,
	   and the offset of the end of the data to unmarshal, respectively.  */
	vm_size_t rcv_ofs, rcv_end_ofs;

	/* The size of this buffer varies from stub to stub.  */
	char init_buf[0];
};

/* Each server stub allocates one of these on its stack first thing,
   and holds all the important generic state throughout RPC processing.  */
struct flick_mach3_rpc_serv_desc
{
	/* This is initially set to point to init_buf,
	   but is dynamically re-allocated if more space is needed.  */
	char *msg_buf;
	vm_size_t msg_buf_size;

	/* Before calling flick_mach3_rpc(),
	   the client stub sets this to the offset of the end of the data it marshaled.
	   It always starts marshaling at offset 4*4, to leave room for a mach_msg_header
	   (which is actually 6*4 bytes, but overwrites the 2*4-byte marshaled IDL ID).  */
	vm_size_t send_end_ofs;

	/* flick_mach3_rpc() sets these to the offset of the data to unmarshal,
	   and the offset of the end of the data to unmarshal, respectively.  */
	vm_size_t rcv_ofs, rcv_end_ofs;

	/* The size of this buffer varies from stub to stub.  */
	char init_buf[0];
};


/*** Encoding ***/

#define flick_mach3_encode_new_glob(max_size)						\
{											\
	while (_desc.d.send_end_ofs + (max_size) > _desc.d.msg_buf_size)		\
	{										\
		mach_msg_return_t result = flick_mach3_rpc_grow_buf(&_desc);		\
		/*XXX result */								\
	}										\
	_e_chunk = _desc.d.msg_buf + _desc.d.send_end_ofs;				\
}
#define flick_mach3_encode_end_glob(max_size)						\
	_desc.d.send_end_ofs += (max_size);

#define flick_mach3_encode_new_chunk(size)	/* do nothing */
#define flick_mach3_encode_end_chunk(size)	(_e_chunk += (size))

#define flick_mach3_encode_prim(_ofs, _data, _name, _bits, _ctype)			\
{											\
	struct { mach_msg_type_t _t; _ctype _v; } *_p = (void*)(_e_chunk + _ofs);	\
	mach_msg_type_t _tmpl = { _name, _bits, 1, 1, 0, 0 };				\
	_p->_t = _tmpl; _p->_v = (_data);						\
}

#define flick_mach3_encode_boolean(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_BOOLEAN, 32, signed32_t);

#define flick_mach3_encode_char8(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_CHAR, 8, signed8_t);
#define flick_mach3_encode_char16(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 8, signed16_t);

#define flick_mach3_encode_signed8(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_8, 8, signed8_t);
#define flick_mach3_encode_unsigned8(ofs, data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_8, 8, unsigned8_t);
#define flick_mach3_encode_signed16(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 16, signed16_t);
#define flick_mach3_encode_unsigned16(ofs, data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 16, unsigned16_t);
#define flick_mach3_encode_signed32(_ofs, _data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_32, 32, signed32_t);
#define flick_mach3_encode_unsigned32(ofs, data)	\
	flick_mach3_encode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_32, 32, unsigned32_t);

#define flick_mach3_encode_port(_ofs, _data, _adjust)					\
{											\
	if (_adjust > 1) {								\
		kern_return_t res = mach_port_mod_refs(mach_task_self(), (_data),	\
			MACH_PORT_RIGHT_SEND, -(_adjust-1));				\
	}										\
	flick_mach3_encode_prim(_ofs, _data,						\
		_adjust ? MACH_MSG_TYPE_MOVE_SEND : MACH_MSG_TYPE_COPY_SEND,		\
		32, mach_port_t);							\
}


/*** Decoding ***/

#if TypeCheck
#define flick_iftypecheck(code) code
#else
#define flick_iftypecheck(code)
#endif

#define flick_mach3_decode_new_glob(max_size)
#define flick_mach3_decode_end_glob(max_size)

#define flick_mach3_decode_new_chunk(size)						\
{											\
	flick_iftypecheck(								\
		if (_desc.d.rcv_ofs + (size) > _d_msgsize)				\
			XXX throw MIG_TYPE_ERROR;					\
	);										\
	_d_chunk = _desc.d.msg_buf + _desc.d.rcv_ofs;					\
}
#define flick_mach3_decode_end_chunk(size)						\
	_desc.d.rcv_ofs += (size);

#define flick_mach3_decode_prim(_ofs, _data, _name, _bits, _ctype)			\
{											\
	struct { mach_msg_type_t _t; _ctype _v; } *_p = (void*)(_d_chunk + _ofs);	\
	flick_iftypecheck( ({								\
		mach_msg_type_t _tmpl = { _name, _bits, 1, 1, 0, 0 };			\
		if (*((signed32_t*)&_tmpl) != *((signed32_t)&_p->_t))			\
			XXX throw MIG_TYPE_ERROR;					\
	)} )										\
	(_data) = _p->_v;								\
}

#define flick_mach3_decode_boolean(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_BOOLEAN, 32, signed32_t);

#define flick_mach3_decode_char8(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_CHAR, 8, signed8_t);
#define flick_mach3_decode_char16(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 8, signed16_t);

#define flick_mach3_decode_signed8(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_8, 8, signed8_t);
#define flick_mach3_decode_unsigned8(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_8, 8, unsigned8_t);
#define flick_mach3_decode_signed16(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 16, signed16_t);
#define flick_mach3_decode_unsigned16(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_16, 16, unsigned16_t);
#define flick_mach3_decode_signed32(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_32, 32, signed32_t);
#define flick_mach3_decode_unsigned32(_ofs, _data)	\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_INTEGER_32, 32, unsigned32_t);

#define flick_mach3_decode_port(_ofs, _data, _adjust)					\
{											\
	flick_mach3_decode_prim(_ofs, _data, MACH_MSG_TYPE_PORT_SEND, 32, mach_port_t);	\
	if (_adjust != 1) {								\
		kern_return_t res = mach_port_mod_refs(mach_task_self(), (_data),	\
			MACH_PORT_RIGHT_SEND, _adjust-1);				\
	}										\
}


/*** Client-side support ***/

mach_msg_return_t flick_mach3_rpc(struct flick_mach3_rpc_desc *rpc,
				  mach_port_t send_target, mach_msg_bits_t send_msgh_bits);

#define flick_mach3_rpc_macro(iscomplex)						\
{											\
	kern_return_t result = flick_mach3_rpc(&_desc.d, _msg_request/*XXX*/,		\
		(iscomplex ? MACH_MSGH_BITS_COMPLEX : 0)				\
		| MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE));\
}

#endif /* _MACH_FLICK_MACH3_GLUE_H_ */