-
Notifications
You must be signed in to change notification settings - Fork 0
/
terminal.c
351 lines (341 loc) · 9.4 KB
/
terminal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#include <msp430.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <ctl.h>
#include "terminal.h"
#define CMD_LEN 64
#ifdef HISTORY
#ifndef CTL_PROC
#error HISTORY must be used with CTL_PROC
#endif
#define HISTORY_SIZE 10
#endif
//used to break up a string into arguments for parsing
//*argv[] is a vector for the arguments and contains pointers to each argument
//*dst is a buffer that needs to be big enough to hold all the arguments
//returns the argument count
unsigned short make_args(char *argv[],const char *src,char *dst){
unsigned short argc=0;
argv[0]=dst;
for(;;){
while(isspace(*src))src++;
//copy non space characters to dst
while(!isspace(*src) && *src)
*dst++=*src++;
//terminate string bit
*dst++=0;
//at the end of src?
if(*src==0)break;
argc++;
argv[argc]=dst;
}
//don't count null strings
if(*argv[argc]==0)argc--;
return argc;
}
//print a list of all commands
int helpCmd(char **argv,unsigned short argc){
int i,rt=0;
if(argc!=0){
//arguments given, print help for given command
//loop through all commands
for(i=0;cmd_tbl[i].name!=NULL;i++){
//look for a match
if(!strcmp(cmd_tbl[i].name,argv[1])){
//match found, print help and exit
printf("%s %s\r\n",cmd_tbl[i].name,cmd_tbl[i].helpStr);
return 0;
}
}
//no match found print error
printf("Error : command \'%s\' not found\r\n",argv[1]);
//fall through and print a list of commands and return -1 for error
rt=-1;
}
//print a list of commands
printf("Possible Commands:\r\n");
for(i=0;cmd_tbl[i].name!=NULL;i++){
printf("\t%s\r\n",cmd_tbl[i].name);
}
return rt;
}
//execute a command
int doCmd(const char *cs){
//buffers for args and arg vector
//NOTE: this limits the maximum # of arguments
// and total length of all arguments
char args[50];
char *argv[10];
unsigned short argc;
int i;
//split string into arguments
argc=make_args(argv,cs,args);
//search for command
for(i=0;cmd_tbl[i].name!=NULL;i++){
//look for a match
if(!strcmp(cmd_tbl[i].name,argv[0])){
//match found, run command and return
return cmd_tbl[i].cmd(argv,argc);
}
}
//unknown command, print help message
printf("unknown command \'%s\'\r\n",argv[0]);
helpCmd(NULL,0);
//unknown command, return error
return 1;
}
//prototype for __putchar to make the compiler happy
int __putchar(int __c);
#ifdef HISTORY
short hist_incr(short h){
h++;
if(h>=HISTORY_SIZE){
h=0;
}
return h;
}
short hist_decr(short h){
h--;
if(h<0){
h=HISTORY_SIZE-1;
}
return h;
}
#endif
//task to communicate with the user over USB
void terminal(void *p) __toplevel{
char *msg=p;
//character from port
int c=0;
//buffer for command
char cmd[CMD_LEN];
#ifdef HISTORY
//buffer for command history
static char history[HISTORY_SIZE][CMD_LEN];
short hist_idx=0,hist_lookback=0;
#endif
#ifdef CTL_PROC
//for parsing escape codes
short esc_idx=-2,num;
CTL_TIME_t esctime;
char escbuffer[10],cmd_id;
#endif
int i;
//command string index
unsigned int cIdx=0;
//initialize command and history buffers
cmd[0]=0;
#ifdef HISTORY
memset(history,0,sizeof(history));
/*for(i=0;i<HISTORY_SIZE;i++){
history[i][0]=0;
}*/
#endif
if(msg!=NULL){
//print message
printf("\r%s\r\n>",msg);
}
for(;;){
//get character
c=getchar();
//check for EOF
if(c==EOF){
//EOF returned, input is not ready. wait a bit
ctl_timeout_wait(ctl_get_current_time()+1024);
continue;
}
#ifdef CTL_PROC
if(esc_idx>-2 && (ctl_get_current_time()-esctime)>10){
//printf("Timeout\r\n");
esc_idx=-2;
}
if(esc_idx==-2){
#endif
//process received character
switch(c){
case '\r':
case '\n':
//return key run command
if(cIdx==0){
/*//if nothing entered, do last command
printf(history[hist_idx]); //print command
strcpy(cmd,history[hist_idx]); //copy into command buffer*/
//if nothing entered, ring bell
putchar(0x07);
break;
}else{
//run command from buffer
cmd[cIdx]=0; //terminate command string
cIdx=0; //reset the command index
#ifdef HISTORY
//save command in history
hist_idx=hist_incr(hist_idx);
strcpy(history[hist_idx],cmd);
hist_lookback=hist_idx;
#endif
}
//send carriage return and new line
printf("\r\n");
//run command
doCmd(cmd);
//print prompt char
putchar('>');
continue;
case '\x7f':
case '\b':
//backspace
if(cIdx==0)continue;
//backup and write over char
printf("\b \b");
//decrement command index
cIdx--;
continue;
case '\t':
//ignore tab character
continue;
#ifdef CTL_PROC
case 0x1B://escape char
//start processing escape sequence
esc_idx=-1;
esctime=ctl_get_current_time();
continue;
#endif
}
#ifdef CTL_PROC
//check for control char
if(!iscntrl(c) && cIdx<(sizeof(cmd)/sizeof(cmd[0]) - 1)){
//echo character
putchar(c);
//put character in command buffer
cmd[cIdx++]=c;
}
}else if(esc_idx==-1){
//check for escape sequence
if(c=='['){
//start of sequence found keep going
esc_idx++;
}else{
//start of sequence not found
//TODO: possibly reprocess chars in the sequence
esc_idx=-2;
}
}else{
if(esc_idx<sizeof(escbuffer)){
escbuffer[esc_idx]=c;
}
if(c>='@' && c<='~'){
//end of control sequence, do stuff
cmd_id=escbuffer[esc_idx];
switch(cmd_id){
case 'A':
//CCU - Cursor Up
//printf("Up\r\n");
//set default number of lines
num=1;
//check if argument is present
if(esc_idx>0){
//get argument
num=escbuffer[0];
}
#ifdef HISTORY
//check for end of history
if(hist_decr(hist_lookback)==hist_idx || history[hist_lookback][0]=='\0'){
putchar(0x07);
break;
}
//replace command
printf("\r\x1B[0K>%s",history[hist_lookback]);
strcpy(cmd,history[hist_lookback]);
cIdx=strlen(cmd);
hist_lookback=hist_decr(hist_lookback);
#endif
break;
case 'B':
//CUD - Cursor Down
//printf("Down\r\n");
//set default number of lines
num=1;
//check if argument is present
if(esc_idx>0){
//get argument
num=escbuffer[0];
}
#ifdef HISTORY
//check for end of history
if(hist_lookback==hist_idx){
putchar(0x07);
printf("\r\x1B[0K>");
cIdx=0;
break;
}
hist_lookback=hist_incr(hist_lookback);
printf("\r\x1B[0K>%s",history[hist_lookback]);
strcpy(cmd,history[hist_lookback]);
cIdx=strlen(cmd);
#endif
break;
case 'C':
//CUF - Cursor Forward
//printf("Forward\r\n");
//set default number of lines
num=1;
//check if argument is present
if(esc_idx>0){
//get argument
num=escbuffer[0];
}
//printf("num = %i\r\n",num);
break;
case 'D':
//CUB - Cursor Back
//printf("Back\r\n");
//set default number of lines
num=1;
//check if argument is present
if(esc_idx>0){
//get argument
num=escbuffer[0];
}
//printf("num = %i\r\n",num);
break;
case '~':
escbuffer[esc_idx]=0;
num=atoi(escbuffer);
//printf("Code = %i\r\n",num);
switch(num){
case 1:
//home key
break;
case 2:
//insert key
break;
case 4:
//end Key
break;
case 5:
//page up key
break;
case 6:
//page down key
/*for(i=0;i<HISTORY_SIZE;i++){
printf("\r%c%i : %s\r\n",i==hist_idx?'>':' ',i,history[i]);
}*/
break;
}
break;
//default:
/*printf("\r\nUnknown command \'%c\' recieved with length %i:\r\n\\e[",cmd_id,esc_idx);
for(i=0;i<=esc_idx;i++){
printf("0x%02X, ",escbuffer[i]);
}
printf("\r\n");*/
}
esc_idx=-3;
}
esc_idx++;
}
#endif
}
}