Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief Command support routines for RTEMS monitor.
0007  */
0008 
0009 /*
0010  * COPYRIGHT (c) 2000 Chris Johns <chrisj@rtems.org>
0011  * 
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 #ifdef HAVE_CONFIG_H
0035 #include "config.h"
0036 #endif
0037 
0038 #include <string.h>
0039 #include <stdio.h>
0040 
0041 #include <rtems.h>
0042 #include <rtems/monitor.h>
0043 
0044 static void
0045 rtems_monitor_show_help (
0046   const rtems_monitor_command_entry_t *help_cmd,
0047   int                           max_cmd_len
0048 )
0049 {
0050 #define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
0051 
0052   if (help_cmd && help_cmd->command)
0053   {
0054     const char *help = help_cmd->usage;
0055     int         help_len = strlen (help);
0056     int         spaces = max_cmd_len - strlen (help_cmd->command);
0057     int         show_this_line = 0;
0058     int         line_one = 1;
0059     int         c;
0060 
0061     fprintf(stdout,"%s", help_cmd->command);
0062 
0063     if (help_len == 0)
0064     {
0065       fprintf(stdout," - No help associated.\n");
0066       return;
0067     }
0068 
0069     while (help_len)
0070     {
0071       fprintf(stdout,"%*c", spaces, ' ');
0072 
0073       if (line_one)
0074         fprintf(stdout," - ");
0075 
0076       spaces   = max_cmd_len + 2;
0077       line_one = 0;
0078 
0079       /*
0080        * See if greater then the line length if so, work back
0081        * from the end for a space, tab or lf or cr.
0082        */
0083 
0084       if (help_len > MAX_HELP_LINE_LENGTH)
0085       {
0086         for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
0087              show_this_line;
0088              show_this_line--)
0089           if ((help[show_this_line] == ' ') ||
0090               (help[show_this_line] == '\n') ||
0091               (help[show_this_line] == '\r'))
0092             break;
0093 
0094         /*
0095          * If show_this_line is 0, it is a very long word !!
0096          */
0097 
0098         if (show_this_line == 0)
0099           show_this_line = MAX_HELP_LINE_LENGTH - 1;
0100       }
0101       else
0102         show_this_line = help_len;
0103 
0104       for (c = 0; c < show_this_line; c++)
0105         if ((help[c] == '\r') || (help[c] == '\n'))
0106           show_this_line = c;
0107         else
0108           putchar (help[c]);
0109 
0110       fprintf(stdout,"\n");
0111 
0112       help     += show_this_line;
0113       help_len -= show_this_line;
0114 
0115       /*
0116        * Move past the line feeds or what ever else is being skipped.
0117        */
0118 
0119       while (help_len)
0120       {
0121         if ((*help != '\r') && (*help != '\n'))
0122           break;
0123 
0124         if (*help != ' ')
0125         {
0126           help++;
0127           help_len--;
0128           break;
0129         }
0130         help++;
0131         help_len--;
0132       }
0133     }
0134   }
0135 }
0136 
0137 void
0138 rtems_monitor_command_usage(
0139   const rtems_monitor_command_entry_t *table,
0140   const char                          *command_name
0141 )
0142 {
0143   const rtems_monitor_command_entry_t *command = table;
0144   int                           max_cmd_len = 0;
0145 
0146   /* if first entry in table is a usage, then print it out */
0147 
0148   if (command_name && (*command_name != '\0'))
0149   {
0150     command = rtems_monitor_command_lookup (command_name);
0151 
0152     if (command)
0153       rtems_monitor_show_help (command, strlen (command_name));
0154     else
0155       fprintf(stdout,"Unrecognised command; try just 'help'\n");
0156     return;
0157   }
0158 
0159   /*
0160    * Find the largest command size.
0161    */
0162 
0163   while (command)
0164   {
0165     int len = command->command ? strlen (command->command) : 0 ;
0166 
0167     if (len > max_cmd_len)
0168       max_cmd_len = len;
0169 
0170     command = command->next;
0171   }
0172 
0173   max_cmd_len++;
0174 
0175   command = table;
0176 
0177   /*
0178    * Now some nice formatting for the help.
0179    */
0180 
0181   while (command)
0182   {
0183     rtems_monitor_show_help (command, max_cmd_len);
0184     command = command->next;
0185   }
0186 }
0187 
0188 
0189 void rtems_monitor_help_cmd(
0190   int                                argc,
0191   char                             **argv,
0192   const rtems_monitor_command_arg_t *command_arg,
0193   bool                               verbose RTEMS_UNUSED
0194 )
0195 {
0196   int arg;
0197   const rtems_monitor_command_entry_t *command =
0198     command_arg->monitor_command_entry;
0199 
0200   if (argc == 1)
0201     rtems_monitor_command_usage(command, 0);
0202   else
0203   {
0204     for (arg = 1; argv[arg]; arg++)
0205       rtems_monitor_command_usage(command, argv[arg]);
0206   }
0207 }
0208 
0209 typedef struct {
0210   const char *name;
0211   size_t length;
0212   const rtems_monitor_command_entry_t *match;
0213 } rtems_monitor_command_lookup_entry;
0214 
0215 static bool rtems_monitor_command_lookup_routine(
0216   const rtems_monitor_command_entry_t *e,
0217   void *arg
0218 )
0219 {
0220   rtems_monitor_command_lookup_entry *le =
0221     (rtems_monitor_command_lookup_entry *) arg;
0222 
0223   /* Check name */
0224   if (strncmp(e->command, le->name, le->length) == 0) {
0225     /* Check for ambiguity */
0226     if (le->match == NULL) {
0227       le->match = e;
0228     } else {
0229       return false;
0230     }
0231   }
0232 
0233   return true;
0234 }
0235 
0236 /**
0237  * @brief Looks for a command with the name @a name in the list of registered
0238  * commands.
0239  *
0240  * The parameter @a name must not be NULL.
0241  *
0242  * Returns the corresponding command entry or NULL if no command is found.
0243  */
0244 const rtems_monitor_command_entry_t *rtems_monitor_command_lookup(
0245   const char *name
0246 )
0247 {
0248   rtems_monitor_command_lookup_entry e = {
0249     .name = name,
0250     .length = strlen( name),
0251     .match = NULL
0252   };
0253 
0254   rtems_monitor_command_iterate(rtems_monitor_command_lookup_routine, &e);
0255 
0256   return e.match;
0257 }