?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file cmdline.c \brief Command-Line Interface Library. */
2 //*****************************************************************************
3 //
4 // File Name : 'cmdline.c'
5 // Title : Command-Line Interface Library
6 // Author : Pascal Stang - Copyright (C) 2003
7 // Created : 2003.07.16
8 // Revised : 2003.07.23
9 // Version : 0.1
10 // Target MCU : Atmel AVR Series
11 // Editor Tabs : 4
12 //
13 // NOTE: This code is currently below version 1.0, and therefore is considered
14 // to be lacking in some functionality or documentation, or may not be fully
15 // tested. Nonetheless, you can expect most functions to work.
16 //
17 // This code is distributed under the GNU Public License
18 // which can be found at http://www.gnu.org/licenses/gpl.txt
19 //
20 //*****************************************************************************
21  
22 //----- Include Files ---------------------------------------------------------
23 #include <avr/io.h> // include I/O definitions (port names, pin names, etc)
24 #include <avr/interrupt.h> // include interrupt support
25 #include <avr/pgmspace.h> // include AVR program memory support
26 #include <string.h> // include standard C string functions
27 #include <stdlib.h> // include stdlib for string conversion functions
28  
29 #include "global.h" // include our global settings
30 #include "cmdline.h"
31  
32 // include project-specific configuration
33 #include "cmdlineconf.h"
34  
35 // defines
36 #define ASCII_BEL 0x07
37 #define ASCII_BS 0x08
38 #define ASCII_CR 0x0D
39 #define ASCII_LF 0x0A
40 #define ASCII_ESC 0x1B
41 #define ASCII_DEL 0x7F
42  
43 #define VT100_ARROWUP 'A'
44 #define VT100_ARROWDOWN 'B'
45 #define VT100_ARROWRIGHT 'C'
46 #define VT100_ARROWLEFT 'D'
47  
48 #define CMDLINE_HISTORY_SAVE 0
49 #define CMDLINE_HISTORY_PREV 1
50 #define CMDLINE_HISTORY_NEXT 2
51  
52  
53 // Global variables
54  
55 // strings
56 u08 PROGMEM CmdlinePrompt[] = "cmd>";
57 u08 PROGMEM CmdlineNotice[] = "cmdline: ";
58 u08 PROGMEM CmdlineCmdNotFound[] = "command not found";
59  
60 // command list
61 // -commands are null-terminated strings
62 static char CmdlineCommandList[CMDLINE_MAX_COMMANDS][CMDLINE_MAX_CMD_LENGTH];
63 // command function pointer list
64 static CmdlineFuncPtrType CmdlineFunctionList[CMDLINE_MAX_COMMANDS];
65 // number of commands currently registered
66 u08 CmdlineNumCommands;
67  
68 u08 CmdlineBuffer[CMDLINE_BUFFERSIZE];
69 u08 CmdlineBufferLength;
70 u08 CmdlineBufferEditPos;
71 u08 CmdlineInputVT100State;
72 u08 CmdlineHistory[CMDLINE_HISTORYSIZE][CMDLINE_BUFFERSIZE];
73 CmdlineFuncPtrType CmdlineExecFunction;
74  
75 // Functions
76  
77 // function pointer to single character output routine
78 static void (*cmdlineOutputFunc)(unsigned char c);
79  
80 void cmdlineInit(void)
81 {
82 // reset vt100 processing state
83 CmdlineInputVT100State = 0;
84 // initialize input buffer
85 CmdlineBufferLength = 0;
86 CmdlineBufferEditPos = 0;
87 // initialize executing function
88 CmdlineExecFunction = 0;
89 // initialize command list
90 CmdlineNumCommands = 0;
91 }
92  
93 void cmdlineAddCommand(u08* newCmdString, CmdlineFuncPtrType newCmdFuncPtr)
94 {
95 // add command string to end of command list
96 strcpy(CmdlineCommandList[CmdlineNumCommands], newCmdString);
97 // add command function ptr to end of function list
98 CmdlineFunctionList[CmdlineNumCommands] = newCmdFuncPtr;
99 // increment number of registered commands
100 CmdlineNumCommands++;
101 }
102  
103 void cmdlineSetOutputFunc(void (*output_func)(unsigned char c))
104 {
105 // set new output function
106 cmdlineOutputFunc = output_func;
107  
108 // should we really do this?
109 // print a prompt
110 //cmdlinePrintPrompt();
111 }
112  
113 void cmdlineInputFunc(unsigned char c)
114 {
115 u08 i;
116 // process the received character
117  
118 // VT100 handling
119 // are we processing a VT100 command?
120 if(CmdlineInputVT100State == 2)
121 {
122 // we have already received ESC and [
123 // now process the vt100 code
124 switch(c)
125 {
126 case VT100_ARROWUP:
127 cmdlineDoHistory(CMDLINE_HISTORY_PREV);
128 break;
129 case VT100_ARROWDOWN:
130 cmdlineDoHistory(CMDLINE_HISTORY_NEXT);
131 break;
132 case VT100_ARROWRIGHT:
133 // if the edit position less than current string length
134 if(CmdlineBufferEditPos < CmdlineBufferLength)
135 {
136 // increment the edit position
137 CmdlineBufferEditPos++;
138 // move cursor forward one space (no erase)
139 cmdlineOutputFunc(ASCII_ESC);
140 cmdlineOutputFunc('[');
141 cmdlineOutputFunc(VT100_ARROWRIGHT);
142 }
143 else
144 {
145 // else, ring the bell
146 cmdlineOutputFunc(ASCII_BEL);
147 }
148 break;
149 case VT100_ARROWLEFT:
150 // if the edit position is non-zero
151 if(CmdlineBufferEditPos)
152 {
153 // decrement the edit position
154 CmdlineBufferEditPos--;
155 // move cursor back one space (no erase)
156 cmdlineOutputFunc(ASCII_BS);
157 }
158 else
159 {
160 // else, ring the bell
161 cmdlineOutputFunc(ASCII_BEL);
162 }
163 break;
164 default:
165 break;
166 }
167 // done, reset state
168 CmdlineInputVT100State = 0;
169 return;
170 }
171 else if(CmdlineInputVT100State == 1)
172 {
173 // we last received [ESC]
174 if(c == '[')
175 {
176 CmdlineInputVT100State = 2;
177 return;
178 }
179 else
180 CmdlineInputVT100State = 0;
181 }
182 else
183 {
184 // anything else, reset state
185 CmdlineInputVT100State = 0;
186 }
187  
188 // Regular handling
189 if( (c >= 0x20) && (c < 0x7F) )
190 {
191 // character is printable
192 // is this a simple append
193 if(CmdlineBufferEditPos == CmdlineBufferLength)
194 {
195 // echo character to the output
196 cmdlineOutputFunc(c);
197 // add it to the command line buffer
198 CmdlineBuffer[CmdlineBufferEditPos++] = c;
199 // update buffer length
200 CmdlineBufferLength++;
201 }
202 else
203 {
204 // edit/cursor position != end of buffer
205 // we're inserting characters at a mid-line edit position
206 // make room at the insert point
207 CmdlineBufferLength++;
208 for(i=CmdlineBufferLength; i>CmdlineBufferEditPos; i--)
209 CmdlineBuffer[i] = CmdlineBuffer[i-1];
210 // insert character
211 CmdlineBuffer[CmdlineBufferEditPos++] = c;
212 // repaint
213 cmdlineRepaint();
214 // reposition cursor
215 for(i=CmdlineBufferEditPos; i<CmdlineBufferLength; i++)
216 cmdlineOutputFunc(ASCII_BS);
217 }
218 }
219 // handle special characters
220 else if(c == ASCII_CR)
221 {
222 // user pressed [ENTER]
223 // echo CR and LF to terminal
224 cmdlineOutputFunc(ASCII_CR);
225 cmdlineOutputFunc(ASCII_LF);
226 // add null termination to command
227 CmdlineBuffer[CmdlineBufferLength++] = 0;
228 CmdlineBufferEditPos++;
229 // command is complete, process it
230 cmdlineProcessInputString();
231 // reset buffer
232 CmdlineBufferLength = 0;
233 CmdlineBufferEditPos = 0;
234 }
235 else if(c == ASCII_BS)
236 {
237 if(CmdlineBufferEditPos)
238 {
239 // is this a simple delete (off the end of the line)
240 if(CmdlineBufferEditPos == CmdlineBufferLength)
241 {
242 // destructive backspace
243 // echo backspace-space-backspace
244 cmdlineOutputFunc(ASCII_BS);
245 cmdlineOutputFunc(' ');
246 cmdlineOutputFunc(ASCII_BS);
247 // decrement our buffer length and edit position
248 CmdlineBufferLength--;
249 CmdlineBufferEditPos--;
250 }
251 else
252 {
253 // edit/cursor position != end of buffer
254 // we're deleting characters at a mid-line edit position
255 // shift characters down, effectively deleting
256 CmdlineBufferLength--;
257 CmdlineBufferEditPos--;
258 for(i=CmdlineBufferEditPos; i<CmdlineBufferLength; i++)
259 CmdlineBuffer[i] = CmdlineBuffer[i+1];
260 // repaint
261 cmdlineRepaint();
262 // add space to clear leftover characters
263 cmdlineOutputFunc(' ');
264 // reposition cursor
265 for(i=CmdlineBufferEditPos; i<(CmdlineBufferLength+1); i++)
266 cmdlineOutputFunc(ASCII_BS);
267 }
268 }
269 else
270 {
271 // else, ring the bell
272 cmdlineOutputFunc(ASCII_BEL);
273 }
274 }
275 else if(c == ASCII_DEL)
276 {
277 // not yet handled
278 }
279 else if(c == ASCII_ESC)
280 {
281 CmdlineInputVT100State = 1;
282 }
283 }
284  
285 void cmdlineRepaint(void)
286 {
287 u08* ptr;
288 u08 i;
289  
290 // carriage return
291 cmdlineOutputFunc(ASCII_CR);
292 // print fresh prompt
293 cmdlinePrintPrompt();
294 // print the new command line buffer
295 i = CmdlineBufferLength;
296 ptr = CmdlineBuffer;
297 while(i--) cmdlineOutputFunc(*ptr++);
298 }
299  
300 void cmdlineDoHistory(u08 action)
301 {
302 switch(action)
303 {
304 case CMDLINE_HISTORY_SAVE:
305 // copy CmdlineBuffer to history if not null string
306 if( strlen(CmdlineBuffer) )
307 strcpy(CmdlineHistory[0], CmdlineBuffer);
308 break;
309 case CMDLINE_HISTORY_PREV:
310 // copy history to current buffer
311 strcpy(CmdlineBuffer, CmdlineHistory[0]);
312 // set the buffer position to the end of the line
313 CmdlineBufferLength = strlen(CmdlineBuffer);
314 CmdlineBufferEditPos = CmdlineBufferLength;
315 // "re-paint" line
316 cmdlineRepaint();
317 break;
318 case CMDLINE_HISTORY_NEXT:
319 break;
320 }
321 }
322  
323 void cmdlineProcessInputString(void)
324 {
325 u08 cmdIndex;
326 u08 i=0;
327  
328 // save command in history
329 cmdlineDoHistory(CMDLINE_HISTORY_SAVE);
330  
331 // find the end of the command (excluding arguments)
332 // find first whitespace character in CmdlineBuffer
333 while( !((CmdlineBuffer[i] == ' ') || (CmdlineBuffer[i] == 0)) ) i++;
334  
335 if(!i)
336 {
337 // command was null or empty
338 // output a new prompt
339 cmdlinePrintPrompt();
340 // we're done
341 return;
342 }
343  
344 // search command list for match with entered command
345 for(cmdIndex=0; cmdIndex<CmdlineNumCommands; cmdIndex++)
346 {
347 if( !strncmp(CmdlineCommandList[cmdIndex], CmdlineBuffer, i) )
348 {
349 // user-entered command matched a command in the list (database)
350 // run the corresponding function
351 CmdlineExecFunction = CmdlineFunctionList[cmdIndex];
352 // new prompt will be output after user function runs
353 // and we're done
354 return;
355 }
356 }
357  
358 // if we did not get a match
359 // output an error message
360 cmdlinePrintError();
361 // output a new prompt
362 cmdlinePrintPrompt();
363 }
364  
365 void cmdlineMainLoop(void)
366 {
367 // do we have a command/function to be executed
368 if(CmdlineExecFunction)
369 {
370 // run it
371 CmdlineExecFunction();
372 // reset
373 CmdlineExecFunction = 0;
374 // output new prompt
375 cmdlinePrintPrompt();
376 }
377 }
378  
379 void cmdlinePrintPrompt(void)
380 {
381 // print a new command prompt
382 u08* ptr = CmdlinePrompt;
383 while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
384 }
385  
386 void cmdlinePrintError(void)
387 {
388 u08 * ptr;
389  
390 // print a notice header
391 // (u08*) cast used to avoid compiler warning
392 ptr = (u08*)CmdlineNotice;
393 while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
394  
395 // print the offending command
396 ptr = CmdlineBuffer;
397 while((*ptr) && (*ptr != ' ')) cmdlineOutputFunc(*ptr++);
398  
399 cmdlineOutputFunc(':');
400 cmdlineOutputFunc(' ');
401  
402 // print the not-found message
403 // (u08*) cast used to avoid compiler warning
404 ptr = (u08*)CmdlineCmdNotFound;
405 while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
406  
407 cmdlineOutputFunc('\r');
408 cmdlineOutputFunc('\n');
409 }
410  
411 // argument retrieval commands
412  
413 // return string pointer to argument [argnum]
414 u08* cmdlineGetArgStr(u08 argnum)
415 {
416 // find the offset of argument number [argnum]
417 u08 idx=0;
418 u08 arg;
419  
420 // find the first non-whitespace character
421 while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] == ' ')) idx++;
422  
423 // we are at the first argument
424 for(arg=0; arg<argnum; arg++)
425 {
426 // find the next whitespace character
427 while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] != ' ')) idx++;
428 // find the first non-whitespace character
429 while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] == ' ')) idx++;
430 }
431 // we are at the requested argument or the end of the buffer
432 return &CmdlineBuffer[idx];
433 }
434  
435 // return argument [argnum] interpreted as a decimal integer
436 long cmdlineGetArgInt(u08 argnum)
437 {
438 char* endptr;
439 return strtol(cmdlineGetArgStr(argnum), &endptr, 10);
440 }
441  
442 // return argument [argnum] interpreted as a hex integer
443 long cmdlineGetArgHex(u08 argnum)
444 {
445 char* endptr;
446 return strtol(cmdlineGetArgStr(argnum), &endptr, 16);
447 }
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3