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 by Pavel Pisa pisa@cmp.felk.cvut.cz
11 (C) 2002 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 *******************************************************************/
26 #include "cmd_proc_priv.h"
28 /* cmd_line processing */
30 char *skip_white(char *p)
32 while(isspace((uint8_t)*p)) p++;
38 * @return Zero if no command was given in line, -CMDERR_BADCMD if
39 * command is not known or has no function assigned to it. If a
40 * command is executed, then the return value of the command function
43 int proc_cmd_line(cmd_io_t *cmd_io, cmd_des_t const **des_arr, char *line)
45 char *p=line, *r, *var;
47 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
52 param[0]=p=skip_white(p);
54 /* Determine the name of the command */
55 if(!isalnum((uint8_t)*p)){
59 while(isalnum((uint8_t)*p)) p++;
62 param[1]=param[2]=skip_white(p);
64 /* Find the command in des_arr */
68 if(!arr_stack_sp) break;
69 des_arr=arr_stack[--arr_stack_sp];
72 if(des==CMD_DES_CONTINUE_AT_ID){
73 /* list continues at new address */
74 des_arr=(const cmd_des_t **)*des_arr;continue;
76 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
77 /* list includes commands from sublists */
78 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
81 arr_stack[arr_stack_sp++]=des_arr+1;
82 des_arr=(const cmd_des_t **)*des_arr;
87 if(!(r=des->name))continue;
91 while((*p==*r)&&i){i--;r++;p++;};
92 if((i==0)&&!*r) break; /* We've found the command */
98 if((*r=='#')&&i&&isdigit((uint8_t)*p)){
111 if(i!=0) continue; /* Try next command */
112 if(des->mode&CDESM_OPCHR){
113 if(!param[2])continue;
114 if(!*param[2])continue;
115 param[3]=skip_white(param[2]+1);
120 if(var){param[1]=var;parcnt++;}
122 if(*param[parcnt]) parcnt++;
125 if(!des->fnc) return -CMDERR_BADCMD;
126 res=des->fnc(cmd_io,des,param);
129 return -CMDERR_BADCMD;
133 * Checks whether the the command allows the operation specified by
136 * @return opchar if perimssions allow this operations, -CMDERR_WRPERM
137 * or -CMDERR_RDPERM if the operation is not allows, -CMDERR_OPCHAR,
138 * if the opchar is not ':' or '?'.
140 int cmd_opchar_check(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
142 int opchar=*param[2];
144 if(!(des->mode&CDESM_WR)){
145 return -CMDERR_WRPERM;
147 }else if(opchar=='?'){
148 if(!(des->mode&CDESM_RD)){
149 return -CMDERR_RDPERM;
152 else return -CMDERR_OPCHAR;
156 int cmd_do_stamp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
158 if(*param[2]!=':') return -CMDERR_OPCHAR;
159 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
160 cmd_io_putc(cmd_io,'=');
161 cmd_io_write(cmd_io,param[3],strlen(param[3]));
166 * Converts integer to string.
167 * @param s Buffer to store the result.
168 * @param val Value to convert.
169 * @param len Minimal width of the converted strign (padded by ' ').
170 * @param form Unused.
173 int i2str(char *s,long val,int len,int form)
182 if((sig=val<0))num=-val;
189 if(mag>~(unsigned long)0/base) break;
199 while(padd){*(s++)=' ';padd--;}
212 * Implementation of a command that reads or writes short pointed by des->info[0].
214 int cmd_do_rw_short(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
220 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
221 ptr=(short*)(des->info[0]);
226 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
232 * Implementation of a command that reads or writes int pointed by des->info[0].
234 int cmd_do_rw_int(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
240 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
241 ptr=(int*)(des->info[0]);
246 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
253 * Implementation of a command that reads or writes long pointed by des->info[0].
255 int cmd_do_rw_long(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
261 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
262 ptr=(long*)(des->info[0]);
267 return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0);
273 * Prints name of the command followed by '=' and the value of val.
275 int cmd_opchar_replong(cmd_io_t *cmd_io, char *param[], long val,int len,int form)
278 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
279 cmd_io_putc(cmd_io,'=');
280 i2str(str,val,len,form);
281 cmd_io_write(cmd_io,str,strlen(str));
287 int cmd_do_rw_bitflag(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
289 unsigned val,mask,*pval;
292 if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar;
293 pval=(unsigned*)(des->info[0]);
294 mask=(unsigned)(des->info[1]);
298 atomic_clear_mask(mask,pval);
300 atomic_set_mask(mask,pval);
301 else return -CMDERR_BADPAR;
303 cmd_io_write(cmd_io,param[0],param[2]-param[0]);
304 cmd_io_putc(cmd_io,'=');
305 cmd_io_putc(cmd_io,*pval&mask?'1':'0');
314 * Implementation of help command
316 int cmd_do_help(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
320 const cmd_des_t **des_arr=*(const cmd_des_t ***)des->info[0];
321 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
324 if (cmd_io->priv.ed_line.io_stack)
325 cmd_io = cmd_io->priv.ed_line.io_stack;
328 filt=skip_white(filt);
329 if(!*filt) filt=NULL;
331 cmd_io_puts(cmd_io,"Help for commands\n");
335 if(!arr_stack_sp) break;
336 des_arr=arr_stack[--arr_stack_sp];
339 if(des==CMD_DES_CONTINUE_AT_ID){
340 /* list continues at new address */
341 des_arr=(const cmd_des_t **)*des_arr;
344 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
345 /* list includes commands from sublists */
346 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
349 arr_stack[arr_stack_sp++]=des_arr+1;
350 des_arr=(const cmd_des_t **)*des_arr;
355 if(!filt || !strncmp(des->name,filt,strlen(filt))) {
358 cmd_io_puts(cmd_io,des->name);
359 cmd_io_puts(cmd_io," - ");
360 cmd_io_puts(cmd_io,help);
361 cmd_io_puts(cmd_io, "\r\n");
369 * Executes command processor. This function is usually called from
370 * application's main loop.
372 int cmd_processor_run(cmd_io_t *cmd_io, cmd_des_t const **commands)
376 if(cmd_io_line_out(cmd_io))
377 return 1; /* Not all the output has been sent. */
379 if(cmd_io_line_in(cmd_io)<=0)
380 return 0; /* Input line not finished or error. */
383 val=proc_cmd_line(cmd_io, commands, cmd_io->priv.ed_line.in->buf);
388 if(cmd_io->priv.ed_line.out->inbuf){
389 cmd_io_putc(cmd_io,'\r');
390 cmd_io_putc(cmd_io,'\n');
393 cmd_io_puts(cmd_io,"ERROR ");
395 cmd_io_puts(cmd_io,s);
396 cmd_io_putc(cmd_io,'\r');
397 cmd_io_putc(cmd_io,'\n');
399 return 1; /* Command line processed */
403 /* Local Variables: */
404 /* c-basic-offset: 2 */