Bug Summary

File:/home/joel/rtems-4.11-work/build/rtems/c/src/../../cpukit/libmisc/monitor/mon-editor.c
Location:line 575, column 9
Description:Value stored to 'rp' is never read

Annotated Source Code

1/**
2 * @file
3 *
4 * @brief Command line editor for RTEMS monitor.
5 */
6
7/*
8 * $Id: mon-editor.c,v 1.5 2010/06/21 16:25:09 joel Exp $
9 *
10 * 2001-01-30 KJO (vac4050@cae597.rsc.raytheon.com):
11 * Fixed rtems_monitor_command_lookup() to accept partial
12 * commands to uniqeness. Added support for setting
13 * the monitor prompt via an environment variable:
14 * RTEMS_MONITOR_PROMPT
15 *
16 * CCJ: 26-3-2000, adding command history and command line
17 * editing. This code is donated from My Right Boot and not
18 * covered by GPL, only the RTEMS license.
19 */
20
21#ifdef HAVE_CONFIG_H1
22#include "config.h"
23#endif
24
25#include <rtems.h>
26
27#include <rtems/monitor.h>
28
29#include <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32#include <inttypes.h>
33#include <termios.h>
34#include <unistd.h>
35
36#ifndef MONITOR_PROMPT"rtems"
37#define MONITOR_PROMPT"rtems" "rtems" /* will have '> ' appended */
38#endif
39
40/*
41 * Some key labels to define special keys.
42 */
43
44#define KEYS_EXTENDED(0x8000) (0x8000)
45#define KEYS_NORMAL_MASK(0x00ff) (0x00ff)
46#define KEYS_INS(0) (0)
47#define KEYS_DEL(1) (1)
48#define KEYS_UARROW(2) (2)
49#define KEYS_DARROW(3) (3)
50#define KEYS_LARROW(4) (4)
51#define KEYS_RARROW(5) (5)
52#define KEYS_HOME(6) (6)
53#define KEYS_END(7) (7)
54#define KEYS_F1(8) (8)
55#define KEYS_F2(9) (9)
56#define KEYS_F3(10) (10)
57#define KEYS_F4(11) (11)
58#define KEYS_F5(12) (12)
59#define KEYS_F6(13) (13)
60#define KEYS_F7(14) (14)
61#define KEYS_F8(15) (15)
62#define KEYS_F9(16) (16)
63#define KEYS_F10(17) (17)
64
65#define RTEMS_COMMAND_BUFFER_SIZE(75) (75)
66
67static char monitor_prompt[32];
68static char buffer[RTEMS_COMMAND_BUFFER_SIZE(75)];
69static int pos;
70static int logged_in;
71
72/*
73 * History data.
74 */
75
76#define RTEMS_COMMAND_HISTORIES(20) (20)
77
78static char history_buffer[RTEMS_COMMAND_HISTORIES(20)][RTEMS_COMMAND_BUFFER_SIZE(75)];
79static int history_pos[RTEMS_COMMAND_HISTORIES(20)];
80static int history;
81static int history_next;
82
83/*
84 * Translation tables. Not sure if this is the best way to
85 * handle this, how-ever I wish to avoid the overhead of
86 * including a more complete and standard environment such
87 * as ncurses.
88 */
89
90struct translation_table
91{
92 char expecting;
93 const struct translation_table *branch;
94 unsigned int key;
95};
96
97static const struct translation_table trans_two[] =
98{
99 { '~', 0, KEYS_INS(0) },
100 { 0, 0, 0 }
101};
102
103static const struct translation_table trans_three[] =
104{
105 { '~', 0, KEYS_DEL(1) },
106 { 0, 0, 0 }
107};
108
109static const struct translation_table trans_tab_csi[] =
110{
111 { '2', trans_two, 0 },
112 { '3', trans_three, 0 },
113 { 'A', 0, KEYS_UARROW(2) },
114 { 'B', 0, KEYS_DARROW(3) },
115 { 'D', 0, KEYS_LARROW(4) },
116 { 'C', 0, KEYS_RARROW(5) },
117 { 'F', 0, KEYS_END(7) },
118 { 'H', 0, KEYS_HOME(6) },
119 { 0, 0, 0 }
120};
121
122static const struct translation_table trans_tab_O[] =
123{
124 { '1', 0, KEYS_F1(8) },
125 { '2', 0, KEYS_F2(9) },
126 { '3', 0, KEYS_F3(10) },
127 { '4', 0, KEYS_F4(11) },
128 { '5', 0, KEYS_F5(12) },
129 { '6', 0, KEYS_F6(13) },
130 { '7', 0, KEYS_F7(14) },
131 { '8', 0, KEYS_F8(15) },
132 { '9', 0, KEYS_F9(16) },
133 { ':', 0, KEYS_F10(17) },
134 { 'P', 0, KEYS_F1(8) },
135 { 'Q', 0, KEYS_F2(9) },
136 { 'R', 0, KEYS_F3(10) },
137 { 'S', 0, KEYS_F4(11) },
138 { 'T', 0, KEYS_F5(12) },
139 { 'U', 0, KEYS_F6(13) },
140 { 'V', 0, KEYS_F7(14) },
141 { 'W', 0, KEYS_F8(15) },
142 { 'X', 0, KEYS_F9(16) },
143 { 'Y', 0, KEYS_F10(17) },
144 { 0, 0, 0 }
145};
146
147static const struct translation_table trans_tab[] =
148{
149 { '[', trans_tab_csi, 0 }, /* CSI command sequences */
150 { 'O', trans_tab_O, 0 }, /* O are the fuction keys */
151 { 0, 0, 0 }
152};
153
154/*
155 * Perform a basic translation for some ANSI/VT100 key codes.
156 * This code could do with a timeout on the ESC as it is
157 * now lost from the input stream. It is not* used by the
158 * line editor below so considiered not worth the effort.
159 */
160
161static unsigned int
162rtems_monitor_getchar (void)
163{
164 const struct translation_table *translation = 0;
165 for (;;)
166 {
167 char c = getchar ();
168 if (c == 27)
169 translation = trans_tab;
170 else
171 {
172 /*
173 * If no translation happing just pass through
174 * and return the key.
175 */
176 if (translation)
177 {
178 /*
179 * Scan the current table for the key, and if found
180 * see if this key is a fork. If so follow it and
181 * wait else return the extended key.
182 */
183 int index = 0;
184 int branched = 0;
185 while ((translation[index].expecting != '\0') ||
186 (translation[index].key != '\0'))
187 {
188 if (translation[index].expecting == c)
189 {
190 /*
191 * A branch is take if more keys are to come.
192 */
193 if (translation[index].branch == 0)
194 return KEYS_EXTENDED(0x8000) | translation[index].key;
195 else
196 {
197 translation = translation[index].branch;
198 branched = 1;
199 break;
200 }
201 }
202 index++;
203 }
204 /*
205 * Who knows what these keys are, just drop them.
206 */
207 if (!branched)
208 translation = 0;
209 }
210 else
211 return c;
212 }
213 }
214}
215
216/*
217 * The line editor with history.
218 */
219
220static int
221rtems_monitor_line_editor (
222 char *command
223)
224{
225 int repeating = 0;
226
227 memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE(75));
228 history = history_next;
229 pos = 0;
230
231 if (!logged_in)
232 fprintf(stdoutstdout,"\nMonitor ready, press enter to login.\n\n");
233 else
234 fprintf(stdoutstdout,"%s $ ", monitor_prompt);
235
236 while (1)
237 {
238 unsigned int extended_key;
239 char c;
240
241 fflush (stdoutstdout);
242
243 extended_key = rtems_monitor_getchar ();
244 c = extended_key & KEYS_NORMAL_MASK(0x00ff);
245
246 /*
247 * Make the extended_key usable as a boolean.
248 */
249 extended_key &= ~KEYS_NORMAL_MASK(0x00ff);
250
251 if (!extended_key && !logged_in)
252 {
253 if (c == '\n')
254 {
255 logged_in = 1;
256 /*
257 * The prompt has changed from `>' to `$' to help know
258 * which version of the monitor code people are using.
259 */
260 fprintf(stdoutstdout,"%s $ ", monitor_prompt);
261 }
262 }
263 else
264 {
265 if (extended_key)
266 {
267 switch (c)
268 {
269 case KEYS_END(7):
270 fprintf(stdoutstdout,buffer + pos);
271 pos = (int) strlen (buffer);
272 break;
273
274 case KEYS_HOME(6):
275 fprintf(stdoutstdout,"\r%s $ ", monitor_prompt);
276 pos = 0;
277 break;
278
279 case KEYS_LARROW(4):
280 if (pos > 0)
281 {
282 pos--;
283 putchar ('\b');
284 }
285 break;
286
287 case KEYS_RARROW(5):
288 if ((pos < RTEMS_COMMAND_BUFFER_SIZE(75)) && (buffer[pos] != '\0'))
289 {
290 putchar (buffer[pos]);
291 pos++;
292 }
293 break;
294
295 case KEYS_UARROW(2):
296 /*
297 * If we are moving up the histories then we need to save the working
298 * buffer.
299 */
300 if (history)
301 {
302 int end;
303 int bs;
304 if (history == history_next)
305 {
306 memcpy (history_buffer[history_next], buffer,
307 RTEMS_COMMAND_BUFFER_SIZE(75));
308 history_pos[history_next] = pos;
309 }
310 history--;
311 memcpy (buffer, history_buffer[history],
312 RTEMS_COMMAND_BUFFER_SIZE(75));
313 pos = history_pos[history];
314 fprintf(stdoutstdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE(75), ' ');
315 fprintf(stdoutstdout,"\r%s $ %s", monitor_prompt, buffer);
316 end = (int) strlen (buffer);
317 for (bs = 0; bs < (end - pos); bs++)
318 putchar ('\b');
319 }
320 break;
321
322 case KEYS_DARROW(3):
323 if (history < history_next)
324 {
325 int end;
326 int bs;
327 history++;
328 memcpy (buffer, history_buffer[history],
329 RTEMS_COMMAND_BUFFER_SIZE(75));
330 pos = history_pos[history];
331 fprintf(stdoutstdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE(75), ' ');
332 fprintf(stdoutstdout,"\r%s $ %s", monitor_prompt, buffer);
333 end = (int) strlen (buffer);
334 for (bs = 0; bs < (end - pos); bs++)
335 putchar ('\b');
336 }
337 break;
338
339 case KEYS_DEL(1):
340 if (buffer[pos] != '\0')
341 {
342 int end;
343 int bs;
344 strcpy (&buffer[pos], &buffer[pos + 1]);
345 fprintf(stdoutstdout,"\r%s $ %s", monitor_prompt, buffer);
346 end = (int) strlen (buffer);
347 for (bs = 0; bs < (end - pos); bs++)
348 putchar ('\b');
349 }
350 break;
351 }
352 }
353 else
354 {
355 switch (c)
356 {
357 case '\b':
358 case '\x7e':
359 case '\x7f':
360 if (pos > 0)
361 {
362 int bs;
363 pos--;
364 strcpy (buffer + pos, buffer + pos + 1);
365 fprintf(stdoutstdout,"\b%s \b", buffer + pos);
366 for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
367 putchar ('\b');
368 }
369 break;
370
371 case '\n':
372 /*
373 * Process the command.
374 */
375 fprintf(stdoutstdout,"\n");
376 repeating = 1;
377 /*
378 * Only process the history if we have a command and
379 *a history.
380 */
381 if (strlen (buffer))
382 {
383 if (history_next && (history == history_next))
384 {
385 /*
386 * Do not place the last command into the history
387 *if the same.
388 */
389 if (strcmp (history_buffer[history_next - 1], buffer))
390 repeating = 0;
391 }
392 else
393 repeating = 0;
394 }
395 if (!repeating)
396 {
397 memcpy (history_buffer[history_next], buffer,
398 RTEMS_COMMAND_BUFFER_SIZE(75));
399 history_pos[history_next] = pos;
400 if (history_next < (RTEMS_COMMAND_HISTORIES(20) - 1))
401 history_next++;
402 else
403 {
404 memmove (history_buffer[0], history_buffer[1],
405 RTEMS_COMMAND_BUFFER_SIZE(75) * (RTEMS_COMMAND_HISTORIES(20) - 1));
406 memmove (&history_pos[0], &history_pos[1],
407 sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES(20) - 1));
408 }
409 }
410 else
411 {
412#ifdef ENABLE_ENTER_REPEATS
413 if (history_next)
414 memcpy (buffer, history_buffer[history_next - 1],
415 RTEMS_COMMAND_BUFFER_SIZE(75));
416#endif
417 }
418 memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE(75));
419 return repeating;
420 break;
421
422 default:
423 if ((pos < (RTEMS_COMMAND_BUFFER_SIZE(75) - 1)) &&
424 (c >= ' ') && (c <= 'z'))
425 {
426 int end;
427 end = strlen (buffer);
428 if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE(75)))
429 {
430 int ch, bs;
431 for (ch = end; ch > pos; ch--)
432 buffer[ch] = buffer[ch - 1];
433 fprintf(stdoutstdout,buffer + pos);
434 for (bs = 0; bs < (end - pos + 1); bs++)
435 putchar ('\b');
436 }
437 buffer[pos++] = c;
438 if (pos > end)
439 buffer[pos] = '\0';
440 putchar (c);
441 }
442 break;
443 }
444 }
445 }
446 }
447}
448
449/*
450 * make_argv(cp): token-count
451 * Break up the command line in 'cp' into global argv[] and argc (return
452 * value).
453 */
454
455int
456rtems_monitor_make_argv(
457 char *cp,
458 int *argc_p,
459 char **argv)
460{
461 int argc = 0;
462
463 while ((cp = strtok(cp, " \t\n\r")))
464 {
465 argv[argc++] = cp;
466 cp = (char *) NULL((void*)0);
467 }
468 argv[argc] = (char *) NULL((void*)0); /* end of argv */
469
470 return *argc_p = argc;
471}
472
473
474/*
475 * Read and break up a monitor command
476 *
477 * We have to loop on the gets call, since it will return NULL under UNIX
478 * RTEMS when we get a signal (eg: SIGALRM).
479 */
480
481int
482rtems_monitor_command_read(char *command,
483 int *argc,
484 char **argv)
485{
486 char *env_prompt;
487
488 env_prompt = getenv("RTEMS_MONITOR_PROMPT");
489
490 /*
491 * put node number in the prompt if we are multiprocessing
492 */
493#if defined(RTEMS_MULTIPROCESSING)
494 if (!rtems_configuration_get_user_multiprocessing_table ()((void*)0))
495 sprintf (monitor_prompt, "%s",
496 (env_prompt == NULL((void*)0)) ? MONITOR_PROMPT"rtems": env_prompt);
497 else /* .... */
498#endif
499 if (rtems_monitor_default_node != rtems_monitor_node)
500 sprintf (monitor_prompt, "%" PRId32"d" "-%s-%" PRId32"d" "", rtems_monitor_node,
501 (env_prompt == NULL((void*)0)) ? MONITOR_PROMPT"rtems" : env_prompt,
502 rtems_monitor_default_node);
503 else
504 sprintf (monitor_prompt, "%" PRId32"d" "-%s", rtems_monitor_node,
505 (env_prompt == NULL((void*)0)) ? MONITOR_PROMPT"rtems" : env_prompt);
506
507 rtems_monitor_line_editor (command);
508
509 return rtems_monitor_make_argv (command, argc, argv);
510}
511
512/*
513 * Main monitor command loop
514 */
515
516void
517rtems_monitor_task(
518 rtems_task_argument monitor_flags
519)
520{
521 rtems_tcb *debugee = 0;
522 rtems_context *rp;
523#if (CPU_HARDWARE_FP1 == TRUE1) || (CPU_SOFTWARE_FP0 == TRUE1)
524 rtems_context_fp *fp;
525#endif
526 char command_buffer[513];
527 int argc;
528 char *argv[64];
529 bool_Bool verbose = false0;
530 struct termios term;
531
532 /*
533 * Make the stdin stream characte not line based.
534 */
535
536 if (tcgetattr (STDIN_FILENO0, &term) < 0)
537 {
538 fprintf(stdoutstdout,"rtems-monitor: cannot get terminal attributes.\n");
539 }
540 else
541 {
542 /*
543 * No echo, no canonical processing.
544 */
545
546 term.c_lflag &= ~(ECHO0000010 | ICANON0000002 | IEXTEN0100000);
547
548 /*
549 * No sigint on BREAK, CR-to-NL off, input parity off,
550 * don't strip 8th bit on input, output flow control off
551 */
552
553 term.c_lflag &= ~(INPCK0000020 | ISTRIP0000040 | IXON0002000);
554 term.c_cc[VMIN6] = 1;
555 term.c_cc[VTIME5] = 0;
556
557 if (tcsetattr (STDIN_FILENO0, TCSANOW0, &term) < 0)
558 {
559 fprintf(stdoutstdout,"cannot set terminal attributes\n");
560 }
561 }
562
563 if (!(monitor_flags & RTEMS_MONITOR_NOSYMLOAD0x0008)) {
564 rtems_monitor_symbols_loadup();
565 }
566
567 if (monitor_flags & RTEMS_MONITOR_SUSPEND0x0001)
568 (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT0);
569
570 for (;;)
571 {
572 const rtems_monitor_command_entry_t *command;
573
574 debugee = _Thread_Executing_Per_CPU_Information.executing;
575 rp = &debugee->Registers;
Value stored to 'rp' is never read
576#if (CPU_HARDWARE_FP1 == TRUE1) || (CPU_SOFTWARE_FP0 == TRUE1)
577 fp = debugee->fp_context; /* possibly 0 */
578#endif
579
580 if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
581 continue;
582 if (argc < 1
583 || (command = rtems_monitor_command_lookup(argv [0])) == 0) {
584 /* no command */
585 fprintf(stdoutstdout,"Unrecognised command; try 'help'\n");
586 continue;
587 }
588
589 command->command_function(argc, argv, &command->command_arg, verbose);
590
591 fflush(stdoutstdout);
592 }
593}
594
595
596void
597rtems_monitor_kill(void)
598{
599 if (rtems_monitor_task_id)
600 rtems_task_delete(rtems_monitor_task_id);
601 rtems_monitor_task_id = 0;
602
603 rtems_monitor_server_kill();
604}
605
606void
607rtems_monitor_init(
608 uint32_t monitor_flags
609)
610{
611 rtems_status_code status;
612
613 rtems_monitor_kill();
614
615 status = rtems_task_create(RTEMS_MONITOR_NAME(( (uint32_t)('R') << 24 | (uint32_t)('M') << 16 |
(uint32_t)('O') << 8 | (uint32_t)('N') ))
,
616 1,
617 RTEMS_MINIMUM_STACK_SIZE(1024*4) * 2,
618 RTEMS_INTERRUPT_LEVEL(0)( (0) & 0x0000000F ),
619 RTEMS_DEFAULT_ATTRIBUTES0x00000000,
620 &rtems_monitor_task_id);
621 if (status != RTEMS_SUCCESSFUL)
622 {
623 rtems_error(status, "could not create monitor task");
624 return;
625 }
626
627 rtems_monitor_node = rtems_object_id_get_node(rtems_monitor_task_id)_Objects_Get_node( rtems_monitor_task_id );
628 rtems_monitor_default_node = rtems_monitor_node;
629
630 rtems_monitor_server_init(monitor_flags);
631
632 if (!(monitor_flags & RTEMS_MONITOR_NOTASK0x0004)) {
633 /*
634 * Start the monitor task itself
635 */
636 status = rtems_task_start(
637 rtems_monitor_task_id, rtems_monitor_task, monitor_flags);
638 if (status != RTEMS_SUCCESSFUL) {
639 rtems_error(status, "could not start monitor");
640 return;
641 }
642 }
643}