1 /*
2  * Simulator of microcontrollers (cmd.src/command.cc)
3  *
4  * Copyright (C) 2002,02 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 <stdlib.h>
31 #include <stdarg.h>
32 #include "i_string.h"
33 
34 // prj
35 #include "fiocl.h"
36 #include "utils.h"
37 #include "appcl.h"
38 
39 // local, cmd
40 #include "commandcl.h"
41 #include "argcl.h"
42 
43 
44 /*
45  * Command line
46  *____________________________________________________________________________
47  */
48 
cl_cmdline(class cl_app * the_app,char * acmd,class cl_console_base * acon)49 cl_cmdline::cl_cmdline(class cl_app *the_app,
50 		       char *acmd, class cl_console_base *acon):
51   cl_base()
52 {
53   app= the_app;
54   cmd= strdup(acmd);
55   params= new cl_list(2, 2, "command line params");
56   tokens= new cl_ustrings(2, 2, "command line tokens");
57   set_name(0);
58   matched_syntax= 0;
59   con= acon;
60 }
61 
~cl_cmdline(void)62 cl_cmdline::~cl_cmdline(void)
63 {
64   if (cmd)
65     free(cmd);
66   delete params;
67   delete tokens;
68 }
69 
70 int
init(void)71 cl_cmdline::init(void)
72 {
73   rest= NULL;
74   params->free_all();
75   tokens->free_all();
76   split();
77   return(0);
78 }
79 
80 char *
skip_delims(char * start)81 cl_cmdline::skip_delims(char *start)
82 {
83   while (*start &&
84 	 strchr(" \t\v\r,", *start))
85     start++;
86   return(start);
87 }
88 
89 int
split(void)90 cl_cmdline::split(void)
91 {
92   //class cl_sim *sim;
93   char *start= cmd;
94   int i;//, j;
95   class cl_cmd_arg *arg;
96 
97   set_name("\n");
98   if (!cmd ||
99       !*cmd)
100     return(0);
101   start+= strspn(start, " \t\v\r,");
102   if (!start)
103     return 0;
104   set_name(0);
105   if (*start == '\n')
106     {
107       // never, as \n stripped by readline
108       set_name("\n");
109       return(0);
110     }
111   else if (*start == '#')
112     return *start= 0;
113   else if (*start == ';')
114     {
115       rest= start+1;
116       *start= 0;
117       return 0;
118     }
119   if (!*start)
120     return(0);
121   // start now points to first word
122   i= strcspn(start, " \t\v\r,;#");
123   // i should be at end of it
124   if (i)
125     {
126       if (*start == '#')
127 	return set_name("\n"), *start= 0;
128       char *n= (char*)malloc(i+1);
129       strncpy(n, start, i);
130       n[i]= '\0';
131       set_name(n);
132       free(n);
133     }
134   start+= i;
135   start= skip_delims(start);
136   while (*start)
137     {
138       char *end= start, *param_str;
139       if (*start == '#')
140 	return *start= '\0';
141       else if (*start == ';')
142 	{
143 	  rest= start+1;
144 	  *start= 0;
145 	  return 0;
146 	}
147       else if (*start == '"')
148 	split_out_string(&start, &end);
149       else if (*start == '>')
150 	split_out_output_redirection(&start, &end);
151       else
152 	{
153 	  char *dot;
154           i= strcspn(start, " \t\v\r,#;");
155           end= start+i;
156           param_str= (char *)malloc(i+1);
157           strncpy(param_str, start, i);
158 	  param_str[i]= '\0';
159 	  tokens->add(strdup(param_str));
160 	  if ((dot= strchr(param_str, '.')) != NULL)
161 	    split_out_bit(dot, param_str);
162 	  else if ((dot= strchr(param_str, '[')) != NULL)
163 	    split_out_array(dot, param_str);
164 	  else if (param_str[0] == '0' && param_str[1] == 'b')
165             {
166               long n= 0;
167 	      for (int i= 2; param_str[i] == '0' || param_str[i] == '1'; i++)
168                 n = (n << 1) | (param_str[i] == '0' ? 0 : 1);
169 	      params->add(arg= new cl_cmd_int_arg(n));
170 	      arg->init();
171             }
172 	  else if (strchr("0123456789-+", *param_str) != NULL)
173 	    {
174 	      // number
175 	      params->add(arg= new cl_cmd_int_arg((long)
176 						  strtol(param_str, 0, 0)));
177 	      arg->init();
178 	    }
179 	  else
180 	    {
181 	      // symbol
182 	      params->add(arg= new cl_cmd_sym_arg(param_str));
183 	      arg->init();
184 	    }
185 	  free(param_str);
186 	}
187       start= end;
188       start= skip_delims(start);
189     }
190   return(0);
191 }
192 
193 void
split_out_string(char ** _start,char ** _end)194 cl_cmdline::split_out_string(char **_start, char **_end)
195 {
196   char *start= *_start, *end;
197   start++;
198   end= start;
199   while (*end &&
200         *end != '"')
201     {
202       if (*end == '\\')
203        {
204          end++;
205          if (*end)
206            end++;
207        }
208       else
209        end++;
210     }
211   if (*end == '"')
212     end--;
213   else
214     con->dd_printf("Unterminated string\n");
215   char *param_str= (char *)malloc(end-start+2);
216   strncpy(param_str, start, 1+end-start);
217   param_str[1+end-start]= '\0';
218   tokens->add(strdup(param_str));
219   class cl_cmd_arg *arg;
220   params->add(arg= new cl_cmd_str_arg(param_str));
221   arg->init();
222   free(param_str);
223   if (*end)
224     end++;
225   if (*end == '"')
226     end++;
227   *_start= start;
228   *_end= end;
229 }
230 
231 void
split_out_output_redirection(char ** _start,char ** _end)232 cl_cmdline::split_out_output_redirection(char **_start, char **_end)
233 {
234   char *start= *_start, *end/*= *_end*/;
235   int i;
236   char mode[2];
237 
238   mode[0]= 'w';
239   mode[1]= '\0';
240   start++;
241   i= strcspn(start, " \t\v\r,");
242   end= start+i;
243   char *param_str= (char *)malloc(i+1);
244   char *n= param_str;
245   strncpy(param_str, start, i);
246   param_str[i]= '\0';
247   if (param_str &&
248       param_str[0] == '>')
249     {
250       n++;
251       mode[0]= 'a';
252     }
253   tokens->add(strdup(n));
254   con->redirect(n, mode);
255   free(param_str);
256   *_start= start;
257   *_end= end;
258 }
259 
260 void
split_out_bit(char * dot,char * param_str)261 cl_cmdline::split_out_bit(char *dot, char *param_str)
262 {
263   class cl_cmd_arg *sfr, *bit;
264 
265   *dot= '\0';
266   dot++;
267   if (strchr("0123456789", *param_str) != NULL)
268     {
269       sfr= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
270       sfr->init();
271     }
272   else
273     {
274       sfr= new cl_cmd_sym_arg(param_str);
275       sfr->init();
276     }
277   if (*dot == '\0')
278     {
279       bit= 0;
280       con->dd_printf("Uncomplete bit address\n");
281       delete sfr;
282     }
283   else
284     {
285       if (strchr("0123456789", *dot) != NULL)
286        {
287          bit= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
288          bit->init();
289        }
290       else
291        {
292          bit= new cl_cmd_sym_arg(dot);
293          bit->init();
294        }
295       class cl_cmd_arg *arg;
296       params->add(arg= new cl_cmd_bit_arg(sfr, bit));
297       arg->init();
298     }
299 }
300 
301 void
split_out_array(char * dot,char * param_str)302 cl_cmdline::split_out_array(char *dot, char *param_str)
303 {
304   class cl_cmd_arg *aname, *aindex;
305 
306   *dot= '\0';
307   dot++;
308   if (strchr("0123456789", *param_str) != NULL)
309     {
310       aname= new cl_cmd_int_arg((long)strtol(param_str, 0, 0));
311       aname->init();
312     }
313   else
314     {
315       aname= new cl_cmd_sym_arg(param_str);
316       aname->init();
317     }
318   if (*dot == '\0')
319     {
320       aname= 0;
321       con->dd_printf("Uncomplete array\n");
322     }
323   else
324     {
325       char *p;
326       p= dot + strlen(dot) - 1;
327       while (p > dot &&
328             *p != ']')
329        {
330          *p= '\0';
331          p--;
332        }
333       if (*p == ']')
334        *p= '\0';
335       if (strlen(dot) == 0)
336        {
337          con->dd_printf("Uncomplete array index\n");
338          delete aname;
339        }
340       else
341        {
342          if (strchr("0123456789", *dot) != NULL)
343            {
344              aindex= new cl_cmd_int_arg((long)strtol(dot, 0, 0));
345              aindex->init();
346            }
347          else
348            {
349              aindex= new cl_cmd_sym_arg(dot);
350              aindex->init();
351            }
352          class cl_cmd_arg *arg;
353          params->add(arg= new cl_cmd_array_arg(aname, aindex));
354          arg->init();
355        }
356     }
357 }
358 
359 int
shift(void)360 cl_cmdline::shift(void)
361 {
362   char *s= skip_delims(cmd);
363 
364   params->free_all();
365   tokens->free_all();
366   set_name(0);
367   if (s && *s)
368     {
369       while (*s &&
370 	     strchr(" \t\v\r,;#", *s) == NULL)
371 	s++;
372       s= skip_delims(s);
373       char *p= strdup(s), *r= rest?strdup(rest):NULL;
374       free(cmd);
375       cmd= p;
376       rest= r;
377       //params= new cl_list(2, 2, "params");
378       split();
379       if (strcmp(get_name(), "\n") == 0)
380 	set_name(0);
381     }
382   return(have_real_name());
383 }
384 
385 int
repeat(void)386 cl_cmdline::repeat(void)
387 {
388   const char *n;
389   return((n= get_name()) &&
390 	 *n == '\n');
391 }
392 
393 class cl_cmd_arg *
param(int num)394 cl_cmdline::param(int num)
395 {
396   if (num >= params->count)
397     return(0);
398   return((class cl_cmd_arg *)(params->at(num)));
399 }
400 
401 void
insert_param(int pos,class cl_cmd_arg * param)402 cl_cmdline::insert_param(int pos, class cl_cmd_arg *param)
403 {
404   if (pos >= params->count)
405     params->add(param);
406   else
407     params->add_at(pos, param);
408 }
409 
410 bool
syntax_match(class cl_uc * uc,const char * syntax)411 cl_cmdline::syntax_match(class cl_uc *uc, const char *syntax)
412 {
413   if (!syntax)
414     return(false);
415   if (!*syntax &&
416       !params->count)
417     {
418       matched_syntax= syntax;
419       return(true);
420     }
421   if (!params->count)
422     return(false);
423   //printf("syntax %s?\n",syntax);
424   const char *p= syntax;
425   int iparam= 0;
426   class cl_cmd_arg *parm= (class cl_cmd_arg *)(params->at(iparam));
427   while (*p &&
428 	 parm)
429     {
430       //printf("***Checking %s as %c\n",parm->get_svalue(),*p);
431       if (uc)
432 	{
433 	  switch (*p)
434 	    {
435 	    case SY_ADDR:
436 	      if (!parm->as_address(uc))
437 		return(false);
438 	      //printf("ADDRESS match %lx\n",parm->value.address);
439 	      break;
440 	    case SY_MEMORY:
441 	      if (!parm->as_memory(uc))
442 		return(false);
443 	      //printf("MEMORY match %s\n",parm->value.memory->class_name);
444 	      break;
445 	    case SY_BIT:
446 	      if (!parm->as_bit(uc))
447 		return(false);
448 	      break;
449 	    case SY_HW:
450 	      if (!parm->as_hw(uc))
451 		return(false);
452 	      break;
453 	    case SY_CELL:
454 	      if (!parm->as_cell(uc))
455 		return false;
456 	      break;
457 	    }
458 	}
459       //else
460 	{
461 	  switch (*p)
462 	    {
463 	    case SY_ADDR: case SY_MEMORY: case SY_BIT: break;
464 	    case SY_NUMBER:
465 	      if (!parm->as_number())
466 		return(false);
467 	      break;
468 	    case SY_DATA:
469 	      if (!parm->as_data())
470 		return(false);
471 	      break;
472 	    case SY_STRING:
473 	      if (!parm->as_string())
474 		return(false);
475 	      break;
476 	    case SY_DATALIST:
477 	      if (!set_data_list(parm, &iparam))
478 		return(false);
479 	      break;
480 	      //default: return(false);
481 	    }
482 	}
483       p++;
484       iparam++;
485       if (iparam < params->count)
486 	parm= (class cl_cmd_arg *)(params->at(iparam));
487       else
488 	parm= 0;
489     }
490   if (!*p &&
491       !parm)
492     {
493       matched_syntax= syntax;
494       return(true);
495     }
496   return(false);
497 }
498 
499 bool
set_data_list(class cl_cmd_arg * parm,int * iparm)500 cl_cmdline::set_data_list(class cl_cmd_arg *parm, int *iparm)
501 {
502   class cl_cmd_arg *next_parm;
503   int len, i, j;
504   t_mem *array;
505 
506   len= 0;
507   array= 0;
508   for (i= *iparm, next_parm= param(i); next_parm; i++, next_parm= param(i))
509     {
510       if (next_parm->is_string())
511 	{
512 	  int l;
513 	  char *s;
514 	  //s= proc_escape(next_parm->get_svalue(), &l);
515 	  if (!next_parm->as_string())
516 	    continue;
517 	  s= next_parm->value.string.string;
518 	  l= next_parm->value.string.len;
519 	  if (!array)
520 	    array= (t_mem*)malloc(sizeof(t_mem)*l);
521 	  else
522 	    array= (t_mem*)realloc(array, sizeof(t_mem)*(l+len));
523 	  for (j= 0; j < l; j++)
524 	    {
525 	      array[len]= s[j];
526 	      len++;
527 	    }
528 	  //if (s)
529 	  //free(s);
530 	}
531       else
532 	{
533 	  if (!next_parm->as_data())
534 	    {
535 	      if (array)
536 		free(array);
537 	      return(false);
538 	    }
539 	  if (!array)
540 	    array= (t_mem*)malloc(sizeof(t_mem));
541 	  else
542 	    array= (t_mem*)realloc(array, sizeof(t_mem)*(1+len));
543 	  array[len]= next_parm->value.data;
544 	  len++;
545 	}
546     }
547   *iparm= i;
548   parm->value.data_list.array= array;
549   parm->value.data_list.len= len;
550   return(true);
551 }
552 
553 bool
restart_at_rest(void)554 cl_cmdline::restart_at_rest(void)
555 {
556   char *newcmd;
557   if ((rest == NULL) ||
558       (*rest == 0))
559     {
560       return false;
561     }
562   newcmd= strdup(rest);
563   if (cmd)
564     free(cmd);
565   cmd= newcmd;
566   return true;
567 }
568 
569 
570 /*
571  * Command
572  *____________________________________________________________________________
573  */
574 
cl_cmd(enum cmd_operate_on op_on,const char * aname,int can_rep)575 cl_cmd::cl_cmd(enum cmd_operate_on op_on,
576 	       const char *aname,
577 	       int can_rep):
578   cl_base()
579 {
580   operate_on= op_on;
581   names= new cl_strings(1, 1, "names of a command");
582   names->add(aname?strdup(aname):strdup("unknown"));
583   can_repeat= can_rep;
584   usage_help= 0;
585   short_help= 0;//short_hlp;//?strdup(short_hlp):NULL;
586   long_help= 0;//long_hlp;//?strdup(long_hlp):NULL;
587 }
588 
589 /*cl_cmd::cl_cmd(class cl_sim *asim):
590   cl_base()
591 {
592   sim= asim;
593   name= short_help= long_help= 0;
594   can_repeat= 0;
595 }*/
596 
597 void
set_help(const char * usage_hlp,const char * short_hlp,const char * long_hlp)598 cl_cmd::set_help(const char *usage_hlp, const char *short_hlp, const char *long_hlp)
599 {
600   usage_help= usage_hlp;
601   short_help= short_hlp;
602   long_help= long_hlp;
603 }
604 
~cl_cmd(void)605 cl_cmd::~cl_cmd(void)
606 {
607   delete names;
608   //if (short_help) free((void*)short_help);
609   //if (long_help) free((void*)long_help);
610 }
611 
612 void
add_name(const char * nam)613 cl_cmd::add_name(const char *nam)
614 {
615   if (nam)
616     names->add(strdup(nam));
617 }
618 
619 int
name_match(const char * aname,int strict)620 cl_cmd::name_match(const char *aname, int strict)
621 {
622   int i;
623 
624   if (names->count == 0 &&
625       !aname)
626     return(1);
627   if (!aname)
628     return(0);
629   if (strict)
630     {
631       for (i= 0; i < names->count; i++)
632 	{
633 	  char *n= (char*)(names->at(i));
634 	  if (strcmp(aname, n) == 0)
635 	    return(1);
636 	}
637     }
638   else
639     {
640       for (i= 0; i < names->count; i++)
641 	{
642 	  char *n= (char*)(names->at(i));
643 	  if (strstr(n, aname) == n)
644 	    return(1);
645 	}
646     }
647   return(0);
648 }
649 
650 int
name_match(class cl_cmdline * cmdline,int strict)651 cl_cmd::name_match(class cl_cmdline *cmdline, int strict)
652 {
653   return(name_match(cmdline->get_name(), strict));
654 }
655 
656 int
syntax_ok(class cl_cmdline * cmdline)657 cl_cmd::syntax_ok(class cl_cmdline *cmdline)
658 {
659   return(1);
660 }
661 
662 int
work(class cl_app * app,class cl_cmdline * cmdline,class cl_console_base * con)663 cl_cmd::work(class cl_app *app,
664 	     class cl_cmdline *cmdline, class cl_console_base *con)
665 {
666   if (!syntax_ok(cmdline))
667     return(0);
668   class cl_sim *sim= app->get_sim();
669   class cl_uc *uc= 0;
670   if (sim)
671     uc= sim->uc;
672   switch (operate_on)
673     {
674     case operate_on_app:
675       if (!app)
676 	{
677 	  con->dd_printf("There is no application to work on!\n");
678 	  return(false);
679 	}
680       return(do_work(app, cmdline, con));
681     case operate_on_sim:
682       if (!sim)
683 	{
684 	  con->dd_printf("There is no simulator to work on!\n");
685 	  return(false);
686 	}
687       return(do_work(sim, cmdline, con));
688     case operate_on_uc:
689       if (!sim)
690 	{
691 	  con->dd_printf("There is no microcontroller to work on!\n");
692 	  return(false);
693 	}
694       return(do_work(uc, cmdline, con));
695     default:
696       return(do_work(cmdline, con));
697     }
698 }
699 
700 int
do_work(class cl_cmdline * cmdline,class cl_console_base * con)701 cl_cmd::do_work(class cl_cmdline *cmdline, class cl_console_base *con)
702 {
703   con->dd_printf("Command \"%s\" does nothing.\n",
704 		 (char*)(names->at(0)));
705   return(0);
706 }
707 
708 int
do_work(class cl_app * app,class cl_cmdline * cmdline,class cl_console_base * con)709 cl_cmd::do_work(class cl_app *app,
710 		class cl_cmdline *cmdline, class cl_console_base *con)
711 {
712   con->dd_printf("Command \"%s\" does nothing on application.\n",
713 		 (char*)(names->at(0)));
714   return(0);
715 }
716 
717 int
do_work(class cl_sim * sim,class cl_cmdline * cmdline,class cl_console_base * con)718 cl_cmd::do_work(class cl_sim *sim,
719 		class cl_cmdline *cmdline, class cl_console_base *con)
720 {
721   con->dd_printf("Command \"%s\" does nothing on simulator.\n",
722 		 (char*)(names->at(0)));
723   return(0);
724 }
725 
726 int
do_work(class cl_uc * uc,class cl_cmdline * cmdline,class cl_console_base * con)727 cl_cmd::do_work(class cl_uc *uc,
728 		class cl_cmdline *cmdline, class cl_console_base *con)
729 {
730   con->dd_printf("Command \"%s\" does nothing on microcontroller.\n",
731 		 (char*)(names->at(0)));
732   return(0);
733 }
734 
735 void
print_short(class cl_console_base * con)736 cl_cmd::print_short(class cl_console_base *con)
737 {
738   int l= usage_help.len();
739 
740   if (!con)
741     return;
742 
743   if (usage_help.nempty())
744     con->dd_printf("%s", (char*)usage_help);
745   if (l > 19)
746     {
747       con->dd_printf("\n");
748       l=0;
749     }
750   while (l < 20)
751     {
752       con->dd_printf(" ");
753       l++;
754     }
755   if (short_help.nempty())
756     {
757 	con->dd_printf("%s", (char*)short_help);
758     }
759   else
760     con->dd_printf("%s", (char*)(names->at(0)));
761   con->dd_printf("\n");
762 }
763 
764 void
syntax_error(class cl_console_base * con)765 cl_cmd::syntax_error(class cl_console_base *con)
766 {
767   if (con)
768     {
769       if (short_help.nempty())
770 	print_short(con);
771       else
772 	con->dd_printf("Error: wrong syntax\n");
773     }
774 }
775 
776 /*
777  * Set of commands
778  *____________________________________________________________________________
779  */
780 
cl_cmdset(void)781 cl_cmdset::cl_cmdset(void):
782   cl_list(5, 5, "cmdset")
783 {
784   //sim= 0;
785   //last_command= 0;
786 }
787 
788 /*cl_cmdset::cl_cmdset(class cl_sim *asim):
789   cl_list(5, 5)
790 {
791   sim= asim;
792   last_command= 0;
793 }*/
794 
795 class cl_cmd *
get_cmd(class cl_cmdline * cmdline,bool accept_last)796 cl_cmdset::get_cmd(class cl_cmdline *cmdline, bool accept_last)
797 {
798   int i;
799 
800   // exact match
801   for (i= 0; i < count; i++)
802     {
803       class cl_cmd *c= (class cl_cmd *)at(i);
804       if (c->name_match(cmdline, 1))
805 	return(c);
806     }
807   // not exact match
808   class cl_cmd *c_matched= 0;
809   for (i= 0; i < count; i++)
810     {
811       class cl_cmd *c= (class cl_cmd *)at(i);
812       if (c->name_match(cmdline, 0))
813 	{
814 	  if (!c_matched)
815 	    c_matched= c;
816 	  else
817 	    return(0);
818 	}
819     }
820   return(c_matched);
821   //return(0);
822 }
823 
824 class cl_cmd *
get_cmd(const char * cmd_name)825 cl_cmdset::get_cmd(const char *cmd_name)
826 {
827   int i;
828 
829   for (i= 0; i < count; i++)
830     {
831       class cl_cmd *c= (class cl_cmd *)at(i);
832       if (c->name_match(cmd_name, 1))
833 	return(c);
834     }
835   return(0);
836 }
837 
838 void
del(char * nam)839 cl_cmdset::del(char *nam)
840 {
841   int i;
842 
843   if (!nam)
844     return;
845   for (i= 0; i < count; i++)
846     {
847       class cl_cmd *cmd= (class cl_cmd *)(at(i));
848       if (cmd->name_match(nam, 1))
849 	free_at(i);
850     }
851 }
852 
853 void
replace(char * nam,class cl_cmd * cmd)854 cl_cmdset::replace(char *nam, class cl_cmd *cmd)
855 {
856   int i;
857 
858   if (!nam)
859     return;
860   for (i= 0; i < count; i++)
861     {
862       class cl_cmd *c= (class cl_cmd *)(at(i));
863       if (c->name_match(nam, 1))
864 	{
865 	  delete c;
866 	  put_at(i, cmd);
867 	}
868     }
869 }
870 
871 
872 /*
873  * Composed command: subset of commands
874  *____________________________________________________________________________
875  */
876 
cl_super_cmd(const char * aname,int can_rep,class cl_cmdset * acommands)877 cl_super_cmd::cl_super_cmd(const char *aname,
878 			   int  can_rep,
879 			   class cl_cmdset *acommands):
880   cl_cmd(operate_on_none, aname, can_rep)
881 {
882   commands= acommands;
883 }
884 
~cl_super_cmd(void)885 cl_super_cmd::~cl_super_cmd(void)
886 {
887   if (commands)
888     delete commands;
889 }
890 
891 int
work(class cl_app * app,class cl_cmdline * cmdline,class cl_console_base * con)892 cl_super_cmd::work(class cl_app *app,
893 		   class cl_cmdline *cmdline, class cl_console_base *con)
894 {
895   class cl_cmd *cmd= 0;
896 
897   if (!commands)
898     return(0);
899 
900   if (!cmdline->shift())
901     {
902       if ((cmd= commands->get_cmd("_no_parameters_")) != 0)
903 	return(cmd->work(app, cmdline, con));
904       int i;
905       con->dd_printf("\"%s\" must be followed by the name of a subcommand\n"
906 		     "List of subcommands:\n", (char*)(names->at(0)));
907       for (i= 0; i < commands->count; i++)
908 	{
909 	  cmd= (class cl_cmd *)(commands->at(i));
910 	  //con->dd_printf("%s\n", (char*)cmd->short_help);
911 	  cmd->print_short(con);
912 	}
913       return(0);
914     }
915   if ((cmd= commands->get_cmd(cmdline, con->is_interactive())) == NULL)
916     {
917       con->dd_printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
918 		     cmdline->get_name(), (char*)(names->at(0)));
919       return(0);
920     }
921   return(cmd->work(app, cmdline, con));
922 }
923 
924 
925 /* End of cmd.src/command.cc */
926