#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "optparser.h"
#include "sopt.h"
#include <cx/hash_map.h>
void cmd_args_free(CmdArgs *args) {
if(args) {
cxMapDestroy(args->options);
if(args->argv) {
free(args->argv);
}
free(args);
}
}
static void cmd_map_put(CxMap *map,
const char *key,
const void *value) {
cxMapPut(map, key, (
void*)value);
}
CmdArgs* cmd_parse_args(
int argc,
char **argv) {
CmdArgs *a = malloc(
sizeof(CmdArgs));
a->options = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
16);
a->argv = argc >
0 ? calloc(argc,
sizeof(
char*)) :
NULL;
a->argc =
0;
const char *
NOARG =
"";
char *option =
NULL;
char optchar =
0;
int optterminated =
0;
for(
int i=
0;i<argc;i++) {
char *arg = argv[i];
size_t len = strlen(arg);
if(len ==
2 && arg[
0] ==
'-' && arg[
1] ==
'-') {
optterminated =
1;
}
else if(!optterminated && len >
1 && arg[
0] ==
'-') {
if(option) {
fprintf(stderr,
"Missing argument for option -%c\n\n", optchar);
cmd_args_free(a);
return NULL;
}
for(
int c=
1;c<len;c++) {
if(option) {
cxMapPut(a->options, cx_hash_key_str(option), &arg[c]);
option =
NULL;
break;
}
switch(arg[c]) {
default: {
fprintf(stderr,
"Unknown option -%c\n\n", arg[c]);
cmd_args_free(a);
return NULL;
}
case 'v': {
cmd_map_put(a->options,
"verbose",
NOARG);
break;
}
case 'k': {
option =
"key";
optchar =
'k';
break;
}
case 'p': {
cmd_map_put(a->options,
"plain",
NOARG);
break;
}
case 'c': {
cmd_map_put(a->options,
"crypt",
NOARG);
break;
}
case 'a': {
cmd_map_put(a->options,
"all",
NOARG);
break;
}
case 'l': {
cmd_map_put(a->options,
"list",
NOARG);
break;
}
case 'd': {
cmd_map_put(a->options,
"date",
NOARG);
break;
}
case 't': {
cmd_map_put(a->options,
"type",
NOARG);
break;
}
case 'R': {
cmd_map_put(a->options,
"recursive",
NOARG);
break;
}
case 'O': {
cmd_map_put(a->options,
"override",
NOARG);
break;
}
case 'i': {
cmd_map_put(a->options,
"insecure",
NOARG);
break;
}
case 'N': {
cmd_map_put(a->options,
"noinput",
NOARG);
break;
}
case 'e': {
cmd_map_put(a->options,
"extended",
NOARG);
break;
}
case 'x': {
cmd_map_put(a->options,
"xml",
NOARG);
break;
}
case 'F': {
option =
"finfo";
optchar =
'F';
break;
}
case 'S': {
cmd_map_put(a->options,
"structure",
NOARG);
break;
}
case 'K': {
cmd_map_put(a->options,
"keep",
NOARG);
break;
}
case 'o': {
option =
"output";
optchar =
'o';
break;
}
case 'u': {
option =
"update";
optchar =
'u';
break;
}
case 'n': {
option =
"namespace";
optchar =
'n';
break;
}
case 'L': {
option =
"lock";
optchar =
'L';
break;
}
case 'T': {
option =
"timeout";
optchar =
'T';
break;
}
case 'V': {
option =
"version";
optchar =
'V';
break;
}
}
}
}
else if(option) {
cmd_map_put(a->options, option, arg);
option =
NULL;
}
else {
a->argv[a->argc++] = arg;
}
}
if(option) {
fprintf(stderr,
"Missing argument for option -%c\n\n", optchar);
cmd_args_free(a);
return NULL;
}
return a;
}
char* cmd_getoption(CmdArgs *arg,
const char *name) {
return cxMapGet(arg->options, cx_hash_key_str(name));
}