1 /*
2 * Simulator of microcontrollers (cmd.src/newcmd.cc)
3 *
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5 * Copyright (C) 2006, Borut Razem - borut.razem@siol.net
6 *
7 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
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 RANTY; 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 /*@1@*/
28
29 #include "ddconfig.h"
30
31 #include <stdio.h>
32 #include <errno.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include "i_string.h"
37
38 //#include "cmdlexcl.h"
39
40 // prj
41 #include "globals.h"
42 #include "utils.h"
43 #include "fiocl.h"
44
45 // sim
46 #include "simcl.h"
47 #include "argcl.h"
48 #include "appcl.h"
49
50 // local
51 #include "newcmdcl.h"
52 #include "cmdutil.h"
53
54
55 /*
56 * Options of console
57 */
58
cl_prompt_option(class cl_console_base * console)59 cl_prompt_option::cl_prompt_option(class cl_console_base *console):
60 cl_optref(console)
61 {
62 con= console;
63 }
64
65 int
init(void)66 cl_prompt_option::init(void)
67 {
68 char *help;
69 help= format_string("Prompt string of console%d", con->get_id());
70 create(con, string_opt, "prompt", help);
71 free(help);
72 default_option("prompt");
73 return(0);
74 }
75
76 void
option_changed(void)77 cl_prompt_option::option_changed(void)
78 {
79 if (!con)
80 return;
81 char *s;
82 option->get_value(&s);
83 con->set_prompt(s);
84 }
85
86
cl_debug_option(class cl_console_base * console)87 cl_debug_option::cl_debug_option(class cl_console_base *console):
88 cl_prompt_option(console)
89 {}
90
91 int
init(void)92 cl_debug_option::init(void)
93 {
94 char *help;
95 help= format_string("Debug messages to console%d", con->get_id());
96 create(con, bool_opt, "debug", help);
97 free(help);
98 default_option("debug");
99 return(0);
100 }
101
102 void
option_changed(void)103 cl_debug_option::option_changed(void)
104 {
105 if (!con)
106 return;
107 bool b;
108 option->get_value(&b);
109 con->set_flag(CONS_DEBUG, b);
110 }
111
112
113 /*
114 * Command console
115 *____________________________________________________________________________
116 */
117
cl_console_base(void)118 cl_console_base::cl_console_base(void):
119 cl_base()
120 {
121 app= 0;
122 flags= 0;
123 prompt= 0;
124 nl= 0;
125 lbuf= 0;
126 prompt_option= 0;
127 null_prompt_option= 0;
128 debug_option= 0;
129 }
130
~cl_console_base(void)131 cl_console_base::~cl_console_base(void)
132 {
133 if (prompt_option)
134 delete prompt_option;
135 if (null_prompt_option)
136 delete null_prompt_option;
137 if (debug_option)
138 delete debug_option;
139 }
140
141 int
init(void)142 cl_console_base::init(void)
143 {
144 cl_base::init();
145 prompt_option= new cl_prompt_option(this);
146 prompt_option->init();
147 null_prompt_option= new cl_optref(this);
148 null_prompt_option->init();
149 null_prompt_option->use("null_prompt");
150 debug_option= new cl_debug_option(this);
151 debug_option->init();
152 welcome();
153 print_prompt();
154 if (get_fin() != NULL)
155 get_fin()->set_echo_color(get_color_ansiseq("command"));
156 last_command= 0;
157 //last_cmdline= 0;
158 last_cmd= chars("");
159 prev_quit= -1;
160 return(0);
161 }
162
163 void
set_startup(chars the)164 cl_console_base::set_startup(chars the)
165 {
166 startup_command= the;
167 }
168
169 void
welcome(void)170 cl_console_base::welcome(void)
171 {
172 if (!(flags & CONS_NOWELCOME))
173 {
174 dd_printf("uCsim %s, Copyright (C) 1997 Daniel Drotos.\n"
175 "uCsim comes with ABSOLUTELY NO WARRANTY; for details type "
176 "`show w'.\n"
177 "This is free software, and you are welcome to redistribute it\n"
178 "under certain conditions; type `show c' for details.\n",
179 VERSIONSTR);
180 }
181 }
182
183 void
print_prompt(void)184 cl_console_base::print_prompt(void)
185 {
186 if (flags & (CONS_FROZEN | CONS_INACTIVE))
187 return;
188
189 if (!(flags & CONS_INTERACTIVE))
190 return;
191
192 if (null_prompt_option->get_value(bool(0)))
193 {
194 class cl_f *fo= get_fout(), *fi= get_fin();
195 char c= 0;
196 if (fi &&
197 fi->eof() &&
198 (fi->id() == fo->id()))
199 return;
200 fo->write(&c, 1);
201 }
202 else
203 {
204 dd_cprintf("prompt_console", "%d", id);
205 dd_cprintf("prompt", "%s", (prompt && prompt[0]) ? prompt : "> ");
206 }
207 }
208
209 int
dd_printf(const char * format,...)210 cl_console_base::dd_printf(const char *format, ...)
211 {
212 va_list ap;
213 int ret= 0;
214
215 va_start(ap, format);
216 ret= cmd_do_print(format, ap);
217 va_end(ap);
218
219 return(ret);
220 }
221
222 int
dd_cprintf(const char * color_name,const char * format,...)223 cl_console_base::dd_cprintf(const char *color_name, const char *format, ...)
224 {
225 va_list ap;
226 int ret= 0;
227 bool bw= false;
228 char *cc;
229 chars cce;
230 class cl_f *fo= get_fout();
231 class cl_option *o= application->options->get_option("black_and_white");
232
233 if (o) o->get_value(&bw);
234 if (!fo ||
235 (fo &&
236 !fo->tty)
237 )
238 bw= true;
239
240 o= application->options->get_option((char*)chars("", "color_%s", color_name));
241 cc= NULL;
242 if (o) o->get_value(&cc);
243 cce= colopt2ansiseq(cc);
244 if (!bw) dd_printf("\033[0m%s", (char*)cce);
245
246 va_start(ap, format);
247 ret= cmd_do_print(format, ap);
248 va_end(ap);
249
250 if (!bw) dd_printf("\033[0m");
251
252 return(ret);
253 }
254
255 chars
get_color_ansiseq(const char * color_name,bool add_reset)256 cl_console_base::get_color_ansiseq(const char *color_name, bool add_reset)
257 {
258 bool bw= false;
259 char *cc;
260 chars cce= "";
261 class cl_f *fo= get_fout();
262 class cl_option *o= application->options->get_option("black_and_white");
263 if (o) o->get_value(&cc);
264
265 if (!fo ||
266 (fo &&
267 !fo->tty) ||
268 bw
269 )
270 return cce;
271
272 o= application->options->get_option((char*)chars("", "color_%s", color_name));
273 cc= NULL;
274 if (o) o->get_value(&cc);
275 if (add_reset)
276 cce.append("\033[0m");
277 cce.append(colopt2ansiseq(cc));
278
279 return cce;
280 }
281
282
283 void
dd_color(const char * color_name)284 cl_console_base::dd_color(const char *color_name)
285 {
286 dd_printf("%s", (char*)(get_color_ansiseq(color_name, true)));
287 }
288
289 int
debug(const char * format,...)290 cl_console_base::debug(const char *format, ...)
291 {
292 if ((flags & CONS_DEBUG) == 0)
293 return(0);
294
295 va_list ap;
296 int ret= 0;
297
298 va_start(ap, format);
299 ret= cmd_do_cprint("debug", format, ap);
300 va_end(ap);
301
302 return(ret);
303 }
304
305 /*
306 * Printing out an integer in binary format
307 */
308
309 void
print_bin(long data,int bits)310 cl_console_base::print_bin(long data, int bits)
311 {
312 long mask= 1;
313
314 mask= mask << ((bits >= 1)?(bits-1):0);
315 while (bits--)
316 {
317 dd_printf("%c", (data&mask)?'1':'0');
318 mask>>= 1;
319 }
320 }
321
322 void
print_char_octal(char c)323 cl_console_base::print_char_octal(char c)
324 {
325 if (strchr("\a\b\f\n\r\t\v\"", c))
326 switch (c)
327 {
328 case '\a': dd_printf("\a"); break;
329 case '\b': dd_printf("\b"); break;
330 case '\f': dd_printf("\f"); break;
331 case '\n': dd_printf("\n"); break;
332 case '\r': dd_printf("\r"); break;
333 case '\t': dd_printf("\t"); break;
334 case '\v': dd_printf("\v"); break;
335 case '\"': dd_printf("\""); break;
336 }
337 else if (isprint(c))
338 dd_printf("%c", c);
339 else
340 dd_printf("\\%03hho", c);
341 }
342
343 int
cmd_do_print(const char * format,va_list ap)344 cl_console_base::cmd_do_print(const char *format, va_list ap)
345 {
346 int ret;
347 class cl_f *fo= get_fout(), *fi= get_fin();
348
349 if (fo)
350 {
351 if (fi &&
352 fi->eof() &&
353 (fi->id() == fo->id()))
354 {
355 return 0;
356 }
357 ret= fo->vprintf((char*)format, ap);
358 //fo->flush();
359 return ret;
360 }
361 else
362 return 0;
363 }
364
365 int
cmd_do_cprint(const char * color_name,const char * format,va_list ap)366 cl_console_base::cmd_do_cprint(const char *color_name, const char *format, va_list ap)
367 {
368 int ret;
369 class cl_f *fo= get_fout(), *fi= get_fin();
370 bool bw= false;
371 char *cc;
372 chars cce;
373 class cl_option *o= application->options->get_option("black_and_white");
374
375 if (o) o->get_value(&bw);
376 if (!fo ||
377 (fo &&
378 !fo->tty)
379 )
380 bw= true;
381
382 o= application->options->get_option((char*)chars("", "color_%s", color_name));
383 cc= NULL;
384 if (o) o->get_value(&cc);
385 cce= colopt2ansiseq(cc);
386
387 if (fo)
388 {
389 if (fi &&
390 fi->eof() &&
391 (fi->id() == fo->id()))
392 {
393 return 0;
394 }
395 if (!bw) fo->prntf("\033[0m%s", (char*)cce);
396 ret= fo->vprintf((char*)format, ap);
397 if (!bw) fo->prntf("\033[0m");
398 //fo->flush();
399 return ret;
400 }
401 else
402 return 0;
403 }
404
405 int
write(char * buf,int count)406 cl_console_base::write(char *buf, int count)
407 {
408 int ret;
409 class cl_f *fo= get_fout(), *fi= get_fin();
410
411 if (fo)
412 {
413 if (fi &&
414 fi->eof() &&
415 (fi->id() == fo->id()))
416 {
417 //deb("do not attempt to write on console, where input is at file_end\n");
418 return 0;
419 }
420 ret= fo->write(buf, count);
421 //fo->flush();
422 return ret;
423 }
424 else
425 return 0;
426 }
427
428 void
tu_cls(void)429 cl_console_base::tu_cls(void)
430 {
431 dd_printf("\033[2J");
432 }
433
434 void
tu_cll(void)435 cl_console_base::tu_cll(void)
436 {
437 dd_printf("\033[K");
438 }
439
440 void
tu_clc(void)441 cl_console_base::tu_clc(void)
442 {
443 tu_save();
444 dd_printf(" ");
445 tu_restore();
446 }
447
448 void
tu_go(int x1,int y1)449 cl_console_base::tu_go(int x1, int y1)
450 {
451 dd_printf("\033[%d;%dH", y1, x1);
452 }
453
454 void
tu_save(void)455 cl_console_base::tu_save(void)
456 {
457 dd_printf("\033[s");
458 }
459
460 void
tu_restore(void)461 cl_console_base::tu_restore(void)
462 {
463 dd_printf("\033[u");
464 }
465
466 void
tu_hide(void)467 cl_console_base::tu_hide(void)
468 {
469 dd_printf("\033[?25l");
470 }
471
472 void
tu_show(void)473 cl_console_base::tu_show(void)
474 {
475 dd_printf("\033[?25h");
476 }
477
478 void
tu_color(int bg,int fg)479 cl_console_base::tu_color(int bg, int fg)
480 {
481 if (bg >= 0)
482 dd_printf("\033[%dm", (tu_bg_color= bg)+40);
483 if (fg >= 0)
484 dd_printf("\033[%dm", (tu_fg_color= fg)+30);
485 }
486
487 void
tu_mouse_on(void)488 cl_console_base::tu_mouse_on(void)
489 {
490 // enable mouse click reports of terminal
491 dd_printf("\033[1;2'z"); // enable locator reporting, as character cells
492 dd_printf("\033[?9h"); // send mouse X,Y on btn press (X10 mode)
493 }
494
495 void
tu_mouse_off(void)496 cl_console_base::tu_mouse_off(void)
497 {
498 dd_printf("\033[?9l"); // do not send mouse X,Y on btn press
499 dd_printf("\033[0;0'z"); // disable locator reporting
500 }
501
502 void
tu_reset(void)503 cl_console_base::tu_reset(void)
504 {
505 tu_mouse_off();
506 //dd_printf("\033c"); // terminal reset
507 dd_printf("\033[!p"); // soft terminal reset
508 }
509
510 /*void
511 cl_console_base::flush(void)
512 {
513 class cl_f *fo= get_fout();
514 if (fo)
515 fo->flush();
516 }*/
517
518 bool
interpret(char * cmd)519 cl_console_base::interpret(char *cmd)
520 {
521 dd_printf("Unknown command\n");
522 return(0);
523 }
524
525 void
set_id(int new_id)526 cl_console_base::set_id(int new_id)
527 {
528 //char *s;
529 id= new_id;
530 if (!have_real_name())
531 set_name(/*s= format_string*/chars("", "console%d", id));
532 //free(s);
533 }
534
535 void
set_prompt(char * p)536 cl_console_base::set_prompt(char *p)
537 {
538 if (prompt)
539 free(prompt);
540 if (p && *p)
541 prompt= strdup(p);
542 else
543 prompt= 0;
544 }
545
546 bool
input_active(void) const547 cl_console_base::input_active(void) const
548 {
549 if ((
550 (flags & CONS_FROZEN) == 0 ||
551 (flags & CONS_INTERACTIVE) != 0
552 )
553 &&
554 (flags & CONS_INACTIVE) == 0
555 )
556 {
557 return true;
558 }
559 else
560 return false;
561 }
562
563 int
proc_input(class cl_cmdset * cmdset)564 cl_console_base::proc_input(class cl_cmdset *cmdset)
565 {
566 int retval= 0, i, do_print_prompt= 1;
567
568 un_redirect();
569 char *cmdstr;
570 i= read_line();
571 if (i < 0)
572 {
573 return 1;
574 }
575 if (i == 0)
576 return 0;
577 cmdstr= lbuf;
578 if (cmdstr==NULL)
579 cmdstr= (char*)"";
580 if (is_frozen())
581 {
582 application->get_sim()->stop(resUSER);
583 set_flag(CONS_FROZEN, false);
584 retval = 0;
585 do_print_prompt= 0;
586 }
587 else
588 {
589 if (cmdstr && *cmdstr == '\004')
590 retval = 1;
591 else
592 {
593 class cl_cmdline *cmdline= 0;
594 class cl_cmd *cm = 0;
595 if (get_flag(CONS_ECHO))
596 dd_printf("%s\n", cmdstr);
597 do
598 {
599 cmdline= new cl_cmdline(app, cmdstr, this);
600 cmdline->init();
601 if (cmdline->repeat() &&
602 is_interactive() &&
603 last_command)
604 {
605 cm= last_command;
606 }
607 else
608 {
609 cm= cmdset->get_cmd(cmdline, is_interactive());
610 last_command = 0;
611 }
612 if (cm)
613 {
614 dd_color("answer");
615 retval= cm->work(app, cmdline, this);
616 if (cm->can_repeat)
617 {
618 last_command = cm;
619 last_cmd= cmdline->cmd;
620 }
621 }
622 else if (cmdline->get_name() != 0)
623 {
624 char *e= cmdline->cmd;
625 if (strlen(e) > 0)
626 {
627 long l= application->eval(e);
628 dd_cprintf("result", "%ld\n", l);
629 }
630 }
631 if (get_fin() != NULL)
632 get_fin()->set_echo_color(get_color_ansiseq("command"));
633 lbuf= cmdline->rest;
634 cmdstr= lbuf;
635 delete cmdline;
636 }
637 while (!lbuf.empty());
638 }
639 }
640 if (!is_frozen())
641 un_redirect();
642 if (!retval &&
643 //cmdstr &&
644 do_print_prompt &&
645 !get_flag(CONS_REDIRECTED))
646 {
647 print_prompt();
648 }
649 lbuf= 0;
650 return(retval);
651 }
652
653 int
set_flag(int flag,bool value)654 cl_console_base::set_flag(int flag, bool value)
655 {
656 if (value)
657 flags|= flag;
658 else
659 flags&= ~flag;
660 return flags;
661 }
662
663 void
set_interactive(bool new_value)664 cl_console_base::set_interactive(bool new_value)
665 {
666 set_flag(CONS_INTERACTIVE, new_value);
667 }
668
669 bool
get_flag(int flag)670 cl_console_base::get_flag(int flag)
671 {
672 return flags & flag;
673 }
674
675 bool
set_cooked(bool new_val)676 cl_console_base::set_cooked(bool new_val)
677 {
678 return false;
679 }
680
681
682 /*
683 * Command interpreter
684 *____________________________________________________________________________
685 */
686
cl_commander_base(class cl_app * the_app,class cl_cmdset * acmdset)687 cl_commander_base::cl_commander_base(class cl_app *the_app, class cl_cmdset *acmdset):
688 cl_base()
689 {
690 app= the_app;
691 cons= new cl_list(1, 1, "consoles");
692 actual_console= frozen_console= config_console= 0;
693 cmdset= acmdset;
694 }
695
~cl_commander_base(void)696 cl_commander_base::~cl_commander_base(void)
697 {
698 cons->free_all();
699 delete cons;
700 delete cmdset;
701 }
702
703 void
add_console(class cl_console_base * console)704 cl_commander_base::add_console(class cl_console_base *console)
705 {
706 if (!console)
707 return;
708 int i=cons->add(console);
709 console->set_id(i);
710 console->init();
711 update_active();
712 }
713
714 void
del_console(class cl_console_base * console)715 cl_commander_base::del_console(class cl_console_base *console)
716 {
717 cons->disconn(console);
718 update_active();
719 delete console;
720 }
721
722 void
activate_console(class cl_console_base * console)723 cl_commander_base::activate_console(class cl_console_base *console)
724 {
725 console->set_flag(CONS_INACTIVE, false);
726 console->print_prompt();
727 update_active();
728 }
729
730 void
deactivate_console(class cl_console_base * console)731 cl_commander_base::deactivate_console(class cl_console_base *console)
732 {
733 console->set_flag(CONS_INACTIVE, true);
734 update_active();
735 }
736
737 int
consoles_prevent_quit(void)738 cl_commander_base::consoles_prevent_quit(void)
739 {
740 int i, r= 0;
741
742 for (i= 0; i < cons->count; i++)
743 {
744 class cl_console_base *c= (class cl_console_base*)(cons->at(i));
745 bool p= c->prevent_quit();
746 if (p)
747 r++;
748 }
749 return r;
750 }
751
752
753 /*
754 * Printing to all consoles
755 */
756
757 int
all_printf(const char * format,...)758 cl_commander_base::all_printf(const char *format, ...)
759 {
760 va_list ap;
761 int i, ret= 0;
762
763 for (i= 0; i < cons->count; i++)
764 {
765 class cl_console_base *c= (class cl_console_base*)(cons->at(i));
766
767 va_start(ap, format);
768 ret= c->cmd_do_print(format, ap);
769 va_end(ap);
770 }
771 return(ret);
772 }
773
774
775 /*
776 * Printing to actual_console
777 */
778
779 int
dd_printf(const char * format,va_list ap)780 cl_commander_base::dd_printf(const char *format, va_list ap)
781 {
782 int ret= 0;
783 class cl_console_base *con;
784
785 if (actual_console)
786 {
787 con= actual_console;
788 }
789 else if (frozen_console)
790 {
791 con= frozen_console;
792 }
793 else
794 {
795 con= 0;
796 }
797 if (con)
798 {
799 ret= con->cmd_do_print(format, ap);
800 }
801 return(ret);
802 }
803
804 int
dd_cprintf(const char * color_name,const char * format,va_list ap)805 cl_commander_base::dd_cprintf(const char *color_name, const char *format, va_list ap)
806 {
807 int ret= 0;
808 class cl_console_base *con;
809
810 if (actual_console)
811 {
812 con= actual_console;
813 }
814 else if (frozen_console)
815 {
816 con= frozen_console;
817 }
818 else
819 {
820 con= 0;
821 }
822 if (con)
823 {
824 ret= con->cmd_do_cprint(color_name, format, ap);
825 }
826 return(ret);
827 }
828
829 int
dd_printf(const char * format,...)830 cl_commander_base::dd_printf(const char *format, ...)
831 {
832 va_list ap;
833 int ret= 0;
834
835 va_start(ap, format);
836 ret= dd_printf(format, ap);
837 va_end(ap);
838
839 return(ret);
840 }
841
842 int
dd_cprintf(const char * color_name,const char * format,...)843 cl_commander_base::dd_cprintf(const char *color_name, const char *format, ...)
844 {
845 va_list ap;
846 int ret= 0;
847
848 va_start(ap, format);
849 ret= dd_cprintf(color_name, format, ap);
850 va_end(ap);
851
852 return(ret);
853 }
854
855 /*
856 * Printing to consoles which have CONS_DEBUG flag set
857 */
858
859 int
debug(const char * format,...)860 cl_commander_base::debug(const char *format, ...)
861 {
862 va_list ap;
863 int i, ret= 0;
864
865 for (i= 0; i < cons->count; i++)
866 {
867 class cl_console_base *c= (class cl_console_base*)(cons->at(i));
868 if (c->get_flag(CONS_DEBUG))
869 {
870 va_start(ap, format);
871 ret= c->cmd_do_cprint("debug", format, ap);
872 va_end(ap);
873 }
874 }
875 return(ret);
876 }
877
878 int
debug(const char * format,va_list ap)879 cl_commander_base::debug(const char *format, va_list ap)
880 {
881 int i, ret= 0;
882
883 for (i= 0; i < cons->count; i++)
884 {
885 class cl_console_base *c= (class cl_console_base*)(cons->at(i));
886 if (c->get_flag(CONS_DEBUG))
887 {
888 ret= c->cmd_do_cprint("debug", format, ap);
889 }
890 }
891 return(ret);
892 }
893
894 int
flag_printf(int iflags,const char * format,...)895 cl_commander_base::flag_printf(int iflags, const char *format, ...)
896 {
897 va_list ap;
898 int i, ret= 0;
899
900 for (i= 0; i < cons->count; i++)
901 {
902 class cl_console_base *c= (class cl_console_base*)(cons->at(i));
903 if ((c->get_flag(iflags)) == iflags)
904 {
905 va_start(ap, format);
906 ret= c->cmd_do_print(format, ap);
907 va_end(ap);
908 }
909 }
910 return(ret);
911 }
912
913 int
input_avail_on_frozen(void)914 cl_commander_base::input_avail_on_frozen(void)
915 {
916 if (!frozen_console || frozen_console->is_tty())
917 return(0);
918 return(frozen_console->input_avail());
919 }
920
921 class cl_console_base *
exec_on(class cl_console_base * cons,char * file_name)922 cl_commander_base::exec_on(class cl_console_base *cons, char *file_name)
923 {
924 if (!cons || !file_name || !fopen(file_name, "r"))
925 return 0;
926
927 class cl_console_base *subcon = cons->clone_for_exec(file_name);
928 subcon->set_flag(CONS_NOWELCOME, true);
929 subcon->set_flag(CONS_INTERACTIVE, false);
930 add_console(subcon);
931 return subcon;
932 }
933
934
935 /* End of cmd.src/newcmd.cc */
936