static uintptr_t findName( tCC* pzName, tOptions* pOpts, tOptDesc* pOD, tCC* const * paz_names, unsigned int name_ct ) { /* * Return the matching index as a pointer sized integer. * The result gets stashed in a char* pointer. */ uintptr_t res = name_ct; size_t len = strlen( (char*)pzName ); uintptr_t idx; if (IS_DEC_DIGIT_CHAR(*pzName)) { char * pz = (char *)(void *)pzName; unsigned long val = strtoul(pz, &pz, 0); if ((*pz == NUL) && (val < name_ct)) return (uintptr_t)val; enumError(pOpts, pOD, paz_names, (int)name_ct); return name_ct; } /* * Look for an exact match, but remember any partial matches. * Multiple partial matches means we have an ambiguous match. */ for (idx = 0; idx < name_ct; idx++) { if (strncmp( (char*)paz_names[idx], (char*)pzName, len) == 0) { if (paz_names[idx][len] == NUL) return idx; /* full match */ res = (res != name_ct) ? ~0 : idx; /* save partial match */ } } if (res < name_ct) return res; /* partial match */ pz_enum_err_fmt = (res == name_ct) ? zNoKey : zAmbigKey; option_usage_fp = stderr; enumError(pOpts, pOD, paz_names, (int)name_ct); return name_ct; }
static uintptr_t findName( tCC* pzName, tOptions* pOpts, tOptDesc* pOD, tCC* const * paz_names, unsigned int name_ct ) { uintptr_t res = name_ct; size_t len = strlen( (char*)pzName ); uintptr_t idx; /* * Look for an exact match, but remember any partial matches. * Multiple partial matches means we have an ambiguous match. */ for (idx = 0; idx < name_ct; idx++) { if (strncmp( (char*)paz_names[idx], (char*)pzName, len) == 0) { if (paz_names[idx][len] == NUL) return idx; /* full match */ if (res != name_ct) { pz_enum_err_fmt = zAmbigKey; option_usage_fp = stderr; enumError( pOpts, pOD, paz_names, (int)name_ct ); } res = idx; /* save partial match */ } } /* * no partial match -> error */ if (res == name_ct) { pz_enum_err_fmt = zNoKey; option_usage_fp = stderr; enumError( pOpts, pOD, paz_names, (int)name_ct ); } /* * Return the matching index as a char* pointer. * The result gets stashed in a char* pointer, so it will have to fit. */ return res; }
/*=export_func optionSetMembers * what: Convert between bit flag values and strings * private: * * arg: tOptions*, pOpts, the program options descriptor * arg: tOptDesc*, pOD, enumeration option description * arg: char const * const *, * paz_names, list of enumeration names * arg: unsigned int, name_ct, number of names in list * * doc: This converts the optArg.argString string from the option description * into the index corresponding to an entry in the name list. * This will match the generated enumeration value. * Full matches are always accepted. Partial matches are accepted * if there is only one partial match. =*/ void optionSetMembers( tOptions* pOpts, tOptDesc* pOD, tCC* const * paz_names, unsigned int name_ct ) { /* * IF the program option descriptor pointer is invalid, * then it is some sort of special request. */ switch ((uintptr_t)pOpts) { case (uintptr_t)OPTPROC_EMIT_USAGE: /* * print the list of enumeration names. */ enumError(OPTPROC_EMIT_USAGE, pOD, paz_names, (int)name_ct ); return; case (uintptr_t)OPTPROC_EMIT_SHELL: { /* * print the name string. */ int ix = 0; uintptr_t bits = (uintptr_t)pOD->optCookie; size_t len = 0; bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; while (bits != 0) { if (bits & 1) { if (len++ > 0) fputs( " | ", stdout ); fputs(paz_names[ix], stdout); } if (++ix >= name_ct) break; bits >>= 1; } return; } case (uintptr_t)OPTPROC_RETURN_VALNAME: { char* pz; uintptr_t bits = (uintptr_t)pOD->optCookie; int ix = 0; size_t len = 5; bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; /* * Replace the enumeration value with the name string. * First, determine the needed length, then allocate and fill in. */ while (bits != 0) { if (bits & 1) len += strlen( paz_names[ix]) + 8; if (++ix >= name_ct) break; bits >>= 1; } pOD->optArg.argString = pz = AGALOC(len, "enum name"); /* * Start by clearing all the bits. We want to turn off any defaults * because we will be restoring to current state, not adding to * the default set of bits. */ strcpy( pz, "none" ); pz += 4; bits = (uintptr_t)pOD->optCookie; bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; ix = 0; while (bits != 0) { if (bits & 1) { strcpy( pz, " + " ); strcpy( pz+3, paz_names[ix]); pz += strlen( paz_names[ix]) + 3; } if (++ix >= name_ct) break; bits >>= 1; } return; } default: break; } if ((pOD->fOptState & OPTST_RESET) != 0) return; { tCC* pzArg = pOD->optArg.argString; uintptr_t res; if ((pzArg == NULL) || (*pzArg == NUL)) { pOD->optCookie = (void*)0; return; } res = (uintptr_t)pOD->optCookie; for (;;) { tSCC zSpn[] = " ,|+\t\r\f\n"; int iv, len; pzArg += strspn( pzArg, zSpn ); iv = (*pzArg == '!'); if (iv) pzArg += strspn( pzArg+1, zSpn ) + 1; len = strcspn( pzArg, zSpn ); if (len == 0) break; if ((len == 3) && (strncmp(pzArg, zAll, (size_t)3) == 0)) { if (iv) res = 0; else res = ~0UL; } else if ((len == 4) && (strncmp(pzArg, zNone, (size_t)4) == 0)) { if (! iv) res = 0; } else do { char* pz; uintptr_t bit = strtoul( pzArg, &pz, 0 ); if (pz != pzArg + len) { char z[ AO_NAME_SIZE ]; tCC* p; int shift_ct; if (*pz != NUL) { if (len >= AO_NAME_LIMIT) break; strncpy( z, pzArg, (size_t)len ); z[len] = NUL; p = z; } else { p = pzArg; } shift_ct = findName(p, pOpts, pOD, paz_names, name_ct); if (shift_ct >= name_ct) { pOD->optCookie = (void*)0; return; } bit = 1UL << shift_ct; } if (iv) res &= ~bit; else res |= bit; } while (0); if (pzArg[len] == NUL) break; pzArg += len + 1; } if (name_ct < (8 * sizeof( uintptr_t ))) { res &= (1UL << name_ct) - 1UL; } pOD->optCookie = (void*)res; } }
/*=export_func optionEnumerationVal * what: Convert from a string to an enumeration value * private: * * arg: tOptions*, pOpts, the program options descriptor * arg: tOptDesc*, pOD, enumeration option description * arg: char const * const *, paz_names, list of enumeration names * arg: unsigned int, name_ct, number of names in list * * ret_type: uintptr_t * ret_desc: the enumeration value * * doc: This converts the optArg.argString string from the option description * into the index corresponding to an entry in the name list. * This will match the generated enumeration value. * Full matches are always accepted. Partial matches are accepted * if there is only one partial match. =*/ uintptr_t optionEnumerationVal( tOptions* pOpts, tOptDesc* pOD, tCC * const * paz_names, unsigned int name_ct ) { uintptr_t res = 0UL; /* * IF the program option descriptor pointer is invalid, * then it is some sort of special request. */ switch ((uintptr_t)pOpts) { case (uintptr_t)OPTPROC_EMIT_USAGE: /* * print the list of enumeration names. */ enumError(pOpts, pOD, paz_names, (int)name_ct); break; case (uintptr_t)OPTPROC_EMIT_SHELL: { unsigned int ix = pOD->optArg.argEnum; /* * print the name string. */ if (ix >= name_ct) printf( "INVALID-%d", ix ); else fputs( paz_names[ ix ], stdout ); break; } case (uintptr_t)OPTPROC_RETURN_VALNAME: { tSCC zInval[] = "*INVALID*"; unsigned int ix = pOD->optArg.argEnum; /* * Replace the enumeration value with the name string. */ if (ix >= name_ct) return (uintptr_t)zInval; pOD->optArg.argString = paz_names[ix]; break; } default: res = findName(pOD->optArg.argString, pOpts, pOD, paz_names, name_ct); if (pOD->fOptState & OPTST_ALLOC_ARG) { AGFREE(pOD->optArg.argString); pOD->fOptState &= ~OPTST_ALLOC_ARG; pOD->optArg.argString = NULL; } } return res; }