Click here to Skip to main content
15,896,153 members
Articles / Programming Languages / C

Another argument parsing function for C and C++

Rate me:
Please Sign up or sign in to vote.
4.72/5 (9 votes)
18 Oct 2013MIT5 min read 30.2K   362   28  
Argument parsing function identifies both optional and positional arguments.
/* ********************************************************************
 * Header File: get_arguments.h
 * Author: Bill Hallahan
 * Date: September 26, 2013
 *
 * Copyright (C) 2013 William Hallahan
 *
 * 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.
 *
 ******************************************************************* */

#ifndef GET_ARGUMENTS_H
#define GET_ARGUMENTS_H

#include "platform_os.h"

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/* The get_arguments function either returns an option
 * character or one of these values. */
typedef enum
{
    ARG_ERROR_INVALID_SWITCH = -2,
    ARG_ERROR_MISSING_SWITCH_ARGUMENT = -1,
    ARG_NO_MORE_ARGUMENTS = 0,
    ARG_POSITIONAL_ARGUMENT = 0x7FFFFFFF
} ArgOptionChar_t;

/* Used to set whether an option requires a parameter. */
typedef enum
{
    OPTION_NO_PARAMETER,
    OPTION_REQUIRES_PARAMETER
} ArgOptionParameter_t;

/* The option structure. 
 * Element c stores the short option character, i.e. "b" for "-b".
 *   name is the long option name string, "build" for "--build".
 * requires_params is set to one of the ArgOptionParameter_t
 *   enum values to indicate whether the option requires a parameter. */
typedef struct
{
    int c;
    TCHAR * long_name;
    ArgOptionParameter_t requires_param;
} ArgOption_t;

 /* ********************************************************************
 * Function: get_arguments
 *
 * Abstract:
 *
 *  The get_arguments function was written to provide argument
 *  parsing code for multiple platforms.  Also, the code can
 *  be used under the terms of the MIT license.
 *
 *  The get_arguments function allows both short and long
 *  optional switches, and will work with the ASCII, UTF-8, and
 *  Unicode character sets.
 *
 *  Both single character and long optional argument switch
 *  named are allowed.
 *
 *  Optional arguments and positional arguments can be interspersed.
 *
 *  The benefit of allowing interspersed optional and positional
 *  arguments comes at the cost of requiring that an optional argument
 *  either does, or does not, take an additional parameter, but not both.
 *
 *  Also, optional argument names cannot start with a digit
 *  character.  This simplified parsing as a dash followed by
 *  a digit character could also be the start of a numeric
 *  positional argument.
 *
 *  Input:
 *
 *    The first two arguments are passed into the 'main' function of
 *    a C or C++ console program.
 *
 *    argc                      - The number of arguments.
 *
 *    argv                      - An array of pointers to argument strings.
 *
 *    argument_option_array_ptr - A pointer to an array of ArgOption_t
 *                                structures that specifies that attributes
 *                                of each optional argument.
 *
 *                                An example declaration for the array might be:
 *
 *                                static const ArgOption_t argument_option_array[] =
 *                                {
 *                                    { 'x', NULL, OPTION_NO_PARAMETER, },
 *                                    { 'f', NULL, OPTION_REQUIRES_PARAMETER, },
 *                                    { 'b', "build", OPTION_REQUIRES_PARAMETER, },
 *                                    { 'h', "help", OPTION_NO_PARAMETER, },
 *                                    {   0, NULL, OPTION_NO_PARAMETER }
 *                                };
 *
 *                                This would allow optional arguments of the form:
 *
 *                                -x
 *                                -f <somestring>
 *                                -b <somestring>
 *                                --build <somestring>
 *                                -h
 *                                --help
 *
 *                                A string must be supplied after the -s parameter
 *                                because OPTION_REQUIRES_PARAMETER is used.
 *                                
 *                                The final line must always be supplied as written
 *                                to terminate the data.
 *
 *                                Either a short argument name, a long
 *                                argument name, or both must be specified.
 *                                If only a long name is specified, the first
 *                                field of the ArgOption_t structure must be
 *                                set to an out-of-band integer value, which
 *                                for either ASCII or Unicode character sets
 *                                can be any value above 0x011FFFF.
 *                                 
 *
 *    arg_index_ptr               A pointer to an 'int' value that is used
 *                                to index into the argv[] array. The value
 *                                pointed to by arg_index_ptr specifies either
 *                                the index of a positional argument or the
 *                                index of the required parameter for an
 *                                optional argument that has the
 *                                OPTION_REQUIRES_PARAMETER attribute.
 *
 *  Returns:
 *
 *    An integer value that is either the option character for an
 *    optional argument, which is the first field in OptionsArg_t
 *    structure that matches the optional argument passed on the
 *    command line, or, one of the following values.
 *
 *    ARG_POSITIONAL_ARGUMENT  - Specified that argument in the argv
 *                               array, indexed by the index value
 *                               pointed to by arg_index_ptr, is a
 *                               positional argument.
 *
 *    ARG_NO_MORE_ARGUMENTS    - Specifies that there are no more
 *                               arguments to parse.
 *
 *    ARG_ERROR_INVALID_SWITCH - Invalid switch specified on the command
 *                               line.
 *
 *    ARG_ERROR_MISSING_SWITCH_ARGUMENT - A dash character for an
 *                                        optional argument was found
 *                                        but is missing required
 *                                        characters following the dash.
 *
 *  Any returned character value, represented as an integer, and
 *  the value of ARG_POSITIONAL_ARGUMENT, are always greater than
 *  zero.  ARG_NO_MORE_ARGUMENTS equals zero, and the error return
 *  values are negative numbers, so parsing should be done until
 *  the return value of this function is not greater than
 *  ARG_NO_MORE_ARGUMENTS, or zero.
 *
 ******************************************************************* */

int get_arguments(int argc,
                  TCHAR *argv[],
                  const ArgOption_t * argument_option_array_ptr,
                  int * arg_index_ptr);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* GET_ARGUMENTS_H */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
United States United States
I'm an electrical engineer who has spend most of my career writing software. My background includes Digital Signal Processing, Multimedia programming, Robotics, Text-To-Speech, and Storage products. Most of the code that I've written is in C, C++ and Python. I know Object Oriented Design and I'm a proponent of Design Patterns.

My hobbies include writing software for fun, amateur radio, chess, and performing magic, mostly for charities.

Comments and Discussions