add code
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Header with useful defines and common includes
|
||||
// to use when defining console commands.
|
||||
//
|
||||
// This file aims to concentrate the most common includes
|
||||
// and utility macros to make command definitions easier to write.
|
||||
//
|
||||
// Created by MightyPork on 2020/03/11.
|
||||
//
|
||||
|
||||
#ifndef LIBCONSOLE_CMDDEF_H
|
||||
#define LIBCONSOLE_CMDDEF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <argtable3.h>
|
||||
#include "console/console.h"
|
||||
|
||||
#if CONSOLE_HAVE_CSP
|
||||
#include <csp/csp.h>
|
||||
#endif
|
||||
|
||||
#include "console/utils.h"
|
||||
|
||||
#endif //LIBCONSOLE_CMDDEF_H
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Console configuration file, filled by CMake
|
||||
*
|
||||
* Created on 2020/03/16.
|
||||
*/
|
||||
|
||||
#ifndef LIBCONSOLE_CONFIG_H
|
||||
#define LIBCONSOLE_CONFIG_H
|
||||
|
||||
#cmakedefine CONSOLE_LINE_BUF_LEN @CONSOLE_LINE_BUF_LEN@
|
||||
#cmakedefine CONSOLE_MAX_NUM_ARGS @CONSOLE_MAX_NUM_ARGS@
|
||||
#cmakedefine CONSOLE_PROMPT_MAX_LEN @CONSOLE_PROMPT_MAX_LEN@
|
||||
#cmakedefine CONSOLE_HISTORY_LEN @CONSOLE_HISTORY_LEN@
|
||||
#cmakedefine01 CONSOLE_FILE_SUPPORT
|
||||
#cmakedefine01 CONSOLE_USE_FILE_IO_STREAMS
|
||||
#cmakedefine01 CONSOLE_USE_TERMIOS
|
||||
#cmakedefine01 CONSOLE_USE_MEMSTREAM
|
||||
#cmakedefine01 CONSOLE_USE_FREERTOS
|
||||
#cmakedefine01 CONSOLE_USE_PTHREADS
|
||||
#cmakedefine01 CONSOLE_TESTING_ALLOC_FUNCS
|
||||
|
||||
#endif //LIBCONSOLE_CONFIG_H
|
||||
@@ -0,0 +1,362 @@
|
||||
/**
|
||||
* Console - VCOM command engine
|
||||
*
|
||||
* Created on 2020/02/28 by Ondrej Hruska
|
||||
*
|
||||
* Parts are based on the console component from esp-idf
|
||||
* licensed under the Apache 2 license.
|
||||
*/
|
||||
|
||||
#ifndef LIBCONSOLE_H
|
||||
#define LIBCONSOLE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <console/config.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
/* Colors */
|
||||
COLOR_RESET = 0xF0,
|
||||
COLOR_BLACK = 0x01,
|
||||
COLOR_RED = 0x02,
|
||||
COLOR_GREEN = 0x03,
|
||||
COLOR_YELLOW = 0x04,
|
||||
COLOR_BLUE = 0x05,
|
||||
COLOR_MAGENTA = 0x06,
|
||||
COLOR_CYAN = 0x07,
|
||||
COLOR_WHITE = 0x08,
|
||||
/* Modifiers */
|
||||
COLOR_NORMAL = 0x0F,
|
||||
COLOR_BOLD = 0x10,
|
||||
COLOR_UNDERLINE = 0x20,
|
||||
COLOR_BLINK = 0x30,
|
||||
COLOR_HIDE = 0x40,
|
||||
} console_color_t;
|
||||
|
||||
#if CONSOLE_USE_FREERTOS
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
typedef SemaphoreHandle_t console_mutex_t;
|
||||
#endif
|
||||
|
||||
#if CONSOLE_USE_PTHREADS
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t console_mutex_t;
|
||||
#endif
|
||||
|
||||
#if CONSOLE_USE_TERMIOS
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Console config struct
|
||||
*/
|
||||
struct console_config {
|
||||
/**
|
||||
* Timeout waiting for execution lock when handling a command.
|
||||
* This should be longer than the slowest command in the system.
|
||||
*/
|
||||
uint32_t execution_lock_timeout_ms;
|
||||
};
|
||||
|
||||
/**
|
||||
* Macro to init the console config struct
|
||||
*/
|
||||
#define CONSOLE_CONFIG_DEFAULTS() { \
|
||||
.execution_lock_timeout_ms = 10000, \
|
||||
}
|
||||
|
||||
typedef struct console_config console_config_t;
|
||||
|
||||
struct console_ctx; // early declaration
|
||||
|
||||
/**
|
||||
* Console context
|
||||
*/
|
||||
typedef struct console_ctx console_ctx_t;
|
||||
|
||||
/**
|
||||
* Console errors - return codes
|
||||
*/
|
||||
enum console_err {
|
||||
CONSOLE_OK = 0,
|
||||
/** unspecified error */
|
||||
CONSOLE_ERROR = 1,
|
||||
/** Allocation failed */
|
||||
CONSOLE_ERR_NO_MEM,
|
||||
/** Function call not allowed (e.g. console not inited) */
|
||||
CONSOLE_ERR_BAD_CALL,
|
||||
/** Argument validation failed */
|
||||
CONSOLE_ERR_INVALID_ARG,
|
||||
/** Command not recognized */
|
||||
CONSOLE_ERR_UNKNOWN_CMD,
|
||||
/** Timeout */
|
||||
CONSOLE_ERR_TIMEOUT,
|
||||
/** IO error (file open fail, etc.) */
|
||||
CONSOLE_ERR_IO,
|
||||
/** Operation denied (not allowed / insufficient rights) */
|
||||
CONSOLE_ERR_NOT_POSSIBLE,
|
||||
/** End marker */
|
||||
_CONSOLE_ERR_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Print string describing console error.
|
||||
* In case of unknown error, the number is shown.
|
||||
*
|
||||
* The argument should be `enum console_err`, but any number is valid.
|
||||
*/
|
||||
void console_err_print_ctx(struct console_ctx *ctx, int e);
|
||||
|
||||
// TODO error-to-string function
|
||||
|
||||
typedef enum console_err console_err_t;
|
||||
|
||||
// early decl's
|
||||
struct cmd_signature;
|
||||
typedef struct cmd_signature cmd_signature_t;
|
||||
|
||||
/**
|
||||
* Command signature, passed as the last argument to the command handler
|
||||
* to perform registration.
|
||||
*
|
||||
* \note Fill only fields that differ from default (zeros/NULLs)
|
||||
*/
|
||||
struct cmd_signature {
|
||||
const char* command; //!< Command name, used in invocations (filled internally, do not set)
|
||||
const char* help; //!< Command help text, shown when called with -h
|
||||
const char* hint; //!< Hint text, generated from argtable if hint==NULL & argtable!=NULL
|
||||
bool no_history; //!< Command skips history
|
||||
bool custom_args; //!< Disable argtable parsing in the handler function, will be parsed manually from argv/argc
|
||||
|
||||
/**
|
||||
* Argtable, struct or array that must end with arg_end().
|
||||
* Used by the register function and for disambiguation.
|
||||
*/
|
||||
void* argtable;
|
||||
};
|
||||
|
||||
/**
|
||||
* Active console context pointer, valid only when handling a console command (otherwise NULL).
|
||||
*
|
||||
* Used by the console printf & other IO methods.
|
||||
*/
|
||||
extern struct console_ctx * console_active_ctx;
|
||||
|
||||
/**
|
||||
* Function handling a callback from the console loop.
|
||||
*/
|
||||
typedef void(*console_callback_t)(console_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Console context struct
|
||||
*/
|
||||
struct console_ctx {
|
||||
#if CONSOLE_USE_FILE_IO_STREAMS
|
||||
// Streams
|
||||
FILE* in; //!< stdin fd, can be -1 if not available (running commands in non-interactive mode)
|
||||
FILE* out; //!< stdout fd
|
||||
|
||||
#if CONSOLE_USE_TERMIOS
|
||||
// original termios is stored here before entering raw mode
|
||||
struct termios orig_termios;
|
||||
#endif
|
||||
|
||||
#else
|
||||
void *ioctx;
|
||||
#endif //CONSOLE_USE_FILE_IO_STREAMS
|
||||
|
||||
#if CONSOLE_FILE_SUPPORT
|
||||
char *history_file;
|
||||
#endif //CONSOLE_FILE_SUPPORT
|
||||
|
||||
bool __internal_heap_allocated;
|
||||
bool exit_allowed;
|
||||
|
||||
char prompt[CONSOLE_PROMPT_MAX_LEN]; //!< Prompt, can be modified by a command or `before_readline_fn`
|
||||
char line_buffer[CONSOLE_LINE_BUF_LEN];
|
||||
|
||||
/**
|
||||
* Callback fired in the command evaluation loop, each time before the prompt is shown and new line read.
|
||||
* This command can print to the output streams, change prompt, shutdown console, etc.
|
||||
*/
|
||||
console_callback_t loop_handler;
|
||||
|
||||
/**
|
||||
* Callback fired before the console task shuts down
|
||||
*/
|
||||
console_callback_t shutdown_handler;
|
||||
|
||||
/**
|
||||
* Shutdown requested. Console will exit as soon as possible.
|
||||
*/
|
||||
bool exit_requested;
|
||||
|
||||
/**
|
||||
* Interactive mode. Enables additional outputs for user convenience.
|
||||
*/
|
||||
bool interactive;
|
||||
|
||||
/**
|
||||
* Enable ANSI colors
|
||||
*/
|
||||
bool use_colors;
|
||||
|
||||
/* These fields are valid only during command execution */
|
||||
const char **argv; //!< The current argv
|
||||
size_t argc; //!< The current argc
|
||||
const cmd_signature_t *cmd; //!< Pointer to the currently executed command signature
|
||||
|
||||
/** Used for argument validation */
|
||||
uint32_t __internal_magic;
|
||||
};
|
||||
|
||||
#define CONSOLE_CTX_MAGIC 0x6f587468
|
||||
|
||||
/**
|
||||
* Command handler type.
|
||||
*
|
||||
* @param ctx - console context, including input/output files
|
||||
* @param reg - signature struct; if not NULL, init the static argtable, fill this struct, and return OK (0).
|
||||
* @return status code, 0 = OK (use cons_err_t constants if possible)
|
||||
*/
|
||||
typedef int (*console_command_t)(console_ctx_t *ctx, struct cmd_signature *reg);
|
||||
|
||||
/**
|
||||
* Intialize the console
|
||||
*
|
||||
* @param config - config pointer, NULL to use defaults
|
||||
* @return status code
|
||||
*/
|
||||
console_err_t console_init(const console_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Register console command
|
||||
*
|
||||
* If the command function is already registered, this creates an alias.
|
||||
* A multi-word command automatically create a command group. The group can
|
||||
* be described using a description string by calling `console_group_add()`
|
||||
* - at convenience before or after the commands are registered.
|
||||
*
|
||||
* @param name - command name (may contain spaces for "multi-part commands")
|
||||
* @param handler pointer to the command handler.
|
||||
* @return status code
|
||||
*/
|
||||
console_err_t console_cmd_register(console_command_t handler, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Register a command group.
|
||||
*
|
||||
* Command groups are created automatically when used.
|
||||
* This method can create a group with description, or attach a custom description
|
||||
* to an existing group.
|
||||
*
|
||||
* @param name - group name (first word of multi-part commands)
|
||||
* @param descr - description to attach, can be NULL
|
||||
* @return staus code
|
||||
*/
|
||||
console_err_t console_group_add(const char *name, const char *descr);
|
||||
|
||||
/**
|
||||
* Add alias to an existing command by name.
|
||||
*
|
||||
* @param original - original command name
|
||||
* @param alias - command's alias
|
||||
* @return status code
|
||||
*/
|
||||
console_err_t console_cmd_add_alias(const char *original, const char *alias);
|
||||
|
||||
/**
|
||||
* Add alias by handler function
|
||||
*
|
||||
* @param handler - command handler
|
||||
* @param alias - new name
|
||||
* @return status code
|
||||
*/
|
||||
console_err_t console_cmd_add_alias_fn(console_command_t handler, const char *alias);
|
||||
|
||||
/**
|
||||
* Internal error print function. Has WEAK linkage, can be overridden.
|
||||
*
|
||||
* This function is used to report detected bugs and should not be called
|
||||
* in well-written "production code".
|
||||
*
|
||||
* @param msg - error message
|
||||
*/
|
||||
void console_internal_error_print(const char *msg);
|
||||
|
||||
/**
|
||||
* This function is guarded by a mutex and will wait for the execution lock as
|
||||
* configured in console_config.
|
||||
*
|
||||
* @brief Run command line
|
||||
* @param[in] outf
|
||||
* @param[in] inf
|
||||
* @param cmdline command line (command name followed by a number of arguments)
|
||||
* @param[out] pRetval return code from the command (set if command was run)
|
||||
* @param[out] pCommandSig - is set to a pointer to the matched command signature, or NULL on error
|
||||
* @return status code
|
||||
*/
|
||||
console_err_t console_handle_cmd(
|
||||
console_ctx_t *ctx,
|
||||
const char *cmdline,
|
||||
int *pRetval,
|
||||
const struct cmd_signature **pCommandSig
|
||||
);
|
||||
|
||||
/**
|
||||
* Count all registered commands
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
size_t console_count_commands(void);
|
||||
|
||||
/**
|
||||
* Create a console IO context and init it to defaults.
|
||||
*
|
||||
* takes stdin and stdout file descriptors, or IO context (based on config flags)
|
||||
*
|
||||
* In the FD variant, pass NULL as STDIN if not available.
|
||||
*
|
||||
* @param ctx - context, if using static alloc, NULL to allocate internally.
|
||||
* @return the context, NULL if alloc or init fails
|
||||
*/
|
||||
console_ctx_t *console_ctx_init(
|
||||
console_ctx_t *ctx,
|
||||
#if CONSOLE_USE_FILE_IO_STREAMS
|
||||
FILE* inf, FILE* outf
|
||||
#else
|
||||
void * ioctx
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* Destroy a console IO context.
|
||||
*
|
||||
* Make sure to release any user fields (ioctx, for example) beforehand.
|
||||
*
|
||||
* @attention ONLY CALL THIS IF THE CONTEXT WAS DYNAMICALLY ALLOCATED!
|
||||
*
|
||||
* @param[in,out] ctx - pointer to context, will be set to NULL.
|
||||
*/
|
||||
void console_ctx_destroy(console_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Console task
|
||||
*
|
||||
* @param[in] param - must be a valid console context (see `console_ctx_init()`)
|
||||
*/
|
||||
void console_task(void *param);
|
||||
|
||||
/**
|
||||
* Variant of 'console_task' for pthreads (returns NULL)
|
||||
*/
|
||||
void* console_task_posix(void *param);
|
||||
|
||||
#include "console_io.h"
|
||||
|
||||
#endif //LIBCONSOLE_H
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Console IO functions.
|
||||
*
|
||||
* This header is included internally by console.h
|
||||
*
|
||||
* Created on 2020/04/09.
|
||||
*/
|
||||
|
||||
#ifndef LIBCONSOLE_IO_H
|
||||
#define LIBCONSOLE_IO_H
|
||||
|
||||
#ifndef LIBCONSOLE_H
|
||||
#error Include console.h!
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
// ------ If the FILE based IO streams option is OFF, these are extern -------
|
||||
|
||||
/**
|
||||
* Write to console context.
|
||||
*
|
||||
* In command context, the more convenient "vconsole_write", "console_print", "console_println"
|
||||
* and "console_printf" functions can be used instead.
|
||||
*
|
||||
* This function is a Linenoise write callback.
|
||||
*
|
||||
* Return number of characters written, -1 on error.
|
||||
*/
|
||||
extern int console_write_ctx(console_ctx_t *ctx, const char *text, size_t len);
|
||||
|
||||
/**
|
||||
* Read from console context's input stream.
|
||||
*
|
||||
* In command context, the more convenient "vconsole_read" function and the
|
||||
* "console_can_read" and "console_have_stdin" helper functions can be used instead.
|
||||
*
|
||||
* This is also a Linenoise read callback.
|
||||
*
|
||||
* Return number of characters read, -1 on error
|
||||
*/
|
||||
extern int console_read_ctx(console_ctx_t *ctx, char *dest, size_t count);
|
||||
|
||||
/**
|
||||
* Check if console input stream has bytes ready.
|
||||
*
|
||||
* @return number of queued bytes, 0 if none, -1 on error.
|
||||
*/
|
||||
extern int console_can_read_ctx(console_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Test if console context is not NULL and has stdin stream available
|
||||
*
|
||||
* @return have stdin
|
||||
*/
|
||||
extern bool console_have_stdin_ctx(console_ctx_t *ctx);
|
||||
|
||||
|
||||
// ----- end extern interface -----
|
||||
|
||||
/**
|
||||
* Print zero-terminated string to to console output
|
||||
*
|
||||
* @param text - characters to write
|
||||
* @return number of characters written, or -1 on error
|
||||
*/
|
||||
int console_print_ctx(console_ctx_t *ctx, const char *text);
|
||||
|
||||
/**
|
||||
* Print zero-terminated string to console output, followed by a newline
|
||||
*
|
||||
* @param text - characters to write
|
||||
* @return number of characters written, or -1 on error
|
||||
*/
|
||||
ssize_t console_println_ctx(console_ctx_t *ctx, const char *text);
|
||||
|
||||
/**
|
||||
* Console printf
|
||||
*
|
||||
* @param ctx - console context
|
||||
* @param color - color to use, COLOR_RESET = default
|
||||
* @param format
|
||||
* @param ...
|
||||
* @return bytes written, or -1 on error
|
||||
*/
|
||||
ssize_t console_printf_ctx(console_ctx_t *ctx, console_color_t color, const char *format, ...) __attribute__((format(printf,3,4)));
|
||||
|
||||
/**
|
||||
* Console vprintf
|
||||
*
|
||||
* @param ctx - console context
|
||||
* @param color - color to use, COLOR_RESET = default
|
||||
* @param format - format string
|
||||
* @param args - varargs passed as a va_list
|
||||
* @return bytes written, or -1 on error
|
||||
*/
|
||||
ssize_t console_vprintf_ctx(console_ctx_t *ctx, console_color_t color, const char *format, va_list args);
|
||||
|
||||
/**
|
||||
* Write to console output
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param text - characters to write
|
||||
* @param len - text length
|
||||
* @return number of characters written, or -1 on error
|
||||
*/
|
||||
ssize_t vconsole_write(const char *text, size_t len);
|
||||
|
||||
|
||||
// -------------------- Convenience functions -------------------------
|
||||
|
||||
/**
|
||||
* Test if we are in the console command context.
|
||||
*
|
||||
* @return in command context
|
||||
*/
|
||||
static inline bool console_context_available(void) {
|
||||
return console_active_ctx != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we are in the console command context AND the console context has an input stream
|
||||
* (input stream may be used in interactive commands)
|
||||
*
|
||||
* @return have stdin
|
||||
*/
|
||||
bool console_have_stdin(void);
|
||||
|
||||
/**
|
||||
* Console printf. Defined as a macro to pass variadic arguments
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param format
|
||||
* @param ...
|
||||
* @return bytes written, or -1 on error
|
||||
*/
|
||||
#define console_printf(format, ...) console_printf_ctx(console_active_ctx, COLOR_RESET, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Console printf with colors. Defined as a macro to pass variadic arguments
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param color - from console_colors_t enum
|
||||
* @param format
|
||||
* @param ...
|
||||
* @return bytes written, or -1 on error
|
||||
*/
|
||||
#define console_color_printf(color, format, ...) console_printf_ctx(console_active_ctx, color, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Read from console input
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param dest - destination buffer
|
||||
* @param count - how many characters to read
|
||||
* @return number of characters read, or -1 on error
|
||||
*/
|
||||
ssize_t vconsole_read(char *dest, size_t count);
|
||||
|
||||
/**
|
||||
* Check if console input stream has bytes ready.
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @return number of queued bytes, 0 if none, -1 on error.
|
||||
*/
|
||||
int console_can_read(void);
|
||||
|
||||
/**
|
||||
* Print zero-terminated string to to console output
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param text - characters to write
|
||||
* @return number of characters written, or -1 on error
|
||||
*/
|
||||
static inline int console_print(const char *text) {
|
||||
return console_print_ctx(console_active_ctx, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print zero-terminated string to console output, followed by a newline
|
||||
*
|
||||
* @attention Can only be used within a console command context
|
||||
*
|
||||
* @param text - characters to write
|
||||
* @return number of characters written, or -1 on error
|
||||
*/
|
||||
ssize_t console_println(const char *text);
|
||||
|
||||
|
||||
#endif //LIBCONSOLE_IO_H
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Prefix Match
|
||||
*
|
||||
* Match input value to a list of options, allowing non-ambiguous abbreviation and partial matching.
|
||||
* This library was designed for command recognition in interactive consoles and command interfaces.
|
||||
*
|
||||
* Created on 2020/06/09 by Ondřej Hruška
|
||||
*/
|
||||
|
||||
#ifndef _PREFIX_MATCH_H
|
||||
#define _PREFIX_MATCH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/** Use case-sensitive matching */
|
||||
#define PREFIXMATCH_CASE_SENSITIVE 1
|
||||
/** Forbid abbreviations */
|
||||
#define PREFIXMATCH_NOABBREV 2
|
||||
/** Allow matching fewer words, if unambiguous */
|
||||
#define PREFIXMATCH_MULTI_PARTIAL 4
|
||||
|
||||
enum pm_test_result {
|
||||
PM_TEST_NO_MATCH = 0,
|
||||
PM_TEST_MATCH = 1,
|
||||
PM_TEST_MATCH_MULTI_PARTIAL = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Recognize (optionally abbreviated) input
|
||||
*
|
||||
* @param[in] value - tested value
|
||||
* @param[in] options - options to match against
|
||||
* @param[in] flags - matching options (bitmask) - accepts PREFIXMATCH_CASE_SENSITIVE and PREFIXMATCH_NOABBREV
|
||||
* @return index of the matched option, -1 on mismatch or ambiguous match
|
||||
*/
|
||||
int prefix_match(const char *value, const char **options, int flags);
|
||||
|
||||
/**
|
||||
* Recognize input consisting of one or more (optionally abbreviated) words
|
||||
*
|
||||
* @param[in] value - tested value
|
||||
* @param[in] options - options to match against, multi-word options separated by the listed delimiters
|
||||
* @param[in] delims - string with a list of possible delimiters (like for strtok)
|
||||
* @param[in] flags - matching options (bitmask) - accepts all options
|
||||
* @return index of the matched option, -1 on mismatch or ambiguous match
|
||||
*/
|
||||
int prefix_multipart_match(const char *restrict value, const char **options, const char* restrict delims, int flags);
|
||||
|
||||
// useful internal functions exported for possible re-use
|
||||
|
||||
/**
|
||||
* Test if two word sentences match, with individual words optionally allowed to be abbreviated.
|
||||
*
|
||||
* @internal
|
||||
* @param[in] tested - tested (optionally abbreviated) sentence
|
||||
* @param[in] full - full sentence
|
||||
* @param[in] delims - list of possible delimiters, same may be used for both sentences
|
||||
* @param[in] flags - matching options (bitmask) - accepts all options
|
||||
* @return 1-match; 0-no match; 2-partial (some words) match, if the PREFIXMATCH_MULTI_PARTIAL flag is set
|
||||
*/
|
||||
enum pm_test_result prefix_multipart_test(const char *restrict tested, const char* restrict full, const char *restrict delims, int flags);
|
||||
|
||||
/**
|
||||
* Count words in a "sentence", delimited by any of the given set of delimiters.
|
||||
*
|
||||
* @internal
|
||||
* @param[in] sentence - one or multi-word string
|
||||
* @param[in] delims - delimiters accepted
|
||||
* @return number of words
|
||||
*/
|
||||
size_t pm_count_words(const char * restrict sentence, const char * restrict delims);
|
||||
|
||||
/**
|
||||
* Measure word length
|
||||
*
|
||||
* @internal
|
||||
* @param[in] word - start of a word that ends with either one of the delimiters, or a null byte.
|
||||
* @param[in] delims - delimiters accepted
|
||||
* @return word length
|
||||
*/
|
||||
size_t pm_word_len(const char * restrict word, const char * restrict delims);
|
||||
|
||||
/**
|
||||
* Skip N words in a sentence.
|
||||
*
|
||||
* @param[in] sentence - one or multi-word string
|
||||
* @param[in] delims - delimiters accepted
|
||||
* @param[in] skip - how many words to skip
|
||||
* @return pointer to the first byte after the last skipped word
|
||||
*/
|
||||
const char *pm_skip_words(const char * restrict sentence, const char * restrict delims, size_t skip);
|
||||
|
||||
#endif //_PREFIX_MATCH_H
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* Utilities for console commands
|
||||
*
|
||||
* Created on 2020/03/11.
|
||||
*/
|
||||
|
||||
#ifndef LIBCONSOLE_UTILS_H
|
||||
#define LIBCONSOLE_UTILS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <console/console.h>
|
||||
|
||||
#ifndef STR
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef OBC_FIRMWARE
|
||||
#define EXPENDABLE_STRING(x) x
|
||||
#define EXPENDABLE_CODE(x) x
|
||||
#else
|
||||
#define EXPENDABLE_STRING(x) ""
|
||||
#define EXPENDABLE_CODE(x) do {} while(0);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read an argument, or return default if it is empty.
|
||||
*
|
||||
* This works for commands arg_int0
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* \code
|
||||
* static struct {
|
||||
* struct arg_int *foo;
|
||||
* } args;
|
||||
*
|
||||
* args.foo = arg_int0(...);
|
||||
*
|
||||
* int foo = GET_ARG_INT0(args.foo, 1234);
|
||||
* \endcode
|
||||
*/
|
||||
#define GET_ARG_INT0(_arg, _def) ((_arg)->count ? (_arg)->ival[0] : (_def))
|
||||
|
||||
/**
|
||||
* Get CSP node ID from an argument table, using own address as default.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* \code
|
||||
* static struct {
|
||||
* struct arg_int *node;
|
||||
* } args;
|
||||
*
|
||||
* args.node = arg_int0(...);
|
||||
*
|
||||
* int node = GET_ARG_CSPADDR0(args.node);
|
||||
* \endcode
|
||||
*/
|
||||
#define GET_ARG_CSPADDR0(_arg) GET_ARG_INT0((_arg), csp_get_address())
|
||||
|
||||
/**
|
||||
* Shortcut to get a timeout argument's value, using CSP_DEF_TIMEOUT_MS as default.
|
||||
*/
|
||||
#define GET_ARG_TIMEOUT0(_arg) GET_ARG_INT0((_arg), CONSOLE_CSP_DEF_TIMEOUT_MS)
|
||||
|
||||
/**
|
||||
* Define an optional CSP node argument
|
||||
*/
|
||||
#define arg_cspaddr0() arg_int0(NULL, NULL, "<node>", EXPENDABLE_STRING("node ID"))
|
||||
|
||||
/**
|
||||
* Define a mandatory CSP node argument
|
||||
*/
|
||||
#define arg_cspaddr1() arg_int1(NULL, NULL, "<node>", EXPENDABLE_STRING("node ID"))
|
||||
|
||||
/**
|
||||
* Define an optional timeout argument, with `CSP_DEF_TIMEOUT_MS`
|
||||
* shown as default. Use `GET_ARG_TIMEOUT0()` to retrieve its value.
|
||||
*/
|
||||
#define arg_timeout0() arg_int0("t", "timeout", "<ms>", EXPENDABLE_STRING("timeout in ms (default "STR(CONSOLE_CSP_DEF_TIMEOUT_MS)")"))
|
||||
|
||||
/**
|
||||
* Define a timeout argument with a custom value shown as default.
|
||||
* Use `GET_ARG_INT0()` with the matching default to retrieve its value.
|
||||
*/
|
||||
#define arg_timeout0_def(_def) arg_int0("t", "timeout", "<ms>", EXPENDABLE_STRING("timeout in ms (default "STR(_def)")"))
|
||||
|
||||
|
||||
#define EMPTY_CMD_SETUP(_helptext) \
|
||||
(void)ctx; \
|
||||
static struct { \
|
||||
struct arg_end *end; \
|
||||
} args; \
|
||||
\
|
||||
if (reg) { \
|
||||
args.end = arg_end(1); \
|
||||
\
|
||||
reg->argtable = &args; \
|
||||
reg->help = EXPENDABLE_STRING(_helptext); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Hexdump a buffer
|
||||
*
|
||||
* @param outf - output file
|
||||
* @param data - data to dump
|
||||
* @param len - data size
|
||||
*/
|
||||
void console_hexdump(const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* Decode hexa string to binary
|
||||
*
|
||||
* @param hex - hexa string, upper or lower case, must have even length
|
||||
* @param dest - destination buffer
|
||||
* @param capacity - buffer size
|
||||
* @return destination length, or: -1 (bad args), -2 (bad format), -3 (too long)
|
||||
*/
|
||||
int console_base16_decode(const char *hex, void *dest, size_t capacity);
|
||||
|
||||
#if CONSOLE_USE_MEMSTREAM
|
||||
|
||||
/**
|
||||
* Data struct for the filecap utilities
|
||||
*/
|
||||
struct console_filecap {
|
||||
char *buf;
|
||||
size_t buf_size;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
typedef struct console_filecap console_filecap_t;
|
||||
|
||||
/**
|
||||
* Open a temporary in-memory file that can be used to capture the output
|
||||
* of functions taking a FILE * argument.
|
||||
*
|
||||
* @param cap - pointer to a filecap struct (can be on stack)
|
||||
* @return success
|
||||
*/
|
||||
console_err_t console_filecap_init(console_filecap_t *cap);
|
||||
|
||||
/**
|
||||
* Clean up the capture struct.
|
||||
*
|
||||
* If the buffer is to be used elsewhere, place NULL in the struct to avoid freeing it.
|
||||
*
|
||||
* If the struct itself was allocated on heap, it is the caller's responsibility to free it manually.
|
||||
*
|
||||
* @param cap - pointer to a filecap struct
|
||||
*/
|
||||
void console_filecap_end(console_filecap_t *cap);
|
||||
|
||||
/**
|
||||
* Print the captured output to console output stream and clean up the struct (calls `console_filecap_end()`)
|
||||
*
|
||||
* @param cap - pointer to a filecap struct
|
||||
*/
|
||||
void console_filecap_print_end(console_filecap_t *cap);
|
||||
|
||||
#endif // CONSOLE_USE_MEMSTREAM
|
||||
|
||||
/**
|
||||
* Cross-platform malloc that can be used from console commands.
|
||||
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc)
|
||||
*/
|
||||
void * __attribute__((malloc)) console_malloc(size_t size);
|
||||
|
||||
/**
|
||||
* Cross-platform realloc that can be used from console commands.
|
||||
*
|
||||
* It is not possible to determine the size of an allocated memory region in a portable way,
|
||||
* that's why this function takes the old size as an argument. On POSIX, the argument is simply ignored.
|
||||
*
|
||||
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc).
|
||||
* NOTE: CSP does not provide realloc, therefore this function allocates a new buffer, copies data, and frees the old buffer.
|
||||
*
|
||||
* Returns the original buffer if the new size is <= old size.
|
||||
*/
|
||||
void * console_realloc(void *ptr, size_t oldsize, size_t newsize);
|
||||
|
||||
/**
|
||||
* Cross-platform calloc that can be used from console commands.
|
||||
* If CSP is available and the platform is not POSIX, the implementation from there is used (i.e. FreeRTOS alloc)
|
||||
*/
|
||||
void * __attribute__((malloc,alloc_size(1,2))) console_calloc(size_t nmemb, size_t size);
|
||||
|
||||
/**
|
||||
* `free()` for memory allocated by `console_malloc()` or `console_calloc()`
|
||||
*/
|
||||
void console_free(void *ptr);
|
||||
|
||||
/**
|
||||
* `strdup()` using `console_malloc()`. Free with `console_free()`
|
||||
*/
|
||||
char * console_strdup(const char *ptr);
|
||||
|
||||
/**
|
||||
* `strndup()` using `console_malloc()`. Free with `console_free()`
|
||||
*/
|
||||
char * console_strndup(const char *ptr, size_t maxlen);
|
||||
|
||||
#endif //LIBCONSOLE_UTILS_H
|
||||
Reference in New Issue
Block a user