Changeset 32e2554 in rtems


Ignore:
Timestamp:
Jun 14, 2000, 5:22:59 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
f585287
Parents:
6f93bb4
Message:

Patch rtems-4.5-beta3-mon.diff from Chris Johns <cjohns@…>
to:

I have also added the ability to register and unregister commands. This
allows me to create a set of monitor commands for the network stack plus
basic memory dump/patch commands (needs a working probe interface). I
will also look at a basic ls/cd/rm/mv/cp command set at some stage.

I have been thinking about changing the monitor in the future to more
like a light weight RTEMS shell, `eshell' for embedded shell. This is a
story for another day but is a process or getting the commands to map to
the filesystem (eg, major=commands, minor=command) and supporting an
environment. The filesystem provide a structure for the commands.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • c/src/libmisc/monitor/mon-command.c

    r6f93bb4 r32e2554  
    1515
    1616/*
     17 * CCJ: 26-3-2000, adding command history and command line
     18 * editing. This code is donated from My Right Boot and not
     19 * covered by GPL, only the RTEMS license.
     20 */
     21
     22/*
     23 * Some key labels to define special keys.
     24 */
     25
     26#define KEYS_EXTENDED    (0x8000)
     27#define KEYS_NORMAL_MASK (0x00ff)
     28#define KEYS_INS         (0)
     29#define KEYS_DEL         (1)
     30#define KEYS_UARROW      (2)
     31#define KEYS_DARROW      (3)
     32#define KEYS_LARROW      (4)
     33#define KEYS_RARROW      (5)
     34#define KEYS_HOME        (6)
     35#define KEYS_END         (7)
     36#define KEYS_F1          (8)
     37#define KEYS_F2          (9)
     38#define KEYS_F3          (10)
     39#define KEYS_F4          (11)
     40#define KEYS_F5          (12)
     41#define KEYS_F6          (13)
     42#define KEYS_F7          (14)
     43#define KEYS_F8          (15)
     44#define KEYS_F9          (16)
     45#define KEYS_F10         (17)
     46
     47#define RTEMS_COMMAND_BUFFER_SIZE (75)
     48
     49static char monitor_prompt[32];
     50static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
     51static int  pos;
     52static int  logged_in;
     53
     54/*
     55 * History data.
     56 */
     57
     58#define RTEMS_COMMAND_HISTORIES (20)
     59
     60static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
     61static int  history_pos[RTEMS_COMMAND_HISTORIES];
     62static int  history;
     63static int  history_next;
     64
     65/*
     66 * Translation tables. Not sure if this is the best way to
     67 * handle this, how-ever I wish to avoid the overhead of
     68 * including a more complete and standard environment such
     69 * as ncurses.
     70 */
     71
     72struct translation_table
     73{
     74  char                     expecting;
     75  struct translation_table *branch;
     76  unsigned int             key;
     77};
     78
     79static struct translation_table trans_two[] =
     80{
     81  { '~', 0, KEYS_INS },
     82  { 0,   0, 0 }
     83};
     84
     85static struct translation_table trans_three[] =
     86{
     87  { '~', 0, KEYS_DEL },
     88  { 0,   0, 0 }
     89};
     90
     91static struct translation_table trans_tab_csi[] =
     92{
     93  { '2', trans_two,   0 },
     94  { '3', trans_three, 0 },
     95  { 'A', 0,           KEYS_UARROW },
     96  { 'B', 0,           KEYS_DARROW },
     97  { 'D', 0,           KEYS_LARROW },
     98  { 'C', 0,           KEYS_RARROW },
     99  { 'F', 0,           KEYS_END },
     100  { 'H', 0,           KEYS_HOME },
     101  { 0,   0,           0 }
     102};
     103
     104static struct translation_table trans_tab_O[] =
     105{
     106  { '1', 0, KEYS_F1 },
     107  { '2', 0, KEYS_F2 },
     108  { '3', 0, KEYS_F3 },
     109  { '4', 0, KEYS_F4 },
     110  { '5', 0, KEYS_F5 },
     111  { '6', 0, KEYS_F6 },
     112  { '7', 0, KEYS_F7 },
     113  { '8', 0, KEYS_F8 },
     114  { '9', 0, KEYS_F9 },
     115  { ':', 0, KEYS_F10 },
     116  { 'P', 0, KEYS_F1 },
     117  { 'Q', 0, KEYS_F2 },
     118  { 'R', 0, KEYS_F3 },
     119  { 'S', 0, KEYS_F4 },
     120  { 'T', 0, KEYS_F5 },
     121  { 'U', 0, KEYS_F6 },
     122  { 'V', 0, KEYS_F7 },
     123  { 'W', 0, KEYS_F8 },
     124  { 'X', 0, KEYS_F9 },
     125  { 'Y', 0, KEYS_F10 },
     126  { 0,   0, 0 }
     127};
     128
     129static struct translation_table trans_tab[] =
     130{
     131  { '[', trans_tab_csi, 0 },    /* CSI command sequences */
     132  { 'O', trans_tab_O,   0 },    /* O are the fuction keys */
     133  { 0,   0,             0 }
     134};
     135
     136/*
     137 * Perform a basic tranlation for some ANSI/VT100 key codes.
     138 * This code could do with a timeout on the ESC as it is
     139 * now lost from the input stream. It is not* used by the
     140 * line editor below so considiered not worth the effort.
     141 */
     142
     143static unsigned int
     144rtems_monitor_getchar (
     145)
     146{
     147  struct translation_table *translation = 0;
     148  for (;;)
     149  {
     150    char c = getchar ();
     151    if (c == 27)
     152      translation = trans_tab;
     153    else
     154    {
     155      /*
     156       * If no translation happing just pass through
     157       * and return the key.
     158       */
     159      if (translation)
     160      {
     161        /*
     162         * Scan the current table for the key, and if found
     163         * see if this key is a fork. If so follow it and
     164         * wait else return the extended key.
     165         */
     166        int index    = 0;
     167        int branched = 0;
     168        while ((translation[index].expecting != '\0') ||
     169               (translation[index].key != '\0'))
     170        {
     171          if (translation[index].expecting == c)
     172          {
     173            /*
     174             * A branch is take if more keys are to come.
     175             */
     176            if (translation[index].branch == 0)
     177              return KEYS_EXTENDED | translation[index].key;
     178            else
     179            {
     180              translation = translation[index].branch;
     181              branched    = 1;
     182              break;
     183            }
     184          }
     185          index++;
     186        }
     187        /*
     188         * Who knows what these keys are, just drop them.
     189         */
     190        if (!branched)
     191          translation = 0;
     192      }
     193      else
     194        return c;
     195    }
     196  }
     197}
     198
     199/*
     200 * The line editor with history.
     201 */
     202
     203static int
     204rtems_monitor_line_editor (
     205    char *command
     206)
     207{
     208  int repeating = 0;
     209
     210  memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
     211  history = history_next;
     212  pos     = 0;
     213         
     214  if (!logged_in)
     215    printf ("\nMonitor ready, press enter to login.\n\n");
     216  else
     217    printf ("%s $ ", monitor_prompt);
     218
     219  while (1)
     220  {
     221    unsigned int extended_key = rtems_monitor_getchar ();
     222    char         c = extended_key & KEYS_NORMAL_MASK;
     223
     224    /*
     225     * Make the extended_key usable as a boolean.
     226     */
     227    extended_key &= ~KEYS_NORMAL_MASK;
     228   
     229    if (!extended_key && !logged_in)
     230    {
     231      if (c == '\n')
     232      {
     233        logged_in = 1;
     234        /*
     235         * The prompt has changed from `>' to `$' to help know
     236         * which version of the monitor code people are using.
     237         */
     238        printf("%s $ ", monitor_prompt);
     239      }
     240    }
     241    else
     242    {
     243      if (extended_key)
     244      {
     245        switch (c)
     246        {
     247          case KEYS_END:
     248            printf (buffer + pos);
     249            pos = (int) strlen (buffer);
     250            break;
     251
     252          case KEYS_HOME:
     253            printf ("\r%s $ ", monitor_prompt);
     254            pos = 0;
     255            break;
     256       
     257          case KEYS_LARROW:
     258            if (pos > 0)
     259            {
     260              pos--;
     261              putchar ('\b');
     262            }
     263            break;
     264
     265          case KEYS_RARROW:
     266            if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
     267            {
     268              putchar (buffer[pos]);
     269              pos++;
     270            }
     271            break;
     272
     273          case KEYS_UARROW:
     274            /*
     275             * If we are moving up the histories then we need to save the working
     276             * buffer.
     277             */
     278            if (history)
     279            {
     280              int end;
     281              int bs;
     282              if (history == history_next)
     283              {
     284                memcpy (history_buffer[history_next], buffer,
     285                        RTEMS_COMMAND_BUFFER_SIZE);
     286                history_pos[history_next] = pos;
     287              }
     288              history--;
     289              memcpy (buffer, history_buffer[history],
     290                      RTEMS_COMMAND_BUFFER_SIZE);
     291              pos = history_pos[history];
     292              printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
     293              printf ("\r%s $ %s", monitor_prompt, buffer);
     294              end = (int) strlen (buffer);
     295              for (bs = 0; bs < (end - pos); bs++)
     296                putchar ('\b');
     297            }
     298            break;
     299                 
     300          case KEYS_DARROW:
     301            if (history < history_next)
     302            {
     303              int end;
     304              int bs;
     305              history++;
     306              memcpy (buffer, history_buffer[history],
     307                      RTEMS_COMMAND_BUFFER_SIZE);
     308              pos = history_pos[history];
     309              printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
     310              printf ("\r%s $ %s", monitor_prompt, buffer);
     311              end = (int) strlen (buffer);
     312              for (bs = 0; bs < (end - pos); bs++)
     313                putchar ('\b');
     314            }
     315            break;
     316
     317          case KEYS_DEL:
     318            if (buffer[pos] != '\0')
     319            {
     320              int end;
     321              int bs;
     322              strcpy (&buffer[pos], &buffer[pos + 1]);
     323              printf ("\r%s $ %s", monitor_prompt, buffer);
     324              end = (int) strlen (buffer);
     325              for (bs = 0; bs < (end - pos); bs++)
     326                putchar ('\b');
     327            }
     328            break;
     329        }
     330      }
     331      else
     332      {
     333        switch (c)
     334        {
     335          case '\b':
     336          case '\x7e':
     337          case '\x7f':
     338            if (pos > 0)
     339            {
     340              int bs;
     341              pos--;
     342              strcpy (buffer + pos, buffer + pos + 1);
     343              printf ("\b%s \b", buffer + pos);
     344              for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
     345                putchar ('\b');
     346            }
     347            break;
     348
     349          case '\n':
     350            /*
     351             * Process the command.
     352             */
     353            printf ("\n");
     354            repeating = 1;
     355            /*
     356             * Only process the history if we have a command and
     357             *a history.
     358             */
     359            if (strlen (buffer))
     360            {
     361              if (history_next && (history == history_next))
     362              {
     363                /*
     364                 * Do not place the last command into the history
     365                 *if the same.
     366                 */
     367                if (strcmp (history_buffer[history_next - 1], buffer))
     368                  repeating = 0;
     369              }
     370              else
     371                repeating = 0;
     372            }
     373            if (!repeating)
     374            {
     375              memcpy (history_buffer[history_next], buffer,
     376                      RTEMS_COMMAND_BUFFER_SIZE);
     377              history_pos[history_next] = pos;
     378              if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
     379                history_next++;
     380              else
     381              {
     382                memmove (history_buffer[0], history_buffer[1],
     383                         RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
     384                memmove (&history_pos[0], &history_pos[1],
     385                         sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
     386              }
     387            }
     388            else
     389            {
     390              if (history_next)
     391                memcpy (buffer, history_buffer[history_next - 1],
     392                        RTEMS_COMMAND_BUFFER_SIZE);
     393            }
     394            memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
     395            return repeating;
     396            break;
     397
     398          default:
     399            if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
     400                (c >= ' ') && (c <= 'z'))
     401            {
     402              int end;
     403              if (c >= 'A' && c <= 'Z')
     404                c += 'a' - 'A';
     405              end = strlen (buffer);
     406              if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
     407              {
     408                int ch, bs;
     409                for (ch = end + 1; ch > pos; ch--)
     410                  buffer[ch] = buffer[ch - 1];
     411                printf (buffer + pos);
     412                for (bs = 0; bs < (end - pos + 1); bs++)
     413                  putchar ('\b');
     414              }
     415              buffer[pos++] = c;
     416              if (pos > end)
     417                buffer[pos] = '\0';
     418              putchar (c);
     419            }
     420            break;
     421        }
     422      }
     423    }
     424  }
     425}
     426
     427/*
    17428 * make_argv(cp): token-count
    18  *      Break up the command line in 'cp' into global argv[] and argc (return
    19  *      value).
     429 *  Break up the command line in 'cp' into global argv[] and argc (return
     430 *  value).
    20431 */
    21432
     
    26437    char **argv)
    27438{
    28     int argc = 0;
    29 
    30     while ((cp = strtok(cp, " \t\n\r")))
    31     {
    32         argv[argc++] = cp;
    33         cp = (char *) NULL;
    34     }
    35     argv[argc] = (char *) NULL;                 /* end of argv */
    36 
    37     return *argc_p = argc;
     439  int argc = 0;
     440
     441  while ((cp = strtok(cp, " \t\n\r")))
     442  {
     443    argv[argc++] = cp;
     444    cp = (char *) NULL;
     445  }
     446  argv[argc] = (char *) NULL;      /* end of argv */
     447
     448  return *argc_p = argc;
    38449}
    39450
     
    51462                           char **argv)
    52463{
    53     static char monitor_prompt[32];
    54    
    55     /*
    56      * put node number in the prompt if we are multiprocessing
    57      */
    58 
    59     if (!rtems_configuration_get_user_multiprocessing_table())
    60         sprintf(monitor_prompt, "%s", MONITOR_PROMPT);
    61     else if (rtems_monitor_default_node != rtems_monitor_node)
    62         sprintf(monitor_prompt, "%d-%s-%d", rtems_monitor_node, MONITOR_PROMPT, rtems_monitor_default_node);
    63     else
    64         sprintf(monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
     464  /*
     465   * put node number in the prompt if we are multiprocessing
     466   */
     467
     468  if (!rtems_configuration_get_user_multiprocessing_table ())
     469    sprintf (monitor_prompt, "%s", MONITOR_PROMPT);
     470  else if (rtems_monitor_default_node != rtems_monitor_node)
     471    sprintf (monitor_prompt, "%d-%s-%d", rtems_monitor_node,
     472             MONITOR_PROMPT, rtems_monitor_default_node);
     473  else
     474    sprintf (monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
    65475
    66476#ifdef RTEMS_UNIX
    67     /* RTEMS on unix gets so many interrupt system calls this is hosed */
    68     printf("%s> ", monitor_prompt);
    69     fflush(stdout);
    70     while (gets(command) == (char *) 0)
    71         ;
     477  /* RTEMS on unix gets so many interrupt system calls this is hosed */
     478  printf ("%s> ", monitor_prompt);
     479  fflush (stdout);
     480  while (gets(command) == (char *) 0)
     481    ;
    72482#else
    73     do
    74     {
    75         printf("%s> ", monitor_prompt);
    76         fflush(stdout);
    77     } while (gets(command) == (char *) 0);
     483  rtems_monitor_line_editor (command);
    78484#endif
    79485
    80     return rtems_monitor_make_argv(command, argc, argv);
     486  return rtems_monitor_make_argv (command, argc, argv);
    81487}
    82488
     
    93499)
    94500{
    95     rtems_monitor_command_entry_t *p;
    96     rtems_monitor_command_entry_t *abbreviated_match = 0;
    97     int abbreviated_matches = 0;
    98     char *command;
    99     int command_length;
    100 
    101     command = argv[0];
    102 
    103     if ((table == 0) || (command == 0))
    104         goto failed;
     501  char *command;
     502
     503  command = argv[0];
     504
     505  if ((table == 0) || (command == 0))
     506    return 0;
    105507   
    106     command_length = strlen(command);
    107 
    108     for (p = table; p->command; p++)
    109         if (STREQ(command, p->command))    /* exact match */
    110             goto done;
    111         else if (STRNEQ(command, p->command, command_length))
     508  while (table)
     509  {
     510    if (table->command)
     511    {
     512      if (STREQ (command, table->command))  /* exact match */
     513      {
     514        if (table->command_function == 0)
     515          return 0;
     516        return table;
     517      }
     518    }
     519    table = table->next;
     520  }
     521
     522  return 0;
     523}
     524
     525void
     526rtems_monitor_show_help (
     527  rtems_monitor_command_entry_t *help_cmd,
     528  int                           max_cmd_len
     529)
     530{
     531#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
     532
     533  if (help_cmd && help_cmd->command)
     534  {
     535    const char *help = help_cmd->usage;
     536    int         help_len = strlen (help);
     537    int         spaces = max_cmd_len - strlen (help_cmd->command);
     538    int         show_this_line = 0;
     539    int         line_one = 1;
     540    int         c;
     541
     542    printf ("%s", help_cmd->command);
     543
     544    if (help_len == 0)
     545    {
     546      printf (" - No help associated.\n");
     547      return;
     548    }
     549 
     550    while (help_len)
     551    {
     552      printf ("%*c", spaces, ' ');
     553     
     554      if (line_one)
     555        printf (" - ");
     556
     557      spaces   = max_cmd_len + 2;
     558      line_one = 0;
     559
     560      /*
     561       * See if greater then the line length if so, work back
     562       * from the end for a space, tab or lf or cr.
     563       */
     564     
     565      if (help_len > MAX_HELP_LINE_LENGTH)
     566      {
     567        for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
     568             show_this_line;
     569             show_this_line--)
     570          if ((help[show_this_line] == ' ') ||
     571              (help[show_this_line] == '\n') ||
     572              (help[show_this_line] == '\r'))
     573            break;
     574
     575        /*
     576         * If show_this_line is 0, it is a very long word !!
     577         */
     578     
     579        if (show_this_line == 0)
     580          show_this_line = MAX_HELP_LINE_LENGTH - 1;
     581      }
     582      else
     583        show_this_line = help_len;
     584
     585      for (c = 0; c < show_this_line; c++)
     586        if ((help[c] == '\r') || (help[c] == '\n'))
     587          show_this_line = c;
     588        else
     589          putchar (help[c]);
     590
     591      printf ("\n");
     592                 
     593      help     += show_this_line;
     594      help_len -= show_this_line;
     595
     596      /*
     597       * Move past the line feeds or what ever else is being skipped.
     598       */
     599   
     600      while (help_len)
     601      {
     602        if ((*help != '\r') && (*help != '\n'))
     603          break;
     604
     605        if (*help != ' ')
    112606        {
    113             abbreviated_matches++;
    114             abbreviated_match = p;
     607          help++;
     608          help_len--;
     609          break;
    115610        }
    116 
    117     /* no perfect match; is there a non-ambigous abbreviated match? */
    118     if ( ! abbreviated_match)
    119     {
    120         printf("Unrecognized command '%s'; try 'help'\n", command);
    121         goto failed;
    122     }   
    123 
    124     if (abbreviated_matches > 1)
    125     {
    126         printf("Command '%s' is ambiguous; try 'help'\n", command);
    127         goto failed;
     611        help++;
     612        help_len--;
     613      }
    128614    }
     615  }
     616}
     617
     618void
     619rtems_monitor_command_usage(
     620  rtems_monitor_command_entry_t *table,
     621  char                          *command_string
     622)
     623{
     624  rtems_monitor_command_entry_t *command = table;
     625  int                           max_cmd_len = 0;
    129626   
    130     p = abbreviated_match;
    131 
    132 done:
    133     if (p->command_function == 0)
    134         goto failed;
    135     return p;
    136 
    137 failed:
    138     return 0;
    139 }
    140 
    141 void
    142 rtems_monitor_command_usage(rtems_monitor_command_entry_t *table,
    143                             char *command_string)
    144 {
    145     rtems_monitor_command_entry_t *help = 0;
    146     char *help_command_argv[2];
     627  /* if first entry in table is a usage, then print it out */
     628
     629  if (command_string && (*command_string != '\0'))
     630  {
     631    char *argv[2];
    147632   
    148     /* if first entry in table is a usage, then print it out */
    149     if (command_string == 0)
    150     {       
    151         if (STREQ(table->command, "--usage--") && table->usage)
    152             help = table;
    153     }
     633    argv[0] = command_string;
     634    argv[1] = 0;
     635   
     636    command = rtems_monitor_command_lookup (table, 1, argv);
     637
     638    if (command)
     639      rtems_monitor_show_help (command, strlen (command_string));
    154640    else
    155     {
    156         help_command_argv[0] = command_string;
    157         help_command_argv[1] = 0;
    158         help = rtems_monitor_command_lookup(table, 1, help_command_argv);
    159     }
    160 
    161     if (help)
    162         printf("%s\n", help->usage);
     641      printf ("Unrecognised command; try just 'help'\n");
     642    return;
     643  }
     644 
     645  /*
     646   * Find the largest command size.
     647   */
     648 
     649  while (command)
     650  {
     651    int len = strlen (command->command);
     652
     653    if (len > max_cmd_len)
     654      max_cmd_len = len;
     655
     656    command = command->next;
     657  }
     658
     659  max_cmd_len++;
     660
     661  command = table;
     662
     663  /*
     664   * Now some nice formatting for the help.
     665   */
     666
     667  while (command)
     668  {
     669    rtems_monitor_show_help (command, max_cmd_len);
     670    command = command->next;
     671  }
    163672}
    164673
     
    172681)
    173682{
    174     int arg;
    175     rtems_monitor_command_entry_t *command;
    176 
    177     command = (rtems_monitor_command_entry_t *) command_arg;
     683  int arg;
     684  rtems_monitor_command_entry_t *command;
     685
     686  command = (rtems_monitor_command_entry_t *) command_arg;
    178687   
    179     if (argc == 1)
    180         rtems_monitor_command_usage(command, 0);
    181     else
    182     {
    183         for (arg=1; argv[arg]; arg++)
    184             rtems_monitor_command_usage(command, argv[arg]);
    185     }
    186 }
     688  if (argc == 1)
     689    rtems_monitor_command_usage(command, 0);
     690  else
     691  {
     692    for (arg = 1; argv[arg]; arg++)
     693      rtems_monitor_command_usage(command, argv[arg]);
     694  }
     695}
  • c/src/libmisc/monitor/mon-monitor.c

    r6f93bb4 r32e2554  
    2828#include <string.h>
    2929#include <stdlib.h>
     30#include <termios.h>
    3031#include <unistd.h>
    3132
     
    5556
    5657/*
     58 * User registered commands.
     59 */
     60
     61rtems_monitor_command_entry_t rtems_registered_commands;
     62
     63/*
    5764 * The top-level commands
    5865 */
    5966
    6067rtems_monitor_command_entry_t rtems_monitor_commands[] = {
    61     { "--usage--",
    62       "\n"
    63       "RTEMS monitor\n"
    64       "\n"
    65       "Commands (may be abbreviated)\n"
    66       "\n"
    67       "  help      -- get this message or command specific help\n"
    68       "  pause     -- pause monitor for a specified number of ticks\n"
    69       "  exit      -- invoke a fatal RTEMS error\n"
    70       "  symbol    -- show entries from symbol table\n"
    71       "  continue  -- put monitor to sleep waiting for explicit wakeup\n"
    72       "  config    -- show system configuration\n"
    73       "  itask     -- list init tasks\n"
    74       "  mpci      -- list mpci config\n"
    75       "  task      -- show task information\n"
    76       "  queue     -- show message queue information\n"
    77       "  extension -- user extensions\n"
    78       "  driver    -- show information about named drivers\n"
    79       "  dname     -- show information about named drivers\n"
    80       "  object    -- generic object information\n"
    81       "  node      -- specify default node for commands that take id's\n"
    82 #ifdef CPU_INVOKE_DEBUGGER
    83       "  debugger  -- invoke system debugger\n"
    84 #endif
    85       ,
    86       0,
    87       0,
    88       (unsigned32) rtems_monitor_commands,
    89     },
    9068    { "config",
    91       "config\n"
    92       "  Show the system configuration.\n",
     69      "Show the system configuration.",
    9370      0,
    9471      rtems_monitor_object_cmd,
    9572      RTEMS_MONITOR_OBJECT_CONFIG,
     73      &rtems_monitor_commands[1],
    9674    },
    9775    { "itask",
    98       "itask\n"
    99       "  List init tasks for the system\n",
     76      "List init tasks for the system",
    10077      0,
    10178      rtems_monitor_object_cmd,
    10279      RTEMS_MONITOR_OBJECT_INIT_TASK,
     80      &rtems_monitor_commands[2],
    10381    },
    10482   { "mpci",
    105       "mpci\n"
    106       "  Show the MPCI system configuration, if configured.\n",
     83      "Show the MPCI system configuration, if configured.",
    10784      0,
    10885      rtems_monitor_object_cmd,
    10986      RTEMS_MONITOR_OBJECT_MPCI,
     87      &rtems_monitor_commands[3],
    11088    },
    11189    { "pause",
    112       "pause [ticks]\n"
    113       "  monitor goes to \"sleep\" for specified ticks (default is 1)\n"
    114       "  monitor will resume at end of period or if explicitly awakened\n",
     90      "Monitor goes to \"sleep\" for specified ticks (default is 1). "
     91      "Monitor will resume at end of period or if explicitly awakened\n"
     92      "  pause [ticks]",
    11593      0,
    11694      rtems_monitor_pause_cmd,
    11795      0,
     96      &rtems_monitor_commands[4],
    11897    },
    11998    { "continue",
    120       "continue\n"
    121       "  put the monitor to sleep waiting for an explicit wakeup from the\n"
    122       "  program running.\n",
     99      "Put the monitor to sleep waiting for an explicit wakeup from the "
     100      "program running.\n",
    123101      0,
    124102      rtems_monitor_continue_cmd,
    125103      0,
     104      &rtems_monitor_commands[5],
    126105    },
    127106    { "go",
    128       "go\n"
    129       "  Alias for 'continue'\n",
     107      "Alias for 'continue'",
    130108      0,
    131109      rtems_monitor_continue_cmd,
    132110      0,
     111      &rtems_monitor_commands[6],
    133112    },
    134113    { "node",
    135       "node [ node number ]\n"
    136       "  Specify default node number for commands that take id's\n",
     114      "Specify default node number for commands that take id's.\n"
     115      "  node [ node number ]",
    137116      0,
    138117      rtems_monitor_node_cmd,
    139118      0,
     119      &rtems_monitor_commands[7],
    140120    },
    141121    { "symbol",
    142       "symbol [ symbolname [symbolname ... ] ]\n"
    143       "  display value associated with specified symbol.\n"
    144       "  Defaults to displaying all known symbols.\n",
     122      "Display value associated with specified symbol. "
     123      "Defaults to displaying all known symbols.\n"
     124      "  symbol [ symbolname [symbolname ... ] ]",
    145125      0,
    146126      rtems_monitor_symbol_cmd,
    147127      (unsigned32) &rtems_monitor_symbols,
     128      &rtems_monitor_commands[8],
    148129    },
    149130    { "extension",
    150       "extension [id [id ...] ]\n"
    151       "  display information about specified extensions.\n"
    152       "  Default is to display information about all extensions on this node\n",
     131      "Display information about specified extensions. "
     132      "Default is to display information about all extensions on this node.\n"
     133      "  extension [id [id ...] ]",
    153134      0,
    154135      rtems_monitor_object_cmd,
    155136      RTEMS_MONITOR_OBJECT_EXTENSION,
     137      &rtems_monitor_commands[9],
    156138    },
    157139    { "task",
    158       "task [id [id ...] ]\n"
    159       "  display information about the specified tasks.\n"
    160       "  Default is to display information about all tasks on this node\n",
     140      "Display information about the specified tasks. "
     141      "Default is to display information about all tasks on this node.\n"
     142      "  task [id [id ...] ]",
    161143      0,
    162144      rtems_monitor_object_cmd,
    163145      RTEMS_MONITOR_OBJECT_TASK,
     146      &rtems_monitor_commands[10],
    164147    },
    165148    { "queue",
    166       "queue [id [id ... ] ]\n"
    167       "  display information about the specified message queues\n"
    168       "  Default is to display information about all queues on this node\n",
     149      "Display information about the specified message queues. "
     150      "Default is to display information about all queues on this node.\n"
     151      "  queue [id [id ... ] ]",
    169152      0,
    170153      rtems_monitor_object_cmd,
    171154      RTEMS_MONITOR_OBJECT_QUEUE,
     155      &rtems_monitor_commands[11],
    172156    },
    173157    { "object",
    174       "object [id [id ...] ]\n"
    175       "  display information about specified RTEMS objects.\n"
    176       "  Object id's must include 'type' information.\n"
    177       "  (which may normally be defaulted)\n",
     158      "Display information about specified RTEMS objects. "
     159      "Object id's must include 'type' information. "
     160      "(which may normally be defaulted)\n"
     161      "  object [id [id ...] ]",
    178162      0,
    179163      rtems_monitor_object_cmd,
    180164      RTEMS_MONITOR_OBJECT_INVALID,
     165      &rtems_monitor_commands[12],
    181166    },
    182167    { "driver",
    183       "driver [ major [ major ... ] ]\n"
    184       "  Display the RTEMS device driver table.\n",
     168      "Display the RTEMS device driver table.\n"
     169      "  driver [ major [ major ... ] ]",
    185170      0,
    186171      rtems_monitor_object_cmd,
    187172      RTEMS_MONITOR_OBJECT_DRIVER,
     173      &rtems_monitor_commands[13],
    188174    },
    189175    { "dname",
    190       "dname\n"
    191       "  Displays information about named drivers.\n",
     176      "Displays information about named drivers.\n",
    192177      0,
    193178      rtems_monitor_object_cmd,
    194179      RTEMS_MONITOR_OBJECT_DNAME,
     180      &rtems_monitor_commands[14],
    195181    },
    196182    { "exit",
    197       "exit [status]\n"
    198       "  Invoke 'rtems_fatal_error_occurred' with 'status'\n"
    199       "  (default is RTEMS_SUCCESSFUL)\n",
     183      "Invoke 'rtems_fatal_error_occurred' with 'status' "
     184      "(default is RTEMS_SUCCESSFUL)\n"
     185      "  exit [status]",
    200186      0,
    201187      rtems_monitor_fatal_cmd,
    202188      RTEMS_SUCCESSFUL,
     189      &rtems_monitor_commands[15],
    203190    },
    204191    { "fatal",
    205       "fatal [status]\n"
    206       "  'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n",
     192      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
     193      "  fatal [status]",
    207194      0,
    208195      rtems_monitor_fatal_cmd,
    209196      RTEMS_TASK_EXITTED,                       /* exit value */
     197      &rtems_monitor_commands[16],
    210198    },
    211199    { "quit",
    212       "quit [status]\n"
    213       "  Alias for 'exit'\n",
     200      "Alias for 'exit'\n",
    214201      0,
    215202      rtems_monitor_fatal_cmd,
    216203      RTEMS_SUCCESSFUL,                         /* exit value */
     204      &rtems_monitor_commands[17],
    217205    },
    218206    { "help",
    219       "help [ command [ command ] ]\n"
    220       "  provide information about commands\n"
    221       "  Default is show basic command summary.\n",
     207      "Provide information about commands. "
     208      "Default is show basic command summary.\n"
     209      "help [ command [ command ] ]",
    222210      0,
    223211      rtems_monitor_help_cmd,
    224212      (unsigned32) rtems_monitor_commands,
     213      &rtems_monitor_commands[18],
    225214    },
    226215#ifdef CPU_INVOKE_DEBUGGER
    227216    { "debugger",
    228       "debugger\n"
    229       "  Enter the debugger, if possible.\n"
    230       "  A continue from the debugger will return to the monitor.\n",
     217      "Enter the debugger, if possible. "
     218      "A continue from the debugger will return to the monitor.\n",
    231219      0,
    232220      rtems_monitor_debugger_cmd,
    233221      0,
     222      &rtems_monitor_commands[19],
    234223    },
    235224#endif           
    236     { 0, 0, 0, 0, 0 },
     225    { 0, 0, 0, 0, 0, &rtems_registered_commands },
    237226};
    238227
     
    419408}
    420409
     410/*
     411 * User registered commands.
     412 */
     413
     414int
     415rtems_monitor_insert_cmd (
     416    rtems_monitor_command_entry_t *command
     417)
     418{
     419    rtems_monitor_command_entry_t *p = rtems_registered_commands.next;
     420
     421    command->next = 0;
     422
     423    if (rtems_registered_commands.next)
     424    {
     425        for (; p->next; p = p->next)
     426        {
     427            if (STREQ(command->command, p->command))
     428                return 0;
     429        }
     430        p->next = command;
     431    }
     432    else
     433        rtems_registered_commands.next = command;
     434 
     435    return 1;
     436}
     437
     438int
     439rtems_monitor_erase_cmd (
     440    rtems_monitor_command_entry_t *command
     441)
     442{
     443    rtems_monitor_command_entry_t *p;
     444    rtems_monitor_command_entry_t **p_prev = &rtems_registered_commands.next;
     445
     446    if (rtems_registered_commands.next)
     447    {
     448        for (p = rtems_registered_commands.next; p->next; p = p->next)
     449        {
     450            if (STREQ(command->command, p->command))
     451            {
     452                *p_prev = p->next;
     453                return 1;
     454            }
     455            p_prev = &p->next;
     456        }
     457    }
     458    return 0;
     459}
    421460
    422461/*
     
    436475    char *argv[64];       
    437476    boolean verbose = FALSE;
    438 
     477    struct termios term;
     478
     479    /*
     480     * Make the stdin stream characte not line based.
     481     */
     482   
     483    if (tcgetattr (STDIN_FILENO, &term) < 0)
     484    {
     485      printf("rtems-monitor: cannot get terminal attributes.\n");
     486    }
     487    else
     488    {
     489      /*
     490       * No echo, no canonical processing.
     491       */
     492
     493      term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
     494 
     495      /*
     496       * No sigint on BREAK, CR-to-NL off, input parity off,
     497       * don't strip 8th bit on input, output flow control off
     498       */
     499
     500      term.c_lflag    &= ~(INPCK | ISTRIP | IXON);
     501      term.c_cc[VMIN]  = 1;
     502      term.c_cc[VTIME] = 0;
     503
     504      if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
     505      {
     506        printf("cannot set terminal attributes\n");
     507      }
     508    }
     509   
    439510    if (monitor_flags & RTEMS_MONITOR_SUSPEND)
    440511        (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
     
    454525                                                    argc,
    455526                                                    argv)) == 0)
     527        {
     528            /* no command */
     529            printf("Unrecognised command; try 'help'\n");
    456530            continue;
     531        }
    457532
    458533        command->command_function(argc, argv, command->command_arg, verbose);
  • c/src/libmisc/monitor/monitor.h

    r6f93bb4 r32e2554  
    295295    unsigned32   arguments_required;    /* # of required args */
    296296    rtems_monitor_command_function_t command_function;
    297 
    298297                               /* Some argument for the command */
    299     unsigned32          command_arg;
     298    unsigned32   command_arg;
     299    struct rtems_monitor_command_entry_s *next;
    300300};
    301301
     
    326326void    rtems_monitor_node_cmd(int, char **, unsigned32, boolean);
    327327void    rtems_monitor_symbols_loadup(void);
     328int     rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
     329int     rtems_monitor_erase_cmd(rtems_monitor_command_entry_t *);
     330
    328331void    rtems_monitor_task(rtems_task_argument);
    329332
  • cpukit/libmisc/monitor/mon-command.c

    r6f93bb4 r32e2554  
    1515
    1616/*
     17 * CCJ: 26-3-2000, adding command history and command line
     18 * editing. This code is donated from My Right Boot and not
     19 * covered by GPL, only the RTEMS license.
     20 */
     21
     22/*
     23 * Some key labels to define special keys.
     24 */
     25
     26#define KEYS_EXTENDED    (0x8000)
     27#define KEYS_NORMAL_MASK (0x00ff)
     28#define KEYS_INS         (0)
     29#define KEYS_DEL         (1)
     30#define KEYS_UARROW      (2)
     31#define KEYS_DARROW      (3)
     32#define KEYS_LARROW      (4)
     33#define KEYS_RARROW      (5)
     34#define KEYS_HOME        (6)
     35#define KEYS_END         (7)
     36#define KEYS_F1          (8)
     37#define KEYS_F2          (9)
     38#define KEYS_F3          (10)
     39#define KEYS_F4          (11)
     40#define KEYS_F5          (12)
     41#define KEYS_F6          (13)
     42#define KEYS_F7          (14)
     43#define KEYS_F8          (15)
     44#define KEYS_F9          (16)
     45#define KEYS_F10         (17)
     46
     47#define RTEMS_COMMAND_BUFFER_SIZE (75)
     48
     49static char monitor_prompt[32];
     50static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
     51static int  pos;
     52static int  logged_in;
     53
     54/*
     55 * History data.
     56 */
     57
     58#define RTEMS_COMMAND_HISTORIES (20)
     59
     60static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
     61static int  history_pos[RTEMS_COMMAND_HISTORIES];
     62static int  history;
     63static int  history_next;
     64
     65/*
     66 * Translation tables. Not sure if this is the best way to
     67 * handle this, how-ever I wish to avoid the overhead of
     68 * including a more complete and standard environment such
     69 * as ncurses.
     70 */
     71
     72struct translation_table
     73{
     74  char                     expecting;
     75  struct translation_table *branch;
     76  unsigned int             key;
     77};
     78
     79static struct translation_table trans_two[] =
     80{
     81  { '~', 0, KEYS_INS },
     82  { 0,   0, 0 }
     83};
     84
     85static struct translation_table trans_three[] =
     86{
     87  { '~', 0, KEYS_DEL },
     88  { 0,   0, 0 }
     89};
     90
     91static struct translation_table trans_tab_csi[] =
     92{
     93  { '2', trans_two,   0 },
     94  { '3', trans_three, 0 },
     95  { 'A', 0,           KEYS_UARROW },
     96  { 'B', 0,           KEYS_DARROW },
     97  { 'D', 0,           KEYS_LARROW },
     98  { 'C', 0,           KEYS_RARROW },
     99  { 'F', 0,           KEYS_END },
     100  { 'H', 0,           KEYS_HOME },
     101  { 0,   0,           0 }
     102};
     103
     104static struct translation_table trans_tab_O[] =
     105{
     106  { '1', 0, KEYS_F1 },
     107  { '2', 0, KEYS_F2 },
     108  { '3', 0, KEYS_F3 },
     109  { '4', 0, KEYS_F4 },
     110  { '5', 0, KEYS_F5 },
     111  { '6', 0, KEYS_F6 },
     112  { '7', 0, KEYS_F7 },
     113  { '8', 0, KEYS_F8 },
     114  { '9', 0, KEYS_F9 },
     115  { ':', 0, KEYS_F10 },
     116  { 'P', 0, KEYS_F1 },
     117  { 'Q', 0, KEYS_F2 },
     118  { 'R', 0, KEYS_F3 },
     119  { 'S', 0, KEYS_F4 },
     120  { 'T', 0, KEYS_F5 },
     121  { 'U', 0, KEYS_F6 },
     122  { 'V', 0, KEYS_F7 },
     123  { 'W', 0, KEYS_F8 },
     124  { 'X', 0, KEYS_F9 },
     125  { 'Y', 0, KEYS_F10 },
     126  { 0,   0, 0 }
     127};
     128
     129static struct translation_table trans_tab[] =
     130{
     131  { '[', trans_tab_csi, 0 },    /* CSI command sequences */
     132  { 'O', trans_tab_O,   0 },    /* O are the fuction keys */
     133  { 0,   0,             0 }
     134};
     135
     136/*
     137 * Perform a basic tranlation for some ANSI/VT100 key codes.
     138 * This code could do with a timeout on the ESC as it is
     139 * now lost from the input stream. It is not* used by the
     140 * line editor below so considiered not worth the effort.
     141 */
     142
     143static unsigned int
     144rtems_monitor_getchar (
     145)
     146{
     147  struct translation_table *translation = 0;
     148  for (;;)
     149  {
     150    char c = getchar ();
     151    if (c == 27)
     152      translation = trans_tab;
     153    else
     154    {
     155      /*
     156       * If no translation happing just pass through
     157       * and return the key.
     158       */
     159      if (translation)
     160      {
     161        /*
     162         * Scan the current table for the key, and if found
     163         * see if this key is a fork. If so follow it and
     164         * wait else return the extended key.
     165         */
     166        int index    = 0;
     167        int branched = 0;
     168        while ((translation[index].expecting != '\0') ||
     169               (translation[index].key != '\0'))
     170        {
     171          if (translation[index].expecting == c)
     172          {
     173            /*
     174             * A branch is take if more keys are to come.
     175             */
     176            if (translation[index].branch == 0)
     177              return KEYS_EXTENDED | translation[index].key;
     178            else
     179            {
     180              translation = translation[index].branch;
     181              branched    = 1;
     182              break;
     183            }
     184          }
     185          index++;
     186        }
     187        /*
     188         * Who knows what these keys are, just drop them.
     189         */
     190        if (!branched)
     191          translation = 0;
     192      }
     193      else
     194        return c;
     195    }
     196  }
     197}
     198
     199/*
     200 * The line editor with history.
     201 */
     202
     203static int
     204rtems_monitor_line_editor (
     205    char *command
     206)
     207{
     208  int repeating = 0;
     209
     210  memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
     211  history = history_next;
     212  pos     = 0;
     213         
     214  if (!logged_in)
     215    printf ("\nMonitor ready, press enter to login.\n\n");
     216  else
     217    printf ("%s $ ", monitor_prompt);
     218
     219  while (1)
     220  {
     221    unsigned int extended_key = rtems_monitor_getchar ();
     222    char         c = extended_key & KEYS_NORMAL_MASK;
     223
     224    /*
     225     * Make the extended_key usable as a boolean.
     226     */
     227    extended_key &= ~KEYS_NORMAL_MASK;
     228   
     229    if (!extended_key && !logged_in)
     230    {
     231      if (c == '\n')
     232      {
     233        logged_in = 1;
     234        /*
     235         * The prompt has changed from `>' to `$' to help know
     236         * which version of the monitor code people are using.
     237         */
     238        printf("%s $ ", monitor_prompt);
     239      }
     240    }
     241    else
     242    {
     243      if (extended_key)
     244      {
     245        switch (c)
     246        {
     247          case KEYS_END:
     248            printf (buffer + pos);
     249            pos = (int) strlen (buffer);
     250            break;
     251
     252          case KEYS_HOME:
     253            printf ("\r%s $ ", monitor_prompt);
     254            pos = 0;
     255            break;
     256       
     257          case KEYS_LARROW:
     258            if (pos > 0)
     259            {
     260              pos--;
     261              putchar ('\b');
     262            }
     263            break;
     264
     265          case KEYS_RARROW:
     266            if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
     267            {
     268              putchar (buffer[pos]);
     269              pos++;
     270            }
     271            break;
     272
     273          case KEYS_UARROW:
     274            /*
     275             * If we are moving up the histories then we need to save the working
     276             * buffer.
     277             */
     278            if (history)
     279            {
     280              int end;
     281              int bs;
     282              if (history == history_next)
     283              {
     284                memcpy (history_buffer[history_next], buffer,
     285                        RTEMS_COMMAND_BUFFER_SIZE);
     286                history_pos[history_next] = pos;
     287              }
     288              history--;
     289              memcpy (buffer, history_buffer[history],
     290                      RTEMS_COMMAND_BUFFER_SIZE);
     291              pos = history_pos[history];
     292              printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
     293              printf ("\r%s $ %s", monitor_prompt, buffer);
     294              end = (int) strlen (buffer);
     295              for (bs = 0; bs < (end - pos); bs++)
     296                putchar ('\b');
     297            }
     298            break;
     299                 
     300          case KEYS_DARROW:
     301            if (history < history_next)
     302            {
     303              int end;
     304              int bs;
     305              history++;
     306              memcpy (buffer, history_buffer[history],
     307                      RTEMS_COMMAND_BUFFER_SIZE);
     308              pos = history_pos[history];
     309              printf ("\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
     310              printf ("\r%s $ %s", monitor_prompt, buffer);
     311              end = (int) strlen (buffer);
     312              for (bs = 0; bs < (end - pos); bs++)
     313                putchar ('\b');
     314            }
     315            break;
     316
     317          case KEYS_DEL:
     318            if (buffer[pos] != '\0')
     319            {
     320              int end;
     321              int bs;
     322              strcpy (&buffer[pos], &buffer[pos + 1]);
     323              printf ("\r%s $ %s", monitor_prompt, buffer);
     324              end = (int) strlen (buffer);
     325              for (bs = 0; bs < (end - pos); bs++)
     326                putchar ('\b');
     327            }
     328            break;
     329        }
     330      }
     331      else
     332      {
     333        switch (c)
     334        {
     335          case '\b':
     336          case '\x7e':
     337          case '\x7f':
     338            if (pos > 0)
     339            {
     340              int bs;
     341              pos--;
     342              strcpy (buffer + pos, buffer + pos + 1);
     343              printf ("\b%s \b", buffer + pos);
     344              for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
     345                putchar ('\b');
     346            }
     347            break;
     348
     349          case '\n':
     350            /*
     351             * Process the command.
     352             */
     353            printf ("\n");
     354            repeating = 1;
     355            /*
     356             * Only process the history if we have a command and
     357             *a history.
     358             */
     359            if (strlen (buffer))
     360            {
     361              if (history_next && (history == history_next))
     362              {
     363                /*
     364                 * Do not place the last command into the history
     365                 *if the same.
     366                 */
     367                if (strcmp (history_buffer[history_next - 1], buffer))
     368                  repeating = 0;
     369              }
     370              else
     371                repeating = 0;
     372            }
     373            if (!repeating)
     374            {
     375              memcpy (history_buffer[history_next], buffer,
     376                      RTEMS_COMMAND_BUFFER_SIZE);
     377              history_pos[history_next] = pos;
     378              if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
     379                history_next++;
     380              else
     381              {
     382                memmove (history_buffer[0], history_buffer[1],
     383                         RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
     384                memmove (&history_pos[0], &history_pos[1],
     385                         sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
     386              }
     387            }
     388            else
     389            {
     390              if (history_next)
     391                memcpy (buffer, history_buffer[history_next - 1],
     392                        RTEMS_COMMAND_BUFFER_SIZE);
     393            }
     394            memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
     395            return repeating;
     396            break;
     397
     398          default:
     399            if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
     400                (c >= ' ') && (c <= 'z'))
     401            {
     402              int end;
     403              if (c >= 'A' && c <= 'Z')
     404                c += 'a' - 'A';
     405              end = strlen (buffer);
     406              if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
     407              {
     408                int ch, bs;
     409                for (ch = end + 1; ch > pos; ch--)
     410                  buffer[ch] = buffer[ch - 1];
     411                printf (buffer + pos);
     412                for (bs = 0; bs < (end - pos + 1); bs++)
     413                  putchar ('\b');
     414              }
     415              buffer[pos++] = c;
     416              if (pos > end)
     417                buffer[pos] = '\0';
     418              putchar (c);
     419            }
     420            break;
     421        }
     422      }
     423    }
     424  }
     425}
     426
     427/*
    17428 * make_argv(cp): token-count
    18  *      Break up the command line in 'cp' into global argv[] and argc (return
    19  *      value).
     429 *  Break up the command line in 'cp' into global argv[] and argc (return
     430 *  value).
    20431 */
    21432
     
    26437    char **argv)
    27438{
    28     int argc = 0;
    29 
    30     while ((cp = strtok(cp, " \t\n\r")))
    31     {
    32         argv[argc++] = cp;
    33         cp = (char *) NULL;
    34     }
    35     argv[argc] = (char *) NULL;                 /* end of argv */
    36 
    37     return *argc_p = argc;
     439  int argc = 0;
     440
     441  while ((cp = strtok(cp, " \t\n\r")))
     442  {
     443    argv[argc++] = cp;
     444    cp = (char *) NULL;
     445  }
     446  argv[argc] = (char *) NULL;      /* end of argv */
     447
     448  return *argc_p = argc;
    38449}
    39450
     
    51462                           char **argv)
    52463{
    53     static char monitor_prompt[32];
    54    
    55     /*
    56      * put node number in the prompt if we are multiprocessing
    57      */
    58 
    59     if (!rtems_configuration_get_user_multiprocessing_table())
    60         sprintf(monitor_prompt, "%s", MONITOR_PROMPT);
    61     else if (rtems_monitor_default_node != rtems_monitor_node)
    62         sprintf(monitor_prompt, "%d-%s-%d", rtems_monitor_node, MONITOR_PROMPT, rtems_monitor_default_node);
    63     else
    64         sprintf(monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
     464  /*
     465   * put node number in the prompt if we are multiprocessing
     466   */
     467
     468  if (!rtems_configuration_get_user_multiprocessing_table ())
     469    sprintf (monitor_prompt, "%s", MONITOR_PROMPT);
     470  else if (rtems_monitor_default_node != rtems_monitor_node)
     471    sprintf (monitor_prompt, "%d-%s-%d", rtems_monitor_node,
     472             MONITOR_PROMPT, rtems_monitor_default_node);
     473  else
     474    sprintf (monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
    65475
    66476#ifdef RTEMS_UNIX
    67     /* RTEMS on unix gets so many interrupt system calls this is hosed */
    68     printf("%s> ", monitor_prompt);
    69     fflush(stdout);
    70     while (gets(command) == (char *) 0)
    71         ;
     477  /* RTEMS on unix gets so many interrupt system calls this is hosed */
     478  printf ("%s> ", monitor_prompt);
     479  fflush (stdout);
     480  while (gets(command) == (char *) 0)
     481    ;
    72482#else
    73     do
    74     {
    75         printf("%s> ", monitor_prompt);
    76         fflush(stdout);
    77     } while (gets(command) == (char *) 0);
     483  rtems_monitor_line_editor (command);
    78484#endif
    79485
    80     return rtems_monitor_make_argv(command, argc, argv);
     486  return rtems_monitor_make_argv (command, argc, argv);
    81487}
    82488
     
    93499)
    94500{
    95     rtems_monitor_command_entry_t *p;
    96     rtems_monitor_command_entry_t *abbreviated_match = 0;
    97     int abbreviated_matches = 0;
    98     char *command;
    99     int command_length;
    100 
    101     command = argv[0];
    102 
    103     if ((table == 0) || (command == 0))
    104         goto failed;
     501  char *command;
     502
     503  command = argv[0];
     504
     505  if ((table == 0) || (command == 0))
     506    return 0;
    105507   
    106     command_length = strlen(command);
    107 
    108     for (p = table; p->command; p++)
    109         if (STREQ(command, p->command))    /* exact match */
    110             goto done;
    111         else if (STRNEQ(command, p->command, command_length))
     508  while (table)
     509  {
     510    if (table->command)
     511    {
     512      if (STREQ (command, table->command))  /* exact match */
     513      {
     514        if (table->command_function == 0)
     515          return 0;
     516        return table;
     517      }
     518    }
     519    table = table->next;
     520  }
     521
     522  return 0;
     523}
     524
     525void
     526rtems_monitor_show_help (
     527  rtems_monitor_command_entry_t *help_cmd,
     528  int                           max_cmd_len
     529)
     530{
     531#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
     532
     533  if (help_cmd && help_cmd->command)
     534  {
     535    const char *help = help_cmd->usage;
     536    int         help_len = strlen (help);
     537    int         spaces = max_cmd_len - strlen (help_cmd->command);
     538    int         show_this_line = 0;
     539    int         line_one = 1;
     540    int         c;
     541
     542    printf ("%s", help_cmd->command);
     543
     544    if (help_len == 0)
     545    {
     546      printf (" - No help associated.\n");
     547      return;
     548    }
     549 
     550    while (help_len)
     551    {
     552      printf ("%*c", spaces, ' ');
     553     
     554      if (line_one)
     555        printf (" - ");
     556
     557      spaces   = max_cmd_len + 2;
     558      line_one = 0;
     559
     560      /*
     561       * See if greater then the line length if so, work back
     562       * from the end for a space, tab or lf or cr.
     563       */
     564     
     565      if (help_len > MAX_HELP_LINE_LENGTH)
     566      {
     567        for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
     568             show_this_line;
     569             show_this_line--)
     570          if ((help[show_this_line] == ' ') ||
     571              (help[show_this_line] == '\n') ||
     572              (help[show_this_line] == '\r'))
     573            break;
     574
     575        /*
     576         * If show_this_line is 0, it is a very long word !!
     577         */
     578     
     579        if (show_this_line == 0)
     580          show_this_line = MAX_HELP_LINE_LENGTH - 1;
     581      }
     582      else
     583        show_this_line = help_len;
     584
     585      for (c = 0; c < show_this_line; c++)
     586        if ((help[c] == '\r') || (help[c] == '\n'))
     587          show_this_line = c;
     588        else
     589          putchar (help[c]);
     590
     591      printf ("\n");
     592                 
     593      help     += show_this_line;
     594      help_len -= show_this_line;
     595
     596      /*
     597       * Move past the line feeds or what ever else is being skipped.
     598       */
     599   
     600      while (help_len)
     601      {
     602        if ((*help != '\r') && (*help != '\n'))
     603          break;
     604
     605        if (*help != ' ')
    112606        {
    113             abbreviated_matches++;
    114             abbreviated_match = p;
     607          help++;
     608          help_len--;
     609          break;
    115610        }
    116 
    117     /* no perfect match; is there a non-ambigous abbreviated match? */
    118     if ( ! abbreviated_match)
    119     {
    120         printf("Unrecognized command '%s'; try 'help'\n", command);
    121         goto failed;
    122     }   
    123 
    124     if (abbreviated_matches > 1)
    125     {
    126         printf("Command '%s' is ambiguous; try 'help'\n", command);
    127         goto failed;
     611        help++;
     612        help_len--;
     613      }
    128614    }
     615  }
     616}
     617
     618void
     619rtems_monitor_command_usage(
     620  rtems_monitor_command_entry_t *table,
     621  char                          *command_string
     622)
     623{
     624  rtems_monitor_command_entry_t *command = table;
     625  int                           max_cmd_len = 0;
    129626   
    130     p = abbreviated_match;
    131 
    132 done:
    133     if (p->command_function == 0)
    134         goto failed;
    135     return p;
    136 
    137 failed:
    138     return 0;
    139 }
    140 
    141 void
    142 rtems_monitor_command_usage(rtems_monitor_command_entry_t *table,
    143                             char *command_string)
    144 {
    145     rtems_monitor_command_entry_t *help = 0;
    146     char *help_command_argv[2];
     627  /* if first entry in table is a usage, then print it out */
     628
     629  if (command_string && (*command_string != '\0'))
     630  {
     631    char *argv[2];
    147632   
    148     /* if first entry in table is a usage, then print it out */
    149     if (command_string == 0)
    150     {       
    151         if (STREQ(table->command, "--usage--") && table->usage)
    152             help = table;
    153     }
     633    argv[0] = command_string;
     634    argv[1] = 0;
     635   
     636    command = rtems_monitor_command_lookup (table, 1, argv);
     637
     638    if (command)
     639      rtems_monitor_show_help (command, strlen (command_string));
    154640    else
    155     {
    156         help_command_argv[0] = command_string;
    157         help_command_argv[1] = 0;
    158         help = rtems_monitor_command_lookup(table, 1, help_command_argv);
    159     }
    160 
    161     if (help)
    162         printf("%s\n", help->usage);
     641      printf ("Unrecognised command; try just 'help'\n");
     642    return;
     643  }
     644 
     645  /*
     646   * Find the largest command size.
     647   */
     648 
     649  while (command)
     650  {
     651    int len = strlen (command->command);
     652
     653    if (len > max_cmd_len)
     654      max_cmd_len = len;
     655
     656    command = command->next;
     657  }
     658
     659  max_cmd_len++;
     660
     661  command = table;
     662
     663  /*
     664   * Now some nice formatting for the help.
     665   */
     666
     667  while (command)
     668  {
     669    rtems_monitor_show_help (command, max_cmd_len);
     670    command = command->next;
     671  }
    163672}
    164673
     
    172681)
    173682{
    174     int arg;
    175     rtems_monitor_command_entry_t *command;
    176 
    177     command = (rtems_monitor_command_entry_t *) command_arg;
     683  int arg;
     684  rtems_monitor_command_entry_t *command;
     685
     686  command = (rtems_monitor_command_entry_t *) command_arg;
    178687   
    179     if (argc == 1)
    180         rtems_monitor_command_usage(command, 0);
    181     else
    182     {
    183         for (arg=1; argv[arg]; arg++)
    184             rtems_monitor_command_usage(command, argv[arg]);
    185     }
    186 }
     688  if (argc == 1)
     689    rtems_monitor_command_usage(command, 0);
     690  else
     691  {
     692    for (arg = 1; argv[arg]; arg++)
     693      rtems_monitor_command_usage(command, argv[arg]);
     694  }
     695}
  • cpukit/libmisc/monitor/mon-monitor.c

    r6f93bb4 r32e2554  
    2828#include <string.h>
    2929#include <stdlib.h>
     30#include <termios.h>
    3031#include <unistd.h>
    3132
     
    5556
    5657/*
     58 * User registered commands.
     59 */
     60
     61rtems_monitor_command_entry_t rtems_registered_commands;
     62
     63/*
    5764 * The top-level commands
    5865 */
    5966
    6067rtems_monitor_command_entry_t rtems_monitor_commands[] = {
    61     { "--usage--",
    62       "\n"
    63       "RTEMS monitor\n"
    64       "\n"
    65       "Commands (may be abbreviated)\n"
    66       "\n"
    67       "  help      -- get this message or command specific help\n"
    68       "  pause     -- pause monitor for a specified number of ticks\n"
    69       "  exit      -- invoke a fatal RTEMS error\n"
    70       "  symbol    -- show entries from symbol table\n"
    71       "  continue  -- put monitor to sleep waiting for explicit wakeup\n"
    72       "  config    -- show system configuration\n"
    73       "  itask     -- list init tasks\n"
    74       "  mpci      -- list mpci config\n"
    75       "  task      -- show task information\n"
    76       "  queue     -- show message queue information\n"
    77       "  extension -- user extensions\n"
    78       "  driver    -- show information about named drivers\n"
    79       "  dname     -- show information about named drivers\n"
    80       "  object    -- generic object information\n"
    81       "  node      -- specify default node for commands that take id's\n"
    82 #ifdef CPU_INVOKE_DEBUGGER
    83       "  debugger  -- invoke system debugger\n"
    84 #endif
    85       ,
    86       0,
    87       0,
    88       (unsigned32) rtems_monitor_commands,
    89     },
    9068    { "config",
    91       "config\n"
    92       "  Show the system configuration.\n",
     69      "Show the system configuration.",
    9370      0,
    9471      rtems_monitor_object_cmd,
    9572      RTEMS_MONITOR_OBJECT_CONFIG,
     73      &rtems_monitor_commands[1],
    9674    },
    9775    { "itask",
    98       "itask\n"
    99       "  List init tasks for the system\n",
     76      "List init tasks for the system",
    10077      0,
    10178      rtems_monitor_object_cmd,
    10279      RTEMS_MONITOR_OBJECT_INIT_TASK,
     80      &rtems_monitor_commands[2],
    10381    },
    10482   { "mpci",
    105       "mpci\n"
    106       "  Show the MPCI system configuration, if configured.\n",
     83      "Show the MPCI system configuration, if configured.",
    10784      0,
    10885      rtems_monitor_object_cmd,
    10986      RTEMS_MONITOR_OBJECT_MPCI,
     87      &rtems_monitor_commands[3],
    11088    },
    11189    { "pause",
    112       "pause [ticks]\n"
    113       "  monitor goes to \"sleep\" for specified ticks (default is 1)\n"
    114       "  monitor will resume at end of period or if explicitly awakened\n",
     90      "Monitor goes to \"sleep\" for specified ticks (default is 1). "
     91      "Monitor will resume at end of period or if explicitly awakened\n"
     92      "  pause [ticks]",
    11593      0,
    11694      rtems_monitor_pause_cmd,
    11795      0,
     96      &rtems_monitor_commands[4],
    11897    },
    11998    { "continue",
    120       "continue\n"
    121       "  put the monitor to sleep waiting for an explicit wakeup from the\n"
    122       "  program running.\n",
     99      "Put the monitor to sleep waiting for an explicit wakeup from the "
     100      "program running.\n",
    123101      0,
    124102      rtems_monitor_continue_cmd,
    125103      0,
     104      &rtems_monitor_commands[5],
    126105    },
    127106    { "go",
    128       "go\n"
    129       "  Alias for 'continue'\n",
     107      "Alias for 'continue'",
    130108      0,
    131109      rtems_monitor_continue_cmd,
    132110      0,
     111      &rtems_monitor_commands[6],
    133112    },
    134113    { "node",
    135       "node [ node number ]\n"
    136       "  Specify default node number for commands that take id's\n",
     114      "Specify default node number for commands that take id's.\n"
     115      "  node [ node number ]",
    137116      0,
    138117      rtems_monitor_node_cmd,
    139118      0,
     119      &rtems_monitor_commands[7],
    140120    },
    141121    { "symbol",
    142       "symbol [ symbolname [symbolname ... ] ]\n"
    143       "  display value associated with specified symbol.\n"
    144       "  Defaults to displaying all known symbols.\n",
     122      "Display value associated with specified symbol. "
     123      "Defaults to displaying all known symbols.\n"
     124      "  symbol [ symbolname [symbolname ... ] ]",
    145125      0,
    146126      rtems_monitor_symbol_cmd,
    147127      (unsigned32) &rtems_monitor_symbols,
     128      &rtems_monitor_commands[8],
    148129    },
    149130    { "extension",
    150       "extension [id [id ...] ]\n"
    151       "  display information about specified extensions.\n"
    152       "  Default is to display information about all extensions on this node\n",
     131      "Display information about specified extensions. "
     132      "Default is to display information about all extensions on this node.\n"
     133      "  extension [id [id ...] ]",
    153134      0,
    154135      rtems_monitor_object_cmd,
    155136      RTEMS_MONITOR_OBJECT_EXTENSION,
     137      &rtems_monitor_commands[9],
    156138    },
    157139    { "task",
    158       "task [id [id ...] ]\n"
    159       "  display information about the specified tasks.\n"
    160       "  Default is to display information about all tasks on this node\n",
     140      "Display information about the specified tasks. "
     141      "Default is to display information about all tasks on this node.\n"
     142      "  task [id [id ...] ]",
    161143      0,
    162144      rtems_monitor_object_cmd,
    163145      RTEMS_MONITOR_OBJECT_TASK,
     146      &rtems_monitor_commands[10],
    164147    },
    165148    { "queue",
    166       "queue [id [id ... ] ]\n"
    167       "  display information about the specified message queues\n"
    168       "  Default is to display information about all queues on this node\n",
     149      "Display information about the specified message queues. "
     150      "Default is to display information about all queues on this node.\n"
     151      "  queue [id [id ... ] ]",
    169152      0,
    170153      rtems_monitor_object_cmd,
    171154      RTEMS_MONITOR_OBJECT_QUEUE,
     155      &rtems_monitor_commands[11],
    172156    },
    173157    { "object",
    174       "object [id [id ...] ]\n"
    175       "  display information about specified RTEMS objects.\n"
    176       "  Object id's must include 'type' information.\n"
    177       "  (which may normally be defaulted)\n",
     158      "Display information about specified RTEMS objects. "
     159      "Object id's must include 'type' information. "
     160      "(which may normally be defaulted)\n"
     161      "  object [id [id ...] ]",
    178162      0,
    179163      rtems_monitor_object_cmd,
    180164      RTEMS_MONITOR_OBJECT_INVALID,
     165      &rtems_monitor_commands[12],
    181166    },
    182167    { "driver",
    183       "driver [ major [ major ... ] ]\n"
    184       "  Display the RTEMS device driver table.\n",
     168      "Display the RTEMS device driver table.\n"
     169      "  driver [ major [ major ... ] ]",
    185170      0,
    186171      rtems_monitor_object_cmd,
    187172      RTEMS_MONITOR_OBJECT_DRIVER,
     173      &rtems_monitor_commands[13],
    188174    },
    189175    { "dname",
    190       "dname\n"
    191       "  Displays information about named drivers.\n",
     176      "Displays information about named drivers.\n",
    192177      0,
    193178      rtems_monitor_object_cmd,
    194179      RTEMS_MONITOR_OBJECT_DNAME,
     180      &rtems_monitor_commands[14],
    195181    },
    196182    { "exit",
    197       "exit [status]\n"
    198       "  Invoke 'rtems_fatal_error_occurred' with 'status'\n"
    199       "  (default is RTEMS_SUCCESSFUL)\n",
     183      "Invoke 'rtems_fatal_error_occurred' with 'status' "
     184      "(default is RTEMS_SUCCESSFUL)\n"
     185      "  exit [status]",
    200186      0,
    201187      rtems_monitor_fatal_cmd,
    202188      RTEMS_SUCCESSFUL,
     189      &rtems_monitor_commands[15],
    203190    },
    204191    { "fatal",
    205       "fatal [status]\n"
    206       "  'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n",
     192      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
     193      "  fatal [status]",
    207194      0,
    208195      rtems_monitor_fatal_cmd,
    209196      RTEMS_TASK_EXITTED,                       /* exit value */
     197      &rtems_monitor_commands[16],
    210198    },
    211199    { "quit",
    212       "quit [status]\n"
    213       "  Alias for 'exit'\n",
     200      "Alias for 'exit'\n",
    214201      0,
    215202      rtems_monitor_fatal_cmd,
    216203      RTEMS_SUCCESSFUL,                         /* exit value */
     204      &rtems_monitor_commands[17],
    217205    },
    218206    { "help",
    219       "help [ command [ command ] ]\n"
    220       "  provide information about commands\n"
    221       "  Default is show basic command summary.\n",
     207      "Provide information about commands. "
     208      "Default is show basic command summary.\n"
     209      "help [ command [ command ] ]",
    222210      0,
    223211      rtems_monitor_help_cmd,
    224212      (unsigned32) rtems_monitor_commands,
     213      &rtems_monitor_commands[18],
    225214    },
    226215#ifdef CPU_INVOKE_DEBUGGER
    227216    { "debugger",
    228       "debugger\n"
    229       "  Enter the debugger, if possible.\n"
    230       "  A continue from the debugger will return to the monitor.\n",
     217      "Enter the debugger, if possible. "
     218      "A continue from the debugger will return to the monitor.\n",
    231219      0,
    232220      rtems_monitor_debugger_cmd,
    233221      0,
     222      &rtems_monitor_commands[19],
    234223    },
    235224#endif           
    236     { 0, 0, 0, 0, 0 },
     225    { 0, 0, 0, 0, 0, &rtems_registered_commands },
    237226};
    238227
     
    419408}
    420409
     410/*
     411 * User registered commands.
     412 */
     413
     414int
     415rtems_monitor_insert_cmd (
     416    rtems_monitor_command_entry_t *command
     417)
     418{
     419    rtems_monitor_command_entry_t *p = rtems_registered_commands.next;
     420
     421    command->next = 0;
     422
     423    if (rtems_registered_commands.next)
     424    {
     425        for (; p->next; p = p->next)
     426        {
     427            if (STREQ(command->command, p->command))
     428                return 0;
     429        }
     430        p->next = command;
     431    }
     432    else
     433        rtems_registered_commands.next = command;
     434 
     435    return 1;
     436}
     437
     438int
     439rtems_monitor_erase_cmd (
     440    rtems_monitor_command_entry_t *command
     441)
     442{
     443    rtems_monitor_command_entry_t *p;
     444    rtems_monitor_command_entry_t **p_prev = &rtems_registered_commands.next;
     445
     446    if (rtems_registered_commands.next)
     447    {
     448        for (p = rtems_registered_commands.next; p->next; p = p->next)
     449        {
     450            if (STREQ(command->command, p->command))
     451            {
     452                *p_prev = p->next;
     453                return 1;
     454            }
     455            p_prev = &p->next;
     456        }
     457    }
     458    return 0;
     459}
    421460
    422461/*
     
    436475    char *argv[64];       
    437476    boolean verbose = FALSE;
    438 
     477    struct termios term;
     478
     479    /*
     480     * Make the stdin stream characte not line based.
     481     */
     482   
     483    if (tcgetattr (STDIN_FILENO, &term) < 0)
     484    {
     485      printf("rtems-monitor: cannot get terminal attributes.\n");
     486    }
     487    else
     488    {
     489      /*
     490       * No echo, no canonical processing.
     491       */
     492
     493      term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
     494 
     495      /*
     496       * No sigint on BREAK, CR-to-NL off, input parity off,
     497       * don't strip 8th bit on input, output flow control off
     498       */
     499
     500      term.c_lflag    &= ~(INPCK | ISTRIP | IXON);
     501      term.c_cc[VMIN]  = 1;
     502      term.c_cc[VTIME] = 0;
     503
     504      if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
     505      {
     506        printf("cannot set terminal attributes\n");
     507      }
     508    }
     509   
    439510    if (monitor_flags & RTEMS_MONITOR_SUSPEND)
    440511        (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
     
    454525                                                    argc,
    455526                                                    argv)) == 0)
     527        {
     528            /* no command */
     529            printf("Unrecognised command; try 'help'\n");
    456530            continue;
     531        }
    457532
    458533        command->command_function(argc, argv, command->command_arg, verbose);
  • cpukit/libmisc/monitor/monitor.h

    r6f93bb4 r32e2554  
    295295    unsigned32   arguments_required;    /* # of required args */
    296296    rtems_monitor_command_function_t command_function;
    297 
    298297                               /* Some argument for the command */
    299     unsigned32          command_arg;
     298    unsigned32   command_arg;
     299    struct rtems_monitor_command_entry_s *next;
    300300};
    301301
     
    326326void    rtems_monitor_node_cmd(int, char **, unsigned32, boolean);
    327327void    rtems_monitor_symbols_loadup(void);
     328int     rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
     329int     rtems_monitor_erase_cmd(rtems_monitor_command_entry_t *);
     330
    328331void    rtems_monitor_task(rtems_task_argument);
    329332
Note: See TracChangeset for help on using the changeset viewer.