Generated from the b-test.def file:


/*  -*- buffer-read-only: t -*- vi: set ro:
 * 
 * DO NOT EDIT THIS FILE   (b-test.c)
 * 
 * It has been AutoGen-ed  Saturday May 24, 2008 at 11:49:29 AM PDT
 * From the definitions    /home/bkorb/ag/addon/bits/b-test.def
 * and the template file   bits.tpl
 */

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "b-test.h"

static char const nm[136] =
    "* INVALID *\0" "alpha\0"       "beta\0"        "gamma\0"
    "delta\0"       "epsilon\0"     "zeta\0"        "eta\0"
    "theta\0"       "iota\0"        "kappa\0"       "lambda\0"
    "mu\0"          "nu\0"          "xi\0"          "omicron\0"
    "pi\0"          "rho\0"         "sigma\0"       "tau\0"
    "upsilon\0"     "phi\0"         "chi\0"         "psi\0"
    "omega\0";

char *
status_names( status_bits_t bits )
{
    static int const nm_ixa[ 39 ] = {
        12,  18,  23,  29,  35,  43,  48,  52,  58,  63,  69,  76,  79,  82,
        85,  93,  96,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
        0,   0,   0,   0,   100, 106, 110, 118, 122, 126, 130 };

    static char buf[ 160 ];
    char * buf_p = buf;
    int ix = 0;

    while (bits != 0) {
        if ((bits & 1) != 0) {
            char const * p = nm + nm_ixa[ix];

            if (buf_p > buf) {
                *(buf_p++) = ',';
                *(buf_p++) = ' ';
            }

            if (p == nm) {
            Oops:
                strncpy(buf_p, nm, sizeof (buf) - (buf_p - buf));
                break;
            }

            while ((*(buf_p++) = *(p++)) != '\0')   ;
            buf_p--;
        }
        bits >>= 1;
        if (++ix > 38) {
            if (bits != 0)
                goto Oops;
            break;
        }
    }

    return buf;
}

static int
str_to_id( char const * str, char const ** p_str )
{
    static char nm_buf[ 8 ];
    int    res  = -1;
    int    part = 1;
    size_t len  = 0;

    /*
     *  Extract the lower cased name with '-' replaced with '_'
     */
    {
        char * p   = nm_buf;

        for (;;) {
            char ch = *(str++);
            switch (ch) {
            case '-':
                ch = '_';
                /* FALLTHROUGH */

            case '_':
                break;

            default:
                if (isupper(ch))
                    ch = tolower(ch);
                else if (! isalnum(ch)) {
                    str--;
                    goto have_name;
                }
            }

            if (++len > 7)
                return -1;

            *(p++) = ch;
        } have_name :;

        *p = '\0';
        len = p - nm_buf;
        if (len == 0)
            return INV_STATUS;
    }

    /*
     * Search the alphabetized table
     */
    do  {
        static struct {
            unsigned short const nm_off, val;
        } nm_ixa[ 24 ] = {
        {  12,   0 }, {  18,   1 }, { 122,  36 }, {  29,   3 }, {  35,   4 },
        {  48,   6 }, {  23,   2 }, {  58,   8 }, {  63,   9 }, {  69,  10 },
        {  76,  11 }, {  79,  12 }, { 130,  38 }, {  85,  14 }, { 118,  35 },
        {  93,  15 }, { 126,  37 }, {  96,  16 }, { 100,  32 }, { 106,  33 },
        {  52,   7 }, { 110,  34 }, {  82,  13 }, {  43,   5 } };

        int av;
        int lo = 0;
        int hi = 23;

        /*
         *  Binary search for first match
         */
        do  {
            char const * p;
            int df;

            av = (lo + hi) / 2;
            p  = nm + nm_ixa[av].nm_off;
            df = strncmp(p, nm_buf, len);

            if (df == 0) {
                res = nm_ixa[av].val;
                if (p[len] == '\0')
                    part = 0;

                break;
            }

            if (df > 0)
                 hi = av - 1;
            else lo = av + 1;

        } while (lo <= hi);

        if (res < 0)
            return INV_STATUS;

        if (part == 0)
            break;

        /*
         * Partial match.  Look for preceeding matches.  One may be full match.
         */
        lo = av;
        while (lo > 0) {
            char const * p = nm + nm_ixa[--lo].nm_off;
            int df = strncmp(p, nm_buf, len);
            if (df != 0)
                break;
            if (p[len] == '\0') {
                part = 0;
                res = nm_ixa[lo].val;
                break;
            }
            part++;
        }

        if (part > 1) {
            *p_str = nm_buf;
            return DUP_STATUS;
        }

        if ((part == 0) || (av == 23))
            break;

        /*
         * Look for a successor match.  No full match possible.
         */
        {
            char const * p = nm + nm_ixa[av+1].nm_off;
            int df = strncmp(p, nm_buf, len);
            if (df == 0) {
                *p_str = nm_buf;
                return DUP_STATUS;
            }
        }
    } while (0);

    while (isspace(*str))  str++;
    *p_str = str;
    return res;
}

int
status_bits(
    status_bits_t * const bits,
    char const * str)
{
    int    ct  = 0;
    int    res = 0;

    memset(bits, '\0', sizeof(status_bits_t));

    another_bit:

    while (isspace(*str) || (*str == ','))  str++;

    for (;;) {
        if (isdigit(*str)) {
            uint64_t num =
                (uint64_t)strtoull(str, &str, 0);
            *bits |= num;
            ct += (num != 0);

        } else if (isalpha(*str)) {
            res = str_to_id(str, &str);
            if (res < 0) {
                if (res == DUP_STATUS)
                    fprintf(stderr, "duplicate matches for '%s'\n", str);
                goto fail_exit;
            }
            ct++;

            *bits |= 1ULL << res;
        } else switch (*str) {
        case ',':
            goto another_bit;

        case '\0':
            return ct;

        default:
            res = INV_STATUS;
            goto fail_exit;
        }
    }

    fail_exit:
    memset(bits, '\0', sizeof(*bits));
    return res;
}

#ifdef TEST_BITS

static char const bit_names[] =
"The known status bit names are:\n\
  alpha   beta    chi     delta   epsilon eta     gamma   iota    kappa\n\
  lambda  mu      nu      omega   omicron phi     pi      psi     rho\n\
  sigma   tau     theta   upsilon xi      zeta\n";

int
main( int argc, char** argv )
{
    static char const fmt_z[] = "'%s' yields: %s\n";
    status_bits_t bts;
    if (argc != 2) {
        fputs(bit_names, stderr);
        return 1;
    }
    {
        int ct = status_bits(&bts, argv[1]);
        if (ct <= 0) {
            char const * pz;
            switch (ct) {
            case 0: pz = "no results"; break;
            case INV_STATUS: pz = "invalid name"; break;
            case DUP_STATUS: pz = "multiple match"; break;
            }
            fprintf(stderr, fmt_z, argv[1], pz);
            fputs(bit_names, stderr);
            return 1;
        }
    }
    {
        char * pz = status_names( bts );
        printf(fmt_z, argv[1], pz);
    }
    return 0;
}
#endif

/* end of b-test.c */