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