1 /*******************************************************************
2 Components for embedded applications builded for
3 laboratory and medical instruments firmware
5 cmd_proc.c - text command processor
6 enables to define multilevel tables of commands
7 which can be received from more inputs and send reply
8 to respective I/O stream output
10 Copyright (C) 2001-2009 by Pavel Pisa pisa@cmp.felk.cvut.cz
11 (C) 2002-2009 by PiKRON Ltd. http://www.pikron.com
12 (C) 2007 by Michal Sojka <sojkam1@fel.cvut.cz>
14 This file can be used and copied according to next
16 - MPL - Mozilla Public License
17 - GPL - GNU Public License
18 - other license provided by project originators
19 *******************************************************************/
27 #include "cmd_proc_priv.h"
29 /* cmd_line processing */
31 char *skip_white(char *p)
33 while(isspace((uint8_t)*p)) p++;
38 * Process a command line
40 * @param cmd_io I/O stack
41 * @param des_arr Pointer to the command descriptors.
42 * @param line Command line to process.
44 * @return Zero if no command was given in line, -CMDERR_BADCMD if
45 * command is not known or has no function assigned to it. If a
46 * command is executed, then the return value of the command function
49 int proc_cmd_line(cmd_io_t *cmd_io, cmd_des_t const **des_arr, char *line)
51 char *p=line, *r, *var;
53 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
58 param[0]=p=skip_white(p);
60 /* Determine the name of the command */
61 if(!isalnum((uint8_t)*p)){
65 while(isalnum((uint8_t)*p)) p++;
68 param[1]=param[2]=skip_white(p);
70 /* Find the command in des_arr */
74 if(!arr_stack_sp) break;
75 des_arr=arr_stack[--arr_stack_sp];
78 if(des==CMD_DES_CONTINUE_AT_ID){
79 /* list continues at new address */
80 des_arr=(const cmd_des_t **)*des_arr;continue;
82 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
83 /* list includes commands from sublists */
84 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
87 arr_stack[arr_stack_sp++]=des_arr+1;
88 des_arr=(const cmd_des_t **)*des_arr;
93 if(!(r=des->name))continue;
97 while((*p==*r)&&i){i--;r++;p++;};
98 if((i==0)&&!*r) break; /* We've found the command (full match) */
99 if((*r=='?')&&i){ /* '?' stands for an arbitrary character */
104 if((*r=='#')&&i&&isdigit((uint8_t)*p)){ /* '#' stands for a digit */
109 if(*r=='*'){ /* '*' stands for any number of any characters */
114 i=1; /* Signal no match */
117 if(i!=0) continue; /* Try next command */
118 /* Setup parameters */
119 if(des->mode&CDESM_OPCHR){
120 if(!param[2])continue;
121 if(!*param[2])continue;
122 param[3]=skip_white(param[2]+1);
127 if(var){param[1]=var;parcnt++;}
129 if(*param[parcnt]) parcnt++;
132 if(!des->fnc) return -CMDERR_BADCMD;
133 res=des->fnc(cmd_io,des,param);
136 return -CMDERR_BADCMD;
140 * Checks whether the the command allows the operation specified by
143 * @return opchar if perimssions allow this operations, -CMDERR_WRPERM
144 * or -CMDERR_RDPERM if the operation is not allows, -CMDERR_OPCHAR,
145 * if the opchar is not ':' or '?'.
147 int cmd_opchar_check(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
149 int opchar=*param[2];
151 if(!(des->mode&CDESM_WR)){
152 return -CMDERR_WRPERM;
154 }else if(opchar=='?'){
155 if(!(des->mode&CDESM_RD)){
156 return -CMDERR_RDPERM;
159 else return -CMDERR_OPCHAR;
163 int cmd_num_suffix(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[], unsigned *pval)
169 if(!p) return -CMDERR_BADSUF;
174 return -CMDERR_BADSUF;
178 }while(*p && !strchr(" :?=",*p));
184 int cmd_do_stamp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
186 if(*param[2]!=':') return -CMDERR_OPCHAR;
187 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
188 cmd_io_putc(cmd_io,'=');
189 cmd_io_write(cmd_io,param[3],strlen(param[3]));
194 * Implementation of a command that reads or writes short pointed by des->info[0].
196 int cmd_do_rw_short(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
202 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
203 ptr=(short*)(des->info[0]);
208 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
214 * Implementation of a command that reads or writes int pointed by des->info[0].
216 int cmd_do_rw_int(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
222 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
223 ptr=(int*)(des->info[0]);
228 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
235 * Implementation of a command that reads or writes long pointed by des->info[0].
237 int cmd_do_rw_long(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
243 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
244 ptr=(long*)(des->info[0]);
249 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
255 * Prints name of the command followed by '=' and the value of val.
257 int cmd_opchar_replong(cmd_io_t *cmd_io, char *param[], long val,int len,int form)
260 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
261 cmd_io_putc(cmd_io,'=');
262 i2str(str,val,len,form);
263 cmd_io_write(cmd_io,str,strlen(str));
269 int cmd_do_rw_bitflag(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
271 unsigned val,mask,*pval;
274 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
275 pval=(unsigned*)(des->info[0]);
276 mask=(unsigned)(des->info[1]);
280 atomic_clear_mask(mask,pval);
282 atomic_set_mask(mask,pval);
283 else return -CMDERR_BADPAR;
285 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
286 cmd_io_putc(cmd_io,'=');
287 cmd_io_putc(cmd_io,*pval&mask?'1':'0');
296 * Implementation of help command
298 int cmd_do_help(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
302 const cmd_des_t **des_arr=*(const cmd_des_t ***)des->info[0];
303 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
306 /* FIXME: This should not be there unconditional */
307 if (cmd_io->priv.ed_line.io_stack)
308 cmd_io = cmd_io->priv.ed_line.io_stack;
311 filt=skip_white(filt);
312 if(!*filt) filt=NULL;
314 cmd_io_puts(cmd_io,"Help for commands\n");
318 if(!arr_stack_sp) break;
319 des_arr=arr_stack[--arr_stack_sp];
322 if(des==CMD_DES_CONTINUE_AT_ID){
323 /* list continues at new address */
324 des_arr=(const cmd_des_t **)*des_arr;
327 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
328 /* list includes commands from sublists */
329 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
332 arr_stack[arr_stack_sp++]=des_arr+1;
333 des_arr=(const cmd_des_t **)*des_arr;
338 if(!filt || !strncmp(des->name,filt,strlen(filt))) {
341 cmd_io_puts(cmd_io,des->name);
342 cmd_io_puts(cmd_io," - ");
343 cmd_io_puts(cmd_io,help);
344 cmd_io_puts(cmd_io, "\r\n");
351 /* Local Variables: */
352 /* c-basic-offset: 2 */