margp
is a miniature argument parsing library for standard C.
It parses simple POSIX-style short and long flags.
It is licensed under the MIT license.
Short flags are provided in arguments taking the form of -[flags][VALUE]
, where [flags]
is
one or more characters, each of which represents some option. Some flags require a string value -
once one of these flags is encountered, the rest of the argument is stored as its value ([VALUE]
).
If the argument just ends after that flag, the next argument will be used as its value instead.
Long flags are provided as arguments in the form --flag
, where flag
is the name of some option.
If this particular option requires a string value, the next argument will be used as its value.
The special argument --
indicates that all further arguments should not be handled as flags.
To specify the flags your program accepts, you define a list of margp_t
values. This must end in an margp_t
with its
type set to margpEnd
.
The margp_t
structure looks like this:
enum {
margpEnd = 0,
margpString,
margpFlag
} type;
char shorthand;
char *name;
void *target;
int setFlagTo;
type
specifies the purpose of this option - the significance of this option will be explained soon!
shorthand
is a single character representing the shorthand flag for this option.
name
is a string specifying the longhand name for this option, without the --
.
Depending on the given type
, the meaning of the rest of the struct changes:
-
If type is
margpString
, this option will expect a string value.target
should be a pointer to achar*
variable, and when this option is encountered, margp will set that variable to the value it finds. -
If type is
margpFlag
, this option will not expect a value.target
should be a pointer to anint
variable, and when this option is encountered, margp will set that variable to the value specified insetFlagTo
. -
If the type is
margpEnd
, this does not specify an actual option, but denotes the end of the list of options.
margp_t flags[] = {
// The `-h` or `--help` flag sets action to actHelp.
{ margpFlag, 'h', "help", &action, actHelp },
// The `-v` or `--version` flag sets action to actVersion.
{ margpFlag, 'v', "version", &action, actVersion },
// The name flag (short `-nNAME` or `-n NAME`, long `--name NAME`)
// sets name to the passed NAME value.
{ margpString, 'n', "name", &name },
// Signify end of margp list
{ margpEnd }
};
To parse margp options, invoke int margp(margp_t *args, int argc, char **argv, int *remainArgc, char ***remainArgv)
.
args
should contain your list of options, in the format specified above.argc
andargv
should be yourmain
function's argc and argv values.remainArgc
andremainArgv
should point to anint
andchar**
variable, respectively. These will be populated with any arguments that aren't parsed as options by margp. Ifmargp
finishes successfully, the variable you pointedremainArgv
to will contain a pointer which needs to be freed when you are done with it.
After parsing, margp
returns 1
on success, and 0
on failure. On failure, margp
has already printed an error
message.
/* Example invocations and output:
*
* example hello world
* DefaultName says: hello world
*
* example -nJoe hello world
*. Joe says: hello world
*
* example hello --name Joe there, world!
*. Joe says: hello there, world!
*
* example -hn Joe hello world
*. THIS IS THE HELP SCREEN
*
* example -nh Joe hello world
*. h says: Joe hello world
*
* example -nJoe -- hello --help world
*. Joe says: hello --help world
*/
#include "margp.h"
#include <stdio.h>
int main(int argc, char **argv)
{
char *name = "DefaultName";
enum { actDefault, actHelp, actVersion } action = actDefault;
int remainArgc, result;
char **remainArgv;
// Parse arguments.
result = margp((margp_t[]) {
// The `-h` or `--help` flag sets action to actHelp.
{ margpFlag, 'h', "help", &action, actHelp },
// The `-v` or `--version` flag sets action to actVersion.
{ margpFlag, 'v', "version", &action, actVersion },
// The name flag (short `-nNAME` or `-n NAME`, long `--name NAME`)
// sets name to the passed NAME value.
{ margpString, 'n', "name", &name },
// Signify end of margp list
{ margpEnd }
}, argc, argv, &remainArgc, &remainArgv);
// Check margp results and print usage if it failed.
if (!result) {
printf("Usage: example [-hvnNAME] [--name name | --help | --version] [message]\n");
return 0;
}
switch (action) {
case actHelp:
printf("THIS IS THE HELP SCREEN\n");
break;
case actVersion:
printf("THIS IS THE VERSION SCREEN\n");
break;
case actDefault:
printf("%s says: ", name);
// Print all non-flag arguments!
for (int i = 0; i < remainArgc; i++)
printf("%s ", remainArgv[i]);
printf("\n");
break;
default:
break;
}
free(remainArgv);
}
Licensed under the MIT license:
Copyright © 2020 Ethan McTague.
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.