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