Return to putshell.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / sntp / libopts |
1.1 ! misho 1: ! 2: /** ! 3: * \file putshell.c ! 4: * ! 5: * Time-stamp: "2010-09-05 06:10:56 bkorb" ! 6: * ! 7: * This module will interpret the options set in the tOptions ! 8: * structure and print them to standard out in a fashion that ! 9: * will allow them to be interpreted by the Bourne or Korn shells. ! 10: * ! 11: * This file is part of AutoOpts, a companion to AutoGen. ! 12: * AutoOpts is free software. ! 13: * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved ! 14: * ! 15: * AutoOpts is available under any one of two licenses. The license ! 16: * in use must be one of these two and the choice is under the control ! 17: * of the user of the license. ! 18: * ! 19: * The GNU Lesser General Public License, version 3 or later ! 20: * See the files "COPYING.lgplv3" and "COPYING.gplv3" ! 21: * ! 22: * The Modified Berkeley Software Distribution License ! 23: * See the file "COPYING.mbsd" ! 24: * ! 25: * These files have the following md5sums: ! 26: * ! 27: * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 ! 28: * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 ! 29: * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd ! 30: */ ! 31: static char const zOptValFmt[] = "%s_%s="; ! 32: static char const zOptEnd[] = "\nexport %s_%s\n"; ! 33: static char const zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n"; ! 34: ! 35: /* = = = START-STATIC-FORWARD = = = */ ! 36: static void ! 37: print_quot_str(tCC* pzStr); ! 38: ! 39: static void ! 40: print_enumeration(tOptions * pOpts, tOptDesc * pOD); ! 41: ! 42: static void ! 43: print_membership(tOptions * pOpts, tOptDesc * pOD); ! 44: ! 45: static void ! 46: print_stacked_arg(tOptions * pOpts, tOptDesc * pOD); ! 47: ! 48: static void ! 49: print_reordering(tOptions * pOpts); ! 50: /* = = = END-STATIC-FORWARD = = = */ ! 51: ! 52: /* ! 53: * Make sure embedded single quotes come out okay. The initial quote has ! 54: * been emitted and the closing quote will be upon return. ! 55: */ ! 56: static void ! 57: print_quot_str(tCC* pzStr) ! 58: { ! 59: /* ! 60: * Handle empty strings to make the rest of the logic simpler. ! 61: */ ! 62: if ((pzStr == NULL) || (*pzStr == NUL)) { ! 63: fputs("''", stdout); ! 64: return; ! 65: } ! 66: ! 67: /* ! 68: * Emit any single quotes/apostrophes at the start of the string and ! 69: * bail if that is all we need to do. ! 70: */ ! 71: while (*pzStr == '\'') { ! 72: fputs("\\'", stdout); ! 73: pzStr++; ! 74: } ! 75: if (*pzStr == NUL) ! 76: return; ! 77: ! 78: /* ! 79: * Start the single quote string ! 80: */ ! 81: fputc('\'', stdout); ! 82: for (;;) { ! 83: tCC* pz = strchr(pzStr, '\''); ! 84: if (pz == NULL) ! 85: break; ! 86: ! 87: /* ! 88: * Emit the string up to the single quote (apostrophe) we just found. ! 89: */ ! 90: (void)fwrite(pzStr, (size_t)(pz - pzStr), (size_t)1, stdout); ! 91: fputc('\'', stdout); ! 92: pzStr = pz; ! 93: ! 94: /* ! 95: * Emit an escaped apostrophe for every one we find. ! 96: * If that ends the string, do not re-open the single quotes. ! 97: */ ! 98: while (*++pzStr == '\'') fputs("\\'", stdout); ! 99: if (*pzStr == NUL) ! 100: return; ! 101: ! 102: fputc('\'', stdout); ! 103: } ! 104: ! 105: /* ! 106: * If we broke out of the loop, we must still emit the remaining text ! 107: * and then close the single quote string. ! 108: */ ! 109: fputs(pzStr, stdout); ! 110: fputc('\'', stdout); ! 111: } ! 112: ! 113: static void ! 114: print_enumeration(tOptions * pOpts, tOptDesc * pOD) ! 115: { ! 116: uintptr_t e_val = pOD->optArg.argEnum; ! 117: printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME); ! 118: ! 119: /* ! 120: * Convert value to string, print that and restore numeric value. ! 121: */ ! 122: (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); ! 123: printf("'%s'", pOD->optArg.argString); ! 124: if (pOD->fOptState & OPTST_ALLOC_ARG) ! 125: AGFREE(pOD->optArg.argString); ! 126: pOD->optArg.argEnum = e_val; ! 127: ! 128: printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME); ! 129: } ! 130: ! 131: static void ! 132: print_membership(tOptions * pOpts, tOptDesc * pOD) ! 133: { ! 134: char const * pz; ! 135: uintptr_t val = 1; ! 136: printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, ! 137: (int)(uintptr_t)(pOD->optCookie)); ! 138: pOD->optCookie = (void*)(uintptr_t)~0UL; ! 139: (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); ! 140: ! 141: /* ! 142: * We are building the typeset list. The list returned starts with ! 143: * 'none + ' for use by option saving stuff. We must ignore that. ! 144: */ ! 145: pz = pOD->optArg.argString + 7; ! 146: while (*pz != NUL) { ! 147: printf("typeset -x -i %s_", pOD->pz_NAME); ! 148: while (IS_PLUS_N_SPACE_CHAR(*pz)) pz++; ! 149: ! 150: for (;;) { ! 151: int ch = *(pz++); ! 152: if (IS_LOWER_CASE_CHAR(ch)) fputc(toupper(ch), stdout); ! 153: else if (IS_UPPER_CASE_CHAR(ch)) fputc(ch, stdout); ! 154: else if (IS_PLUS_N_SPACE_CHAR(ch)) goto name_done; ! 155: else if (ch == NUL) { pz--; goto name_done; } ! 156: else fputc('_', stdout); ! 157: } name_done:; ! 158: printf("=%1$lu # 0x%1$lX\n", (unsigned long)val); ! 159: val <<= 1; ! 160: } ! 161: ! 162: AGFREE(pOD->optArg.argString); ! 163: pOD->optArg.argString = NULL; ! 164: pOD->fOptState &= ~OPTST_ALLOC_ARG; ! 165: } ! 166: ! 167: static void ! 168: print_stacked_arg(tOptions * pOpts, tOptDesc * pOD) ! 169: { ! 170: tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n"; ! 171: ! 172: tArgList* pAL = (tArgList*)pOD->optCookie; ! 173: tCC** ppz = pAL->apzArgs; ! 174: int ct = pAL->useCt; ! 175: ! 176: printf(zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct); ! 177: ! 178: while (--ct >= 0) { ! 179: tSCC numarg_z[] = "%s_%s_%d="; ! 180: tSCC end_z[] = "\nexport %s_%s_%d\n"; ! 181: ! 182: printf(numarg_z, pOpts->pzPROGNAME, pOD->pz_NAME, ! 183: pAL->useCt - ct); ! 184: print_quot_str(*(ppz++)); ! 185: printf(end_z, pOpts->pzPROGNAME, pOD->pz_NAME, ! 186: pAL->useCt - ct); ! 187: } ! 188: } ! 189: ! 190: static void ! 191: print_reordering(tOptions * pOpts) ! 192: { ! 193: int optIx; ! 194: ! 195: fputs("set --", stdout); ! 196: ! 197: for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) { ! 198: ! 199: char* pzArg = pOpts->origArgVect[ optIx ]; ! 200: ! 201: if (strchr(pzArg, '\'') == NULL) ! 202: printf(" '%s'", pzArg); ! 203: ! 204: else { ! 205: fputs(" '", stdout); ! 206: for (;;) { ! 207: char ch = *(pzArg++); ! 208: switch (ch) { ! 209: case '\'': fputs("'\\''", stdout); break; ! 210: case NUL: goto arg_done; ! 211: default: fputc(ch, stdout); break; ! 212: } ! 213: } arg_done:; ! 214: fputc('\'', stdout); ! 215: } ! 216: } ! 217: fputs("\nOPTION_CT=0\n", stdout); ! 218: } ! 219: ! 220: /*=export_func optionPutShell ! 221: * what: write a portable shell script to parse options ! 222: * private: ! 223: * arg: tOptions*, pOpts, the program options descriptor ! 224: * doc: This routine will emit portable shell script text for parsing ! 225: * the options described in the option definitions. ! 226: =*/ ! 227: void ! 228: optionPutShell(tOptions* pOpts) ! 229: { ! 230: int optIx = 0; ! 231: tSCC zOptCtFmt[] = "OPTION_CT=%d\nexport OPTION_CT\n"; ! 232: tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n"; ! 233: tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n"; ! 234: tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n"; ! 235: ! 236: printf(zOptCtFmt, pOpts->curOptIdx-1); ! 237: ! 238: do { ! 239: tOptDesc* pOD = pOpts->pOptDesc + optIx; ! 240: ! 241: if (SKIP_OPT(pOD)) ! 242: continue; ! 243: ! 244: /* ! 245: * Equivalence classes are hard to deal with. Where the ! 246: * option data wind up kind of squishes around. For the purposes ! 247: * of emitting shell state, they are not recommended, but we'll ! 248: * do something. I guess we'll emit the equivalenced-to option ! 249: * at the point in time when the base option is found. ! 250: */ ! 251: if (pOD->optEquivIndex != NO_EQUIVALENT) ! 252: continue; /* equivalence to a different option */ ! 253: ! 254: /* ! 255: * Equivalenced to a different option. Process the current option ! 256: * as the equivalenced-to option. Keep the persistent state bits, ! 257: * but copy over the set-state bits. ! 258: */ ! 259: if (pOD->optActualIndex != optIx) { ! 260: tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex; ! 261: p->optArg = pOD->optArg; ! 262: p->fOptState &= OPTST_PERSISTENT_MASK; ! 263: p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK; ! 264: printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME); ! 265: pOD = p; ! 266: } ! 267: ! 268: /* ! 269: * If the argument type is a set membership bitmask, then we always ! 270: * emit the thing. We do this because it will always have some sort ! 271: * of bitmask value and we need to emit the bit values. ! 272: */ ! 273: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { ! 274: print_membership(pOpts, pOD); ! 275: continue; ! 276: } ! 277: ! 278: /* ! 279: * IF the option was either specified or it wakes up enabled, ! 280: * then we will emit information. Otherwise, skip it. ! 281: * The idea is that if someone defines an option to initialize ! 282: * enabled, we should tell our shell script that it is enabled. ! 283: */ ! 284: if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) { ! 285: continue; ! 286: } ! 287: ! 288: /* ! 289: * Handle stacked arguments ! 290: */ ! 291: if ( (pOD->fOptState & OPTST_STACKED) ! 292: && (pOD->optCookie != NULL) ) { ! 293: print_stacked_arg(pOpts, pOD); ! 294: continue; ! 295: } ! 296: ! 297: /* ! 298: * If the argument has been disabled, ! 299: * Then set its value to the disablement string ! 300: */ ! 301: if ((pOD->fOptState & OPTST_DISABLED) != 0) { ! 302: printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME, ! 303: (pOD->pz_DisablePfx != NULL) ! 304: ? pOD->pz_DisablePfx : "false"); ! 305: continue; ! 306: } ! 307: ! 308: /* ! 309: * If the argument type is numeric, the last arg pointer ! 310: * is really the VALUE of the string that was pointed to. ! 311: */ ! 312: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) { ! 313: printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, ! 314: (int)pOD->optArg.argInt); ! 315: continue; ! 316: } ! 317: ! 318: /* ! 319: * If the argument type is an enumeration, then it is much ! 320: * like a text value, except we call the callback function ! 321: * to emit the value corresponding to the "optArg" number. ! 322: */ ! 323: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) { ! 324: print_enumeration(pOpts, pOD); ! 325: continue; ! 326: } ! 327: ! 328: /* ! 329: * If the argument type is numeric, the last arg pointer ! 330: * is really the VALUE of the string that was pointed to. ! 331: */ ! 332: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) { ! 333: printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME, ! 334: (pOD->optArg.argBool == 0) ? "false" : "true"); ! 335: continue; ! 336: } ! 337: ! 338: /* ! 339: * IF the option has an empty value, ! 340: * THEN we set the argument to the occurrence count. ! 341: */ ! 342: if ( (pOD->optArg.argString == NULL) ! 343: || (pOD->optArg.argString[0] == NUL) ) { ! 344: ! 345: printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, ! 346: pOD->optOccCt); ! 347: continue; ! 348: } ! 349: ! 350: /* ! 351: * This option has a text value ! 352: */ ! 353: printf(zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME); ! 354: print_quot_str(pOD->optArg.argString); ! 355: printf(zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME); ! 356: ! 357: } while (++optIx < pOpts->presetOptCt ); ! 358: ! 359: if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0) ! 360: && (pOpts->curOptIdx < pOpts->origArgCt)) ! 361: print_reordering(pOpts); ! 362: ! 363: fflush(stdout); ! 364: } ! 365: ! 366: /* ! 367: * Local Variables: ! 368: * mode: C ! 369: * c-file-style: "stroustrup" ! 370: * indent-tabs-mode: nil ! 371: * End: ! 372: * end of autoopts/putshell.c */