1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1991-1994, 1996, 2002-2008, 2012 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18
19 #include <common/ac/assert.h>
20
21 #include <common/fstrcmp.h>
22 #include <common/sizeof.h>
23 #include <common/trace.h>
24 #include <libaegis/aer/expr/name.h>
25 #include <libaegis/aer/value/boolean.h>
26 #include <libaegis/aer/value/enum.h>
27 #include <libaegis/aer/value/integer.h>
28 #include <libaegis/aer/value/real.h>
29 #include <libaegis/aer/value/string.h>
30 #include <libaegis/aer/value/struct.h>
31 #include <libaegis/aer/value/time.h>
32 #include <libaegis/meta_type.h>
33 #include <libaegis/zero.h>
34
35
36 static const char *boolean_s[] =
37 {
38 "false",
39 "true",
40 };
41 static string_ty *boolean_f[SIZEOF(boolean_s)];
42
43
44 const char *
boolean_ename(bool this_thing)45 boolean_ename(bool this_thing)
46 {
47 return (this_thing ? boolean_s[1] : boolean_s[0]);
48 }
49
50
51 static bool
boolean_parse(string_ty * name,void * ptr)52 boolean_parse(string_ty *name, void *ptr)
53 {
54 slow_to_fast(boolean_s, boolean_f, SIZEOF(boolean_s));
55 for (size_t j = 0; j < SIZEOF(boolean_f); ++j)
56 {
57 if (str_equal(name, boolean_f[j]))
58 {
59 *(bool *)ptr = (bool)j;
60 return true;
61 }
62 }
63 return false;
64 }
65
66
67 static string_ty *
boolean_fuzzy(string_ty * name)68 boolean_fuzzy(string_ty *name)
69 {
70 return generic_enum_fuzzy(name, boolean_f, SIZEOF(boolean_f));
71 }
72
73
74 static rpt_value::pointer
boolean_convert(void * this_thing)75 boolean_convert(void *this_thing)
76 {
77 return rpt_value_boolean::create(*(bool *)this_thing);
78 }
79
80
81 static bool
boolean_is_set(void * this_thing)82 boolean_is_set(void *this_thing)
83 {
84 return (*(bool *)this_thing);
85 }
86
87
88 meta_type boolean_type =
89 {
90 "boolean",
91 0, // alloc
92 0, // free
93 boolean_parse,
94 0, // list_parse
95 0, // struct_parse
96 boolean_fuzzy,
97 boolean_convert,
98 boolean_is_set,
99 };
100
101
102 static rpt_value::pointer
integer_convert(void * this_thing)103 integer_convert(void *this_thing)
104 {
105 return rpt_value_integer::create(magic_zero_decode(*(long *)this_thing));
106 }
107
108
109 static bool
integer_is_set(void * this_thing)110 integer_is_set(void *this_thing)
111 {
112 return (*(long *)this_thing != 0);
113 }
114
115
116 meta_type integer_type =
117 {
118 "integer",
119 0, // alloc
120 0, // free
121 0, // enum_parse
122 0, // list_parse
123 0, // struct_parse
124 0, // fuzzy
125 integer_convert,
126 integer_is_set,
127 };
128
129
130 static rpt_value::pointer
time_convert(void * this_thing)131 time_convert(void *this_thing)
132 {
133 return rpt_value_time::create(*(time_t *)this_thing);
134 }
135
136
137 static bool
time_is_set(void * this_thing)138 time_is_set(void *this_thing)
139 {
140 return (*(time_t *)this_thing != 0);
141 }
142
143
144 meta_type time_type =
145 {
146 "time",
147 0, // alloc
148 0, // free
149 0, // enum_parse
150 0, // list_parse
151 0, // struct_parse
152 0, // fuzzy
153 time_convert,
154 time_is_set,
155 };
156
157
158 static rpt_value::pointer
real_convert(void * this_thing)159 real_convert(void *this_thing)
160 {
161 return rpt_value_real::create(*(double *)this_thing);
162 }
163
164
165 static bool
real_is_set(void * this_thing)166 real_is_set(void *this_thing)
167 {
168 return (*(double *)this_thing != 0);
169 }
170
171
172 meta_type real_type =
173 {
174 "real",
175 0, // alloc
176 0, // free
177 0, // enum_parse
178 0, // list_parse
179 0, // struct_parse
180 0, // fuzzy
181 real_convert,
182 real_is_set,
183 };
184
185
186 static rpt_value::pointer
string_convert(void * this_thing)187 string_convert(void *this_thing)
188 {
189 return rpt_value_string::create(nstring(*(string_ty **)this_thing));
190 }
191
192
193 static bool
string_is_set(void * this_thing)194 string_is_set(void *this_thing)
195 {
196 return (*(string_ty **)this_thing != 0);
197 }
198
199
200 meta_type string_type =
201 {
202 "string",
203 0, // alloc
204 0, // free
205 0, // enum_parse
206 0, // list_parse
207 0, // struct_parse
208 0, // fuzzy
209 string_convert,
210 string_is_set,
211 };
212
213
214 void *
generic_struct_parse(void * this_thing,string_ty * name,meta_type ** type_pp,unsigned long * mask_p,int * redefinition_ok_p,type_table_ty * table,size_t table_length)215 generic_struct_parse(void *this_thing, string_ty *name, meta_type **type_pp,
216 unsigned long *mask_p, int *redefinition_ok_p, type_table_ty *table,
217 size_t table_length)
218 {
219 type_table_ty *tp;
220 void *addr;
221 type_table_ty *table_end;
222
223 trace(("generic_struct_parse(this_thing = %p, name = %p, "
224 "type_pp = %p)\n{\n",
225 this_thing, name, type_pp));
226 table_end = table + table_length;
227 addr = 0;
228 for (tp = table; tp < table_end; ++tp)
229 {
230 if (!tp->fast_name)
231 tp->fast_name = str_from_c(tp->name);
232 if (str_equal(name, tp->fast_name))
233 {
234 *type_pp = tp->type;
235 trace_pointer(*type_pp);
236 addr = (char *)this_thing + tp->offset;
237 trace_pointer(addr);
238 *mask_p = tp->mask;
239 *redefinition_ok_p = tp->redefinition_ok;
240 break;
241 }
242 }
243 trace(("return %p;\n}\n", addr));
244 return addr;
245 }
246
247
248 string_ty *
generic_struct_fuzzy(string_ty * name,type_table_ty * table,size_t table_length)249 generic_struct_fuzzy(string_ty *name, type_table_ty *table, size_t table_length)
250 {
251 type_table_ty *tp;
252 type_table_ty *table_end;
253 string_ty *best_name;
254 double best_weight;
255
256 trace(("generic_struct_fuzzy(name = %p)\n{\n", name));
257 table_end = table + table_length;
258 best_name = 0;
259 best_weight = 0.6;
260 for (tp = table; tp < table_end; ++tp)
261 {
262 double weight;
263
264 assert(tp->fast_name);
265 weight = fstrcmp(name->str_text, tp->name);
266 if (weight > best_weight)
267 {
268 best_name = tp->fast_name;
269 best_weight = weight;
270 }
271 }
272 trace(("return %p;\n", best_name));
273 trace(("}\n"));
274 return best_name;
275 }
276
277
278 rpt_value::pointer
generic_struct_convert(void * that,type_table_ty * table,size_t table_length)279 generic_struct_convert(void *that, type_table_ty *table, size_t table_length)
280 {
281 generic_struct *this_thing;
282 type_table_ty *tp;
283 type_table_ty *table_end;
284
285 this_thing = *(generic_struct **)that;
286 if (!this_thing)
287 return rpt_value::pointer();
288 trace(("generic_struct_convert(this_thing = %p)\n{\n",
289 this_thing));
290 table_end = table + table_length;
291 rpt_value_struct *rvs = new rpt_value_struct();
292 rpt_value::pointer result(rvs);
293 for (tp = table; tp < table_end; ++tp)
294 {
295 if (!tp->fast_name)
296 tp->fast_name = str_from_c(tp->name);
297 void *addr = (char *)this_thing + tp->offset;
298 if (tp->mask ? (this_thing->mask & tp->mask) : tp->type->is_set(addr))
299 {
300 rpt_value::pointer vp = tp->type->convert(addr);
301 if (vp)
302 {
303 rvs->assign(tp->name, vp);
304 }
305 }
306 }
307 trace(("return %p;\n}\n", result.get()));
308 return result;
309 }
310
311
312 bool
generic_struct_is_set(void * this_thing)313 generic_struct_is_set(void *this_thing)
314 {
315 return (*(generic_struct **)this_thing != 0);
316 }
317
318
319 string_ty *
generic_enum_fuzzy(string_ty * name,string_ty ** table,size_t table_length)320 generic_enum_fuzzy(string_ty *name, string_ty **table, size_t table_length)
321 {
322 size_t j;
323 string_ty *best_name;
324 double best_weight;
325
326 best_name = 0;
327 best_weight = 0.6;
328 for (j = 0; j < table_length; ++j)
329 {
330 double weight;
331
332 assert(table[j]);
333 weight = fstrcmp(name->str_text, table[j]->str_text);
334 if (weight > best_weight)
335 {
336 best_name = table[j];
337 best_weight = weight;
338 }
339 }
340 return best_name;
341 }
342
343
344 rpt_value::pointer
generic_enum_convert(int n,string_ty ** table,size_t table_length)345 generic_enum_convert(int n, string_ty **table, size_t table_length)
346 {
347 if (n < 0 || n >= (int)table_length)
348 return rpt_value_integer::create(n);
349 assert(table[n]);
350 return rpt_value_enumeration::create(n, nstring(table[n]));
351 }
352
353
354 void
generic_enum__init(const char * const * table,size_t table_length)355 generic_enum__init(const char *const *table, size_t table_length)
356 {
357 for (size_t j = 0; j < table_length; ++j)
358 {
359 nstring name(table[j]);
360 rpt_value::pointer value = rpt_value_enumeration::create(j, name);
361 rpt_expr_name__init(name, value);
362 }
363 }
364
365
366 static int enum_option;
367
368
369 void
type_enum_option_set(void)370 type_enum_option_set(void)
371 {
372 enum_option = 1;
373 }
374
375
376 int
type_enum_option_query(void)377 type_enum_option_query(void)
378 {
379 return enum_option;
380 }
381
382
383 void
type_enum_option_clear(void)384 type_enum_option_clear(void)
385 {
386 enum_option = 0;
387 }
388
389
390 // vim: set ts=8 sw=4 et :
391