From 967ad7898243e083f485a03414fce0018bfce881 Mon Sep 17 00:00:00 2001 From: gramanas Date: Wed, 14 Nov 2018 21:01:08 +0200 Subject: Rename actionparser to clparser --- CMakeLists.txt | 4 +- src/actionhelper.h | 2 +- src/actionparser.c | 429 ----------------------------------------------------- src/actionparser.h | 76 ---------- src/actions.h | 2 +- src/clparser.c | 412 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/clparser.h | 68 +++++++++ src/confparser.h | 2 +- src/dbhelper.h | 2 +- 9 files changed, 486 insertions(+), 511 deletions(-) delete mode 100644 src/actionparser.c delete mode 100644 src/actionparser.h create mode 100644 src/clparser.c create mode 100644 src/clparser.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e3ea656..8d88de5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,7 @@ configure_file( set(ckBin_src ${SRC_DIR}/ck.c) set(ckUnitTest_src ${UNIT_TEST_DIR}/ck-test.c) set(ckLib_src - ${SRC_DIR}/actionparser.c + ${SRC_DIR}/clparser.c ${SRC_DIR}/actions.c ${SRC_DIR}/actionhelper.c ${SRC_DIR}/confparser.c @@ -67,7 +67,7 @@ set(ckLib_src ) set(ckLib_hdr - ${SRC_DIR}/actionparser.h + ${SRC_DIR}/clparser.h ${SRC_DIR}/actions.h ${SRC_DIR}/actionhelper.h ${SRC_DIR}/confparser.h diff --git a/src/actionhelper.h b/src/actionhelper.h index 0c96a8a..f7da0dd 100644 --- a/src/actionhelper.h +++ b/src/actionhelper.h @@ -56,7 +56,7 @@ int restore_make_links(cklist *from, cklist *to); /************************/ /* PRINT RESULTS & HELP */ /************************/ -#define X(ACTION) \ +#define X(ACTION) \ void print_##ACTION##_result(int err); \ void print_##ACTION##_help(void); CK_ACTIONS diff --git a/src/actionparser.c b/src/actionparser.c deleted file mode 100644 index 398ba5e..0000000 --- a/src/actionparser.c +++ /dev/null @@ -1,429 +0,0 @@ -/* actionparser.c - Action parser for ck -------------------------------*- C -*- - * - * This file is part of ck, the config keeper - * - * ----------------------------------------------------------------------------- - * - * Copyright (C) 2018 Anastasis Grammenos - * GPLv3 (see LICENCE for the full notice) - * - * -------------------------------------------------------------------------- */ -#include "ckutil.h" -#include "actionparser.h" -#include "confparser.h" -#include "ckinfo.h" -#include "ckerrlog.h" - -ERRLOG(parser); - -/* accepted commands */ -/* [0] is the count */ -const char* const strINIT[] = {"3", "init", "i", "-i"}; -const char* const strADD[] = {"3", "add", "a", "-a"}; -const char* const strDEL[] = {"4", "delete", "del","d", "-d"}; -const char* const strEDIT[] = {"3", "edit", "e", "-e"}; -const char* const strLIST[] = {"5", "list", "ls", "l", "-l", "-ls"}; -const char* const strSEARCH[] = {"4", "search", "grep", "s", "-s"}; -const char* const strHELP[] = {"5", "help", "h", "-?", "-h", "--help"}; -const char* const strRESTORE[] = {"3", "restore","r", "-r"}; -const char* const strConfDir[] = {"2", "--config", "-c"}; -const char* const strVerbose1[] = {"2", "--verbose", "-v"}; -const char* const strVersion[] = {"2", "version", "--version"}; -const char* const strVerbose2[] = {"2", "--Verbose", "-V"}; - -/* Number of opts */ -static int optNum; - -/* holds the list of the opts - * as given by the user */ -static const char **opts; - -/* points to the current token */ -static const char *token; - -/* the position to be read */ -static int pos = 0; - -/* Advance one token. - * Returns 1 if it exists - * 0 otherwise */ -int next_token() { - if (pos < optNum) { - token = opts[pos]; - pos++; - return 1; - } - else { - token = NULL; - return 0; - } -} - -void fill_args_list(int arg_num, UserOpt *opt) { - for (int i = 0; i < arg_num; i++) { - if (next_token()) { - list_add(opt->args, token); - } - } -} - -/* When starting to parse the action, - * `pos` should be at 2 - * like so "ck ACTION ..." - * ^ */ -int parse_INIT(UserOpt *opt) { - /* INIT expects 2 arguments - * starting from 0 */ - int arg_num = 2; - if (optNum != pos /* already consumed */ + arg_num) { - opt->err = PERR_INIT_WRONG; - return -1; - } - - fill_args_list(arg_num, opt); - return 0; -} - -int parse_ADD(UserOpt *opt) { - /* ADD expects 2 to 4 arguments */ - if (optNum < pos + 2 - || optNum > pos + 4) { - opt->err = PERR_ADD_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_DEL(UserOpt *opt) { - /* DEL expects 1 to 2 arguments */ - if (optNum < pos + 1 - || optNum > pos + 2) { - opt->err = PERR_DEL_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_EDIT(UserOpt *opt) { - /* EDIT expects 1 to 2 arguments */ - if (optNum < pos + 1 - || optNum > pos + 2) { - opt->err = PERR_EDIT_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_LIST(UserOpt *opt) { - /* List expects 1 to 6 arguments */ - if (optNum < pos + 1 - || optNum > pos + 6) { - opt->err = PERR_LIST_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_SEARCH(UserOpt *opt) { - /* Search expects a maximum of 1 argument */ - if (optNum < pos + 1 - || optNum > pos + 1) { - opt->err = PERR_SEARCH_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_HELP(UserOpt *opt) { - /* Help expects a maximum of 1 argument */ - if (optNum < pos + 1 - || optNum > pos + 1) { - opt->err = PERR_HELP_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -int parse_RESTORE(UserOpt *opt) { - /* Restore expects 1 to 2 arguments */ - if (optNum < pos + 1 - || optNum > pos + 2) { - opt->err = PERR_RESTORE_WRONG; - return -1; - } - - int arg_num = optNum - pos; - fill_args_list(arg_num, opt); - return 0; -} - -void determine_action(UserOpt *opt) { - /* get action */ - if (!next_token()) { - opt->action = CK_WRONG_ACTION; - return; - } - - char actionName[STR_S] = ""; - opt->action = parser_get_action(token, actionName); - if (opt->action != CK_WRONG_ACTION) { - LOG("Action to perform: %s", actionName); - } - return; -} - -int parse_vals(UserOpt *opt) { - /* find the action */ - determine_action(opt); - if (opt->action == CK_WRONG_ACTION) { - opt->err = PERR_UNKNOWN_ACTION; - return -1; - } - - switch (opt->action) { -#define X(ACTION) \ - case CKA_##ACTION: \ - return parse_##ACTION(opt); - CK_ACTIONS -#undef X - default: - return -1; - } -} - -CkAction parser_get_action(const char *name, char *actionName) { - int i; -#define X(ACTION) \ - for (i = 1; i < atoi(str##ACTION[0]) + 1; i++) { \ - if (strcmp(name, str##ACTION[i]) == 0) { \ - if (actionName) { \ - strcpy(actionName, str##ACTION[1]); \ - } \ - return CKA_##ACTION; \ - } \ - } - CK_ACTIONS; -#undef X - return CK_WRONG_ACTION; -} - -UserOpt make_empty_user_opt() { - UserOpt opt; - opt.action = CK_WRONG_ACTION; - opt.err = PERR_NOERR; - opt.confDir = NULL; - opt.args = list_make_new(); - return opt; -} - - -/* called to free the resources - * UserOpt holds */ -void free_user_opt(UserOpt *opt) { - if (opt->confDir != NULL) { - free(opt->confDir); - } - list_free(opt->args); -} - -/* find the correct config */ -int get_config(UserOpt *opt) { - /* If it's a cli option */ - if (next_token()) { - for (int i = 1; i < atoi(strConfDir[0]) + 1; i++) { - if (strcmp(token, strConfDir[i]) == 0) { - if (!next_token()) { - ERR("Config needs a value"); - return -1; - } - char dir[STR_L] = ""; - realpath(token, dir); - if (!util_is_dir(dir)) { - ERR("%s is not a directory", token); - return -1; - } - opt->confDir = malloc(strlen(dir) + 1); - strcpy(opt->confDir, dir); - // remove trailing `/` - if (opt->confDir[strlen(dir) - 1] == '/') { - opt->confDir[strlen(dir) - 1] = '\0'; - } - return 0; - } - } - /* rewind */ - pos = pos - 1; - token = opts[pos]; - } - - return find_config(opt); -} - -int version() { - /* get first token */ - if (next_token()) { - for (int i = 1; i < atoi(strVersion[0]) + 1; i++) { - if (strcmp(token, strVersion[i]) == 0) { - print_version(); - return 1; - } - } - // rewind - pos = pos - 1; - token = opts[pos]; - } - return 0; -} - -void verbose() { - /* get first token */ - if (next_token()) { - for (int i = 1; i < atoi(strVerbose1[0]) + 1; i++) { - if (strcmp(token, strVerbose1[i]) == 0) { - errlog_set_verbose(1); - return; - } - } - - for (int i = 1; i < atoi(strVerbose2[0]) + 1; i++) { - if (strcmp(token, strVerbose2[i]) == 0) { - errlog_set_verbose(2); - return; - } - } - - // rewind - pos = pos - 1; - token = opts[pos]; - } -} - -char * get_possible_action_strings(char *dest, CkAction ckAction) { - char buf[STR_M] = ""; - switch (ckAction) { -#define X(ACTION) \ - case CKA_##ACTION: \ - strcpy(buf, "{ "); \ - for (int i = 1; i < atoi(str##ACTION[0]); i++) { \ - strcat(buf, str##ACTION[i]); \ - strcat(buf, ", "); \ - } \ - strcat(buf, str##ACTION[atoi(str##ACTION[0])]); \ - strcat(buf, " }"); \ - break; - CK_ACTIONS -#undef X - default: - dest = NULL; - return NULL; - } - - strcpy(dest, buf); - return dest; -} - -void print_parser_error(UserOpt *opt) { - char errStr[STR_L] = ""; - char names[STR_M] = ""; - get_possible_action_strings(names, opt->action); - - switch (opt->err) { - case PERR_NOERR: - return; - case PERR_UNKNOWN_ACTION: - ERR("Unknown action: %s", token); - return; - case PERR_INIT_WRONG: - sprintf(errStr, "Initialize database\nUsage: %s version_control_dir secret_dir", names); - break; - case PERR_ADD_WRONG: - sprintf(errStr, "Add config \nUsage: %s ProgramName ConfigPath [-s](secret) [-p](primary)", names); - break; - case PERR_DEL_WRONG: - sprintf(errStr, "Delete config or program\nUsage: %s {ProgramName} | {-c ConfigPath (as shown by ck list)}", names); - break; - case PERR_EDIT_WRONG: - sprintf(errStr, "Edit config with $EDITOR (%s)\nUsage: %s ProgramName [configBasename]", getenv("EDITOR"), names); - break; - case PERR_LIST_WRONG: - sprintf(errStr, "List programs, configs and more\nUsage: %s {programs|paths|-p ProgramName} [-t list-type] | {tree | ckconf} [-a] [-b]", names); - break; - case PERR_SEARCH_WRONG: - sprintf(errStr, "Search through the configs with grep\nUsage: %s search-term", names); - break; - case PERR_HELP_WRONG: - sprintf(errStr, "Get help for a ck action.\nUsage: %s action", names); - break; - case PERR_RESTORE_WRONG: - sprintf(errStr, "Restore links of programs.\nUsage: %s {all} | {-p programName}", names); - } - HELP("%s", errStr); -} - -void print_parser_help() { - char names[STR_M] = ""; - ckhelp("ck - the config keeper"); - ckhelp("Usage:"); - ckhelp("Init\t%s", get_possible_action_strings(names, CKA_INIT)); - ckhelp("Add\t%s", get_possible_action_strings(names, CKA_ADD)); - ckhelp("Delete\t%s", get_possible_action_strings(names, CKA_DEL)); - ckhelp("Edit\t%s", get_possible_action_strings(names, CKA_EDIT)); - ckhelp("List\t%s", get_possible_action_strings(names, CKA_LIST)); - ckhelp("Search\t%s", get_possible_action_strings(names, CKA_SEARCH)); - ckhelp("Restore\t%s", get_possible_action_strings(names, CKA_RESTORE)); - ckhelp("Help\t%s", get_possible_action_strings(names, CKA_HELP)); - report_help(); -} - -int parse_action(int argc, const char **argv, UserOpt *opt) { - /* make empty user opt */ - *opt = make_empty_user_opt(); - opts = argv; - optNum = argc; - /* skip the program name */ - next_token(); - /* set verbose level */ - verbose(); - /* handle version info */ - if (version()) { - return -1; - } - /* figure what is the config file */ - if (get_config(opt)) { - return -1; - } - /* If the remaining arguments are < 1 - * print help and exit */ - if (optNum - pos < 1) { - print_parser_help(); - return -1; - } - /* parse values */ - if (parse_vals(opt)) { - print_parser_error(opt); - return -1; - } - if (opt->err == PERR_NOERR) { - return 0; - } - print_parser_error(opt); - return -1; -} diff --git a/src/actionparser.h b/src/actionparser.h deleted file mode 100644 index 24ad763..0000000 --- a/src/actionparser.h +++ /dev/null @@ -1,76 +0,0 @@ -/* actionparser.h - Action parser for ck -------------------------------*- C -*- - * - * This file is part of ck, the config keeper - * - * ----------------------------------------------------------------------------- - * - * Copyright (C) 2018 Anastasis Grammenos - * GPLv3 (see LICENCE for the full notice) - * - * ----------------------------------------------------------------------------- - * - * The code here and in actionparser.c is responsible for parsing - * the user's input from the command line and return a struct - * of the user's options ready to be handled by the rest of the - * procedures. - * - * -------------------------------------------------------------------------- */ -#ifndef ACTIONPARSER_H -#define ACTIONPARSER_H - -#include "cklist.h" - -#define CK_ACTIONS \ - X(INIT) \ - X(ADD) \ - X(DEL) \ - X(EDIT) \ - X(LIST) \ - X(SEARCH) \ - X(RESTORE) \ - X(HELP) - -enum ParseErrors { - PERR_NOERR = 0, -#define X(ACTION) \ - PERR_##ACTION##_WRONG, - CK_ACTIONS -#undef X - PERR_UNKNOWN_ACTION, -}; -typedef enum ParseErrors ParseError; - -enum CkActions { - CK_WRONG_ACTION, -#define X(ACTION) \ - CKA_##ACTION, - CK_ACTIONS -#undef X -}; -typedef enum CkActions CkAction; - -enum ActionParserResults { - APR_OK, - APR_ERR, - APR_HELP, - APR_VERSION -}; -typedef enum ActionParserResults ActionParseResult; - -typedef struct UserOptions UserOpt; -struct UserOptions { - ParseError err; - CkAction action; - char *confDir; - cklist *args; -}; - - -/* Parse cli args, fill UserOpt struct - * and return the result enum */ -int parse_action(int argc, const char **argv, UserOpt *opt); -CkAction parser_get_action(const char *name, char *actionName); -char * get_possible_action_strings(char *dest, CkAction ckAction); -void free_user_opt(UserOpt *opt); - -#endif // ACTIONPARSER_H diff --git a/src/actions.h b/src/actions.h index aa8cf44..d261cc6 100644 --- a/src/actions.h +++ b/src/actions.h @@ -17,7 +17,7 @@ #define ACTIONS_H #include "ckutil.h" -#include "actionparser.h" +#include "clparser.h" #include "confparser.h" #define X(ACTION) \ diff --git a/src/clparser.c b/src/clparser.c new file mode 100644 index 0000000..6dbd62a --- /dev/null +++ b/src/clparser.c @@ -0,0 +1,412 @@ +/* clparser.c - Command line parser for ck -----------------------------*- C -*- + * + * This file is part of ck, the config keeper + * + * ----------------------------------------------------------------------------- + * + * Copyright (C) 2018 Anastasis Grammenos + * GPLv3 (see LICENCE for the full notice) + * + * -------------------------------------------------------------------------- */ +#include "ckutil.h" +#include "clparser.h" +#include "confparser.h" +#include "ckinfo.h" +#include "ckerrlog.h" +#include "actionhelper.h" + +ERRLOG(parser); + +/* accepted commands */ +/* [0] is the count */ +const char* const strINIT[] = {"3", "init", "i", "-i"}; +const char* const strADD[] = {"3", "add", "a", "-a"}; +const char* const strDEL[] = {"4", "delete", "del","d", "-d"}; +const char* const strEDIT[] = {"3", "edit", "e", "-e"}; +const char* const strLIST[] = {"5", "list", "ls", "l", "-l", "-ls"}; +const char* const strSEARCH[] = {"4", "search", "grep", "s", "-s"}; +const char* const strHELP[] = {"5", "help", "h", "-?", "-h", "--help"}; +const char* const strRESTORE[] = {"3", "restore","r", "-r"}; +const char* const strConfDir[] = {"2", "--config", "-c"}; +const char* const strVerbose1[] = {"2", "--verbose", "-v"}; +const char* const strVersion[] = {"2", "version", "--version"}; +const char* const strVerbose2[] = {"2", "--Verbose", "-V"}; + +/* Number of opts */ +static int optNum; + +/* holds the list of the opts + * as given by the user */ +static const char **opts; + +/* points to the current token */ +static const char *token; + +/* the position to be read */ +static int pos = 0; + +/* Advance one token. + * Returns 1 if it exists + * 0 otherwise */ +int next_token() { + if (pos < optNum) { + token = opts[pos]; + pos++; + return 1; + } + else { + token = NULL; + return 0; + } +} + +static void fill_args_list(int arg_num, UserOpt *opt) { + for (int i = 0; i < arg_num; i++) { + if (next_token()) { + list_add(opt->args, token); + } + } +} + +/* When starting to parse the action, + * `pos` should be at 2 + * like so "ck ACTION ..." + * ^ */ +static int parse_INIT(UserOpt *opt) { + /* INIT expects 2 arguments + * starting from 0 */ + int arg_num = 2; + if (optNum != pos /* already consumed */ + arg_num) { + opt->err = PERR_INIT_WRONG; + return -1; + } + + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_ADD(UserOpt *opt) { + /* ADD expects 2 to 4 arguments */ + if (optNum < pos + 2 + || optNum > pos + 4) { + opt->err = PERR_ADD_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_DEL(UserOpt *opt) { + /* DEL expects 1 to 2 arguments */ + if (optNum < pos + 1 + || optNum > pos + 2) { + opt->err = PERR_DEL_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_EDIT(UserOpt *opt) { + /* EDIT expects 1 to 2 arguments */ + if (optNum < pos + 1 + || optNum > pos + 2) { + opt->err = PERR_EDIT_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_LIST(UserOpt *opt) { + /* List expects 1 to 6 arguments */ + if (optNum < pos + 1 + || optNum > pos + 6) { + opt->err = PERR_LIST_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_SEARCH(UserOpt *opt) { + /* Search expects a maximum of 1 argument */ + if (optNum < pos + 1 + || optNum > pos + 1) { + opt->err = PERR_SEARCH_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_HELP(UserOpt *opt) { + /* Help expects a maximum of 1 argument */ + if (optNum < pos + 1 + || optNum > pos + 1) { + opt->err = PERR_HELP_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static int parse_RESTORE(UserOpt *opt) { + /* Restore expects 1 to 2 arguments */ + if (optNum < pos + 1 + || optNum > pos + 2) { + opt->err = PERR_RESTORE_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} + +static void determine_action(UserOpt *opt) { + /* get action */ + if (!next_token()) { + opt->action = CK_WRONG_ACTION; + return; + } + + char actionName[STR_S] = ""; + opt->action = parser_get_action(token, actionName); + if (opt->action != CK_WRONG_ACTION) { + LOG("Action to perform: %s", actionName); + } + return; +} + +static int parse_vals(UserOpt *opt) { + /* find the action */ + determine_action(opt); + if (opt->action == CK_WRONG_ACTION) { + opt->err = PERR_UNKNOWN_ACTION; + return -1; + } + + switch (opt->action) { +#define X(ACTION) \ + case CKA_##ACTION: \ + return parse_##ACTION(opt); + CK_ACTIONS +#undef X + default: + return -1; + } +} + +CkAction parser_get_action(const char *name, char *actionName) { + int i; +#define X(ACTION) \ + for (i = 1; i < atoi(str##ACTION[0]) + 1; i++) { \ + if (strcmp(name, str##ACTION[i]) == 0) { \ + if (actionName) { \ + strcpy(actionName, str##ACTION[1]); \ + } \ + return CKA_##ACTION; \ + } \ + } + CK_ACTIONS; +#undef X + return CK_WRONG_ACTION; +} + +static UserOpt make_empty_user_opt() { + UserOpt opt; + opt.action = CK_WRONG_ACTION; + opt.err = PERR_NOERR; + opt.confDir = NULL; + opt.args = list_make_new(); + return opt; +} + + +/* called to free the resources + * UserOpt holds */ +void free_user_opt(UserOpt *opt) { + if (opt->confDir != NULL) { + free(opt->confDir); + } + list_free(opt->args); +} + +/* find the correct config */ +static int get_config(UserOpt *opt) { + /* If it's a cli option */ + if (next_token()) { + for (int i = 1; i < atoi(strConfDir[0]) + 1; i++) { + if (strcmp(token, strConfDir[i]) == 0) { + if (!next_token()) { + ERR("Config needs a value"); + return -1; + } + char dir[STR_L] = ""; + realpath(token, dir); + if (!util_is_dir(dir)) { + ERR("%s is not a directory", token); + return -1; + } + opt->confDir = malloc(strlen(dir) + 1); + strcpy(opt->confDir, dir); + // remove trailing `/` + if (opt->confDir[strlen(dir) - 1] == '/') { + opt->confDir[strlen(dir) - 1] = '\0'; + } + return 0; + } + } + /* rewind */ + pos = pos - 1; + token = opts[pos]; + } + + return find_config(opt); +} + +static int version() { + /* get first token */ + if (next_token()) { + for (int i = 1; i < atoi(strVersion[0]) + 1; i++) { + if (strcmp(token, strVersion[i]) == 0) { + print_version(); + return 1; + } + } + // rewind + pos = pos - 1; + token = opts[pos]; + } + return 0; +} + +static void verbose() { + /* get first token */ + if (next_token()) { + for (int i = 1; i < atoi(strVerbose1[0]) + 1; i++) { + if (strcmp(token, strVerbose1[i]) == 0) { + errlog_set_verbose(1); + return; + } + } + + for (int i = 1; i < atoi(strVerbose2[0]) + 1; i++) { + if (strcmp(token, strVerbose2[i]) == 0) { + errlog_set_verbose(2); + return; + } + } + + // rewind + pos = pos - 1; + token = opts[pos]; + } +} + +char * get_possible_action_strings(char *dest, CkAction ckAction) { + char buf[STR_M] = ""; + switch (ckAction) { +#define X(ACTION) \ + case CKA_##ACTION: \ + strcpy(buf, "{ "); \ + for (int i = 1; i < atoi(str##ACTION[0]); i++) { \ + strcat(buf, str##ACTION[i]); \ + strcat(buf, ", "); \ + } \ + strcat(buf, str##ACTION[atoi(str##ACTION[0])]); \ + strcat(buf, " }"); \ + break; + CK_ACTIONS +#undef X + default: + dest = NULL; + return NULL; + } + + strcpy(dest, buf); + return dest; +} + +static void print_parser_error(UserOpt *opt) { + char names[STR_M] = ""; + get_possible_action_strings(names, opt->action); + + switch (opt->err) { + case PERR_NOERR: + return; + case PERR_UNKNOWN_ACTION: + ERR("Unknown action: %s", token); + return; +#define X(ACTION) \ + case PERR_ ##ACTION## _WRONG: \ + HELP("Usage:\n%s", names); \ + print_##ACTION##_help(); \ + break; + CK_ACTIONS; +#undef X + } +} + +static void print_parser_help() { + char names[STR_M] = ""; + ckhelp("ck - the config keeper"); + ckhelp("Usage:"); + ckhelp("Init\t%s", get_possible_action_strings(names, CKA_INIT)); + ckhelp("Add\t%s", get_possible_action_strings(names, CKA_ADD)); + ckhelp("Delete\t%s", get_possible_action_strings(names, CKA_DEL)); + ckhelp("Edit\t%s", get_possible_action_strings(names, CKA_EDIT)); + ckhelp("List\t%s", get_possible_action_strings(names, CKA_LIST)); + ckhelp("Search\t%s", get_possible_action_strings(names, CKA_SEARCH)); + ckhelp("Restore\t%s", get_possible_action_strings(names, CKA_RESTORE)); + ckhelp("Help\t%s", get_possible_action_strings(names, CKA_HELP)); + report_help(); +} + +int parse_action(int argc, const char **argv, UserOpt *opt) { + /* make empty user opt */ + *opt = make_empty_user_opt(); + opts = argv; + optNum = argc; + /* skip the program name */ + next_token(); + /* set verbose level */ + verbose(); + /* handle version info */ + if (version()) { + return -1; + } + /* figure what is the config file */ + if (get_config(opt)) { + return -1; + } + /* If the remaining arguments are < 1 + * print help and exit */ + if (optNum - pos < 1) { + print_parser_help(); + return -1; + } + /* parse values */ + if (parse_vals(opt)) { + print_parser_error(opt); + return -1; + } + if (opt->err == PERR_NOERR) { + return 0; + } + print_parser_error(opt); + return -1; +} diff --git a/src/clparser.h b/src/clparser.h new file mode 100644 index 0000000..9b22b87 --- /dev/null +++ b/src/clparser.h @@ -0,0 +1,68 @@ +/* clparser.h - Command line parser for ck -----------------------------*- C -*- + * + * This file is part of ck, the config keeper + * + * ----------------------------------------------------------------------------- + * + * Copyright (C) 2018 Anastasis Grammenos + * GPLv3 (see LICENCE for the full notice) + * + * ----------------------------------------------------------------------------- + * + * The code here and in clparser.c is responsible for parsing + * the user's input from the command line and return a struct + * of the user's options ready to be handled by the rest of the + * procedures. + * + * -------------------------------------------------------------------------- */ +#ifndef CLPARSER_H +#define CLPARSER_H + +#include "cklist.h" + +#define CK_ACTIONS \ + X(INIT) \ + X(ADD) \ + X(DEL) \ + X(EDIT) \ + X(LIST) \ + X(SEARCH) \ + X(RESTORE) \ + X(HELP) + +enum ParseErrors { + PERR_NOERR = 0, +#define X(ACTION) \ + PERR_##ACTION##_WRONG, + CK_ACTIONS +#undef X + PERR_UNKNOWN_ACTION, +}; +typedef enum ParseErrors ParseError; + +enum CkActions { + CK_WRONG_ACTION, +#define X(ACTION) \ + CKA_##ACTION, + CK_ACTIONS +#undef X +}; +typedef enum CkActions CkAction; + +typedef struct UserOptions UserOpt; +struct UserOptions { + ParseError err; + CkAction action; + char *confDir; + cklist *args; +}; + + +/* Parse cli args, fill UserOpt struct + * and return the result enum */ +int parse_action(int argc, const char **argv, UserOpt *opt); +CkAction parser_get_action(const char *name, char *actionName); +char * get_possible_action_strings(char *dest, CkAction ckAction); +void free_user_opt(UserOpt *opt); + +#endif // CLPARSER_H diff --git a/src/confparser.h b/src/confparser.h index 11ada7f..ebcf0c7 100644 --- a/src/confparser.h +++ b/src/confparser.h @@ -16,7 +16,7 @@ #ifndef CONFPARSER_H #define CONFPARSER_H -#include "actionparser.h" +#include "clparser.h" #define CONFIG_VARIABLES_TABLE \ X(vc_dir, " version_control_dir = %s ", "Version Control directory") \ diff --git a/src/dbhelper.h b/src/dbhelper.h index 86e3a99..31559cc 100644 --- a/src/dbhelper.h +++ b/src/dbhelper.h @@ -18,7 +18,7 @@ #include -#include "actionparser.h" +#include "clparser.h" #include "ckutil.h" /********************/ -- cgit v1.2.3