1 | /*************************************************************************/ |
2 | /* */ |
3 | /* Language Technologies Institute */ |
4 | /* Carnegie Mellon University */ |
5 | /* Copyright (c) 2001 */ |
6 | /* All Rights Reserved. */ |
7 | /* */ |
8 | /* Permission is hereby granted, free of charge, to use and distribute */ |
9 | /* this software and its documentation without restriction, including */ |
10 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
11 | /* distribute, sublicense, and/or sell copies of this work, and to */ |
12 | /* permit persons to whom this work is furnished to do so, subject to */ |
13 | /* the following conditions: */ |
14 | /* 1. The code must retain the above copyright notice, this list of */ |
15 | /* conditions and the following disclaimer. */ |
16 | /* 2. Any modifications must be clearly marked as such. */ |
17 | /* 3. Original authors' names are not deleted. */ |
18 | /* 4. The authors' names are not used to endorse or promote products */ |
19 | /* derived from this software without specific prior written */ |
20 | /* permission. */ |
21 | /* */ |
22 | /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */ |
23 | /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ |
24 | /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ |
25 | /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */ |
26 | /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ |
27 | /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ |
28 | /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ |
29 | /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ |
30 | /* THIS SOFTWARE. */ |
31 | /* */ |
32 | /*************************************************************************/ |
33 | /* Author: Alan W Black (awb@cs.cmu.edu) */ |
34 | /* Date: January 2001 */ |
35 | /*************************************************************************/ |
36 | /* */ |
37 | /* Const Vals, and macros to define them */ |
38 | /* */ |
39 | /* Before you give up in disgust bear with me on this. Every single */ |
40 | /* line in this file has been *very* carefully decided on after much */ |
41 | /* thought, experimentation and reading more specs of the C language */ |
42 | /* than most people even thought existed. However inspite of that, the */ |
43 | /* result is still unsatisfying from an elegance point of view but the */ |
44 | /* given all the constraints this is probably the best compromise. */ |
45 | /* */ |
46 | /* This file offers macros for defining const cst_vals. I know many */ |
47 | /* are already laughing at me for wanting runtime types on objects and */ |
48 | /* will use this code as exemplars of why this should be done in C++, I */ |
49 | /* say good luck to them with their 4M footprint while I go for my */ |
50 | /* 50K footprint. But I *will* do cst_vals in 8 bytes and I *will* */ |
51 | /* have them defined const so they are in the text segment */ |
52 | /* */ |
53 | /* The problem here is that there is not yet a standard way to do */ |
54 | /* initialization of unions. There is one in the C99 standard and GCC */ |
55 | /* already supports it, but other compilers do not so I can't use that */ |
56 | /* */ |
57 | /* So I need a way to make an object that will have the right 8 bytes */ |
58 | /* for ints, floats, strings and cons cells that will work on any C */ |
59 | /* compiler and will be of type const cst_val. That unfortunately */ |
60 | /* isn't trivial. */ |
61 | /* */ |
62 | /* For the time being ignoring byte order, and address size, which */ |
63 | /* will be ignored in the particular discuss (though dealt with below) */ |
64 | /* I'd like to do something like */ |
65 | /* */ |
66 | /* const cst_val fredi = { CST_VAL_TYPE_INT,-1, 42 }; */ |
67 | /* const cst_val fredf = { CST_VAL_TYPE_FLOAT,-1, 4.2 }; */ |
68 | /* const cst_val freds = { CST_VAL_TYPE_STRING,-1, "42" }; */ |
69 | /* */ |
70 | /* Even if you accept warnings this isn't going to work, if you add */ |
71 | /* extra {} you can get rid of some warnings but the fval/ival/ *vval */ |
72 | /* part isn't going to work, the compiler *may* try to take the value */ |
73 | /* and assign it using the type of the first field defined in the */ |
74 | /* union. This could be made to work for ints and void* as pointers */ |
75 | /* can be used as ints (even of 64 bit architectures) but the float */ |
76 | /* isn't going to work. Casting will cause the float to be changed to */ |
77 | /* an int by CPP which isn't what you want, what you want is that the */ |
78 | /* four byte region gets filled with the four bytes that represent the */ |
79 | /* float itself. Now you could get the four byte represention of the */ |
80 | /* float and pretend that is an int (0xbfff9a4 for 4.2 on intel), that */ |
81 | /* would work but that doesn't seem satifying and I'd need to have a */ |
82 | /* preprocessor that could convert that. You could make atoms always */ |
83 | /* have a pointer to another piece of memory, but that would take up */ |
84 | /* another 4 bytes not just for these constants but all other cst_vals */ |
85 | /* create */ |
86 | /* */ |
87 | /* So you could do */ |
88 | /* */ |
89 | /* const cst_val_int fredi = { CST_VAL_TYPE_INT,-1, 42 }; */ |
90 | /* const cst_val_float fredf = { CST_VAL_TYPE_FLOAT,-1, 4.2 }; */ |
91 | /* const cst_val_string freds = { CST_VAL_TYPE_STRING,-1, "42" }; */ |
92 | /* */ |
93 | /* Though that's a slippery slope I don't want to have these explicit */ |
94 | /* new types, the first short defines the type perfectly adequately */ |
95 | /* and the whole point of runtime types is that there is one object */ |
96 | /* type. */ |
97 | /* */ |
98 | /* Well just initialize them at runtime, but, that isn't thread safe, */ |
99 | /* slows down startup, requires a instance implicitly in the code and */ |
100 | /* on the heap. As these are const, they should go in ROM. */ |
101 | /* */ |
102 | /* At this moment, I think the second version is the least problematic */ |
103 | /* though it makes defining val_consts more unpleasant than they should */ |
104 | /* be and forces changes elsewhere in the code even when the compiler */ |
105 | /* does support initialization of unions */ |
106 | /* */ |
107 | /* */ |
108 | /*************************************************************************/ |
109 | #ifndef _CST_VAL_CONSTS_H__ |
110 | #define _CST_VAL_CONSTS_H__ |
111 | |
112 | #include "cst_val_defs.h" |
113 | |
114 | #include <stdint.h> |
115 | |
116 | /* There is built-in int to string conversions here for numbers */ |
117 | /* up to 20, note if you make this bigger you have to hand change */ |
118 | /* other things too */ |
119 | #define CST_CONST_INT_MAX 19 |
120 | |
121 | #ifndef NO_UNION_INITIALIZATION |
122 | |
123 | /* This is the simple way when initialization of unions is supported */ |
124 | |
125 | #define DEF_CONST_VAL_INT(N,V) const cst_val N = {{.a={.type=CST_VAL_TYPE_INT,.ref_count=-1,.v={.ival=V}}}} |
126 | #define DEF_CONST_VAL_STRING(N,S) const cst_val N = {{.a={.type=CST_VAL_TYPE_STRING,.ref_count=-1,.v={.vval= (void *)S}}}} |
127 | #define DEF_CONST_VAL_FLOAT(N,F) const cst_val N = {{.a={.type=CST_VAL_TYPE_FLOAT,.ref_count=-1,.v={.fval=F}}}} |
128 | #define DEF_CONST_VAL_CONS(N,A,D) const cst_val N = {{.cc={.car=(cst_val *)A,.cdr=(cst_val *)D }}} |
129 | |
130 | extern const cst_val val_int_0; |
131 | extern const cst_val val_int_1; |
132 | extern const cst_val val_int_2; |
133 | extern const cst_val val_int_3; |
134 | extern const cst_val val_int_4; |
135 | extern const cst_val val_int_5; |
136 | extern const cst_val val_int_6; |
137 | extern const cst_val val_int_7; |
138 | extern const cst_val val_int_8; |
139 | extern const cst_val val_int_9; |
140 | extern const cst_val val_int_10; |
141 | extern const cst_val val_int_11; |
142 | extern const cst_val val_int_12; |
143 | extern const cst_val val_int_13; |
144 | extern const cst_val val_int_14; |
145 | extern const cst_val val_int_15; |
146 | extern const cst_val val_int_16; |
147 | extern const cst_val val_int_17; |
148 | extern const cst_val val_int_18; |
149 | extern const cst_val val_int_19; |
150 | extern const cst_val val_int_20; |
151 | extern const cst_val val_int_21; |
152 | extern const cst_val val_int_22; |
153 | extern const cst_val val_int_23; |
154 | extern const cst_val val_int_24; |
155 | |
156 | extern const cst_val val_string_0; |
157 | extern const cst_val val_string_1; |
158 | extern const cst_val val_string_2; |
159 | extern const cst_val val_string_3; |
160 | extern const cst_val val_string_4; |
161 | extern const cst_val val_string_5; |
162 | extern const cst_val val_string_6; |
163 | extern const cst_val val_string_7; |
164 | extern const cst_val val_string_8; |
165 | extern const cst_val val_string_9; |
166 | extern const cst_val val_string_10; |
167 | extern const cst_val val_string_11; |
168 | extern const cst_val val_string_12; |
169 | extern const cst_val val_string_13; |
170 | extern const cst_val val_string_14; |
171 | extern const cst_val val_string_15; |
172 | extern const cst_val val_string_16; |
173 | extern const cst_val val_string_17; |
174 | extern const cst_val val_string_18; |
175 | extern const cst_val val_string_19; |
176 | extern const cst_val val_string_20; |
177 | extern const cst_val val_string_21; |
178 | extern const cst_val val_string_22; |
179 | extern const cst_val val_string_23; |
180 | extern const cst_val val_string_24; |
181 | |
182 | #else |
183 | /* Only GCC seems to currently support the C99 standard for giving */ |
184 | /* explicit names for fields for initializing unions, because we want */ |
185 | /* things to be const, and to be small structures this is really useful */ |
186 | /* thus for compilers not supporting no_union_initization we use other */ |
187 | /* structure that we know (hope ?) are the same size and use agressive */ |
188 | /* casting. The goal here is wholly justified but the method here isn't */ |
189 | /* pretty */ |
190 | |
191 | /* These structures are defined *solely* to get round initialization */ |
192 | /* problems if you need to use these in any code you are using, you are */ |
193 | /* unquestionably doing the wrong thing */ |
194 | typedef struct cst_val_atom_struct_float { |
195 | #ifdef WORDS_BIGENDIAN |
196 | #if UINTPTR_MAX > 0xfffffffful |
197 | int ref_count; |
198 | int type; /* order is here important */ |
199 | #else |
200 | short ref_count; |
201 | short type; /* order is here important */ |
202 | #endif |
203 | #else |
204 | #if UINTPTR_MAX > 0xfffffffful |
205 | int type; /* order is here important */ |
206 | int ref_count; |
207 | #else |
208 | short type; /* order is here important */ |
209 | short ref_count; |
210 | #endif |
211 | #endif |
212 | #if UINTPTR_MAX > 0xfffffffful |
213 | double fval; |
214 | #else |
215 | float fval; |
216 | #endif |
217 | } cst_val_float; |
218 | |
219 | typedef struct cst_val_atom_struct_int { |
220 | #ifdef WORDS_BIGENDIAN |
221 | #if UINTPTR_MAX > 0xfffffffful |
222 | int ref_count; |
223 | int type; /* order is here important (and unintuitive) */ |
224 | #else |
225 | short ref_count; |
226 | short type; /* order is here important (and unintuitive) */ |
227 | #endif |
228 | #else |
229 | #if UINTPTR_MAX > 0xfffffffful |
230 | int type; /* order is here important */ |
231 | int ref_count; |
232 | #else |
233 | short type; /* order is here important */ |
234 | short ref_count; |
235 | #endif |
236 | #endif |
237 | #if UINTPTR_MAX > 0xfffffffful |
238 | long long ival; |
239 | #else |
240 | int ival; |
241 | #endif |
242 | } cst_val_int; |
243 | |
244 | typedef struct cst_val_atom_struct_void { |
245 | #ifdef WORDS_BIGENDIAN |
246 | #if UINTPTR_MAX > 0xfffffffful |
247 | int ref_count; |
248 | int type; /* order is here important */ |
249 | #else |
250 | short ref_count; |
251 | short type; /* order is here important */ |
252 | #endif |
253 | #else |
254 | #if UINTPTR_MAX > 0xfffffffful |
255 | int type; /* order is here important */ |
256 | int ref_count; |
257 | #else |
258 | short type; /* order is here important */ |
259 | short ref_count; |
260 | #endif |
261 | #endif |
262 | void *vval; |
263 | } cst_val_void; |
264 | |
265 | #ifdef WORDS_BIGENDIAN |
266 | #define DEF_CONST_VAL_INT(N,V) const cst_val_int N={-1, CST_VAL_TYPE_INT, V} |
267 | #define DEF_CONST_VAL_STRING(N,S) const cst_val_void N={-1,CST_VAL_TYPE_STRING,(void *)S} |
268 | #define DEF_CONST_VAL_FLOAT(N,F) const cst_val_float N={-1,CST_VAL_TYPE_FLOAT,(float)F} |
269 | #else |
270 | #define DEF_CONST_VAL_INT(N,V) const cst_val_int N={CST_VAL_TYPE_INT,-1,V} |
271 | #define DEF_CONST_VAL_STRING(N,S) const cst_val_void N={CST_VAL_TYPE_STRING,-1,(void *)S} |
272 | #define DEF_CONST_VAL_FLOAT(N,F) const cst_val_float N={CST_VAL_TYPE_FLOAT,-1,(float)F} |
273 | #endif |
274 | #define DEF_CONST_VAL_CONS(N,A,D) const cst_val_cons N={A,D} |
275 | |
276 | /* in the non-union intialization version we these consts have to be */ |
277 | /* more typed than need, we'll cast the back later */ |
278 | extern const cst_val_int val_int_0; |
279 | extern const cst_val_int val_int_1; |
280 | extern const cst_val_int val_int_2; |
281 | extern const cst_val_int val_int_3; |
282 | extern const cst_val_int val_int_4; |
283 | extern const cst_val_int val_int_5; |
284 | extern const cst_val_int val_int_6; |
285 | extern const cst_val_int val_int_7; |
286 | extern const cst_val_int val_int_8; |
287 | extern const cst_val_int val_int_9; |
288 | extern const cst_val_int val_int_10; |
289 | extern const cst_val_int val_int_11; |
290 | extern const cst_val_int val_int_12; |
291 | extern const cst_val_int val_int_13; |
292 | extern const cst_val_int val_int_14; |
293 | extern const cst_val_int val_int_15; |
294 | extern const cst_val_int val_int_16; |
295 | extern const cst_val_int val_int_17; |
296 | extern const cst_val_int val_int_18; |
297 | extern const cst_val_int val_int_19; |
298 | extern const cst_val_int val_int_20; |
299 | extern const cst_val_int val_int_21; |
300 | extern const cst_val_int val_int_22; |
301 | extern const cst_val_int val_int_23; |
302 | extern const cst_val_int val_int_24; |
303 | |
304 | extern const cst_val_void val_string_0; |
305 | extern const cst_val_void val_string_1; |
306 | extern const cst_val_void val_string_2; |
307 | extern const cst_val_void val_string_3; |
308 | extern const cst_val_void val_string_4; |
309 | extern const cst_val_void val_string_5; |
310 | extern const cst_val_void val_string_6; |
311 | extern const cst_val_void val_string_7; |
312 | extern const cst_val_void val_string_8; |
313 | extern const cst_val_void val_string_9; |
314 | extern const cst_val_void val_string_10; |
315 | extern const cst_val_void val_string_11; |
316 | extern const cst_val_void val_string_12; |
317 | extern const cst_val_void val_string_13; |
318 | extern const cst_val_void val_string_14; |
319 | extern const cst_val_void val_string_15; |
320 | extern const cst_val_void val_string_16; |
321 | extern const cst_val_void val_string_17; |
322 | extern const cst_val_void val_string_18; |
323 | extern const cst_val_void val_string_19; |
324 | extern const cst_val_void val_string_20; |
325 | extern const cst_val_void val_string_21; |
326 | extern const cst_val_void val_string_22; |
327 | extern const cst_val_void val_string_23; |
328 | extern const cst_val_void val_string_24; |
329 | |
330 | #endif |
331 | |
332 | #define DEF_STATIC_CONST_VAL_INT(N,V) static DEF_CONST_VAL_INT(N,V) |
333 | #define DEF_STATIC_CONST_VAL_STRING(N,S) static DEF_CONST_VAL_STRING(N,S) |
334 | #define DEF_STATIC_CONST_VAL_FLOAT(N,F) static DEF_CONST_VAL_FLOAT(N,F) |
335 | #define DEF_STATIC_CONST_VAL_CONS(N,A,D) static DEF_CONST_VAL_CONS(N,A,D) |
336 | |
337 | /* Some actual val consts */ |
338 | /* The have casts as in the non-union intialize case the casts are necessary */ |
339 | /* but in the union initial case these casts are harmless */ |
340 | |
341 | #define VAL_INT_0 (cst_val *)&val_int_0 |
342 | #define VAL_INT_1 (cst_val *)&val_int_1 |
343 | #define VAL_INT_2 (cst_val *)&val_int_2 |
344 | #define VAL_INT_3 (cst_val *)&val_int_3 |
345 | #define VAL_INT_4 (cst_val *)&val_int_4 |
346 | #define VAL_INT_5 (cst_val *)&val_int_5 |
347 | #define VAL_INT_6 (cst_val *)&val_int_6 |
348 | #define VAL_INT_7 (cst_val *)&val_int_7 |
349 | #define VAL_INT_8 (cst_val *)&val_int_8 |
350 | #define VAL_INT_9 (cst_val *)&val_int_9 |
351 | #define VAL_INT_10 (cst_val *)&val_int_10 |
352 | #define VAL_INT_11 (cst_val *)&val_int_11 |
353 | #define VAL_INT_12 (cst_val *)&val_int_12 |
354 | #define VAL_INT_13 (cst_val *)&val_int_13 |
355 | #define VAL_INT_14 (cst_val *)&val_int_14 |
356 | #define VAL_INT_15 (cst_val *)&val_int_15 |
357 | #define VAL_INT_16 (cst_val *)&val_int_16 |
358 | #define VAL_INT_17 (cst_val *)&val_int_17 |
359 | #define VAL_INT_18 (cst_val *)&val_int_18 |
360 | #define VAL_INT_19 (cst_val *)&val_int_19 |
361 | #define VAL_INT_20 (cst_val *)&val_int_20 |
362 | #define VAL_INT_21 (cst_val *)&val_int_21 |
363 | #define VAL_INT_22 (cst_val *)&val_int_22 |
364 | #define VAL_INT_23 (cst_val *)&val_int_23 |
365 | #define VAL_INT_24 (cst_val *)&val_int_24 |
366 | |
367 | const cst_val *val_int_n(int n); |
368 | |
369 | #define VAL_STRING_0 (cst_val *)&val_string_0 |
370 | #define VAL_STRING_1 (cst_val *)&val_string_1 |
371 | #define VAL_STRING_2 (cst_val *)&val_string_2 |
372 | #define VAL_STRING_3 (cst_val *)&val_string_3 |
373 | #define VAL_STRING_4 (cst_val *)&val_string_4 |
374 | #define VAL_STRING_5 (cst_val *)&val_string_5 |
375 | #define VAL_STRING_6 (cst_val *)&val_string_6 |
376 | #define VAL_STRING_7 (cst_val *)&val_string_7 |
377 | #define VAL_STRING_8 (cst_val *)&val_string_8 |
378 | #define VAL_STRING_9 (cst_val *)&val_string_9 |
379 | #define VAL_STRING_10 (cst_val *)&val_string_10 |
380 | #define VAL_STRING_11 (cst_val *)&val_string_11 |
381 | #define VAL_STRING_12 (cst_val *)&val_string_12 |
382 | #define VAL_STRING_13 (cst_val *)&val_string_13 |
383 | #define VAL_STRING_14 (cst_val *)&val_string_14 |
384 | #define VAL_STRING_15 (cst_val *)&val_string_15 |
385 | #define VAL_STRING_16 (cst_val *)&val_string_16 |
386 | #define VAL_STRING_17 (cst_val *)&val_string_17 |
387 | #define VAL_STRING_18 (cst_val *)&val_string_18 |
388 | #define VAL_STRING_19 (cst_val *)&val_string_19 |
389 | #define VAL_STRING_20 (cst_val *)&val_string_20 |
390 | #define VAL_STRING_21 (cst_val *)&val_string_21 |
391 | #define VAL_STRING_22 (cst_val *)&val_string_22 |
392 | #define VAL_STRING_23 (cst_val *)&val_string_23 |
393 | #define VAL_STRING_24 (cst_val *)&val_string_24 |
394 | |
395 | const cst_val *val_string_n(int n); |
396 | |
397 | |
398 | #endif |
399 | |