initial commit
This commit is contained in:
commit
d92b42f49c
|
@ -0,0 +1 @@
|
|||
example
|
|
@ -0,0 +1,10 @@
|
|||
.PHONY: all clean
|
||||
ALL=clean example
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
clean:
|
||||
rm -f example
|
||||
|
||||
example:
|
||||
gcc example.c -o example
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARGH_PARSE \
|
||||
bool argh_used = true; \
|
||||
bool argh_repeat = false; \
|
||||
bool argh_val = false; \
|
||||
char *ARGH_ARGV[argc]; \
|
||||
char *argh_name; \
|
||||
int ARGH_ARGC = 0; \
|
||||
int argh_diff = 0; \
|
||||
int argh_offset = 0; \
|
||||
while(argh_offset < argc)
|
||||
|
||||
// check for a flag which is either present or not
|
||||
#define ARGH_BOOL(short_name, long_name) \
|
||||
/* ARGH_VAL cannot be used with ARGH_BOOL */ \
|
||||
(argh_name = NULL, \
|
||||
/* short name exact match */ \
|
||||
(( 0 == strcmp(argv[argh_offset], short_name) \
|
||||
/* short name prefix match, for specify multiple short names with a single param, -xyz instead -x -y -z. this mutates argv for the next pass, -xyz to -yz */ \
|
||||
|| ((0 == strncmp(argv[argh_offset], short_name, 2) && strlen(argv[argh_offset]) > 2 && (argv[argh_offset]++, argv[argh_offset][0] = '-', argh_repeat = true))) \
|
||||
/* long name exact match */ \
|
||||
|| 0 == strcmp(argv[argh_offset], long_name)) \
|
||||
/* set argh_used to avoid adding to ARGH_ARGV, return true */ \
|
||||
? argh_used = true \
|
||||
/* return false */ \
|
||||
: false))
|
||||
|
||||
// check for a flag which if present is followed by a value
|
||||
#define ARGH_FLAG(short_name, long_name) \
|
||||
/* set argh_name so we can print it later as an error if no value is next in argv */ \
|
||||
(argh_name = long_name, \
|
||||
/* maybe set arg_diff=strlen(short_name) in case flag is "--nameVALUE" not "--name VALUE" */ \
|
||||
( (argh_diff = strlen(argv[argh_offset]) != strlen(short_name) ? strlen(short_name) : 0, \
|
||||
/* short name prefix match, if argh_diff == 0 then this is an exact match */ \
|
||||
0 == strncmp(argv[argh_offset], short_name, strlen(short_name))) \
|
||||
/* maybe set arg_diff=strlen(long_name) in case flag is "--nameVALUE" not "--name VALUE" */ \
|
||||
|| (argh_diff = strlen(argv[argh_offset]) != strlen(long_name) ? strlen(long_name) : 0, \
|
||||
/* long name prefix match, if argh_diff == 0 then this is an exact match */ \
|
||||
0 == strncmp(argv[argh_offset], long_name, strlen(long_name)))) \
|
||||
/* set argh_used to avoid adding to ARGH_ARGV, return true */ \
|
||||
? argh_used = true \
|
||||
/* return false */ \
|
||||
: false)
|
||||
|
||||
// get value for the current flag
|
||||
#define ARGH_VAL() \
|
||||
/* assert can only be used with ARGH_FLAG */ \
|
||||
((argh_name == NULL) \
|
||||
? (fprintf(stderr, "fatal: ARGH_VAL can only be used with ARGH_FLAG\n", argh_name), exit(1), NULL) \
|
||||
/* if argh_diff, use suffix of current argv instead of next argv */ \
|
||||
: (argh_diff \
|
||||
? (argv[argh_offset] + argh_diff) \
|
||||
/* else use next argv as long as it exists and does not start with "-" */ \
|
||||
: ((argh_offset < argc - 1 && strlen(argv[argh_offset + 1]) > 0 && argv[argh_offset + 1][0] != '-') \
|
||||
/* set argh_val to offset argv one additional space, return val */ \
|
||||
? (argh_val = true, argv[argh_offset + 1]) \
|
||||
: (fprintf(stderr, "fatal: needs value %s\n", argh_name), exit(1), NULL))))
|
||||
|
||||
#define ARGH_NEXT() \
|
||||
/* reset argh name, which is set by ARGH_FLAG */ \
|
||||
argh_name = NULL; \
|
||||
/* if not argh_used, save as a positional argument for later, then reset argh_used */ \
|
||||
if (!argh_used) \
|
||||
ARGH_ARGV[ARGH_ARGC++] = argv[argh_offset]; \
|
||||
argh_used = false; \
|
||||
/* if argh_val, offset argv an additional space because of ARGH_VAL, then reset argh_val */ \
|
||||
if (argh_val) \
|
||||
argh_offset++; \
|
||||
argh_val = false; \
|
||||
/* if not argh_repeat, offset argv, then reset */ \
|
||||
if (!argh_repeat) \
|
||||
argh_offset++; \
|
||||
argh_repeat = false; \
|
||||
/* check if we are done with all of argv and break is so */ \
|
||||
if (argh_offset == argc) \
|
||||
break;
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "argh.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (strcmp(argv[argc - 1], "-h") == 0 || strcmp(argv[argc - 1], "--help") == 0) {
|
||||
fprintf(stderr, "usage: example [-l|--lz4] [-h N|--head N] [-p|--prefix] POS1 ... POSN\n");
|
||||
exit(1);
|
||||
}
|
||||
bool prefix = false;
|
||||
bool lz4 = false;
|
||||
int head = 0;
|
||||
ARGH_PARSE {
|
||||
ARGH_NEXT();
|
||||
if ARGH_BOOL("-p", "--prefix") { prefix = true;}
|
||||
else if ARGH_BOOL("-l", "--lz4") { lz4 = true; }
|
||||
else if ARGH_FLAG("-h", "--head") { head = atol(ARGH_VAL()); }
|
||||
}
|
||||
printf("head: %d, prefix: %d, lz4: %d\n", head, prefix, lz4);
|
||||
for (int i = 0; i < ARGH_ARGC; i++)
|
||||
printf("positional arg %d: %s\n", i, ARGH_ARGV[i]);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020-present Nathan Todd-Stone
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,52 @@
|
|||
## why
|
||||
|
||||
minimal [argument parsing](./example.c) shouldn't require a hundred lines of code.
|
||||
|
||||
## what
|
||||
|
||||
header only argument parsing for c inspired by the simplicity of [argh](https://pythonhosted.org/argh/).
|
||||
|
||||
## example
|
||||
|
||||
```c
|
||||
#include "argh.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (strcmp(argv[argc - 1], "-h") == 0 || strcmp(argv[argc - 1], "--help") == 0) {
|
||||
fprintf(stderr, "usage: example [-l|--lz4] [-h N|--head N] [-p|--prefix] POS1 ... POSN\n");
|
||||
exit(1);
|
||||
}
|
||||
bool prefix = false;
|
||||
bool lz4 = false;
|
||||
int head = 0;
|
||||
ARGH_PARSE {
|
||||
ARGH_NEXT();
|
||||
if ARGH_BOOL("-p", "--prefix") { prefix = true;}
|
||||
else if ARGH_BOOL("-l", "--lz4") { lz4 = true; }
|
||||
else if ARGH_FLAG("-h", "--head") { head = atol(ARGH_VAL()); }
|
||||
}
|
||||
printf("head: %d, prefix: %d, lz4: %d\n", head, prefix, lz4);
|
||||
for (int i = 0; i < ARGH_ARGC; i++)
|
||||
printf("pos arg %d: %s\n", i, ARGH_ARGV[i]);
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
>> make
|
||||
|
||||
>> ./example -lph5 asdf 123
|
||||
head: 5, prefix: 1, lz4: 1
|
||||
pos arg 0: asdf
|
||||
pos arg 1: 123
|
||||
|
||||
>> ./example --lz4 asdf -p 123 --head 5
|
||||
head: 5, prefix: 1, lz4: 1
|
||||
pos arg 0: asdf
|
||||
pos arg 1: 123
|
||||
|
||||
|
||||
>> ./example asdf 123 --head 5 --lz4
|
||||
head: 5, prefix: 0, lz4: 1
|
||||
pos arg 0: asdf
|
||||
pos arg 1: 123
|
||||
```
|
Loading…
Reference in New Issue