version 0.5.2
[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 /*
11   This file is part of microcontroller simulator: ucsim.
12
13   UCSIM is free software; you can redistribute it and/or modify
14   it under the terms of the GNU General Public License as published by
15   the Free Software Foundation; either version 2 of the License, or
16   (at your option) any later version.
17   
18   UCSIM is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22   
23   You should have received a copy of the GNU General Public License
24   along with UCSIM; see the file COPYING.  If not, write to the Free
25   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26   02111-1307, USA.
27 */
28 /*@1@*/
29
30 #include "ddconfig.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include "i_string.h"
36
37   // local, prj
38 #include "stypes.h"
39 #include "optioncl.h"
40 #include "globals.h"
41 #include "utils.h"
42
43   // sim.src
44 #include "simcl.h"
45
46
47 /*struct id_element option_type_names[]= {
48   { non_opt     , "non" },
49   { integer_opt , "integer" },
50   { float_opt   , "float" },
51   { bool_opt    , "boolean" },
52   { string_opt  , "string" },
53   { pointer_opt , "pointer" },
54   { 0, 0 }
55   };*/
56
57 /*
58  * Base class for option's objects
59  *____________________________________________________________________________
60  *
61  */
62
63 cl_option::cl_option(class cl_base *the_creator, char *aname, char *Ihelp):
64   cl_base()
65 {
66   creator= the_creator;
67   set_name(aname);
68   help= strdup(Ihelp);
69   char *s= (char*)malloc(strlen(aname)+100);
70   sprintf(s, "users of option \"%s\"", aname);
71   users= new cl_list(2, 2, s);
72   free(s);
73   memset(&value, 0, sizeof(value));
74   show();
75 }
76
77 class cl_option &
78 cl_option::operator=(class cl_option &o)
79 {
80   //memcpy(&value, &(o.value), sizeof(union option_value));
81   //fprintf(stderr,"opt%p\"%s\"=%p\"%s\"\nold=%p\n",this,object_name(this),&o,object_name(&o),value.sval);
82   value= o.value;
83   //fprintf(stderr,"new=%p\n",value.sval);
84   inform_users();
85   return(*this);
86 }
87
88 cl_option::~cl_option(void)
89 {
90   users->disconn_all();
91   delete users;
92   free(help);
93 }
94
95 void
96 cl_option::pre_remove(void)
97 {
98   int i;
99
100   for (i= 0; i < users->count; i++)
101     {
102       class cl_optref *user= (class cl_optref *)(users->at(i));
103       user->option_removing();
104     }
105 }
106
107 void
108 cl_option::new_reference(class cl_optref *ref)
109 {
110   users->add(ref);
111 }
112
113 void
114 cl_option::del_reference(class cl_optref *ref)
115 {
116   users->disconn(ref);
117 }
118
119 void
120 cl_option::inform_users(void)
121 {
122   int i;
123
124   for (i= 0; i < users->count; i++)
125     {
126       class cl_optref *user= (class cl_optref *)(users->at(i));
127       //fprintf(stderr,"%p\"%s\" informs user %p\"%s\"\n",this,object_name(this),user,object_name(user));
128       user->option_changed();
129     }
130 }
131
132
133 void
134 cl_option::get_value(bool *val)
135 {
136   if (val)
137     *val= value.bval;
138 }
139
140 void
141 cl_option::set_value(bool opt)
142 {
143   value.bval= opt;
144   inform_users();
145 }
146
147
148 void
149 cl_option::get_value(char **val)
150 {
151   if (val)
152     *val= value.sval;
153 }
154
155 void
156 cl_option::set_value(char *opt)
157 {
158   //fprintf(stderr,"set_string_value (%s) to %p\"%s\"\n",opt,this,object_name(this));
159   //fprintf(stderr,"old value=%p\"%s\"\n",value.sval,value.sval);
160   if (value.sval)
161     free(value.sval);
162   if (opt &&
163       *opt)
164     value.sval= strdup(opt);
165   else
166     value.sval= strdup("");
167   //fprintf(stderr,"new value=%p\"%s\"\n",value.sval,value.sval);
168   inform_users();
169 }
170
171
172 void
173 cl_option::get_value(void **val)
174 {
175   if (val)
176     *val= value.pval;
177 }
178
179 void
180 cl_option::set_value(void *opt)
181 {
182   value.pval= opt;
183   inform_users();
184 }
185
186
187 void
188 cl_option::get_value(long *val)
189 {
190   if (val)
191     *val= value.ival;
192 }
193
194 void
195 cl_option::set_value(long opt)
196 {
197   value.ival= opt;
198   inform_users();
199 }
200
201
202 void
203 cl_option::get_value(double *val)
204 {
205   if (val)
206     *val= value.fval;
207 }
208
209 void
210 cl_option::set_value(double opt)
211 {
212   value.fval= opt;
213   inform_users();
214 }
215
216
217 /*
218  * List of options
219  */
220
221 void *
222 cl_options::key_of(void *item)
223 {
224   return(((class cl_base *)item)->get_name());
225 }
226
227 int
228 cl_options::compare(void *key1, void *key2)
229 {
230   //class cl_option *k1, *k2;
231   int i;
232   char *k1, *k2;
233
234   k1= /*(class cl_option *)*/(char *)key1;
235   k2= /*(class cl_option *)*/(char *)key2;
236   if ((i= strcmp(k1, k2)) != 0)
237     return(i);
238   return(i);
239 }
240
241 void
242 cl_options::new_option(class cl_option *opt)
243 {
244   add(opt);
245 }
246
247 void
248 cl_options::del_option(class cl_option *opt)
249 {
250   opt->pre_remove();
251   disconn(opt);
252   delete opt;
253 }
254
255 class cl_option *
256 cl_options::get_option(char *the_name)
257 {
258   t_index idx;
259
260   if (search(the_name, idx))
261     return((class cl_option *)(at(idx)));
262   return(0);
263 }
264
265 class cl_option *
266 cl_options::get_option(char *the_name, class cl_base *creator)
267 {
268   t_index idx;
269   class cl_option *o;
270
271   if (!search(the_name, idx))
272     return(0);
273   if (idx > 0)
274     {
275       idx--;
276       o= (class cl_option *)(at(idx));
277       while (compare(the_name, key_of(o)) == 0 &&
278              idx > 0)
279         {
280           idx--;
281           o= (class cl_option *)(at(idx));
282         }
283       if (compare(the_name, key_of(o)) != 0)
284         idx++;
285     }
286   o= (class cl_option *)(at(idx));
287   while (compare(the_name, key_of(o)) == 0 &&
288          o->get_creator() != creator &&
289          idx < count)
290     {
291       idx++;
292       o= (class cl_option *)(at(idx));
293       if (compare(the_name, key_of(o)) == 0 &&
294           o->get_creator() == creator)
295         return(o);
296     }
297   if (compare(the_name, key_of(o)) == 0 &&
298       o->get_creator() == creator)
299     return(o);
300   return(0);
301 }
302
303 class cl_option *
304 cl_options::get_option(char *the_name, char *creator)
305 {
306   t_index idx;
307   class cl_option *o;
308
309   if (!search(the_name, idx))
310     return(0);
311   if (idx > 0)
312     {
313       idx--;
314       o= (class cl_option *)(at(idx));
315       while (compare(the_name, key_of(o)) == 0 &&
316              idx > 0)
317         {
318           idx--;
319           o= (class cl_option *)(at(idx));
320         }
321       if (compare(the_name, key_of(o)) != 0)
322         idx++;
323     }
324   o= (class cl_option *)(at(idx));
325   while (compare(the_name, key_of(o)) == 0 &&
326          strcmp(object_name(o->get_creator()), creator) != 0 &&
327          idx < count)
328     {
329       idx++;
330       o= (class cl_option *)(at(idx));
331       if (compare(the_name, key_of(o)) == 0 &&
332           strcmp(object_name(o->get_creator()), creator) == 0)
333         return(o);
334     }
335   if (compare(the_name, key_of(o)) == 0 &&
336       strcmp(object_name(o->get_creator()), creator) == 0)
337     return(o);
338   return(0);
339 }
340
341 class cl_option *
342 cl_options::get_option(int idx)
343 {
344   if (idx >= count)
345     return(0);
346   return((class cl_option *)(at(idx)));
347 }
348
349 int
350 cl_options::nuof_options(char *the_name)
351 {
352   int i, n= 0;
353
354   for (i= 0; i < count; i++)
355     {
356       class cl_option *o= (class cl_option *)(at(i));
357       if (strcmp(the_name, o->get_name()) == 0)
358         n++;
359     }
360   return(n);
361 }
362
363 int
364 cl_options::nuof_options(char *the_name, char *creator)
365 {
366   int i, n= 0;
367
368   for (i= 0; i < count; i++)
369     {
370       class cl_option *o= (class cl_option *)(at(i));
371       if (strcmp(the_name, o->get_name()) == 0 &&
372           strcmp(creator, object_name(o->get_creator())) == 0)
373         n++;
374     }
375   return(n);
376 }
377
378 class cl_option *
379 cl_options::set_value(char *the_name, cl_base *creator, bool value)
380 {
381   class cl_option *o= get_option(the_name, creator);
382
383   if (o)
384     o->set_value(value);
385   return(o);
386 }
387
388 class cl_option *
389 cl_options::set_value(char *the_name, cl_base *creator, char *value)
390 {
391   class cl_option *o= get_option(the_name, creator);
392
393   if (o)
394     o->set_value(value);
395   return(o);
396 }
397
398 class cl_option *
399 cl_options::set_value(char *the_name, cl_base *creator, void *value)
400 {
401   class cl_option *o= get_option(the_name, creator);
402
403   if (o)
404     o->set_value(value);
405   return(o);
406 }
407
408 class cl_option *
409 cl_options::set_value(char *the_name, cl_base *creator, long value)
410 {
411   class cl_option *o= get_option(the_name, creator);
412
413   if (o)
414     o->set_value(value);
415   return(o);
416 }
417
418 class cl_option *
419 cl_options::set_value(char *the_name, cl_base *creator, double value)
420 {
421   class cl_option *o= get_option(the_name, creator);
422
423   if (o)
424     o->set_value(value);
425   return(o);
426 }
427
428
429 /*
430  * Reference to an option
431  */
432
433 cl_optref::cl_optref(class cl_base *the_owner)
434 {
435   option =0;
436   owner= the_owner;
437 }
438
439 cl_optref::cl_optref(class cl_base *the_owner, class cl_option *new_option)
440 {
441   owner= the_owner;
442   option= new_option;
443   application->options->new_option(option);
444   if (option)
445     {
446       option->new_reference(this);
447       set_name(option->get_name());
448     }
449 }
450
451 cl_optref::~cl_optref(void)
452 {
453   if (option)
454     {
455       option->del_reference(this);
456       if (option->get_creator() == owner)
457         application->options->del_option(option);
458     }
459 }
460
461 class cl_option *
462 cl_optref::create(class cl_base *creator,
463                   enum option_type type,
464                   char *the_name, char *help)
465 {
466   if (option)
467     option->del_reference(this);
468   switch (type)
469     {
470     case non_opt:
471       option= 0;
472       break;
473     case integer_opt:
474       option= new cl_number_option(creator, the_name, help);
475       break;
476     case float_opt:
477       option= new cl_float_option(creator, the_name, help);
478       break;
479     case bool_opt:
480       option= new cl_bool_option(creator, the_name, help);
481       break;
482     case string_opt:
483       option= new cl_string_option(creator, the_name, help);
484       break;
485     case pointer_opt:
486       option= new cl_pointer_option(creator, the_name, help);
487       break;
488     default:
489       option= 0;
490       break;
491     }
492   if (option)
493     {
494       application->options->new_option(option);
495       option->new_reference(this);
496       set_name(option->get_name());
497     }
498   
499   return(option);
500 }
501
502 void
503 cl_optref::default_option(char *the_name)
504 {
505   class cl_option *o= application->options->get_option(the_name, application);
506
507   if (o &&
508       option)
509     {
510       //memcpy(option->get_value(), o->get_value(), sizeof(union option_value));
511       *option= *o;
512       option->inform_users();
513     }
514   /*else
515     fprintf(stderr,"can not set opt from default, option=%p, o=%p\n",option,o);*/
516 }
517
518 class cl_option *
519 cl_optref::use(void)
520 {
521   if (option)
522     {
523       option->del_reference(this);
524       option->new_reference(this);
525     }
526   return(option);
527 }
528
529 class cl_option *
530 cl_optref::use(char *the_name)
531 {
532   if (option)
533     option->del_reference(this);
534   option= application->options->get_option(the_name);
535   if (option)
536     {
537       option->new_reference(this);
538       set_name(option->get_name());
539     }
540   return(option);
541 }
542
543 void
544 cl_optref::option_removing(void)
545 {
546   option= 0;
547 }
548
549 bool
550 cl_optref::get_value(bool)
551 {
552   if (!option)
553     {
554       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
555               "bool option: %s\n", object_name(owner), get_name());
556       return(DD_FALSE);
557     }
558   else
559     {
560       bool v;
561       option->get_value(&v);
562       return(v);
563     }
564 }
565
566 char *
567 cl_optref::get_value(char *)
568 {
569   if (!option)
570     {
571       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
572               "string option: %s\n", object_name(owner), get_name());
573       return(0);
574     }
575   else
576     {
577       char *s= 0;
578       option->get_value(&s);
579       return(s);
580     }
581 }
582
583 void *
584 cl_optref::get_value(void *)
585 {
586   if (!option)
587     {
588       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
589               "pointer option: %s\n", object_name(owner), get_name());
590       return(NIL);
591     }
592   else
593     {
594       void *p= NIL;
595       option->get_value(&p);
596       return(p);
597     }
598 }
599
600 long
601 cl_optref::get_value(long)
602 {
603   if (!option)
604     {
605       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
606               "number option: %s\n", object_name(owner), get_name());
607       return(0);
608     }
609   else
610     {
611       long l= 0;
612       option->get_value(&l);
613       return(l);
614     }
615 }
616
617 double
618 cl_optref::get_value(double)
619 {
620   if (!option)
621     {
622       fprintf(stderr, "Warning: \"%s\" is sdereferencing a non-existent "
623               "float option: %s\n", object_name(owner), get_name());
624       return(0);
625     }
626   else
627     {
628       double d= 0;
629       option->get_value(&d);
630       return(d);
631     }
632 }
633
634
635 /*
636  * BOOL type of option
637  *____________________________________________________________________________
638  *
639  */
640
641 cl_bool_option::cl_bool_option(class cl_base *the_creator,
642                                char *aname, char *Ihelp):
643   cl_option(the_creator, aname, Ihelp)
644 {}
645
646 void
647 cl_bool_option::print(class cl_console *con)
648 {
649   if (/**(bool *)option*/value.bval)
650     con->dd_printf("TRUE");
651   else
652     con->dd_printf("FALSE");
653 }
654
655 void
656 cl_bool_option::set_value(char *s)
657 {
658   char c;
659
660   if (s)
661     {
662       c= toupper(*s);
663       if (c == '1' ||
664           c == 'T' ||
665           c == 'Y')
666         /**(bool *)option=*/ value.bval= DD_TRUE;
667       else
668         /**(bool *)option=*/ value.bval= DD_FALSE;
669     }
670   inform_users();
671 }
672
673
674 /*
675  * STRING type of option
676  *____________________________________________________________________________
677  *
678  */
679
680 cl_string_option::cl_string_option(class cl_base *the_creator,
681                                    char *aname, char *Ihelp):
682   cl_option(the_creator, aname, Ihelp)
683 {}
684
685 class cl_option &
686 cl_string_option::operator=(class cl_option &o)
687 {
688   //fprintf(stderr,"string=otheropt%p\"%s\"\nold=%p\"%s\"\n",&o,object_name(&o),value.sval,value.sval);
689   set_value((o.get_value())->sval);
690   //fprintf(stderr,"new=%p\"%s\"\n",value.sval,value.sval);
691   return(*this);
692 }
693
694 void
695 cl_string_option::print(class cl_console *con)
696 {
697   if (/**(bool *)option*/value.sval)
698     con->dd_printf("\"%s\"", value.sval);
699   else
700     con->dd_printf("(null)");
701 }
702
703
704 /*
705  * PONITER type of option
706  *____________________________________________________________________________
707  *
708  */
709
710 cl_pointer_option::cl_pointer_option(class cl_base *the_creator,
711                                      char *aname, char *Ihelp):
712   cl_option(the_creator, aname, Ihelp)
713 {}
714
715 class cl_option &
716 cl_pointer_option::operator=(class cl_option &o)
717 {
718   set_value((o.get_value())->pval);
719   return(*this);
720 }
721
722 void
723 cl_pointer_option::print(class cl_console *con)
724 {
725   if (value.pval)
726     con->dd_printf("\"%p\"", value.pval);
727   else
728     con->dd_printf("(null)");
729 }
730
731
732 /*
733  * Debug on console
734  */
735 /*
736 cl_cons_debug_opt::cl_cons_debug_opt(class cl_app *the_app,
737                                      char *Iid,
738                                      char *Ihelp):
739   cl_option(0, Iid, Ihelp)
740 {
741   app= the_app;
742 }
743
744 void
745 cl_cons_debug_opt::print(class cl_console *con)
746 {
747   if (con->flags & CONS_DEBUG)
748     con->dd_printf("TRUE");
749   else
750     con->dd_printf("FALSE");
751 }
752
753 void
754 cl_cons_debug_opt::get_value(bool *val)
755 {
756   if (val)
757     *val= app->get_commander()->actual_console?
758       (app->get_commander()->actual_console->flags & CONS_DEBUG):0;
759 }
760
761 void
762 cl_cons_debug_opt::set_value(bool opt)
763 {
764   if (app->get_commander()->actual_console)
765     {
766       if (opt)
767         app->get_commander()->actual_console->flags|= CONS_DEBUG;
768       else
769         app->get_commander()->actual_console->flags&= ~CONS_DEBUG;
770     }
771   inform_users();
772 }
773
774 void
775 cl_cons_debug_opt::set_value(char *s)
776 {
777   char c;
778
779   if (s &&
780       app->get_commander()->actual_console)
781     {
782       c= toupper(*s);
783       if (c == '1' ||
784           c == 'T' ||
785           c == 'Y')
786         set_value(1);
787       else
788         set_value(0);
789     }
790 }
791 */
792
793 /*
794  * NUMBER type of option
795  *____________________________________________________________________________
796  *
797  */
798
799 cl_number_option::cl_number_option(class cl_base *the_creator,
800                                    char *aname, char *Ihelp):
801   cl_option(the_creator, aname, Ihelp)
802 {}
803
804 void
805 cl_number_option::print(class cl_console *con)
806 {
807   con->dd_printf("%ld", value.ival);
808 }
809
810 void
811 cl_number_option::set_value(char *s)
812 {
813   if (s)
814     value.ival= strtol(s, NIL, 0);
815   inform_users();
816 }
817
818
819 /*
820  * FLOAT type of option
821  *____________________________________________________________________________
822  *
823  */
824
825 cl_float_option::cl_float_option(class cl_base *the_creator,
826                                  char *aname, char *Ihelp):
827   cl_option(the_creator, aname, Ihelp)
828 {}
829
830 void
831 cl_float_option::print(class cl_console *con)
832 {
833   con->dd_printf("%.3f", value.fval);
834 }
835
836 void
837 cl_float_option::set_value(char *s)
838 {
839   if (s)
840     value.fval= strtod(s, NIL);
841   inform_users();
842 }
843
844
845 /* End of option.cc */