Skip to content

Generate argument parsing logic in C from a simple config

License

Notifications You must be signed in to change notification settings

new-mentat/argen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

argen

argen lets you generate argument parsing logic in C from a simple config. No more having to write that tedious arg-parsing C code!

argen

// this is what the entry point looks like from the above example

int main(int argc, char **argv) {
	int block_size;
	int fave_number;
	int quiet;
	char* username;
	char* out_file;
	char* in_file;
	char* *words;
	size_t words__size;

	parse_args(argc, argv, &block_size, &fave_number, &quiet, &username, &out_file, &in_file, &words, &words__size);

	/* call your code here */
	return 0;
}

Installation

Standalone

argen can easily be installed as a pre-built executable. Download from the latest compiled binaries and run ./install.

Source

# install rust via rustup.rs
# clone the source code
$ git clone https://github.com/kynelee/argen.git
$ cd argen
# build
$ cargo build --release
# copy binary
$ cp target/release/argen /usr/local/bin/argen

If you intend on doing development, you will find integration testing with gcc easy and pretty with this line:

cargo run -- examples/example_spec.toml | tee a.c | pygmentize -l c && gcc a.c

Usage

# write to main.c
$ argen -o main.c spec.toml
# write to stdout
$ argen spec.toml

The spec.toml file specifies how you want your C code to parse arguments:

# argen spec
# example usages:
#  $ ./program --block-size 10 --set-flag file1.txt file2.txt word1 word2
#  $ ./program file1.txt

# There are "non_positional" options and "positional" arguments.
#   These take some different fields.
#   This example is exhaustive in showing all  available fields.
#   Positional arguments are *ordered*:
#     All required positional arguments must precede non-required ones.
#     Only the last positional argument can be multiple-valued.


####################
## non-positional ##
####################

[[non_positional]]
c_var = "block_size"               # required, variable name in C
c_type = "int"                     # required, variable type in C (int or char*)
                                   #   for int: calls atoi(arg) to turn arg into int
long = "block-size"                # required, specifies option name
help_name = "num"                  # optional, name of the option's arg shown in --help output
help_descr = "Set the block size"  # optional, description in the --help output
short = "b"                        # optional, shortcut for argument name, 1 ASCII character only
aliases = ["size"]                 # optional, aliases for option
default = "12"                     # optional, default value for variable
                                   #   for int:   assigned as literal
                                   #   for char*: assigned as quoted literal
#required = false                  # optional, makes the option mandatory
                                   #   if set, cannot also provide default
                                   #   (defaults to false)

[[non_positional]]
c_var = "flag_set"
c_type = "int"
long = "set-flag"
help_descr = "Enable something"
flag = true                      # optional, make the option take no argument
                                 #   c_type must be int
                                 #   c_var is 1 if flag is set, 0 otherwise
                                 #   flags cannot also be required


################
## positional ##
################

[[positional]]
c_var  = "input_file"      # required, variable name in C
c_type = "char*"           # required, variable type in C (int or char*)
                           #   for int: calls atoi(arg) to turn arg into int
required = true            # optional, makes the argument mandatory
                           #   if set, cannot also provide default
                           #   (defaults to false)
help_name = "FILE"         # required, NOTE: this is required unlike non-positional
                           #   name of the argument shown in --help output
help_descr = "input file"  # optional, description in the --help output

[[positional]]
c_var = "output_file"
c_type = "char*"
help_name = "OUT"
help_descr = "file for output"
default = "output.txt"          # optional, default value for variable
                                #   for int:   assigned as literal
                                #   for char*: assigned as quoted literal

[[positional]]
multi = true                   # optional, only valid for last positional argument
                               #   we note the different behaviors here
c_var = "words"
c_type = "char*"               # with multi, we can only use char*
                               #   words will actually be a char**,
                               #   and another variable words__size is made
help_name = "WORD"             # with multi, you should be singular here
help_descr = "word(s) to use"
default = "someword"           # with multi, if no values are given and a
                               #   default is specified, words__size will be 1
                               #     and words[0] is the default value
                               #   if no values are given and *no* default is
                               #     specified, words_size will be 0
#required = false              # with multi, makes at least one value mandatory
                               #   (still defaults to false)

After generating and compiling the C code, you will have fully functional argument parsing.