1c9ad202912d4d9c2aa14b241721cf6826ab38ee
[fw/sdcc] / sim / ucsim / option.cc
1 /*
2  * Simulator of microcontrollers (option.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include "i_string.h"
34
35   // local, prj
36 #include "stypes.h"
37 #include "optioncl.h"
38 #include "globals.h"
39 #include "utils.h"
40
41   // sim.src
42 #include "simcl.h"
43
44
45 /*
46  * Base class for option's objects
47  *____________________________________________________________________________
48  *
49  */
50
51 cl_option::cl_option(class cl_base *the_creator, char *aname, char *Ihelp):
52   cl_base()
53 {
54   creator= the_creator;
55   set_name(aname);
56   help= strdup(Ihelp);
57   users= new cl_list(2, 2);
58   memset(&value, 0, sizeof(value));
59 }
60
61 class cl_option &
62 cl_option::operator=(class cl_option &o)
63 {
64   //memcpy(&value, &(o.value), sizeof(union option_value));
65   //fprintf(stderr,"opt%p\"%s\"=%p\"%s\"\nold=%p\n",this,object_name(this),&o,object_name(&o),value.sval);
66   value= o.value;
67   //fprintf(stderr,"new=%p\n",value.sval);
68   inform_users();
69   return(*this);
70 }
71
72 cl_option::~cl_option(void)
73 {
74   users->disconn_all();
75   delete users;
76   free(help);
77 }
78
79 void
80 cl_option::pre_remove(void)
81 {
82   int i;
83
84   for (i= 0; i < users->count; i++)
85     {
86       class cl_optref *user= (class cl_optref *)(users->at(i));
87       user->option_removing();
88     }
89 }
90
91 void
92 cl_option::new_reference(class cl_optref *ref)
93 {
94   users->add(ref);
95 }
96
97 void
98 cl_option::del_reference(class cl_optref *ref)
99 {
100   users->disconn(ref);
101 }
102
103 void
104 cl_option::inform_users(void)
105 {
106   int i;
107
108   for (i= 0; i < users->count; i++)
109     {
110       class cl_optref *user= (class cl_optref *)(users->at(i));
111       //fprintf(stderr,"%p\"%s\" informs user %p\"%s\"\n",this,object_name(this),user,object_name(user));
112       user->option_changed();
113     }
114 }
115
116
117 void
118 cl_option::get_value(bool *val)
119 {
120   if (val)
121     *val= value.bval;
122 }
123
124 void
125 cl_option::set_value(bool opt)
126 {
127   value.bval= opt;
128   inform_users();
129 }
130
131
132 void
133 cl_option::get_value(char **val)
134 {
135   if (val)
136     *val= value.sval;
137 }
138
139 void
140 cl_option::set_value(char *opt)
141 {
142   //fprintf(stderr,"set_string_value (%s) to %p\"%s\"\n",opt,this,object_name(this));
143   //fprintf(stderr,"old value=%p\"%s\"\n",value.sval,value.sval);
144   if (value.sval)
145     free(value.sval);
146   if (opt &&
147       *opt)
148     value.sval= strdup(opt);
149   else
150     value.sval= strdup("");
151   //fprintf(stderr,"new value=%p\"%s\"\n",value.sval,value.sval);
152   inform_users();
153 }
154
155
156 /*
157  * List of options
158  */
159
160 void *
161 cl_options::key_of(void *item)
162 {
163   return(((class cl_base *)item)->get_name());
164 }
165
166 int
167 cl_options::compare(void *key1, void *key2)
168 {
169   //class cl_option *k1, *k2;
170   int i;
171   char *k1, *k2;
172
173   k1= /*(class cl_option *)*/(char *)key1;
174   k2= /*(class cl_option *)*/(char *)key2;
175   if ((i= strcmp(k1, k2)) != 0)
176     return(i);
177   return(i);
178 }
179
180 void
181 cl_options::new_option(class cl_option *opt)
182 {
183   add(opt);
184 }
185
186 void
187 cl_options::del_option(class cl_option *opt)
188 {
189   opt->pre_remove();
190   disconn(opt);
191   delete opt;
192 }
193
194 class cl_option *
195 cl_options::get_option(char *the_name)
196 {
197   t_index idx;
198
199   if (search(the_name, idx))
200     return((class cl_option *)(at(idx)));
201   return(0);
202 }
203
204 class cl_option *
205 cl_options::get_option(char *the_name, class cl_base *creator)
206 {
207   t_index idx;
208   class cl_option *o;
209
210   if (!search(the_name, idx))
211     return(0);
212   if (idx > 0)
213     {
214       idx--;
215       o= (class cl_option *)(at(idx));
216       while (compare(the_name, key_of(o)) == 0 &&
217              idx > 0)
218         {
219           idx--;
220           o= (class cl_option *)(at(idx));
221         }
222       if (compare(the_name, key_of(o)) != 0)
223         idx++;
224     }
225   o= (class cl_option *)(at(idx));
226   while (compare(the_name, key_of(o)) == 0 &&
227          o->get_creator() != creator &&
228          idx < count)
229     {
230       idx++;
231       o= (class cl_option *)(at(idx));
232       if (compare(the_name, key_of(o)) == 0 &&
233           o->get_creator() == creator)
234         return(o);
235     }
236   if (compare(the_name, key_of(o)) == 0 &&
237       o->get_creator() == creator)
238     return(o);
239   return(0);
240 }
241
242 class cl_option *
243 cl_options::get_option(char *the_name, char *creator)
244 {
245   t_index idx;
246   class cl_option *o;
247
248   if (!search(the_name, idx))
249     return(0);
250   if (idx > 0)
251     {
252       idx--;
253       o= (class cl_option *)(at(idx));
254       while (compare(the_name, key_of(o)) == 0 &&
255              idx > 0)
256         {
257           idx--;
258           o= (class cl_option *)(at(idx));
259         }
260       if (compare(the_name, key_of(o)) != 0)
261         idx++;
262     }
263   o= (class cl_option *)(at(idx));
264   while (compare(the_name, key_of(o)) == 0 &&
265          strcmp(object_name(o->get_creator()), creator) != 0 &&
266          idx < count)
267     {
268       idx++;
269       o= (class cl_option *)(at(idx));
270       if (compare(the_name, key_of(o)) == 0 &&
271           strcmp(object_name(o->get_creator()), creator) == 0)
272         return(o);
273     }
274   if (compare(the_name, key_of(o)) == 0 &&
275       strcmp(object_name(o->get_creator()), creator) == 0)
276     return(o);
277   return(0);
278 }
279
280 class cl_option *
281 cl_options::get_option(int idx)
282 {
283   if (idx >= count)
284     return(0);
285   return((class cl_option *)(at(idx)));
286 }
287
288 int
289 cl_options::nuof_options(char *the_name)
290 {
291   int i, n= 0;
292
293   for (i= 0; i < count; i++)
294     {
295       class cl_option *o= (class cl_option *)(at(i));
296       if (strcmp(the_name, o->get_name()) == 0)
297         n++;
298     }
299   return(n);
300 }
301
302 int
303 cl_options::nuof_options(char *the_name, char *creator)
304 {
305   int i, n= 0;
306
307   for (i= 0; i < count; i++)
308     {
309       class cl_option *o= (class cl_option *)(at(i));
310       if (strcmp(the_name, o->get_name()) == 0 &&
311           strcmp(creator, object_name(o->get_creator())) == 0)
312         n++;
313     }
314   return(n);
315 }
316
317 class cl_option *
318 cl_options::set_value(char *the_name, cl_base *creator, bool value)
319 {
320   class cl_option *o= get_option(the_name, creator);
321
322   if (o)
323     o->set_value(value);
324   return(o);
325 }
326
327 class cl_option *
328 cl_options::set_value(char *the_name, cl_base *creator, char *value)
329 {
330   class cl_option *o= get_option(the_name, creator);
331
332   if (o)
333     o->set_value(value);
334   return(o);
335 }
336
337
338 /*
339  * Reference to an option
340  */
341
342 cl_optref::cl_optref(class cl_base *the_owner)
343 {
344   option =0;
345   owner= the_owner;
346 }
347
348 cl_optref::cl_optref(class cl_base *the_owner, class cl_option *new_option)
349 {
350   owner= the_owner;
351   option= new_option;
352   application->options->new_option(option);
353   if (option)
354     {
355       option->new_reference(this);
356       set_name(option->get_name());
357     }
358 }
359
360 cl_optref::~cl_optref(void)
361 {
362   if (option)
363     {
364       option->del_reference(this);
365       if (option->get_creator() == owner)
366         application->options->del_option(option);
367     }
368 }
369
370 class cl_option *
371 cl_optref::create(class cl_base *creator,
372                   enum option_type type,
373                   char *the_name, char *help)
374 {
375   if (option)
376     option->del_reference(this);
377   switch (type)
378     {
379     case non_opt:
380       option= 0;
381       break;
382       /*case integer_opt:
383       option= new cl_option(creator, the_name, help);
384       break;*/
385       /*case float_opt:
386       option= new cl_option(creator, the_name, help);
387       break;*/
388     case bool_opt:
389       option= new cl_bool_option(creator, the_name, help);
390       break;
391     case string_opt:
392       option= new cl_string_option(creator, the_name, help);
393       break;
394       /*case pointer_opt:
395       option= new cl_option(creator, the_name, help);
396       break;*/
397     default:
398       option= 0;
399       break;
400     }
401   if (option)
402     {
403       application->options->new_option(option);
404       option->new_reference(this);
405       set_name(option->get_name());
406     }
407   
408   return(option);
409 }
410
411 void
412 cl_optref::default_option(char *the_name)
413 {
414   class cl_option *o= application->options->get_option(the_name, application);
415
416   if (o &&
417       option)
418     {
419       //memcpy(option->get_value(), o->get_value(), sizeof(union option_value));
420       *option= *o;
421       option->inform_users();
422     }
423   /*else
424     fprintf(stderr,"can not set opt from default, option=%p, o=%p\n",option,o);*/
425 }
426
427 class cl_option *
428 cl_optref::use(void)
429 {
430   if (option)
431     {
432       option->del_reference(this);
433       option->new_reference(this);
434     }
435   return(option);
436 }
437
438 class cl_option *
439 cl_optref::use(char *the_name)
440 {
441   if (option)
442     option->del_reference(this);
443   option= application->options->get_option(the_name);
444   if (option)
445     {
446       option->new_reference(this);
447       set_name(option->get_name());
448     }
449   return(option);
450 }
451
452 void
453 cl_optref::option_removing(void)
454 {
455   option= 0;
456 }
457
458 bool
459 cl_optref::get_value(bool)
460 {
461   if (!option)
462     {
463       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
464               "bool option: %s\n", object_name(owner), get_name());
465       return(DD_FALSE);
466     }
467   else
468     {
469       bool v;
470       option->get_value(&v);
471       return(v);
472     }
473 }
474
475 char *
476 cl_optref::get_value(char *)
477 {
478   if (!option)
479     {
480       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
481               "string option: %s\n", object_name(owner), get_name());
482       return(0);
483     }
484   else
485     {
486       char *s= 0;
487       option->get_value(&s);
488       return(s);
489     }
490 }
491
492
493 /*
494  * BOOL type of option
495  *____________________________________________________________________________
496  *
497  */
498
499 cl_bool_option::cl_bool_option(class cl_base *the_creator,
500                                char *aname, char *Ihelp):
501   cl_option(the_creator, aname, Ihelp)
502 {}
503
504 void
505 cl_bool_option::print(class cl_console *con)
506 {
507   if (/**(bool *)option*/value.bval)
508     con->dd_printf("TRUE");
509   else
510     con->dd_printf("FALSE");
511 }
512
513 void
514 cl_bool_option::set_value(char *s)
515 {
516   char c;
517
518   if (s)
519     {
520       c= toupper(*s);
521       if (c == '1' ||
522           c == 'T' ||
523           c == 'Y')
524         /**(bool *)option=*/ value.bval= DD_TRUE;
525       else
526         /**(bool *)option=*/ value.bval= DD_FALSE;
527     }
528   inform_users();
529 }
530
531
532 /*
533  * STRING type of option
534  *____________________________________________________________________________
535  *
536  */
537
538 cl_string_option::cl_string_option(class cl_base *the_creator,
539                                    char *aname, char *Ihelp):
540   cl_option(the_creator, aname, Ihelp)
541 {}
542
543 class cl_option &
544 cl_string_option::operator=(class cl_option &o)
545 {
546   //fprintf(stderr,"string=otheropt%p\"%s\"\nold=%p\"%s\"\n",&o,object_name(&o),value.sval,value.sval);
547   set_value((o.get_value())->sval);
548   //fprintf(stderr,"new=%p\"%s\"\n",value.sval,value.sval);
549   return(*this);
550 }
551
552 void
553 cl_string_option::print(class cl_console *con)
554 {
555   if (/**(bool *)option*/value.sval)
556     con->dd_printf("\"%s\"", value.sval);
557   else
558     con->dd_printf("(null)");
559 }
560
561 /*
562  * Debug on console
563  */
564
565 cl_cons_debug_opt::cl_cons_debug_opt(class cl_app *the_app,
566                                      char *Iid,
567                                      char *Ihelp):
568   cl_option(0, Iid, Ihelp)
569 {
570   app= the_app;
571 }
572
573 void
574 cl_cons_debug_opt::print(class cl_console *con)
575 {
576   if (/*sim->cmd->actual_console &&
577         sim->cmd->actual_console*/con->flags & CONS_DEBUG)
578     con->dd_printf("TRUE");
579   else
580     con->dd_printf("FALSE");
581 }
582
583 void
584 cl_cons_debug_opt::get_value(bool *val)
585 {
586   if (val)
587     *val= app->get_commander()->actual_console?
588       (app->get_commander()->actual_console->flags & CONS_DEBUG):0;
589 }
590
591 void
592 cl_cons_debug_opt::set_value(bool opt)
593 {
594   if (app->get_commander()->actual_console)
595     {
596       if (opt)
597         app->get_commander()->actual_console->flags|= CONS_DEBUG;
598       else
599         app->get_commander()->actual_console->flags&= ~CONS_DEBUG;
600     }
601   inform_users();
602 }
603
604 void
605 cl_cons_debug_opt::set_value(char *s)
606 {
607   char c;
608
609   if (s &&
610       app->get_commander()->actual_console)
611     {
612       c= toupper(*s);
613       if (c == '1' ||
614           c == 'T' ||
615           c == 'Y')
616         //app->get_commander()->actual_console->flags|= CONS_DEBUG;
617         set_value(1);
618       else
619         //app->get_commander()->actual_console->flags&= ~CONS_DEBUG;
620         set_value(0);
621     }
622 }
623
624
625 /* End of option.cc */