# Command line argument handling library

## 0. Contents

This is the documentation of libargh-1.0.8.

## 1. Purpose

Handles commandline parameters.

## 2. Supported

C, C++

## 3. Headers

### 3.1. C++ header: argh.hh

    #ifndef optrar_argh_hh
    #define optrar_argh_hh

    /* Copyright (C) 1992,2003 Bisqwit (http://iki.fi/bisqwit/) */

    /*
     * C++ USAGE EXAMPLE
     *

    #include <argh.hh>

    int main(int argc, const char *const *argv)
    {
        vector<string> files;

        string buildfn;
        bool worst = false;

        ParamHandler Argh;

        Argh.AddLong("worst",   'w').SetBool().SetDesc("Least optimal.");
        Argh.AddLong("help",    'h').SetBool().SetDesc("This help.");
        Argh.AddLong("version", 'V').SetBool().SetDesc("Displays version information.");
        Argh.AddLong("build",   'b').SetString().SetDesc("Builds the archive.", "<file>");
        Argh.AddLong("make",    'b');

        Argh.AddBool('k');
        Argh.AddDesc('k', "This option does nothing.");
        Argh.AddLong("idle", 500).SetDesc("This option does nothing.");

        Argh.StartParse(argc, argv);
        for(;;)
        {
            int c = Argh.GetParam();
            if(c == -1)break;
            switch(c)
            {
                case 'w': worst = Argh.GetBool(); break;
                case 'V': printf("%s\n", VERSION); return 0;
                case 'b': buildfn = Argh.GetString(); break;
                case 'k': break; // -k
                case 500: break; // --idle
                case 'h':
                    printf(
                        "This is software\n"
                        "\nUsage: software [<option> [<...>]] <file> [<...>]\n"
                        "\nThis software does something for the files.\n"
                        "\nOptions:\n");
                    Argh.ListOptions();
                    printf("\nNo warranty whatsoever.\n");
                    return 0;
                default:
                    files.push_back(Argh.GetString());
            }
        }
        if(!Argh.ok())return -1;
        if(!files.size())
        {
            fprintf(stderr, "Error: At least one file must be specified.\n");
            return -1;
        }

        ...
    }

    */

    /* The header begins here. */

    #include <string>
    class ParamHandler
    {
    private:
        /* No copying */
        void operator=(const ParamHandler &);
        ParamHandler (const ParamHandler &);
        class Reference;
    public:
        typedef long keytype;

        ParamHandler();
        virtual ~ParamHandler();
        virtual void PrintOpt(unsigned space, const std::string &opts, const std::string &desc);

        Reference AddLong(const std::string &longname, keytype alias);
        Reference AddBool(keytype c);
        Reference AddInt(keytype c, int min, int max);
        Reference AddFloat(keytype c, double min, double max);
        Reference AddString(keytype c, unsigned min=1, unsigned max=std::string::npos);
        Reference AddDesc(keytype c, const std::string &s, const std::string &param="");

        // Support for many conventions
        void StartParse(int ac, const char *const *av, int firstarg=1);
        void StartParse(int ac, const char **av, int firstarg=1);
        void StartParse(int ac, char **av, int firstarg=1);
        void StartParse(int ac, char *const*av, int firstarg=1);

        const std::string ProgName() const { return A0; }

        /* --not-x, --no-x, --without-x and --with-x are recognized.
         * Therefore you should use GetBool().
         */
        inline const bool GetBool() const      { return polarity; }
        inline const int GetInt() const        { return intparm; }
        inline const double GetFloat() const   { return doubleparm; }
        inline const std::string &GetString() const { return param; }
        inline const bool ok() const           { return !error; }

        keytype GetParam();
        void ListOptions();

    private:
        static inline keytype char2opt(char c1, char c2) { return (unsigned char)c1 + (unsigned char)c2 * 256; }
        static inline keytype char3opt(char c1, char c2, char c3) { return (unsigned char)c1 + 256 * char2opt(c2, c3); }

        void ErrorIllegalOption(keytype key);
        void ErrorNeedsArg(keytype key);
        void ErrorNeedsArg(const std::string &longo);
        void ErrorNeedNoArg(const std::string &longo);
        void InternalError(keytype key, const char *s);
        void ErrorOutOfRange(const std::string &param);
        void ErrorUnknownOption(const char *s, bool negafail);

    public:
        /* argh_atypemap needs this and I don't know how to make it friend. */
        class ArgInfo { public: char type; int min,max;unsigned maxl;double fmin,fmax; };
    private:
        class argh_aliasmap *aliases;
        class argh_descsmap *descs;
        class argh_atypemap *argtypes;
        class Reference
        {
            ParamHandler *par;
            keytype key;
        public:
            Reference(ParamHandler *p, keytype k) : par(p), key(k) { }
            Reference &SetBool();
            Reference &SetInt(int min, int max);
            Reference &SetFloat(double min, double max);
            Reference &SetString(unsigned min=1, unsigned max=std::string::npos);
            Reference &SetDesc(const std::string &s, const std::string &param="");
        };
        Reference MakeRef(keytype key);
        int ParseError();
        int ShortOpt(keytype key, const char *s);
    private:
        int argc; const char *const *argv;
        const char *A0;
        /* parser volatile */
        int argpos; bool opts; std::string longo, longobuf; std::string param;
        const char *shortpointer; bool error, polarity; int intparm; double doubleparm;
    };

    #endif

### 3.2. C header: argh.h

    #ifndef optrar_argh_h
    #define optrar_argh_h

    /* Copyright (C) 1992,2003 Bisqwit (http://iki.fi/bisqwit/) */

    #ifdef __cplusplus
    extern "C" {
    #endif

    extern void argh_init(void);
    extern void argh_done(void);
    extern void argh_add_long(const char *longname, int alias);
    extern void argh_add_bool(int alias);
    extern void argh_add_int(int c, int min, int max);
    extern void argh_add_float(int c, double min, double max);
    extern void argh_add_string(int c, unsigned minlen, unsigned maxlen);
    extern void argh_add_desc(int c, const char *s, const char *optparam);
    extern void argh_start_parse(int argc, const char *const *argv);
    extern int argh_get_bool(void);
    extern int argh_get_int(void);
    extern double argh_get_float(void);
    extern int argh_ok(void);
    extern int argh_get_param(void);
    extern void argh_list_options(void);
    /* Note: This pointer is only valid until next argh_get_param() call */
    /* Attention: Do not try to free() it. */
    extern const char *argh_get_string(void);

    #ifdef __cplusplus
    }
    #endif

    /* C language usage example:

    static int stereo=0;
    static int Rate  =43200;
    static char *host = NULL;

    static void PrintVersionInfo(void)
    {
        printf("erec - polydriving recording server v"VERSION" (C) 1992,2000 Bisqwit\n");
    }

    #include <argh.h>

    int main(int argc, const char *const *argv)
    {
        int Heelp = 0;

        argh_init();

        argh_add_long("stereo", '2'); argh_add_bool('2'); argh_add_desc('2', "Specifies stereo sound. Default is mono.", NULL);
        argh_add_long("mono",   'm'); argh_add_bool('m'); argh_add_desc('m', "Redundant. It's here for esd compatibility.", NULL);
        argh_add_long("rate",   'r'); argh_add_int('r',18,999999); argh_add_desc('r', "Specifies recording rate. 43200 is default.", "<num>");
        argh_add_long("device", 'd'); argh_add_string('d',1,1023); argh_add_desc('d', "Specify device.", "<file>");
        argh_add_long("help",   'h'); argh_add_bool('h'); argh_add_desc('h', "Help", NULL);
        argh_add_long("version",'V'); argh_add_bool('V'); argh_add_desc('V', "Version information", NULL);

        argh_start_parse(argc, argv);
        for(;;)
        {
            int c = argh_get_param();
            if(c == -1)break;
            switch(c)
            {
                case 'V':
                    PrintVersionInfo();
                    return 0;
                case 'h':
                    Heelp = 1;
                    break;
                case '2':
                    if(argh_get_bool())++stereo;else stereo=0;
                    break;
                case 'm':
                    if(argh_get_bool())stereo = 0;else ++stereo;
                    break;
                case 'r':
                    Rate = argh_get_int();
                    break;
                case 'd':
                    strncpy(Device, argh_get_string(), sizeof Device);
                    Device[sizeof(Device)-1] = 0;
                    break;
                default:
                {
                    const char *s = argh_get_string();
                    host = (char *)malloc(strlen(s)+1);
                    strcpy(host, s);
                }
            }
        }
        if(!host)host = (char *)"10.104.2.2";

        if(!argh_ok())return -1;

        if(Heelp)
        {
            PrintVersionInfo();
            printf(
                "\nAllows multiple applications request recorded data"
                "\nat the same time with different stream attributes.\n");
            printf(
                "Usage: erec [<options> [<...>]] [<host> | none]\n"
                "Options:\n");
            argh_list_options();
            printf("\n"
                "If <host> is other than none, the output will be sent with esdcat.\n");
            return 0;
        }

        ...
    }

    */

    #endif

## 4. Copying

libargh has been written by Joel Yliluoma, a.k.a. Bisqwit,
and is distributed under the terms of the General Public License (GPL).

## 5. Requirements

argh has been written in C++, utilizing the standard template library.
GNU make is required.
libargh compiles without warnings at least on g++ versions 3.0.1 and 3.0.3.

## 6. Downloading

The official home page of libargh is at http://iki.fi/bisqwit/source/libargh.html.
Check there for new versions.

Generated from `progdesc.php` (last updated: Sat, 25 Jan 2003 16:52:14 +0200)
with `docmaker.php` (last updated: Thu, 13 Feb 2003 15:11:29 +0200)
at Sat, 27 Sep 2003 16:17:09 +0300