BACK to addon.html#bits

 /*  -*- buffer-read-only: t -*- vi: set ro:
  * 
  * DO NOT EDIT THIS FILE   (b-test.c)
  * 
  * It has been AutoGen-ed  April 15, 2012 at 11:22:25 AM by AutoGen 5.16pre23
  * From the definitions    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] =
 /*     0 */ "* INVALID *\0"
 /*    12 */ "alpha\0"
 /*    18 */ "beta\0"
 /*    23 */ "gamma\0"
 /*    29 */ "delta\0"
 /*    35 */ "epsilon\0"
 /*    43 */ "zeta\0"
 /*    48 */ "eta\0"
 /*    52 */ "theta\0"
 /*    58 */ "iota\0"
 /*    63 */ "kappa\0"
 /*    69 */ "lambda\0"
 /*    76 */ "mu\0"
 /*    79 */ "nu\0"
 /*    82 */ "xi\0"
 /*    85 */ "omicron\0"
 /*    93 */ "pi\0"
 /*    96 */ "rho\0"
 /*   100 */ "sigma\0"
 /*   106 */ "tau\0"
 /*   110 */ "upsilon\0"
 /*   118 */ "phi\0"
 /*   122 */ "chi\0"
 /*   126 */ "psi\0"
 /*   130 */ "omega";
 
 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 an earlier match.  One may be a 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, (char **)&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 */