2 * Simulator of microcontrollers (cmd.src/command.cc)
4 * Copyright (C) 2002,02 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
10 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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
28 //#include "ddconfig.h"
36 //#include "i_string.h"
44 #include "commandcl.h"
50 *____________________________________________________________________________
53 cl_cmdline::cl_cmdline(class cl_app
*the_app
,
54 const char *acmd
, class cl_console_base
*acon
):
59 params
= new cl_list(2, 2, "command line params");
60 tokens
= new cl_ustrings(2, 2, "command line tokens");
66 cl_cmdline::~cl_cmdline(void)
75 cl_cmdline::init(void)
85 cl_cmdline::skip_delims(char *start
)
88 strchr(" \t\v\r,", *start
))
94 cl_cmdline::split(void)
99 class cl_cmd_arg
*arg
;
105 start
+= strspn(start
, " \t\v\r,");
111 // never, as \n stripped by readline
115 else if (*start
== '#')
117 else if (*start
== ';')
125 // start now points to first word
126 i
= strcspn(start
, " \t\v\r,;#");
127 // i should be at end of it
131 return set_name("\n"), *start
= 0;
132 char *n
= (char*)malloc(i
+1);
133 strncpy(n
, start
, i
);
139 start
= skip_delims(start
);
142 char *end
= start
, *param_str
;
145 else if (*start
== ';')
151 else if (*start
== '"')
152 split_out_string(&start
, &end
);
153 else if (*start
== '>')
154 split_out_output_redirection(&start
, &end
);
158 i
= strcspn(start
, " \t\v\r,#;");
160 /*param_str= (char *)malloc(i+1);
161 strncpy(param_str, start, i);
165 ps
.appendn(start
, i
);
166 expand_commands(&ps
);
167 tokens
->add(strdup(/*param_str*/ps
.c_str()));
168 param_str
= (char*)ps
.c_str();
169 if ((dot
= strchr(param_str
, '[')) != NULL
)
172 for (p
= dot
+1; *p
&& *p
!= ']' && *p
!= ':'; p
++);
174 split_out_bit(dot
, param_str
);
176 split_out_array(dot
, param_str
);
178 else if ((dot
= strchr(param_str
, '.')) != NULL
&& dot
!= param_str
)
179 split_out_bit(dot
, param_str
);
180 else if (param_str
[0] == '0' && param_str
[1] == 'b')
184 for (ii
= 2; param_str
[ii
] == '0' || param_str
[ii
] == '1'; ii
++)
185 n
= (n
<< 1) | (param_str
[ii
] == '0' ? 0 : 1);
186 params
->add(arg
= new cl_cmd_int_arg(n
));
189 else if (strchr("0123456789-+", *param_str
) != NULL
)
192 params
->add(arg
= new cl_cmd_int_arg((long)
193 strtol(param_str
, 0, 0)));
199 params
->add(arg
= new cl_cmd_sym_arg(param_str
));
205 start
= skip_delims(start
);
211 cl_cmdline::split_out_string(char **_start
, char **_end
)
213 char *start
= *_start
, *end
;
231 con
->dd_cprintf("error", "Unterminated string\n");
233 ps
.appendn(start
, 1+end
-start
);
234 expand_commands(&ps
);
235 tokens
->add(strdup(ps
.c_str()));
236 class cl_cmd_arg
*arg
;
237 params
->add(arg
= new cl_cmd_str_arg(ps
.c_str()));
249 cl_cmdline::split_out_output_redirection(char **_start
, char **_end
)
251 char *start
= *_start
;
264 j
= token_length(start
);
266 con
->redirect(get_token(start
).c_str(), mode
);
272 cl_cmdline::add_bit(char *dot
, char *colon
, class cl_cmd_arg
*sfr
)
274 class cl_cmd_arg
*bit_low
= NULL
, *bit_high
= NULL
;
280 char *end
= strchr(colon
, ']');
286 con
->dd_cprintf("error", "Incomplete bit address\n");
294 con
->dd_cprintf("error", "Incomplete bit address\n");
303 if (strchr("0123456789", *dot
) != NULL
)
305 bit_low
= new cl_cmd_int_arg((long)strtol(dot
, 0, 0));
310 bit_low
= new cl_cmd_sym_arg(dot
);
318 class cl_cmd_arg
*arg
;
319 params
->add(arg
= new cl_cmd_bit_arg(sfr
, bit_low
, bit_high
));
324 cl_cmdline::split_out_bit(char *dot
, char *param_str
)
327 class cl_cmd_arg
*sfr
;
330 colon
= strchr(dot
+1, ':');
334 if (strchr("0123456789", *param_str
) != NULL
)
336 sfr
= new cl_cmd_int_arg((long)strtol(param_str
, 0, 0));
341 sfr
= new cl_cmd_sym_arg(param_str
);
345 add_bit(dot
, colon
, sfr
);
349 cl_cmdline::split_out_array(char *dot
, char *param_str
)
351 class cl_cmd_arg
*aname
, *aindex
;
355 if (strchr("0123456789", *param_str
) != NULL
)
357 aname
= new cl_cmd_int_arg((long)strtol(param_str
, 0, 0));
362 aname
= new cl_cmd_sym_arg(param_str
);
368 con
->dd_cprintf("error", "Incomplete array\n");
372 char *p
= strchr(dot
, ']');
375 con
->dd_cprintf("error", "Missing ']' in array index\n");
381 if (strlen(dot
) == 0)
383 con
->dd_cprintf("error", "Incomplete array index\n");
388 if (strchr("0123456789", *dot
) != NULL
)
390 aindex
= new cl_cmd_int_arg((long)strtol(dot
, 0, 0));
395 aindex
= new cl_cmd_sym_arg(dot
);
398 class cl_cmd_arg
*arg
= new cl_cmd_array_arg(aname
, aindex
);
400 if (*p
== '.' || *p
== '[')
401 add_bit(p
+1, strchr(p
+1, ':'), arg
);
410 cl_cmdline::token_length(char *start
)
419 for (i
=1; start
[i
]!=0 && start
[i
]!='\"'; i
++)
428 return strcspn(start
, " \t\v\r,;");
432 cl_cmdline::get_token(char *start
)
442 for (i
=1; start
[i
]!=0 && start
[i
]!='\"'; i
++)
452 case 'a': cs
+= '\a'; break;
453 case 'b': cs
+= '\b'; break;
454 case 'e': cs
+= '\x1b'; break;
455 case 'f': cs
+= '\f'; break;
456 case 'n': cs
+= '\n'; break;
457 case 'r': cs
+= '\r'; break;
458 case 't': cs
+= '\t'; break;
459 case 'v': cs
+= '\v'; break;
460 case '\'': cs
+= '\''; break;
461 case '\"': cs
+= '\"'; break;
476 int l
= strcspn(start
, " \t\v\r,;");
484 cl_cmdline::expand_commands(chars
*params
)
486 int start
= -1, end
= -1;
488 char *s
= params
->str();
491 for (i
= 0; s
[i
]; i
++)
497 else if (s
[i
] == '$')
501 if ((level
== 0) && s
[i
+1])
506 else if (s
[i
] == ')')
513 //printf("S:%d E:%d L:%d\n",start,end,level);
514 if ((start
< 0) && (end
< 0))
516 if ((start
< 0) || (end
< 0) || (level
!= 0))
518 con
->dd_cprintf("error", "Syntax error: unbalanced command expansion\n");
522 cmd
.appendn(&s
[start
], end
-start
+1);
523 //printf("OK |%s|\n", cmd.c_str());
528 cl_cmdline::shift(void)
530 char *s
= skip_delims(cmd
);
538 strchr(" \t\v\r,;#", *s
) == NULL
)
541 char *p
= strdup(s
), *r
= rest
?strdup(rest
):(char*)NULL
;
545 //params= new cl_list(2, 2, "params");
547 if (strcmp(get_name(), "\n") == 0)
550 return(have_real_name());
554 cl_cmdline::repeat(void)
557 return((n
= get_name()) &&
562 cl_cmdline::param(int num
)
564 if (num
>= params
->count
)
566 return((class cl_cmd_arg
*)(params
->at(num
)));
570 cl_cmdline::insert_param(int pos
, class cl_cmd_arg
*param
)
572 if (pos
>= params
->count
)
575 params
->add_at(pos
, param
);
579 cl_cmdline::syntax_match(class cl_uc
*uc
, const char *syntax
)
586 matched_syntax
= syntax
;
591 //printf("syntax %s?\n",syntax);
592 const char *p
= syntax
;
594 class cl_cmd_arg
*parm
= (class cl_cmd_arg
*)(params
->at(iparam
));
598 //printf("***Checking %s as %c\n",parm->get_svalue(),*p);
604 if (!parm
->as_address(uc
))
606 //printf("ADDRESS match %lx\n",parm->value.address);
609 if (!parm
->as_memory(uc
))
611 //printf("MEMORY match %s\n",parm->value.memory->class_name);
614 if (!parm
->as_bit(uc
))
618 if (!parm
->as_hw(uc
))
622 if (!parm
->as_cell(uc
))
631 case SY_ADDR
: case SY_MEMORY
: case SY_BIT
: break;
633 if (!parm
->as_number())
637 if (!parm
->as_data())
641 if (!parm
->as_string())
645 if (!set_data_list(parm
, &iparam
))
648 //default: return(false);
653 if (iparam
< params
->count
)
654 parm
= (class cl_cmd_arg
*)(params
->at(iparam
));
661 matched_syntax
= syntax
;
668 cl_cmdline::set_data_list(class cl_cmd_arg
*parm
, int *iparm
)
670 class cl_cmd_arg
*next_parm
;
676 for (i
= *iparm
, next_parm
= param(i
); next_parm
; i
++, next_parm
= param(i
))
678 if (next_parm
->is_string())
682 //s= proc_escape(next_parm->get_svalue(), &l);
683 if (!next_parm
->as_string())
685 s
= next_parm
->value
.string
.string
;
686 l
= next_parm
->value
.string
.len
;
688 array
= (t_mem
*)malloc(sizeof(t_mem
)*l
);
691 temp
= (t_mem
*)realloc(array
, sizeof(t_mem
)*(l
+len
));
696 for (j
= 0; j
< l
; j
++)
706 if (!next_parm
->as_data())
713 array
= (t_mem
*)malloc(sizeof(t_mem
));
716 temp
= (t_mem
*)realloc(array
, sizeof(t_mem
)*(1+len
));
721 array
[len
]= next_parm
->value
.data
;
726 parm
->value
.data_list
.array
= array
;
727 parm
->value
.data_list
.len
= len
;
732 cl_cmdline::restart_at_rest(void)
735 if ((rest
== NULL
) ||
740 newcmd
= strdup(rest
);
750 *____________________________________________________________________________
753 cl_cmd::cl_cmd(enum cmd_operate_on op_on
,
759 names
= new cl_strings(1, 1, "names of a command");
760 names
->add(aname
?strdup(aname
):strdup("unknown"));
763 short_help
= 0;//short_hlp;//?strdup(short_hlp):NULL;
764 long_help
= 0;//long_hlp;//?strdup(long_hlp):NULL;
767 /*cl_cmd::cl_cmd(class cl_sim *asim):
771 name= short_help= long_help= 0;
776 cl_cmd::set_help(const char *usage_hlp
, const char *short_hlp
, const char *long_hlp
)
778 usage_help
= usage_hlp
;
779 short_help
= short_hlp
;
783 cl_cmd::~cl_cmd(void)
786 //if (short_help) free((void*)short_help);
787 //if (long_help) free((void*)long_help);
791 cl_cmd::add_name(const char *nam
)
794 names
->add(strdup(nam
));
798 cl_cmd::name_match(const char *aname
, int strict
)
802 if (names
->count
== 0 &&
809 for (i
= 0; i
< names
->count
; i
++)
811 const char *n
= names
->at(i
);
812 if (strcmp(aname
, n
) == 0)
818 for (i
= 0; i
< names
->count
; i
++)
820 const char *n
= names
->at(i
);
821 if (strstr(n
, aname
) == n
)
829 cl_cmd::name_match(class cl_cmdline
*cmdline
, int strict
)
831 return(name_match(cmdline
->get_name(), strict
));
835 cl_cmd::syntax_ok(class cl_cmdline
*cmdline
)
841 cl_cmd::work(class cl_app
*app
,
842 class cl_cmdline
*cmdline
, class cl_console_base
*con
)
844 if (!syntax_ok(cmdline
))
846 class cl_sim
*sim
= app
->get_sim();
855 con
->dd_cprintf("error", "There is no application to work on!\n");
858 return(do_work(app
, cmdline
, con
));
862 con
->dd_cprintf("error", "There is no simulator to work on!\n");
865 return(do_work(sim
, cmdline
, con
));
869 con
->dd_cprintf("error", "There is no microcontroller to work on!\n");
872 return(do_work(uc
, cmdline
, con
));
874 return(do_work(cmdline
, con
));
879 cl_cmd::do_work(class cl_cmdline
*cmdline
, class cl_console_base
*con
)
881 con
->dd_cprintf("answer", "Command \"%s\" does nothing.\n",
887 cl_cmd::do_work(class cl_app
*app
,
888 class cl_cmdline
*cmdline
, class cl_console_base
*con
)
890 con
->dd_cprintf("answer", "Command \"%s\" does nothing on application.\n",
896 cl_cmd::do_work(class cl_sim
*sim
,
897 class cl_cmdline
*cmdline
, class cl_console_base
*con
)
899 con
->dd_cprintf("answer", "Command \"%s\" does nothing on simulator.\n",
905 cl_cmd::do_work(class cl_uc
*uc
,
906 class cl_cmdline
*cmdline
, class cl_console_base
*con
)
908 con
->dd_cprintf("answer", "Command \"%s\" does nothing on microcontroller.\n",
914 cl_cmd::print_short(class cl_console_base
*con
)
916 int l
= usage_help
.len();
921 if (usage_help
.nempty())
922 con
->dd_printf("%s", usage_help
.c_str());
925 con
->dd_printf("\n");
933 if (short_help
.nempty())
935 con
->dd_printf("%s", short_help
.c_str());
938 con
->dd_printf("%s", names
->at(0));
939 con
->dd_printf("\n");
943 cl_cmd::syntax_error(class cl_console_base
*con
)
947 if (short_help
.nempty())
950 con
->dd_cprintf("error", "Error: wrong syntax\n");
956 *____________________________________________________________________________
959 cl_cmdset::cl_cmdset(void):
960 cl_list(5, 5, "cmdset")
966 /*cl_cmdset::cl_cmdset(class cl_sim *asim):
974 cl_cmdset::get_cmd(class cl_cmdline
*cmdline
, bool accept_last
)
979 for (i
= 0; i
< count
; i
++)
981 class cl_cmd
*c
= (class cl_cmd
*)at(i
);
982 if (c
->name_match(cmdline
, 1))
986 class cl_cmd
*c_matched
= 0;
987 for (i
= 0; i
< count
; i
++)
989 class cl_cmd
*c
= (class cl_cmd
*)at(i
);
990 if (c
->name_match(cmdline
, 0))
1003 cl_cmdset::get_cmd(const char *cmd_name
)
1007 for (i
= 0; i
< count
; i
++)
1009 class cl_cmd
*c
= (class cl_cmd
*)at(i
);
1010 if (c
->name_match(cmd_name
, 1))
1017 cl_cmdset::del(char *nam
)
1023 for (i
= 0; i
< count
; i
++)
1025 class cl_cmd
*cmd
= (class cl_cmd
*)(at(i
));
1026 if (cmd
->name_match(nam
, 1))
1032 cl_cmdset::replace(char *nam
, class cl_cmd
*cmd
)
1038 for (i
= 0; i
< count
; i
++)
1040 class cl_cmd
*c
= (class cl_cmd
*)(at(i
));
1041 if (c
->name_match(nam
, 1))
1051 * Composed command: subset of commands
1052 *____________________________________________________________________________
1055 cl_super_cmd::cl_super_cmd(const char *aname
,
1057 class cl_cmdset
*acommands
):
1058 cl_cmd(operate_on_none
, aname
, can_rep
)
1060 commands
= acommands
;
1063 cl_super_cmd::~cl_super_cmd(void)
1070 cl_super_cmd::work(class cl_app
*app
,
1071 class cl_cmdline
*cmdline
, class cl_console_base
*con
)
1073 class cl_cmd
*cmd
= 0;
1078 if (!cmdline
->shift())
1080 if ((cmd
= commands
->get_cmd("_no_parameters_")) != 0)
1081 return(cmd
->work(app
, cmdline
, con
));
1083 con
->dd_printf("\"%s\" must be followed by the name of a subcommand\n"
1084 "List of subcommands:\n", names
->at(0));
1085 for (i
= 0; i
< commands
->count
; i
++)
1087 cmd
= (class cl_cmd
*)(commands
->at(i
));
1088 //con->dd_printf("%s\n", cmd->short_help.c_str());
1089 cmd
->print_short(con
);
1093 if ((cmd
= commands
->get_cmd(cmdline
, con
->is_interactive())) == NULL
)
1095 con
->dd_printf("Undefined subcommand: \"%s\". Try \"help %s\".\n",
1096 cmdline
->get_name(), names
->at(0));
1099 return(cmd
->work(app
, cmdline
, con
));
1103 /* End of cmd.src/command.cc */