Annotation of embedaddon/ntp/sntp/libopts/enumeration.c, revision 1.1
1.1 ! misho 1:
! 2: /**
! 3: * \file enumeration.c
! 4: *
! 5: * Time-stamp: "2011-04-06 10:48:22 bkorb"
! 6: *
! 7: * Automated Options Paged Usage module.
! 8: *
! 9: * This routine will run run-on options through a pager so the
! 10: * user may examine, print or edit them at their leisure.
! 11: *
! 12: * This file is part of AutoOpts, a companion to AutoGen.
! 13: * AutoOpts is free software.
! 14: * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved
! 15: *
! 16: * AutoOpts is available under any one of two licenses. The license
! 17: * in use must be one of these two and the choice is under the control
! 18: * of the user of the license.
! 19: *
! 20: * The GNU Lesser General Public License, version 3 or later
! 21: * See the files "COPYING.lgplv3" and "COPYING.gplv3"
! 22: *
! 23: * The Modified Berkeley Software Distribution License
! 24: * See the file "COPYING.mbsd"
! 25: *
! 26: * These files have the following md5sums:
! 27: *
! 28: * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
! 29: * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
! 30: * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
! 31: */
! 32:
! 33: static char const * pz_enum_err_fmt;
! 34:
! 35: /* = = = START-STATIC-FORWARD = = = */
! 36: static void
! 37: enum_err(tOptions * pOpts, tOptDesc * pOD,
! 38: char const * const * paz_names, int name_ct);
! 39:
! 40: static uintptr_t
! 41: find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD,
! 42: char const * const * paz_names, unsigned int name_ct);
! 43:
! 44: static void
! 45: set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 46: unsigned int name_ct);
! 47:
! 48: static void
! 49: set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 50: unsigned int name_ct);
! 51:
! 52: static void
! 53: set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 54: unsigned int name_ct);
! 55: /* = = = END-STATIC-FORWARD = = = */
! 56:
! 57: static void
! 58: enum_err(tOptions * pOpts, tOptDesc * pOD,
! 59: char const * const * paz_names, int name_ct)
! 60: {
! 61: size_t max_len = 0;
! 62: size_t ttl_len = 0;
! 63: int ct_down = name_ct;
! 64: int hidden = 0;
! 65:
! 66: /*
! 67: * A real "pOpts" pointer means someone messed up. Give a real error.
! 68: */
! 69: if (pOpts > OPTPROC_EMIT_LIMIT)
! 70: fprintf(option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName,
! 71: pOD->optArg.argString, pOD->pz_Name);
! 72:
! 73: fprintf(option_usage_fp, zValidKeys, pOD->pz_Name);
! 74:
! 75: /*
! 76: * If the first name starts with this funny character, then we have
! 77: * a first value with an unspellable name. You cannot specify it.
! 78: * So, we don't list it either.
! 79: */
! 80: if (**paz_names == 0x7F) {
! 81: paz_names++;
! 82: hidden = 1;
! 83: ct_down = --name_ct;
! 84: }
! 85:
! 86: /*
! 87: * Figure out the maximum length of any name, plus the total length
! 88: * of all the names.
! 89: */
! 90: {
! 91: char const * const * paz = paz_names;
! 92:
! 93: do {
! 94: size_t len = strlen(*(paz++)) + 1;
! 95: if (len > max_len)
! 96: max_len = len;
! 97: ttl_len += len;
! 98: } while (--ct_down > 0);
! 99:
! 100: ct_down = name_ct;
! 101: }
! 102:
! 103: /*
! 104: * IF any one entry is about 1/2 line or longer, print one per line
! 105: */
! 106: if (max_len > 35) {
! 107: do {
! 108: fprintf(option_usage_fp, " %s\n", *(paz_names++));
! 109: } while (--ct_down > 0);
! 110: }
! 111:
! 112: /*
! 113: * ELSE IF they all fit on one line, then do so.
! 114: */
! 115: else if (ttl_len < 76) {
! 116: fputc(' ', option_usage_fp);
! 117: do {
! 118: fputc(' ', option_usage_fp);
! 119: fputs(*(paz_names++), option_usage_fp);
! 120: } while (--ct_down > 0);
! 121: fputc('\n', option_usage_fp);
! 122: }
! 123:
! 124: /*
! 125: * Otherwise, columnize the output
! 126: */
! 127: else {
! 128: int ent_no = 0;
! 129: char zFmt[16]; /* format for all-but-last entries on a line */
! 130:
! 131: sprintf(zFmt, "%%-%ds", (int)max_len);
! 132: max_len = 78 / max_len; /* max_len is now max entries on a line */
! 133: fputs(" ", option_usage_fp);
! 134:
! 135: /*
! 136: * Loop through all but the last entry
! 137: */
! 138: ct_down = name_ct;
! 139: while (--ct_down > 0) {
! 140: if (++ent_no == max_len) {
! 141: /*
! 142: * Last entry on a line. Start next line, too.
! 143: */
! 144: fprintf(option_usage_fp, "%s\n ", *(paz_names++));
! 145: ent_no = 0;
! 146: }
! 147:
! 148: else
! 149: fprintf(option_usage_fp, zFmt, *(paz_names++) );
! 150: }
! 151: fprintf(option_usage_fp, "%s\n", *paz_names);
! 152: }
! 153:
! 154: if (pOpts > OPTPROC_EMIT_LIMIT) {
! 155: fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden);
! 156:
! 157: (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
! 158: /* NOTREACHED */
! 159: }
! 160:
! 161: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
! 162: fprintf(option_usage_fp, zLowerBits, name_ct);
! 163: fputs(zSetMemberSettings, option_usage_fp);
! 164: } else {
! 165: fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden);
! 166: }
! 167: }
! 168:
! 169:
! 170: static uintptr_t
! 171: find_name(char const * pzName, tOptions * pOpts, tOptDesc * pOD,
! 172: char const * const * paz_names, unsigned int name_ct)
! 173: {
! 174: /*
! 175: * Return the matching index as a pointer sized integer.
! 176: * The result gets stashed in a char* pointer.
! 177: */
! 178: uintptr_t res = name_ct;
! 179: size_t len = strlen((char*)pzName);
! 180: uintptr_t idx;
! 181:
! 182: if (IS_DEC_DIGIT_CHAR(*pzName)) {
! 183: char * pz = (char *)(void *)pzName;
! 184: unsigned long val = strtoul(pz, &pz, 0);
! 185: if ((*pz == NUL) && (val < name_ct))
! 186: return (uintptr_t)val;
! 187: enum_err(pOpts, pOD, paz_names, (int)name_ct);
! 188: return name_ct;
! 189: }
! 190:
! 191: /*
! 192: * Look for an exact match, but remember any partial matches.
! 193: * Multiple partial matches means we have an ambiguous match.
! 194: */
! 195: for (idx = 0; idx < name_ct; idx++) {
! 196: if (strncmp((char*)paz_names[idx], (char*)pzName, len) == 0) {
! 197: if (paz_names[idx][len] == NUL)
! 198: return idx; /* full match */
! 199:
! 200: res = (res != name_ct) ? ~0 : idx; /* save partial match */
! 201: }
! 202: }
! 203:
! 204: if (res < name_ct)
! 205: return res; /* partial match */
! 206:
! 207: pz_enum_err_fmt = (res == name_ct) ? zNoKey : zAmbigKey;
! 208: option_usage_fp = stderr;
! 209: enum_err(pOpts, pOD, paz_names, (int)name_ct);
! 210: return name_ct;
! 211: }
! 212:
! 213:
! 214: /*=export_func optionKeywordName
! 215: * what: Convert between enumeration values and strings
! 216: * private:
! 217: *
! 218: * arg: tOptDesc*, pOD, enumeration option description
! 219: * arg: unsigned int, enum_val, the enumeration value to map
! 220: *
! 221: * ret_type: char const *
! 222: * ret_desc: the enumeration name from const memory
! 223: *
! 224: * doc: This converts an enumeration value into the matching string.
! 225: =*/
! 226: char const *
! 227: optionKeywordName(tOptDesc * pOD, unsigned int enum_val)
! 228: {
! 229: tOptDesc od;
! 230:
! 231: od.optArg.argEnum = enum_val;
! 232: (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, &od );
! 233: return od.optArg.argString;
! 234: }
! 235:
! 236:
! 237: /*=export_func optionEnumerationVal
! 238: * what: Convert from a string to an enumeration value
! 239: * private:
! 240: *
! 241: * arg: tOptions*, pOpts, the program options descriptor
! 242: * arg: tOptDesc*, pOD, enumeration option description
! 243: * arg: char const * const *, paz_names, list of enumeration names
! 244: * arg: unsigned int, name_ct, number of names in list
! 245: *
! 246: * ret_type: uintptr_t
! 247: * ret_desc: the enumeration value
! 248: *
! 249: * doc: This converts the optArg.argString string from the option description
! 250: * into the index corresponding to an entry in the name list.
! 251: * This will match the generated enumeration value.
! 252: * Full matches are always accepted. Partial matches are accepted
! 253: * if there is only one partial match.
! 254: =*/
! 255: uintptr_t
! 256: optionEnumerationVal(tOptions * pOpts, tOptDesc * pOD,
! 257: char const * const * paz_names, unsigned int name_ct)
! 258: {
! 259: uintptr_t res = 0UL;
! 260:
! 261: /*
! 262: * IF the program option descriptor pointer is invalid,
! 263: * then it is some sort of special request.
! 264: */
! 265: switch ((uintptr_t)pOpts) {
! 266: case (uintptr_t)OPTPROC_EMIT_USAGE:
! 267: /*
! 268: * print the list of enumeration names.
! 269: */
! 270: enum_err(pOpts, pOD, paz_names, (int)name_ct);
! 271: break;
! 272:
! 273: case (uintptr_t)OPTPROC_EMIT_SHELL:
! 274: {
! 275: unsigned int ix = pOD->optArg.argEnum;
! 276: /*
! 277: * print the name string.
! 278: */
! 279: if (ix >= name_ct)
! 280: printf("INVALID-%d", ix);
! 281: else
! 282: fputs(paz_names[ ix ], stdout);
! 283:
! 284: break;
! 285: }
! 286:
! 287: case (uintptr_t)OPTPROC_RETURN_VALNAME:
! 288: {
! 289: tSCC zInval[] = "*INVALID*";
! 290: unsigned int ix = pOD->optArg.argEnum;
! 291: /*
! 292: * Replace the enumeration value with the name string.
! 293: */
! 294: if (ix >= name_ct)
! 295: return (uintptr_t)zInval;
! 296:
! 297: pOD->optArg.argString = paz_names[ix];
! 298: break;
! 299: }
! 300:
! 301: default:
! 302: res = find_name(pOD->optArg.argString, pOpts, pOD, paz_names, name_ct);
! 303:
! 304: if (pOD->fOptState & OPTST_ALLOC_ARG) {
! 305: AGFREE(pOD->optArg.argString);
! 306: pOD->fOptState &= ~OPTST_ALLOC_ARG;
! 307: pOD->optArg.argString = NULL;
! 308: }
! 309: }
! 310:
! 311: return res;
! 312: }
! 313:
! 314: static void
! 315: set_memb_usage(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 316: unsigned int name_ct)
! 317: {
! 318: /*
! 319: * print the list of enumeration names.
! 320: */
! 321: enum_err(OPTPROC_EMIT_USAGE, pOD, paz_names, (int)name_ct );
! 322: }
! 323:
! 324: static void
! 325: set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 326: unsigned int name_ct)
! 327: {
! 328: /*
! 329: * print the name string.
! 330: */
! 331: int ix = 0;
! 332: uintptr_t bits = (uintptr_t)pOD->optCookie;
! 333: size_t len = 0;
! 334:
! 335: bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1;
! 336:
! 337: while (bits != 0) {
! 338: if (bits & 1) {
! 339: if (len++ > 0) fputs(" | ", stdout);
! 340: fputs(paz_names[ix], stdout);
! 341: }
! 342: if (++ix >= name_ct) break;
! 343: bits >>= 1;
! 344: }
! 345: }
! 346:
! 347: static void
! 348: set_memb_names(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names,
! 349: unsigned int name_ct)
! 350: {
! 351: static char const none[] = "none";
! 352: static char const plus[3] = " + ";
! 353:
! 354: char * pz;
! 355: uintptr_t bits = (uintptr_t)pOD->optCookie;
! 356: int ix = 0;
! 357: size_t len = sizeof(none);
! 358:
! 359: bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1;
! 360:
! 361: /*
! 362: * Replace the enumeration value with the name string.
! 363: * First, determine the needed length, then allocate and fill in.
! 364: */
! 365: while (bits != 0) {
! 366: if (bits & 1)
! 367: len += strlen(paz_names[ix]) + sizeof(plus);
! 368: if (++ix >= name_ct) break;
! 369: bits >>= 1;
! 370: }
! 371:
! 372: pOD->optArg.argString = pz = AGALOC(len, "enum name");
! 373:
! 374: /*
! 375: * Start by clearing all the bits. We want to turn off any defaults
! 376: * because we will be restoring to current state, not adding to
! 377: * the default set of bits.
! 378: */
! 379: memcpy(pz, none, sizeof(none)-1);
! 380: pz += sizeof(none)-1;
! 381: bits = (uintptr_t)pOD->optCookie;
! 382: bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1;
! 383: ix = 0;
! 384:
! 385: while (bits != 0) {
! 386: if (bits & 1) {
! 387: size_t nln = strlen(paz_names[ix]);
! 388: memcpy(pz, plus, sizeof(plus));
! 389: memcpy(pz+sizeof(plus), paz_names[ix], nln);
! 390: pz += strlen(paz_names[ix]) + 3;
! 391: }
! 392: if (++ix >= name_ct) break;
! 393: bits >>= 1;
! 394: }
! 395: *pz = NUL;
! 396: }
! 397:
! 398: /*=export_func optionSetMembers
! 399: * what: Convert between bit flag values and strings
! 400: * private:
! 401: *
! 402: * arg: tOptions*, pOpts, the program options descriptor
! 403: * arg: tOptDesc*, pOD, enumeration option description
! 404: * arg: char const * const *,
! 405: * paz_names, list of enumeration names
! 406: * arg: unsigned int, name_ct, number of names in list
! 407: *
! 408: * doc: This converts the optArg.argString string from the option description
! 409: * into the index corresponding to an entry in the name list.
! 410: * This will match the generated enumeration value.
! 411: * Full matches are always accepted. Partial matches are accepted
! 412: * if there is only one partial match.
! 413: =*/
! 414: void
! 415: optionSetMembers(tOptions * pOpts, tOptDesc * pOD,
! 416: char const* const * paz_names, unsigned int name_ct)
! 417: {
! 418: /*
! 419: * IF the program option descriptor pointer is invalid,
! 420: * then it is some sort of special request.
! 421: */
! 422: switch ((uintptr_t)pOpts) {
! 423: case (uintptr_t)OPTPROC_EMIT_USAGE:
! 424: set_memb_usage(pOpts, pOD, paz_names, name_ct);
! 425: return;
! 426:
! 427: case (uintptr_t)OPTPROC_EMIT_SHELL:
! 428: set_memb_shell(pOpts, pOD, paz_names, name_ct);
! 429: return;
! 430:
! 431: case (uintptr_t)OPTPROC_RETURN_VALNAME:
! 432: set_memb_names(pOpts, pOD, paz_names, name_ct);
! 433: return;
! 434:
! 435: default:
! 436: break;
! 437: }
! 438:
! 439: if ((pOD->fOptState & OPTST_RESET) != 0)
! 440: return;
! 441:
! 442: {
! 443: char const* pzArg = pOD->optArg.argString;
! 444: uintptr_t res;
! 445: if ((pzArg == NULL) || (*pzArg == NUL)) {
! 446: pOD->optCookie = (void*)0;
! 447: return;
! 448: }
! 449:
! 450: res = (uintptr_t)pOD->optCookie;
! 451: for (;;) {
! 452: tSCC zSpn[] = " ,|+\t\r\f\n";
! 453: int iv, len;
! 454:
! 455: pzArg += strspn(pzArg, zSpn);
! 456: iv = (*pzArg == '!');
! 457: if (iv)
! 458: pzArg += strspn(pzArg+1, zSpn) + 1;
! 459:
! 460: len = strcspn(pzArg, zSpn);
! 461: if (len == 0)
! 462: break;
! 463:
! 464: if ((len == 3) && (strncmp(pzArg, zAll, 3) == 0)) {
! 465: if (iv)
! 466: res = 0;
! 467: else res = ~0UL;
! 468: }
! 469: else if ((len == 4) && (strncmp(pzArg, zNone, 4) == 0)) {
! 470: if (! iv)
! 471: res = 0;
! 472: }
! 473: else do {
! 474: char* pz;
! 475: uintptr_t bit = strtoul(pzArg, &pz, 0);
! 476:
! 477: if (pz != pzArg + len) {
! 478: char z[ AO_NAME_SIZE ];
! 479: char const* p;
! 480: int shift_ct;
! 481:
! 482: if (*pz != NUL) {
! 483: if (len >= AO_NAME_LIMIT)
! 484: break;
! 485: memcpy(z, pzArg, (size_t)len);
! 486: z[len] = NUL;
! 487: p = z;
! 488: } else {
! 489: p = pzArg;
! 490: }
! 491:
! 492: shift_ct = find_name(p, pOpts, pOD, paz_names, name_ct);
! 493: if (shift_ct >= name_ct) {
! 494: pOD->optCookie = (void*)0;
! 495: return;
! 496: }
! 497: bit = 1UL << shift_ct;
! 498: }
! 499: if (iv)
! 500: res &= ~bit;
! 501: else res |= bit;
! 502: } while (0);
! 503:
! 504: if (pzArg[len] == NUL)
! 505: break;
! 506: pzArg += len + 1;
! 507: }
! 508: if (name_ct < (8 * sizeof(uintptr_t))) {
! 509: res &= (1UL << name_ct) - 1UL;
! 510: }
! 511:
! 512: pOD->optCookie = (void*)res;
! 513: }
! 514: }
! 515:
! 516: /*
! 517: * Local Variables:
! 518: * mode: C
! 519: * c-file-style: "stroustrup"
! 520: * indent-tabs-mode: nil
! 521: * End:
! 522: * end of autoopts/enumeration.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>