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++;
39 * @return Zero if no command was given in line, -CMDERR_BADCMD if
40 * command is not known or has no function assigned to it. If a
41 * command is executed, then the return value of the command function
44 int proc_cmd_line(cmd_io_t *cmd_io, cmd_des_t const **des_arr, char *line)
46 char *p=line, *r, *var;
48 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
53 param[0]=p=skip_white(p);
55 /* Determine the name of the command */
56 if(!isalnum((uint8_t)*p)){
60 while(isalnum((uint8_t)*p)) p++;
63 param[1]=param[2]=skip_white(p);
65 /* Find the command in des_arr */
69 if(!arr_stack_sp) break;
70 des_arr=arr_stack[--arr_stack_sp];
73 if(des==CMD_DES_CONTINUE_AT_ID){
74 /* list continues at new address */
75 des_arr=(const cmd_des_t **)*des_arr;continue;
77 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
78 /* list includes commands from sublists */
79 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
82 arr_stack[arr_stack_sp++]=des_arr+1;
83 des_arr=(const cmd_des_t **)*des_arr;
88 if(!(r=des->name))continue;
92 while((*p==*r)&&i){i--;r++;p++;};
93 if((i==0)&&!*r) break; /* We've found the command */
99 if((*r=='#')&&i&&isdigit((uint8_t)*p)){
112 if(i!=0) continue; /* Try next command */
113 if(des->mode&CDESM_OPCHR){
114 if(!param[2])continue;
115 if(!*param[2])continue;
116 param[3]=skip_white(param[2]+1);
121 if(var){param[1]=var;parcnt++;}
123 if(*param[parcnt]) parcnt++;
126 if(!des->fnc) return -CMDERR_BADCMD;
127 res=des->fnc(cmd_io,des,param);
130 return -CMDERR_BADCMD;
134 * Checks whether the the command allows the operation specified by
137 * @return opchar if perimssions allow this operations, -CMDERR_WRPERM
138 * or -CMDERR_RDPERM if the operation is not allows, -CMDERR_OPCHAR,
139 * if the opchar is not ':' or '?'.
141 int cmd_opchar_check(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
143 int opchar=*param[2];
145 if(!(des->mode&CDESM_WR)){
146 return -CMDERR_WRPERM;
148 }else if(opchar=='?'){
149 if(!(des->mode&CDESM_RD)){
150 return -CMDERR_RDPERM;
153 else return -CMDERR_OPCHAR;
157 int cmd_num_suffix(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[], unsigned *pval)
163 if(!p) return -CMDERR_BADSUF;
168 return -CMDERR_BADSUF;
172 }while(*p && !strchr(" :?=",*p));
178 int cmd_do_stamp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
180 if(*param[2]!=':') return -CMDERR_OPCHAR;
181 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
182 cmd_io_putc(cmd_io,'=');
183 cmd_io_write(cmd_io,param[3],strlen(param[3]));
188 * Implementation of a command that reads or writes short pointed by des->info[0].
190 int cmd_do_rw_short(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
196 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
197 ptr=(short*)(des->info[0]);
202 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
208 * Implementation of a command that reads or writes int pointed by des->info[0].
210 int cmd_do_rw_int(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
216 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
217 ptr=(int*)(des->info[0]);
222 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
229 * Implementation of a command that reads or writes long pointed by des->info[0].
231 int cmd_do_rw_long(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
237 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
238 ptr=(long*)(des->info[0]);
243 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
249 * Prints name of the command followed by '=' and the value of val.
251 int cmd_opchar_replong(cmd_io_t *cmd_io, char *param[], long val,int len,int form)
254 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
255 cmd_io_putc(cmd_io,'=');
256 i2str(str,val,len,form);
257 cmd_io_write(cmd_io,str,strlen(str));
263 int cmd_do_rw_bitflag(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
265 unsigned val,mask,*pval;
268 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
269 pval=(unsigned*)(des->info[0]);
270 mask=(unsigned)(des->info[1]);
274 atomic_clear_mask(mask,pval);
276 atomic_set_mask(mask,pval);
277 else return -CMDERR_BADPAR;
279 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
280 cmd_io_putc(cmd_io,'=');
281 cmd_io_putc(cmd_io,*pval&mask?'1':'0');
290 * Implementation of help command
292 int cmd_do_help(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
296 const cmd_des_t **des_arr=*(const cmd_des_t ***)des->info[0];
297 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
300 /* FIXME: This should not be there unconditional */
301 if (cmd_io->priv.ed_line.io_stack)
302 cmd_io = cmd_io->priv.ed_line.io_stack;
305 filt=skip_white(filt);
306 if(!*filt) filt=NULL;
308 cmd_io_puts(cmd_io,"Help for commands\n");
312 if(!arr_stack_sp) break;
313 des_arr=arr_stack[--arr_stack_sp];
316 if(des==CMD_DES_CONTINUE_AT_ID){
317 /* list continues at new address */
318 des_arr=(const cmd_des_t **)*des_arr;
321 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
322 /* list includes commands from sublists */
323 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
326 arr_stack[arr_stack_sp++]=des_arr+1;
327 des_arr=(const cmd_des_t **)*des_arr;
332 if(!filt || !strncmp(des->name,filt,strlen(filt))) {
335 cmd_io_puts(cmd_io,des->name);
336 cmd_io_puts(cmd_io," - ");
337 cmd_io_puts(cmd_io,help);
338 cmd_io_puts(cmd_io, "\r\n");
345 /* Local Variables: */
346 /* c-basic-offset: 2 */