From 469bc96773d1804debc0779ce949b57d5cb6c495 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sun, 6 Dec 2015 22:16:25 -0500 Subject: [PATCH] Added comments to the posix-style opt.h header --- source/opt.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/source/opt.h b/source/opt.h index 5e64c3f..126fcbe 100644 --- a/source/opt.h +++ b/source/opt.h @@ -1,9 +1,41 @@ +/* This file implements a simple POSIX-style option parsing implementation as + * a set of macros. The file is heavily influenced and inspired by the arg.h + * file from suckless.org (http://git.suckless.org/libsl/tree/arg.h). That file + * is in turn inspired by the corresponding macros defined in plan9. + * + * The interface in this file assumes that the main function will have the + * following prototype: + * + * int main(int argc, char** argv); + * + * An example usage of the interface would look something like the follwoing: + * + * char* ARGV0; + * int main(int argc, char** argv) { + * OPTBEGIN { + * case 'a': printf("Simple option\n"); break; + * case 'b': printf("Option with arg: %s\n", OPTARG()); break; + * default: printf("Unknown option!\n"); + * } OPTEND; + * return 0; + * } + */ #ifndef OPT_H #define OPT_H +/* This variable contains the value of argv[0] so that it can be referenced + * again once the option parsing is done. This variable must be defined by the + * program. + * + * NOTE: Ensure that you define this variable with external linkage (i.e. not + * static) + */ extern char* ARGV0; -static inline char* getarg(int* p_argc, char*** p_argv) { +/* This is a helper function used by the macros in this file to parse the next + * option from the command line. + */ +static inline char* getopt(int* p_argc, char*** p_argv) { if (!(*p_argv)[0][1] && !(*p_argv)[1]) { return (char*)0; } else if ((*p_argv)[0][1]) { @@ -15,15 +47,15 @@ static inline char* getarg(int* p_argc, char*** p_argv) { } } -/* use main(int argc, char *argv[]) */ +/* This macro is almost identical to the ARGBEGIN macro from suckless.org. If + * it ain't broke, don't fix it. */ #define OPTBEGIN \ for ( \ ARGV0 = *argv, argc--, argv++; \ argv[0] && argv[0][1] && argv[0][0] == '-'; \ argc--, argv++ \ ) { \ - char argc_ , **argv_, *optarg_; \ - int brk_; \ + int brk_; char argc_ , **argv_, *optarg_; \ if (argv[0][1] == '-' && !argv[0][2]) { \ argv++, argc--; break; \ } \ @@ -32,17 +64,25 @@ static inline char* getarg(int* p_argc, char*** p_argv) { argc_ = argv[0][0]; \ switch (argc_) +/* Terminate the option parsing. */ #define OPTEND }} +/* Get the current option chracter */ #define OPTC() (argc_) +/* Get an argument from the command line and return it as a string. If no + * argument is available, this macro returns NULL */ #define OPTARG() \ - (optarg_ = getarg(&argc,&argv), brk_ = (optarg_!=0), optarg_) + (optarg_ = getopt(&argc,&argv), brk_ = (optarg_!=0), optarg_) +/* Get an argument from the command line and return it as a string. If no + * argument is available, this macro executes the provided code. If that code + * returns, then abort is called. */ #define EOPTARG(code) \ - (optarg_ = getarg(&argc,&argv), \ + (optarg_ = getopt(&argc,&argv), \ (!optarg_ ? ((code), abort(), (char*)0) : (brk_ = 1, optarg_))) +/* Helper macro to recognize number options */ #define OPTNUM \ case '0': \ case '1': \ @@ -55,6 +95,7 @@ static inline char* getarg(int* p_argc, char*** p_argv) { case '8': \ case '9' +/* Helper macro to recognize "long" options ala GNU style. */ #define OPTLONG \ case '-' -- 2.52.0