Loading...
Searching...
No Matches
parser.c
1/***********************************************************************************
2 * @file shell.c *
3 * @author Matt Ricci *
4 * @addtogroup Shell *
5 ***********************************************************************************/
6
7#include "parser.h"
8
9#include <string.h>
10#include <stdbool.h>
11
12/* =============================================================================== */
20ArgParser ArgParser_init() {
21 ArgParser parser;
22 parser.initialised = true;
23 parser.error.status = PARSER_STATUS_OK;
24 parser.error.msg = "";
25 parser.numArgs = 0;
26 parser.numGroups = 0;
27 parser.addArg = ArgParser_addArg;
28 parser.addMutexGroup = ArgParser_addMutexGroup;
29 parser.parseArgs = ArgParser_parseArgs;
30 return parser;
31}
32
33/* =============================================================================== */
42int ArgParser_addArg(ArgParser *parser, const char *name, char shorthand, ArgType type, bool required) {
43 if (parser->numArgs >= MAX_ARGS) {
44 parser->error.status = PARSER_STATUS_ERROR;
45 parser->error.msg = "Error: Too many arguments";
46 return -1;
47 }
48 Argument *arg = &parser->args[parser->numArgs++];
49 strncpy(arg->name, name, MAX_ARG_LEN - 1);
50 arg->name[MAX_ARG_LEN - 1] = '\0';
51 arg->shorthand = shorthand;
52 arg->type = type;
53 arg->required = required;
54 arg->provided = false;
55 arg->value[0] = '\0';
56 return parser->numArgs - 1;
57}
58
59/* =============================================================================== */
68int ArgParser_addMutexGroup(ArgParser *parser, int indices[], int count) {
69 if (parser->numGroups >= MAX_GROUPS) {
70 parser->error.status = PARSER_STATUS_ERROR;
71 parser->error.msg = "Error: Too many exclusion groups";
72 return -1;
73 }
74 ExclusionGroup *group = &parser->groups[parser->numGroups++];
75 group->count = count;
76 for (int i = 0; i < count; i++) {
77 group->indices[i] = indices[i];
78 }
79 return parser->numGroups - 1;
80}
81
82/* =============================================================================== */
91bool ArgParser_parseArgs(ArgParser *parser, int argc, char *argv[]) {
92 for (int i = 0; i < argc; i++) {
93 bool matched = false;
94 for (int j = 0; j < parser->numArgs; j++) {
95 Argument *arg = &parser->args[j];
96 // Match full name or shorthand
97 if (strcmp(argv[i], arg->name) == 0 || (strlen(argv[i]) == 2 && argv[i][0] == '-' && argv[i][1] == arg->shorthand)) {
98 if (arg->type == ARG_TYPE_BOOL) {
99 arg->provided = true;
100 } else if (arg->type == ARG_TYPE_STRING) {
101 if (i + 1 < argc) {
102 strncpy(arg->value, argv[++i], MAX_VALUE_LEN - 1);
103 arg->value[MAX_VALUE_LEN - 1] = '\0';
104 arg->provided = true;
105 } else {
106 // TODO: Make sprintf compatible for arg name print
107 parser->error.status = PARSER_STATUS_ERROR;
108 parser->error.msg = "Error: Missing value for argument";
109 return false;
110 }
111 }
112 matched = true;
113 break;
114 }
115 }
116 if (!matched) {
117 // TODO: Make sprintf compatible for arg name print
118 parser->error.status = PARSER_STATUS_ERROR;
119 parser->error.msg = "Error: Unknown argument";
120 return false;
121 }
122 }
123
124 // Check for required arguments
125 for (int i = 0; i < parser->numArgs; i++) {
126 Argument *arg = &parser->args[i];
127 if (arg->required && !arg->provided) {
128 parser->error.status = PARSER_STATUS_ERROR;
129 parser->error.msg = "Error: Missing required argument";
130 return false;
131 }
132 }
133
134 // Check for mutually exclusive arguments
135 for (int i = 0; i < parser->numGroups; i++) {
136 ExclusionGroup *group = &parser->groups[i];
137 int count = 0;
138 for (int j = 0; j < group->count; j++) {
139 if (parser->args[group->indices[j]].provided) {
140 count++;
141 }
142 }
143 if (count > 1) {
144 parser->error.status = PARSER_STATUS_ERROR;
145 parser->error.msg = "Error: Mutually exclusive arguments provided in group";
146 return false;
147 }
148 }
149
150 return true;
151}