Skip to content

Commit

Permalink
added command line argument parser
Browse files Browse the repository at this point in the history
  • Loading branch information
ajaykrishna97 committed Sep 18, 2023
1 parent 57f36be commit 8332251
Show file tree
Hide file tree
Showing 6 changed files with 399 additions and 19 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,12 @@

### 15-JUL-2023
- Added bang and bang bang! support
- Added command history
- Added command history

### 18-SEP-2023
- Added command line argument parser
- Updated example with argument parser
- added argument options
- "-v --version"
- "-h --help"

28 changes: 28 additions & 0 deletions CLI/include/cla_parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* cla_parser.h
*
* Created on: 17-Sep-2023
* Author: Ajay Krishna R
*/

#ifndef INCLUDE_CLA_PARSER_H_
#define INCLUDE_CLA_PARSER_H_

#include <stdbool.h>

typedef enum CLA_ERROR_CODE
{
CLA_NO_ERROR = 0x0000,

CLA_ERROR_TOO_FEW_ARG = 0x0001,
CLA_ERROR_UNKNOWN_OPT = 0x0002,
CLA_ERROR_EXIT_FLAG = 0x0003,

CLA_ERROR_MAX
}CLA_ERROR_CODE_T;

#define CLA_HELPSTR_SPACER 10



#endif /* INCLUDE_CLA_PARSER_H_ */
57 changes: 57 additions & 0 deletions CLI/include/cla_parser_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* cla_parser_api.h
*
* Created on: 17-Sep-2023
* Author: Ajay Krishna R
*/

#ifndef INCLUDE_CLA_PARSER_API_H_
#define INCLUDE_CLA_PARSER_API_H_

#include "dtypes.h"

#define CLA_DEBUG_EN 1

#define PRINTF_CLA printf

#define LOG_DEBUG_CLA if(CLA_DEBUG_EN) PRINTF_CLA
#define LOG_ERROR_CLA PRINTF_CLA("CLA_ERROR:"); \
PRINTF_CLA

#define LOGD_CLA(...) LOG_DEBUG_CLA(__VA_ARGS__)
#define LOGE_CLA(...) LOG_ERROR_CLA(__VA_ARGS__)


#define CLA_HDLR(cla_char) bool cla_char ## _method_CLA(char **args ,uint16_t argc)

#define CLA_ADD(cla_char , cla_str , exit_flag , arg_count, help_str) \
{cla_char , #cla_str , exit_flag, cla_str ## _method_CLA , arg_count,help_str}

typedef bool (*cla_handler)(char **args , uint16_t argc);


typedef enum CLI_ARG_STATUS
{
CLA_FAILED = -1,
CLA_SUCCESS =0,
CLA_EXIT = 1,
}CLA_STATUS;


typedef struct cla_context_st
{
char cla_char;
char *cla_alt_string;

bool exit_flag;
cla_handler handler;
uint8_t arg_count;
char *help_string;

}cla_ctx, *p_cla_ctx;

CLA_STATUS cla_parse(cla_ctx *cla_list, char** args , uint16_t argc);
void cla_print_help(cla_ctx *cla_list);


#endif /* INCLUDE_CLA_PARSER_API_H_ */
251 changes: 251 additions & 0 deletions CLI/src/cla_parser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/*
* cla_parser.c
*
* Created on: 17-Sep-2023
* Author: Ajay Krishna R
*/

#include "cla_parser.h"
#include "cla_parser_api.h"
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

#include "helper.h"


static char *error_string[CLA_ERROR_MAX] =
{
"Success",
"Too few argument",
"Unknown opt"
"Exit flag true"
};

CLA_ERROR_CODE_T validate_cla(cla_ctx *cla_list ,char** args ,uint16_t argc, bool invoke_flag)
{
CLA_ERROR_CODE_T status = CLA_NO_ERROR;

if(NULL != cla_list)
{

for(int32_t i=0;i< argc;i++)
{
if('-' == args[i][0])
{
if('-' == args[i][1])
{
status = CLA_ERROR_UNKNOWN_OPT;

for(p_cla_ctx ctx = cla_list; ctx->cla_alt_string != NULL; ctx++)
{
if(strcmp(ctx->cla_alt_string,&args[i][1]))
{
status = CLA_NO_ERROR;

if((i+ctx->arg_count) < argc)
{
for(int32_t j = i+1 ; j < i+ctx->arg_count ;j++)
{
if('-' == args[j][0])
{
status = CLA_ERROR_TOO_FEW_ARG;
break;
}
}
if (status != CLA_NO_ERROR)
{
break;
} else {
i = i+ctx->arg_count;
break;
}
}
else{
status = CLA_ERROR_TOO_FEW_ARG;
break;
}
}
}

if(CLA_NO_ERROR == status)
{
/*DO NOTHING*/
}
else
{
LOGD_CLA(
"validation failed for argument:%s | Reason:%s\n",
args[i],error_string[status]);
break;
}
}
else
{
status = CLA_ERROR_UNKNOWN_OPT;

for(p_cla_ctx ctx = cla_list; ctx->cla_alt_string != NULL; ctx++)
{
if(ctx->cla_char == args[i][1])
{
status = CLA_NO_ERROR;

if((i+ctx->arg_count) < argc)
{
for(int32_t j = i+1 ; j < i+ctx->arg_count ;j++)
{
if('-' == args[j][0])
{
status = CLA_ERROR_TOO_FEW_ARG;
break;
}
}
if (status != CLA_NO_ERROR)
{
break;
} else {
i = i+ctx->arg_count;
break;
}
}
else{
status = CLA_ERROR_TOO_FEW_ARG;
break;
}
}
}

if(CLA_NO_ERROR == status)
{
/*DO NOTHING*/
}
else
{
LOGD_CLA(
"validation failed for argument:%s | Reason:%s\n",
args[i],error_string[status]);
break;
}

}
}
else
{
LOGD_CLA("Invalid argument:%s\n",args[i]);
}
}
}
else
{
}

return status;
}

CLA_ERROR_CODE_T invoke_cla(cla_ctx *cla_list, char **args, uint16_t argc, bool invoke_flag)
{
CLA_STATUS ret_val = CLA_NO_ERROR;
bool exit_flag = false;

if (NULL != cla_list) {

for (int32_t i = 0; i < argc; i++)
{
if ('-' == args[i][0]) {
if ('-' == args[i][1])
{

for (p_cla_ctx ctx = cla_list; ctx->cla_alt_string != NULL;
ctx++)
{
if (strcmp(ctx->cla_alt_string, &args[i][1]))
{
ctx->handler(&args[i + 1], ctx->arg_count);
i = i+ctx->arg_count;
exit_flag = ctx->exit_flag;

break;
}
}
}
else
{
for (p_cla_ctx ctx = cla_list; ctx->cla_alt_string != NULL;
ctx++)
{
if (ctx->cla_char == args[i][1])
{
ctx->handler(&args[i + 1], ctx->arg_count);
i = i+ctx->arg_count;
exit_flag = ctx->exit_flag;
break;
}
}
}
} else {
}

if(exit_flag == true)
{
ret_val = CLA_ERROR_EXIT_FLAG;
break;
}
}
}
else {
}

return (ret_val);
}


CLA_STATUS cla_parse(cla_ctx *cla_list, char** args , uint16_t argc)
{
CLA_STATUS status = CLA_SUCCESS;
if(NULL != args && argc > 1&& cla_list != NULL)
{

if(CLA_NO_ERROR == validate_cla(cla_list,&args[1],(argc-1),false))
{
CLA_ERROR_CODE_T invocation_status;

invocation_status = invoke_cla(cla_list,&args[1],(argc-1),false);

switch(invocation_status)
{
case CLA_NO_ERROR:
status = CLA_SUCCESS;
break;
case CLA_ERROR_UNKNOWN_OPT:
status = CLA_FAILED;
break;
case CLA_ERROR_TOO_FEW_ARG:
status = CLA_FAILED;
break;
case CLA_ERROR_EXIT_FLAG:
status = CLA_EXIT;
break;
case CLA_ERROR_MAX:
status = CLA_FAILED;
break;
}
}
else{
status = CLA_FAILED;
}
}

return status;
}



void cla_print_help(cla_ctx *cla_list)
{
for (p_cla_ctx ctx = cla_list; ctx->cla_alt_string != NULL;
ctx++)
{
LOGD_CLA("-%c --%s%s%s\n",ctx->cla_char,ctx->cla_alt_string, printFormatSpace(ctx->cla_alt_string,CLA_HELPSTR_SPACER),ctx->help_string);
}
}
Loading

0 comments on commit 8332251

Please sign in to comment.