1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * POSIX getopt for Windows
9  * Code given out at the 1985 UNIFORUM conference in Dallas.
10  *
11  * From std-unix@ut-sally.UUCP (Moderator, John Quarterman) Sun Nov  3 14:34:15 1985
12  * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET
13  * Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP
14  * Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix
15  * From: std-unix@ut-sally.UUCP (Moderator, John Quarterman)
16  * Newsgroups: mod.std.unix
17  * Subject: public domain AT&T getopt source
18  * Message-ID: <3352@ut-sally.UUCP>
19  * Date: 3 Nov 85 19:34:15 GMT
20  * Date-Received: 4 Nov 85 12:25:09 GMT
21  * Organization: IEEE/P1003 Portable Operating System Environment Committee
22  * Lines: 91
23  * Approved: jsq@ut-sally.UUC
24  * Here's something you've all been waiting for:  the AT&T public domain
25  * source for getopt(3).  It is the code which was given out at the 1985
26  * UNIFORUM conference in Dallas.  I obtained it by electronic mail
27  * directly from AT&T.  The people there assure me that it is indeed
28  * in the public domain
29  * There is no manual page.  That is because the one they gave out at
30  * UNIFORUM was slightly different from the current System V Release 2
31  * manual page.  The difference apparently involved a note about the
32  * famous rules 5 and 6, recommending using white space between an option
33  * and its first argument, and not grouping options that have arguments.
34  * Getopt itself is currently lenient about both of these things White
35  * space is allowed, but not mandatory, and the last option in a group can
36  * have an argument.  That particular version of the man page evidently
37  * has no official existence, and my source at AT&T did not send a copy.
38  * The current SVR2 man page reflects the actual behavor of this getopt.
39  * However, I am not about to post a copy of anything licensed by AT&T.
40  */
41 
42 #include <assert.h>
43 #include <stdarg.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 
47 #include "fsl_common.h"
48 #include "fsl_str.h"
49 
50 #include "fsl_component_generic_list.h"
51 #include "fsl_component_serial_manager.h"
52 
53 #include "fsl_shell.h"
54 
55 /*
56  * The OSA_USED macro can only be defined when the OSA component is used.
57  * If the source code of the OSA component does not exist, the OSA_USED cannot be defined.
58  * OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED
59  * also cannot be defined.
60  * The source code path of the OSA component is <MCUXpresso_SDK>/components/osa.
61  *
62  */
63 #if defined(OSA_USED)
64 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
65 #include "fsl_component_common_task.h"
66 #else
67 #include "fsl_os_abstraction.h"
68 #endif
69 
70 #endif
71 
72 /*******************************************************************************
73  * Definitions
74  ******************************************************************************/
75 #if defined(OSA_USED)
76 #define SHELL_WRITEX SHELL_WriteSynchronization
77 #else
78 #define SHELL_WRITEX SHELL_Write
79 #endif
80 
81 /* Weak function. */
82 #if defined(__GNUC__)
83 #define __WEAK_FUNC __attribute__((weak))
84 #elif defined(__ICCARM__)
85 #define __WEAK_FUNC __weak
86 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
87 #define __WEAK_FUNC __attribute__((weak))
88 #elif defined(__DSC__) || defined(__CW__)
89 #define __WEAK_FUNC __attribute__((weak))
90 #endif
91 
92 #if (!defined(GCOV_DO_COVERAGE) || (GCOV_DO_COVERAGE == 0))
93 #define SHELL_STATIC static
94 #else
95 #define SHELL_STATIC __WEAK_FUNC
96 #endif
97 
98 #if defined(OSA_USED)
99 #if (defined(USE_RTOS) && (USE_RTOS > 0U))
100 static OSA_MUTEX_HANDLE_DEFINE(s_shellMutex);
101 #define SHELL_MUTEX_CREATE()   (void)OSA_MutexCreate(s_shellMutex)
102 #define SHELL_ENTER_CRITICAL() (void)OSA_MutexLock(s_shellMutex, osaWaitForever_c)
103 #define SHELL_EXIT_CRITICAL()  (void)OSA_MutexUnlock(s_shellMutex)
104 #else
105 #define SHELL_MUTEX_CREATE()
106 #define SHELL_ENTER_CRITICAL()
107 #define SHELL_EXIT_CRITICAL()
108 #endif
109 #else
110 #ifdef SDK_OS_FREE_RTOS
111 #include "FreeRTOS.h"
112 #include "queue.h"
113 #include "semphr.h"
114 static QueueHandle_t s_shellMutex;
115 
116 #define SHELL_MUTEX_CREATE()   s_shellMutex = xSemaphoreCreateMutex()
117 #define SHELL_ENTER_CRITICAL() (void)xSemaphoreTakeRecursive(s_shellMutex, portMAX_DELAY)
118 #define SHELL_EXIT_CRITICAL()  (void)xSemaphoreGiveRecursive(s_shellMutex)
119 #else /* BM case*/
120 #define SHELL_MUTEX_CREATE()
121 #define SHELL_ENTER_CRITICAL()
122 #define SHELL_EXIT_CRITICAL()
123 #endif
124 #endif
125 
126 #define KEY_ESC (0x1BU)
127 #define KET_DEL (0x7FU)
128 
129 #define SHELL_EVENT_DATA_ARRIVED (1U << 0)
130 #define SHELL_EVENT_DATA_SENT    (1U << 1)
131 
132 #define SHELL_SPRINTF_BUFFER_SIZE (64U)
133 
134 /*! @brief A type for the handle special key. */
135 typedef enum _fun_key_status
136 {
137     kSHELL_Normal   = 0U, /*!< Normal key */
138     kSHELL_Special  = 1U, /*!< Special key */
139     kSHELL_Function = 2U, /*!< Function key */
140 } fun_key_status_t;
141 
142 /*! @brief Data structure for Shell environment. */
143 typedef struct _shell_context_handle
144 {
145     list_label_t commandContextListHead; /*!< Command shellContextHandle list queue head */
146     serial_handle_t serialHandle;        /*!< Serial manager handle */
147     uint8_t
148         serialWriteHandleBuffer[SERIAL_MANAGER_WRITE_HANDLE_SIZE];   /*!< The buffer for serial manager write handle */
149     serial_write_handle_t serialWriteHandle;                         /*!< The serial manager write handle */
150     uint8_t serialReadHandleBuffer[SERIAL_MANAGER_READ_HANDLE_SIZE]; /*!< The buffer for serial manager read handle */
151     serial_read_handle_t serialReadHandle;                           /*!< The serial manager read handle */
152     char *prompt;                                                    /*!< Prompt string */
153 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
154 
155 #if defined(OSA_USED)
156 
157 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
158     common_task_message_t commontaskMsg; /*!< Message for common task */
159 #else
160     uint8_t event[OSA_EVENT_HANDLE_SIZE]; /*!< Event instance */
161     uint8_t taskId[OSA_TASK_HANDLE_SIZE]; /*!< Task handle */
162 #endif
163 
164 #endif
165 
166 #endif
167     char line[SHELL_BUFFER_SIZE];                          /*!< Consult buffer */
168     char hist_buf[SHELL_HISTORY_COUNT][SHELL_BUFFER_SIZE]; /*!< History buffer*/
169     char printBuffer[SHELL_SPRINTF_BUFFER_SIZE];           /*!< Buffer for print */
170     uint32_t printLength;                                  /*!< All length has been printed */
171     uint16_t hist_current;                                 /*!< Current history command in hist buff*/
172     uint16_t hist_count;                                   /*!< Total history command in hist buff*/
173     enum _fun_key_status stat;                             /*!< Special key status */
174     uint8_t cmd_num;                                       /*!< Number of user commands */
175     uint8_t l_pos;                                         /*!< Total line position */
176     uint8_t c_pos;                                         /*!< Current line position */
177     volatile uint8_t notificationPost;                     /*!< The serial manager notification is post */
178     uint8_t exit;                                          /*!< Exit Flag*/
179     uint8_t printBusy : 1;                                 /*!< Print is busy */
180     uint8_t taskBusy : 1;                                  /*!< Task is busy */
181 } shell_context_handle_t;
182 
183 #if 0
184 #define SHELL_STRUCT_OFFSET(type, field) ((size_t) & (((type *)0)->field))
185 #define SHEEL_COMMAND_POINTER(node) \
186     ((shell_command_t *)(((uint32_t)(node)) - SHELL_STRUCT_OFFSET(shell_command_t, link)))
187 #else
188 #define SHEEL_COMMAND_POINTER(node) \
189     ((shell_command_t *)(((uint32_t)(node)) - (sizeof(shell_command_t) - sizeof(list_element_t))))
190 #endif
191 /*******************************************************************************
192  * Prototypes
193  ******************************************************************************/
194 static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< help command */
195 
196 static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< exit command */
197 
198 static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[]); /*!< parse line command */
199 
200 static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count); /*!< compare string command */
201 
202 static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd); /*!< process a command */
203 
204 static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle,
205                                     uint8_t hist_pos); /*!< get commands history */
206 
207 static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle); /*!< auto complete command */
208 
209 static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle,
210                                     uint8_t *ch); /*!< get a char from communication interface */
211 
212 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
213 SHELL_STATIC void SHELL_Task(void *param); /*!<  Shell task*/
214 #endif
215 
216 /*******************************************************************************
217  * Variables
218  ******************************************************************************/
219 
220 static SHELL_COMMAND_DEFINE(help, "\r\n\"help\": List all the registered commands\r\n", SHELL_HelpCommand, 0);
221 static SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0);
222 
223 static char s_paramBuffer[SHELL_BUFFER_SIZE];
224 
225 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
226 #if defined(OSA_USED)
227 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
228 #else
229 /*
230  * \brief Defines the serial manager task's stack
231  */
232 static OSA_TASK_DEFINE(SHELL_Task, SHELL_TASK_PRIORITY, 1, SHELL_TASK_STACK_SIZE, false);
233 #endif
234 #endif /* OSA_USED */
235 #endif /* SHELL_NON_BLOCKING_MODE */
236 /*******************************************************************************
237  * Code
238  ******************************************************************************/
239 
240 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
SHELL_SerialManagerRxCallback(void * callbackParam,serial_manager_callback_message_t * message,serial_manager_status_t status)241 SHELL_STATIC void SHELL_SerialManagerRxCallback(void *callbackParam,
242                                                 serial_manager_callback_message_t *message,
243                                                 serial_manager_status_t status)
244 {
245     shell_context_handle_t *shellHandle;
246 
247     assert(callbackParam);
248     assert(message);
249 
250     shellHandle = (shell_context_handle_t *)callbackParam;
251 
252     if (0U == shellHandle->notificationPost)
253     {
254         shellHandle->notificationPost = 1U;
255 #if defined(OSA_USED)
256 
257 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
258         shellHandle->commontaskMsg.callback      = SHELL_Task;
259         shellHandle->commontaskMsg.callbackParam = shellHandle;
260         (void)COMMON_TASK_post_message(&shellHandle->commontaskMsg);
261 #else
262         (void)OSA_EventSet((osa_event_handle_t)shellHandle->event, SHELL_EVENT_DATA_ARRIVED);
263 #endif
264 
265 #else
266         SHELL_Task(shellHandle);
267 #endif
268     }
269 }
270 #endif
271 
SHELL_WriteBuffer(char * buffer,int32_t * indicator,char val,int len)272 static void SHELL_WriteBuffer(char *buffer, int32_t *indicator, char val, int len)
273 {
274     shell_context_handle_t *shellContextHandle;
275     int i              = 0;
276     shellContextHandle = (shell_context_handle_t *)(void *)buffer;
277 
278     for (i = 0; i < len; i++)
279     {
280         if ((*indicator + 1) >= (int32_t)SHELL_SPRINTF_BUFFER_SIZE)
281         {
282 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
283             if (NULL == shellContextHandle->serialHandle)
284             {
285                 for (uint32_t index = 0; index < ((uint32_t)*indicator); index++)
286                 {
287                     (void)putchar(shellContextHandle->printBuffer[index]);
288                 }
289             }
290             else
291 #endif
292             {
293                 (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle,
294                                                   (uint8_t *)shellContextHandle->printBuffer, (uint32_t)*indicator);
295             }
296 
297             shellContextHandle->printLength += (uint32_t)*indicator;
298             *indicator = 0;
299         }
300 
301         shellContextHandle->printBuffer[*indicator] = val;
302         (*indicator)++;
303     }
304 }
305 
SHELL_Sprintf(void * buffer,const char * formatString,va_list ap)306 static int SHELL_Sprintf(void *buffer, const char *formatString, va_list ap)
307 {
308     shell_context_handle_t *shellContextHandle;
309     uint32_t length;
310     shellContextHandle = (shell_context_handle_t *)buffer;
311 
312     length = (uint32_t)StrFormatPrintf(formatString, ap, (char *)buffer, SHELL_WriteBuffer);
313     shellContextHandle->printLength += length;
314     return (int32_t)length;
315 }
316 
SHELL_hisOperation(uint8_t ch,shell_context_handle_t * shellContextHandle)317 static void SHELL_hisOperation(uint8_t ch, shell_context_handle_t *shellContextHandle)
318 {
319     switch ((char)ch)
320     {
321         /* History operation here */
322         case 'A': /* Up key */
323             SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current);
324             if (shellContextHandle->hist_current < (shellContextHandle->hist_count - 1U))
325             {
326                 shellContextHandle->hist_current++;
327             }
328             break;
329         case 'B': /* Down key */
330             SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current);
331             if (shellContextHandle->hist_current > 0U)
332             {
333                 shellContextHandle->hist_current--;
334             }
335             break;
336         case 'D': /* Left key */
337             if ((bool)shellContextHandle->c_pos)
338             {
339                 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
340                 shellContextHandle->c_pos--;
341             }
342             break;
343         case 'C': /* Right key */
344             if (shellContextHandle->c_pos < shellContextHandle->l_pos)
345             {
346                 (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos], 1);
347                 shellContextHandle->c_pos++;
348             }
349             break;
350         default:
351             /* MISRA C-2012 Rule 16.4 */
352             break;
353     }
354 }
355 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
SHELL_Task(void * param)356 SHELL_STATIC void SHELL_Task(void *param)
357 #else
358 void SHELL_Task(shell_handle_t shellHandle)
359 #endif
360 {
361 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
362     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)param;
363 #else
364     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
365 #endif
366     uint8_t ch;
367 
368     if (NULL != shellContextHandle)
369     {
370         uint32_t osaCurrentSr = 0U;
371 
372         osaCurrentSr                         = DisableGlobalIRQ();
373         shellContextHandle->notificationPost = 0U;
374         if (shellContextHandle->taskBusy > 0U)
375         {
376             EnableGlobalIRQ(osaCurrentSr);
377             return;
378         }
379         shellContextHandle->taskBusy = 1U;
380         EnableGlobalIRQ(osaCurrentSr);
381 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
382 
383 #if defined(OSA_USED)
384 
385 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
386 #else
387         osa_event_flags_t ev = 0;
388 
389         do
390         {
391             if (KOSA_StatusSuccess == OSA_EventWait((osa_event_handle_t)shellContextHandle->event, osaEventFlagsAll_c,
392                                                     0U, osaWaitForever_c, &ev))
393             {
394                 if (0U != (ev & SHELL_EVENT_DATA_ARRIVED))
395 #endif
396 
397 #endif
398 
399 #endif
400         {
401             shellContextHandle->notificationPost = 0U;
402             do
403             {
404                 if ((bool)shellContextHandle->exit)
405                 {
406                     if (shellContextHandle->serialReadHandle != NULL)
407                     {
408                         (void)SerialManager_CloseReadHandle(shellContextHandle->serialReadHandle);
409                         shellContextHandle->serialReadHandle = NULL;
410                     }
411                     if (shellContextHandle->serialWriteHandle != NULL)
412                     {
413                         (void)SerialManager_CloseWriteHandle(shellContextHandle->serialWriteHandle);
414                         shellContextHandle->serialWriteHandle = NULL;
415                     }
416                     break;
417                 }
418                 if (kStatus_SHELL_Success != (shell_status_t)SHELL_GetChar(shellContextHandle, &ch))
419                 {
420                     /* If error occurred when getting a char, exit the task and waiting the new data arriving. */
421                     break;
422                 }
423 
424                 /* Special key */
425                 if (ch == KEY_ESC)
426                 {
427                     shellContextHandle->stat = kSHELL_Special;
428                     continue;
429                 }
430                 else if (shellContextHandle->stat == kSHELL_Special)
431                 {
432                     /* Function key */
433                     if ((char)ch == '[')
434                     {
435                         shellContextHandle->stat = kSHELL_Function;
436                         continue;
437                     }
438                     shellContextHandle->stat = kSHELL_Normal;
439                 }
440                 else if (shellContextHandle->stat == kSHELL_Function)
441                 {
442                     shellContextHandle->stat = kSHELL_Normal;
443                     SHELL_hisOperation(ch, shellContextHandle);
444                     continue;
445                 }
446                 /* Handle tab key */
447                 else if ((char)ch == '\t')
448                 {
449 #if SHELL_AUTO_COMPLETE
450                     /* Move the cursor to the beginning of line */
451                     uint32_t i;
452                     for (i = 0; i < (uint32_t)shellContextHandle->c_pos; i++)
453                     {
454                         (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
455                     }
456                     /* Do auto complete */
457                     SHELL_AutoComplete(shellContextHandle);
458                     /* Move position to end */
459                     shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->line);
460                     shellContextHandle->c_pos = shellContextHandle->l_pos;
461 #endif
462                     continue;
463                 }
464                 /* Handle backspace key */
465                 else if ((ch == KET_DEL) || ((char)ch == '\b'))
466                 {
467                     /* There must be at last one char */
468                     if (shellContextHandle->c_pos == 0U)
469                     {
470                         continue;
471                     }
472 
473                     shellContextHandle->l_pos--;
474                     shellContextHandle->c_pos--;
475 
476                     if (shellContextHandle->l_pos > shellContextHandle->c_pos)
477                     {
478                         (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos],
479                                       &shellContextHandle->line[shellContextHandle->c_pos + 1U],
480                                       (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
481                         shellContextHandle->line[shellContextHandle->l_pos] = '\0';
482                         (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
483                         (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
484                                            strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
485                         (void)SHELL_WRITEX(shellContextHandle, "  \b", 3);
486 
487                         /* Reset position */
488                         uint32_t i;
489                         for (i = (uint32_t)shellContextHandle->c_pos; i <= (uint32_t)shellContextHandle->l_pos; i++)
490                         {
491                             (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
492                         }
493                     }
494                     else /* Normal backspace operation */
495                     {
496                         (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
497                         shellContextHandle->line[shellContextHandle->l_pos] = '\0';
498                     }
499                     continue;
500                 }
501                 else
502                 {
503                     /* MISRA C-2012 Rule 15.7 */
504                 }
505 
506                 /* Input too long */
507                 if (shellContextHandle->l_pos >= (SHELL_BUFFER_SIZE - 1U))
508                 {
509                     shellContextHandle->l_pos = 0U;
510                 }
511 
512                 /* Handle end of line, break */
513                 if (((char)ch == '\r') || ((char)ch == '\n'))
514                 {
515                     static char endoflinechar = '\0';
516 
517                     if (((uint8_t)endoflinechar != 0U) && ((uint8_t)endoflinechar != ch))
518                     {
519                         continue;
520                     }
521                     else
522                     {
523                         endoflinechar = (char)ch;
524                         /* Print new line. */
525                         (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2U);
526                         /* If command line is not NULL, will start process it. */
527                         if (0U != strlen(shellContextHandle->line))
528                         {
529                             SHELL_ProcessCommand(shellContextHandle, shellContextHandle->line);
530                         }
531                         /* Print prompt. */
532                         (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->prompt,
533                                            strlen(shellContextHandle->prompt));
534                         /* Reset all params */
535                         shellContextHandle->c_pos = shellContextHandle->l_pos = 0;
536                         shellContextHandle->hist_current                      = 0;
537                         (void)memset(shellContextHandle->line, 0, sizeof(shellContextHandle->line));
538                         continue;
539                     }
540                 }
541 
542                 /* Normal character */
543                 if (shellContextHandle->c_pos < shellContextHandle->l_pos)
544                 {
545                     (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos + 1U],
546                                   &shellContextHandle->line[shellContextHandle->c_pos],
547                                   (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
548                     shellContextHandle->line[shellContextHandle->c_pos] = (char)ch;
549                     (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
550                                        strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
551                     /* Move the cursor to new position */
552                     uint32_t i;
553                     for (i = (uint32_t)shellContextHandle->c_pos; i < (uint32_t)shellContextHandle->l_pos; i++)
554                     {
555                         (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
556                     }
557                 }
558                 else
559                 {
560                     shellContextHandle->line[shellContextHandle->l_pos] = (char)ch;
561                     (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->l_pos], 1);
562                 }
563 
564                 ch = 0;
565                 shellContextHandle->l_pos++;
566                 shellContextHandle->c_pos++;
567             } while (0U == shellContextHandle->exit);
568         }
569 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
570 
571 #if defined(OSA_USED)
572 
573 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
574 #else
575             }
576         } while (1U == gUseRtos_c); /* USE_RTOS = 0 for BareMetal and 1 for OS */
577 #endif
578 
579 #endif
580 
581 #endif
582         osaCurrentSr                 = DisableGlobalIRQ();
583         shellContextHandle->taskBusy = 0U;
584         EnableGlobalIRQ(osaCurrentSr);
585     }
586 }
587 
SHELL_HelpCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)588 static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
589 {
590     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
591     shell_command_t *shellCommandContextHandle;
592     list_element_handle_t p = LIST_GetHead(&shellContextHandle->commandContextListHead);
593 
594     while (p != NULL)
595     {
596         shellCommandContextHandle = SHEEL_COMMAND_POINTER(p);
597         if ((shellCommandContextHandle->pcHelpString != NULL) && (bool)strlen(shellCommandContextHandle->pcHelpString))
598         {
599             (void)SHELL_WRITEX(shellContextHandle, shellCommandContextHandle->pcHelpString,
600                                strlen(shellCommandContextHandle->pcHelpString));
601         }
602 
603         p = LIST_GetNext(p);
604     }
605     return kStatus_SHELL_Success;
606 }
607 
SHELL_ExitCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)608 static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
609 {
610     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
611     /* Skip warning */
612     (void)SHELL_WRITEX(shellContextHandle, "\r\nSHELL exited\r\n", strlen("\r\nSHELL exited\r\n"));
613     shellContextHandle->exit = (uint8_t) true;
614     return kStatus_SHELL_Success;
615 }
616 
SHELL_ProcessCommand(shell_context_handle_t * shellContextHandle,const char * cmd)617 static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd)
618 {
619     shell_command_t *tmpCommand = NULL;
620     const char *tmpCommandString;
621     int32_t argc;
622     char *argv[SHELL_BUFFER_SIZE] = {0};
623     list_element_handle_t p;
624     uint8_t flag = 1;
625     uint8_t tmpCommandLen;
626     uint8_t tmpLen;
627     uint8_t i = 0;
628 
629     tmpLen = (uint8_t)strlen(cmd);
630     if (tmpLen >= SHELL_BUFFER_SIZE - 1U)
631     {
632         (void)SHELL_Printf(shellContextHandle,
633                            "Command line length should not more than SHELL_BUFFER_SIZE, please input command less "
634                            "(SHELL_BUFFER_SIZE - 1) characters again!\r\n");
635         return;
636     }
637     else
638     {
639         argc = SHELL_ParseLine(cmd, tmpLen, argv);
640     }
641 
642     if ((argc > 0))
643     {
644         p = LIST_GetHead(&shellContextHandle->commandContextListHead);
645         while (p != NULL)
646         {
647             tmpCommand       = SHEEL_COMMAND_POINTER(p);
648             tmpCommandString = tmpCommand->pcCommand;
649             tmpCommandLen    = (uint8_t)strlen(tmpCommandString);
650             /* Compare with space or end of string */
651             if ((cmd[tmpCommandLen] == ' ') || (cmd[tmpCommandLen] == (char)0x00))
652             {
653                 if (SHELL_StringCompare(tmpCommandString, argv[0], (int32_t)tmpCommandLen) == 0)
654                 {
655                     /* support commands with optional number of parameters */
656                     if (tmpCommand->cExpectedNumberOfParameters == (uint8_t)SHELL_IGNORE_PARAMETER_COUNT)
657                     {
658                         flag = 0;
659                     }
660                     else if ((tmpCommand->cExpectedNumberOfParameters == 0U) && (argc == 1))
661                     {
662                         flag = 0;
663                     }
664                     else if (tmpCommand->cExpectedNumberOfParameters > 0U)
665                     {
666                         if ((argc - 1) == (int32_t)tmpCommand->cExpectedNumberOfParameters)
667                         {
668                             flag = 0;
669                         }
670                     }
671                     else
672                     {
673                         flag = 1;
674                     }
675                     break;
676                 }
677             }
678             p = LIST_GetNext(p);
679         }
680         if (NULL == p)
681         {
682             tmpCommand = NULL;
683         }
684     }
685 
686     if ((tmpCommand != NULL) && (flag == 1U))
687     {
688         (void)SHELL_Write(
689             shellContextHandle,
690             "\r\nIncorrect command parameter(s).  Enter \"help\" to view a list of available commands.\r\n\r\n",
691             strlen(
692                 "\r\nIncorrect command parameter(s).  Enter \"help\" to view a list of available commands.\r\n\r\n"));
693     }
694     else if (tmpCommand != NULL)
695     {
696         tmpLen = (uint8_t)strlen(cmd);
697         /* Compare with last command. Push back to history buffer if different */
698         if (tmpLen != (uint8_t)SHELL_StringCompare(cmd, shellContextHandle->hist_buf[0], (int32_t)strlen(cmd)))
699         {
700             for (i = SHELL_HISTORY_COUNT - 1U; i > 0U; i--)
701             {
702                 (void)memset(shellContextHandle->hist_buf[i], (int)'\0', SHELL_BUFFER_SIZE);
703                 tmpLen = (uint8_t)strlen(shellContextHandle->hist_buf[i - 1U]);
704                 (void)memcpy(shellContextHandle->hist_buf[i], shellContextHandle->hist_buf[i - 1U], tmpLen);
705             }
706             (void)memset(shellContextHandle->hist_buf[0], (int)'\0', SHELL_BUFFER_SIZE);
707             tmpLen = (uint8_t)strlen(cmd);
708             (void)memcpy(shellContextHandle->hist_buf[0], cmd, tmpLen);
709             if (shellContextHandle->hist_count < SHELL_HISTORY_COUNT)
710             {
711                 shellContextHandle->hist_count++;
712             }
713         }
714         if (kStatus_SHELL_RetUsage == tmpCommand->pFuncCallBack(shellContextHandle, argc, argv))
715         {
716             if (NULL != tmpCommand->pcHelpString)
717             {
718                 (void)SHELL_WRITEX(shellContextHandle, tmpCommand->pcHelpString, strlen(tmpCommand->pcHelpString));
719             }
720             else
721             {
722                 (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
723             }
724         }
725     }
726     else
727     {
728         (void)SHELL_Write(
729             shellContextHandle,
730             "\r\nCommand not recognized.  Enter 'help' to view a list of available commands.\r\n\r\n",
731             strlen("\r\nCommand not recognized.  Enter 'help' to view a list of available commands.\r\n\r\n"));
732     }
733 }
734 
SHELL_GetHistoryCommand(shell_context_handle_t * shellContextHandle,uint8_t hist_pos)735 static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle, uint8_t hist_pos)
736 {
737     uint32_t i;
738     uint32_t tmp;
739 
740     if (shellContextHandle->hist_buf[0][0] == '\0')
741     {
742         shellContextHandle->hist_current = 0;
743         return;
744     }
745 
746 #if 0 /*hist_pos is passed from hist_current. And hist_current is only changed in case 'A'/'B',as hist_count is 3 \
747          most, it can't be more than 3  */
748     if (hist_pos >= SHELL_HISTORY_COUNT)
749     {
750         hist_pos = SHELL_HISTORY_COUNT - 1U;
751     }
752 #endif
753 
754     tmp = strlen(shellContextHandle->line);
755     /* Clear current if have */
756     if (tmp > 0U)
757     {
758         (void)memset(shellContextHandle->line, (int)'\0', tmp);
759         for (i = 0U; i < tmp; i++)
760         {
761             (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
762         }
763     }
764 
765     shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->hist_buf[hist_pos]);
766     shellContextHandle->c_pos = shellContextHandle->l_pos;
767     (void)memcpy(shellContextHandle->line, shellContextHandle->hist_buf[hist_pos], shellContextHandle->l_pos);
768     (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->hist_buf[hist_pos],
769                        strlen(shellContextHandle->hist_buf[hist_pos]));
770 }
771 
SHELL_AutoComplete(shell_context_handle_t * shellContextHandle)772 static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle)
773 {
774     int32_t minLen;
775     list_element_handle_t p;
776     shell_command_t *tmpCommand = NULL;
777     const char *namePtr;
778     const char *cmdName;
779 
780     minLen  = (int32_t)SHELL_BUFFER_SIZE;
781     namePtr = NULL;
782 
783     /* Empty tab, list all commands */
784     if (shellContextHandle->line[0] == '\0')
785     {
786         (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
787         return;
788     }
789 
790     (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2);
791 
792     /* Do auto complete */
793     p = LIST_GetHead(&shellContextHandle->commandContextListHead);
794     while (p != NULL)
795     {
796         tmpCommand = SHEEL_COMMAND_POINTER(p);
797         cmdName    = tmpCommand->pcCommand;
798         if (SHELL_StringCompare(shellContextHandle->line, cmdName, (int32_t)strlen(shellContextHandle->line)) == 0)
799         {
800             /* Show possible matches */
801             (void)SHELL_Printf(shellContextHandle, "%s    ", cmdName);
802             if (minLen > ((int32_t)strlen(cmdName)))
803             {
804                 namePtr = cmdName;
805                 minLen  = (int32_t)strlen(namePtr);
806             }
807         }
808         p = LIST_GetNext(p);
809     }
810     /* Auto complete string */
811     if (namePtr != NULL)
812     {
813         (void)memcpy(shellContextHandle->line, namePtr, (uint32_t)minLen);
814     }
815     SHELL_PrintPrompt(shellContextHandle);
816     (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->line, strlen(shellContextHandle->line));
817     return;
818 }
819 
SHELL_StringCompare(const char * str1,const char * str2,int32_t count)820 static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count)
821 {
822     while ((bool)(count--))
823     {
824         if (*str1++ != *str2++)
825         {
826             return (int32_t)(*(str1 - 1) - *(str2 - 1));
827         }
828     }
829     return 0;
830 }
831 
SHELL_ParseLine(const char * cmd,uint32_t len,char * argv[])832 static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[])
833 {
834     uint32_t argc;
835     char *p;
836     uint32_t position;
837 
838     /* Init params */
839     (void)memset(s_paramBuffer, (int)'\0', len + 1U);
840     (void)memcpy(s_paramBuffer, cmd, len);
841 
842     p        = s_paramBuffer;
843     position = 0;
844     argc     = 0;
845 
846     while (position < len)
847     {
848         /* Skip all blanks */
849         while ((position < len) && ((char)(*p) == ' '))
850         {
851             *p = '\0';
852             p++;
853             position++;
854         }
855 
856         if (position >= len)
857         {
858             break;
859         }
860 
861         /* Process begin of a string */
862         if (*p == '"')
863         {
864             p++;
865             position++;
866             argv[argc] = p;
867             argc++;
868             /* Skip this string */
869             while ((*p != '"') && (position < len))
870             {
871                 p++;
872                 position++;
873             }
874             /* Skip '"' */
875             *p = '\0';
876             p++;
877             position++;
878         }
879         else /* Normal char */
880         {
881             argv[argc] = p;
882             argc++;
883             while (((char)*p != ' ') && (position < len))
884             {
885                 p++;
886                 position++;
887             }
888         }
889     }
890     return (int32_t)argc;
891 }
892 
SHELL_GetChar(shell_context_handle_t * shellContextHandle,uint8_t * ch)893 static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle, uint8_t *ch)
894 {
895     shell_status_t status;
896 
897 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
898     if (NULL == shellContextHandle->serialHandle)
899     {
900         int ret;
901         ret = getchar();
902         if (ret > 0)
903         {
904             *ch    = (uint8_t)ret;
905             status = kStatus_SHELL_Success;
906         }
907         else
908         {
909             status = kStatus_SHELL_Error;
910         }
911     }
912     else
913 #endif
914     {
915 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
916         uint32_t length = 0;
917 
918         (void)SerialManager_TryRead(shellContextHandle->serialReadHandle, ch, 1, &length);
919 
920         if (length > 0U)
921         {
922             status = kStatus_SHELL_Success;
923         }
924         else
925         {
926             status = kStatus_SHELL_Error;
927         }
928 #else
929         status = (shell_status_t)SerialManager_ReadBlocking(shellContextHandle->serialReadHandle, ch, 1);
930 #endif
931     }
932 
933     return status;
934 }
935 
SHELL_Init(shell_handle_t shellHandle,serial_handle_t serialHandle,char * prompt)936 shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt)
937 {
938     shell_context_handle_t *shellContextHandle;
939     serial_manager_status_t status = kStatus_SerialManager_Error;
940     (void)status;
941 
942     assert(shellHandle);
943 #if !(!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
944     assert(serialHandle);
945 #endif
946     assert(prompt);
947     assert(SHELL_HANDLE_SIZE >= sizeof(shell_context_handle_t));
948 
949     shellContextHandle = (shell_context_handle_t *)shellHandle;
950 
951     /* memory set for shellHandle */
952     (void)memset(shellHandle, 0, SHELL_HANDLE_SIZE);
953 
954 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
955     if (NULL == serialHandle)
956     {
957     }
958     else
959 #endif
960     {
961 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
962 
963 #if defined(OSA_USED)
964 
965 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
966         (void)COMMON_TASK_init();
967 #else
968         if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t)shellContextHandle->event, 1U))
969         {
970             return kStatus_SHELL_Error;
971         }
972 
973         if (KOSA_StatusSuccess !=
974             OSA_TaskCreate((osa_task_handle_t)shellContextHandle->taskId, OSA_TASK(SHELL_Task), shellContextHandle))
975         {
976             return kStatus_SHELL_Error;
977         }
978 #endif
979 
980 #endif
981 
982 #endif
983     }
984 
985     shellContextHandle->prompt       = prompt;
986     shellContextHandle->serialHandle = serialHandle;
987 
988 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
989     if (NULL == serialHandle)
990     {
991     }
992     else
993 #endif
994     {
995         shellContextHandle->serialWriteHandle = (serial_write_handle_t)&shellContextHandle->serialWriteHandleBuffer[0];
996         status = SerialManager_OpenWriteHandle(shellContextHandle->serialHandle, shellContextHandle->serialWriteHandle);
997         assert(kStatus_SerialManager_Success == status);
998 
999         shellContextHandle->serialReadHandle = (serial_read_handle_t)&shellContextHandle->serialReadHandleBuffer[0];
1000         status = SerialManager_OpenReadHandle(shellContextHandle->serialHandle, shellContextHandle->serialReadHandle);
1001         assert(kStatus_SerialManager_Success == status);
1002 
1003 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
1004         status = SerialManager_InstallRxCallback(shellContextHandle->serialReadHandle, SHELL_SerialManagerRxCallback,
1005                                                  shellContextHandle);
1006         assert(kStatus_SerialManager_Success == status);
1007 #endif
1008         (void)status;
1009     }
1010 
1011     (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(help));
1012     (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(exit));
1013     SHELL_MUTEX_CREATE();
1014     (void)SHELL_Write(shellContextHandle, "\r\nCopyright  2022  NXP\r\n", strlen("\r\nCopyright  2022  NXP\r\n"));
1015     SHELL_PrintPrompt(shellContextHandle);
1016 
1017     return kStatus_SHELL_Success;
1018 }
1019 
SHELL_RegisterCommand(shell_handle_t shellHandle,shell_command_t * shellCommand)1020 shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t *shellCommand)
1021 {
1022     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
1023     assert(shellHandle);
1024     assert(shellCommand);
1025 
1026     /* memory set for shellHandle */
1027     (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1028 
1029     (void)LIST_AddTail(&shellContextHandle->commandContextListHead, &shellCommand->link);
1030 
1031     return kStatus_SHELL_Success;
1032 }
1033 
SHELL_UnregisterCommand(shell_command_t * shellCommand)1034 shell_status_t SHELL_UnregisterCommand(shell_command_t *shellCommand)
1035 {
1036     assert(shellCommand);
1037 
1038     (void)LIST_RemoveElement(&shellCommand->link);
1039 
1040     /* memory set for shellHandle */
1041     (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1042 
1043     return kStatus_SHELL_Success;
1044 }
1045 
SHELL_Write(shell_handle_t shellHandle,const char * buffer,uint32_t length)1046 shell_status_t SHELL_Write(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1047 {
1048     shell_context_handle_t *shellContextHandle;
1049     uint32_t primask;
1050     shell_status_t status;
1051 
1052     assert(shellHandle);
1053     assert(buffer);
1054 
1055     if (!(bool)length)
1056     {
1057         return kStatus_SHELL_Success;
1058     }
1059 
1060     shellContextHandle = (shell_context_handle_t *)shellHandle;
1061 
1062     primask = DisableGlobalIRQ();
1063     if ((bool)shellContextHandle->printBusy)
1064     {
1065         EnableGlobalIRQ(primask);
1066         return kStatus_SHELL_Error;
1067     }
1068     shellContextHandle->printBusy = 1U;
1069     EnableGlobalIRQ(primask);
1070 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1071     if (NULL == shellContextHandle->serialHandle)
1072     {
1073         status = kStatus_SHELL_Success;
1074         for (uint32_t index = 0; index < length; index++)
1075         {
1076             (void)putchar(buffer[index]);
1077         }
1078     }
1079     else
1080 #endif
1081     {
1082         status = (shell_status_t)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, (uint8_t *)buffer,
1083                                                              length);
1084     }
1085 
1086     shellContextHandle->printBusy = 0U;
1087 
1088     return status;
1089 }
1090 
SHELL_Printf(shell_handle_t shellHandle,const char * formatString,...)1091 int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...)
1092 {
1093     shell_context_handle_t *shellContextHandle;
1094     uint32_t length;
1095     uint32_t primask;
1096     va_list ap;
1097 
1098     assert(shellHandle);
1099     assert(formatString);
1100 
1101     shellContextHandle = (shell_context_handle_t *)shellHandle;
1102 
1103     primask = DisableGlobalIRQ();
1104     if ((bool)shellContextHandle->printBusy)
1105     {
1106         EnableGlobalIRQ(primask);
1107         return -1;
1108     }
1109     shellContextHandle->printBusy = 1U;
1110     EnableGlobalIRQ(primask);
1111 
1112     va_start(ap, formatString);
1113 
1114     shellContextHandle->printLength = 0U;
1115     length                          = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1116 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1117     if (NULL == shellContextHandle->serialHandle)
1118     {
1119         for (uint32_t index = 0; index < length; index++)
1120         {
1121             (void)putchar(shellContextHandle->printBuffer[index]);
1122         }
1123     }
1124     else
1125 #endif
1126     {
1127         (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle,
1128                                           (uint8_t *)shellContextHandle->printBuffer, length);
1129     }
1130     va_end(ap);
1131 
1132     shellContextHandle->printBusy = 0U;
1133     return (int32_t)shellContextHandle->printLength;
1134 }
1135 
SHELL_WriteSynchronization(shell_handle_t shellHandle,const char * buffer,uint32_t length)1136 shell_status_t SHELL_WriteSynchronization(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1137 {
1138     shell_status_t status;
1139 
1140     assert(SHELL_checkRunningInIsr() == false);
1141 
1142     SHELL_ENTER_CRITICAL();
1143     status = SHELL_Write(shellHandle, buffer, length);
1144 
1145     SHELL_EXIT_CRITICAL();
1146 
1147     return status;
1148 }
1149 
SHELL_PrintfSynchronization(shell_handle_t shellHandle,const char * formatString,...)1150 int SHELL_PrintfSynchronization(shell_handle_t shellHandle, const char *formatString, ...)
1151 {
1152     shell_status_t status;
1153     shell_context_handle_t *shellContextHandle;
1154     va_list ap;
1155     uint32_t length;
1156 
1157     assert(SHELL_checkRunningInIsr() == false);
1158 
1159     shellContextHandle = (shell_context_handle_t *)shellHandle;
1160 
1161     SHELL_ENTER_CRITICAL();
1162     va_start(ap, formatString);
1163     length = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1164 
1165     status = SHELL_Write(shellHandle, (const char *)shellContextHandle->printBuffer, length);
1166     va_end(ap);
1167     SHELL_EXIT_CRITICAL();
1168 
1169     return (status == kStatus_SHELL_Success) ? (int)length : 0;
1170 }
SHELL_ChangePrompt(shell_handle_t shellHandle,char * prompt)1171 void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt)
1172 {
1173     shell_context_handle_t *shellContextHandle;
1174     assert(shellHandle);
1175     assert(prompt);
1176 
1177     shellContextHandle = (shell_context_handle_t *)shellHandle;
1178 
1179     shellContextHandle->prompt = prompt;
1180     SHELL_PrintPrompt(shellContextHandle);
1181 }
1182 
SHELL_PrintPrompt(shell_handle_t shellHandle)1183 void SHELL_PrintPrompt(shell_handle_t shellHandle)
1184 {
1185     shell_context_handle_t *shellContextHandle;
1186     assert(shellHandle);
1187 
1188     shellContextHandle = (shell_context_handle_t *)shellHandle;
1189 
1190     (void)SHELL_Write(shellContextHandle, "\r\n", 2U);
1191     (void)SHELL_Write(shellContextHandle, shellContextHandle->prompt, strlen(shellContextHandle->prompt));
1192 }
1193