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
130extern const cst_val val_int_0;
131extern const cst_val val_int_1;
132extern const cst_val val_int_2;
133extern const cst_val val_int_3;
134extern const cst_val val_int_4;
135extern const cst_val val_int_5;
136extern const cst_val val_int_6;
137extern const cst_val val_int_7;
138extern const cst_val val_int_8;
139extern const cst_val val_int_9;
140extern const cst_val val_int_10;
141extern const cst_val val_int_11;
142extern const cst_val val_int_12;
143extern const cst_val val_int_13;
144extern const cst_val val_int_14;
145extern const cst_val val_int_15;
146extern const cst_val val_int_16;
147extern const cst_val val_int_17;
148extern const cst_val val_int_18;
149extern const cst_val val_int_19;
150extern const cst_val val_int_20;
151extern const cst_val val_int_21;
152extern const cst_val val_int_22;
153extern const cst_val val_int_23;
154extern const cst_val val_int_24;
155
156extern const cst_val val_string_0;
157extern const cst_val val_string_1;
158extern const cst_val val_string_2;
159extern const cst_val val_string_3;
160extern const cst_val val_string_4;
161extern const cst_val val_string_5;
162extern const cst_val val_string_6;
163extern const cst_val val_string_7;
164extern const cst_val val_string_8;
165extern const cst_val val_string_9;
166extern const cst_val val_string_10;
167extern const cst_val val_string_11;
168extern const cst_val val_string_12;
169extern const cst_val val_string_13;
170extern const cst_val val_string_14;
171extern const cst_val val_string_15;
172extern const cst_val val_string_16;
173extern const cst_val val_string_17;
174extern const cst_val val_string_18;
175extern const cst_val val_string_19;
176extern const cst_val val_string_20;
177extern const cst_val val_string_21;
178extern const cst_val val_string_22;
179extern const cst_val val_string_23;
180extern 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 */
194typedef 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
219typedef 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
244typedef 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 */
278extern const cst_val_int val_int_0;
279extern const cst_val_int val_int_1;
280extern const cst_val_int val_int_2;
281extern const cst_val_int val_int_3;
282extern const cst_val_int val_int_4;
283extern const cst_val_int val_int_5;
284extern const cst_val_int val_int_6;
285extern const cst_val_int val_int_7;
286extern const cst_val_int val_int_8;
287extern const cst_val_int val_int_9;
288extern const cst_val_int val_int_10;
289extern const cst_val_int val_int_11;
290extern const cst_val_int val_int_12;
291extern const cst_val_int val_int_13;
292extern const cst_val_int val_int_14;
293extern const cst_val_int val_int_15;
294extern const cst_val_int val_int_16;
295extern const cst_val_int val_int_17;
296extern const cst_val_int val_int_18;
297extern const cst_val_int val_int_19;
298extern const cst_val_int val_int_20;
299extern const cst_val_int val_int_21;
300extern const cst_val_int val_int_22;
301extern const cst_val_int val_int_23;
302extern const cst_val_int val_int_24;
303
304extern const cst_val_void val_string_0;
305extern const cst_val_void val_string_1;
306extern const cst_val_void val_string_2;
307extern const cst_val_void val_string_3;
308extern const cst_val_void val_string_4;
309extern const cst_val_void val_string_5;
310extern const cst_val_void val_string_6;
311extern const cst_val_void val_string_7;
312extern const cst_val_void val_string_8;
313extern const cst_val_void val_string_9;
314extern const cst_val_void val_string_10;
315extern const cst_val_void val_string_11;
316extern const cst_val_void val_string_12;
317extern const cst_val_void val_string_13;
318extern const cst_val_void val_string_14;
319extern const cst_val_void val_string_15;
320extern const cst_val_void val_string_16;
321extern const cst_val_void val_string_17;
322extern const cst_val_void val_string_18;
323extern const cst_val_void val_string_19;
324extern const cst_val_void val_string_20;
325extern const cst_val_void val_string_21;
326extern const cst_val_void val_string_22;
327extern const cst_val_void val_string_23;
328extern 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
367const 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
395const cst_val *val_string_n(int n);
396
397
398#endif
399

source code of include/flite/cst_val_const.h