Command line argument handling library

0. Contents

This is the documentation of libargh-1.0.8.
   1. Purpose
   2. Supported
   3. Headers
      3.1. C++ header: argh.hh
      3.2. C header: argh.h
   4. Copying
   5. Requirements
   6. Downloading

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