📄 vk_popt.cpp
字号:
/* --------------------------------------------------------------------- * Implementation of Popt functions vk_popt.cpp * This is a seriously hacked version of the popt libraries. * No credit to me, all thanks and many apologies to the Red Hat team * --------------------------------------------------------------------- * popt is Copyright (c) 1998 Red Hat Software and distributed under * an X11-style license, which is in turn compatible the GNU GPL v.2. */#include "vk_popt.h"#include "vk_option.h" /* namespace VkOPTION */#include "vk_utils.h"/* return a vkPoptOption initialised to null */vkPoptOption nullOpt(){ vkPoptOption _nullOpt = TABLE_END; return _nullOpt;}const char * vkPoptPeekArg( vkPoptContext con ){ const char * ret = NULL; if ( con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers ) ret = con->leftovers[con->nextLeftover]; return ret;}const char * vkPoptGetArg( vkPoptContext con ){ const char * ret = NULL; if ( con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers ) { ret = con->leftovers[con->nextLeftover++]; } return ret;}const char ** vkPoptGetArgs( vkPoptContext con ){ if ( con == NULL || con->leftovers == NULL || con->numLeftovers == con->nextLeftover ) return NULL; /* some apps like [like RPM ;-) ] need this NULL terminated */ con->leftovers[con->numLeftovers] = NULL; return (con->leftovers + con->nextLeftover);}vkPoptContext vkPoptGetContext( int argc, const char ** argv, const vkPoptOption * options ){ vkPoptContext con = (vkPoptContext)malloc( sizeof(*con) ); if ( con == NULL ) { return NULL; } memset( con, 0, sizeof(*con) ); con->os = con->optionStack; con->os->argc = argc; con->os->argv = argv; con->os->next = 1; /* skip argv[0] */ con->leftovers = (const char**)calloc( (argc + 1), sizeof(*con->leftovers) ); con->options = options; con->flags = PCONTEXT_POSIXMEHARDER; con->finalArgvAlloced = argc * 2; con->finalArgv = (const char**)calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) ); return con;}static void vkCleanOSE( struct optionStackEntry *os ){ os->nextArg = (const char*)_free( os->nextArg ); os->argv = (const char**)_free( os->argv );}const vkPoptOption * vkFindOption( const vkPoptOption * opt, const char * longFlag, char shortFlag, int singleDash ){ /* this happens when a single - is given */ if ( singleDash && !shortFlag && (longFlag && *longFlag == '\0') ) shortFlag = '-'; for (; opt->longFlag || opt->shortFlag || opt->arg; opt++) { if ( opt->arg != NULL ) { /* is-a table */ /* recurse on included sub-tables. */ const vkPoptOption* opt2 = vkFindOption( opt->arg, longFlag, shortFlag, singleDash ); if ( opt2 == NULL ) continue; /* no match in sub-table */ /* found match: return option */ return opt2; } else { /* is-a leaf */ if ( longFlag && opt->longFlag && !singleDash && !strcmp( longFlag, opt->longFlag ) ) break; /* longFlag match */ if (shortFlag && shortFlag == opt->shortFlag) break; /* shortFlag match */ } } if ( !opt->longFlag && !opt->shortFlag ) return NULL; /* end of optArr: no match found */ /* found match */ return opt;}static const char * vkExpandNextArg( const char * s ){ char *t, *te; size_t tn = strlen(s) + 1; char c; te = t = (char*)malloc(tn);; if ( t == NULL ) return NULL; while ((c = *s++) != '\0') { *te++ = c; } *te = '\0'; /* memory leak, hard to plug */ t = (char*)realloc(t, strlen(t) + 1); return t;}/* get next option opt_ret returns 0 on success, 1 on last item, PERROR_* on error */int vkPoptGetNextOpt( vkPoptContext con, char *arg_val/*OUT*/, const vkPoptOption** opt_ret/*OUT*/ ){ const vkPoptOption * opt = NULL; int done = 0; if ( con == NULL ) { return 1; } while ( !done ) { const char * origOptString = NULL; const char * longArg = NULL; int shorty = 0; while ( !con->os->nextCharArg && con->os->next == con->os->argc && con->os > con->optionStack ) { vkCleanOSE( con->os-- ); } if ( !con->os->nextCharArg && con->os->next == con->os->argc ) { return 1; } /* process next long option */ if ( !con->os->nextCharArg ) { char * localOptString, * optString; int thisopt; thisopt = con->os->next; if ( con->os->argv != NULL ) origOptString = con->os->argv[con->os->next++]; if ( origOptString == NULL ) { return PERROR_BADOPT; } if ( strcmp(origOptString, "--") == 0 ) { return PERROR_BADQUOTE; } if ( con->restLeftover || *origOptString != '-' ) { if ( con->flags & PCONTEXT_POSIXMEHARDER ) con->restLeftover = 1; if ( con->leftovers != NULL ) con->leftovers[con->numLeftovers++] = origOptString; continue; } /* make a copy we can hack at */ localOptString = optString = strcpy((char*)alloca(strlen(origOptString) + 1), origOptString); if ( optString[0] == '\0' ) return PERROR_BADOPT; if ( optString[1] == '-' && !optString[2] ) { con->restLeftover = 1; continue; } else { char *oe; int singleDash; optString++; if ( *optString == '-' ) singleDash = 0, optString++; else singleDash = 1; /* Check for "--long=arg" option. */ for ( oe = optString; *oe && *oe != '='; oe++ ) { }; if ( *oe == '=' ) { /* FIX: don't use '=' for shortopts */ if ( singleDash ) return PERROR_NODASH; *oe++ = '\0'; /* longArg is mapped back to persistent storage. */ longArg = origOptString + (oe - localOptString); /* FIX: catch cases where --longarg=<no-arg> */ if ( strlen(longArg) == 0 ) { //printf("1: returning PERROR_NOARG\n"); return PERROR_NOARG; } } #if 0 else if ( singleDash == 0 ) { /* FIX: catch cases where we didn't find an '=', and this is a --longarg option */ //printf("2: returning PERROR_NOARG\n"); return PERROR_NOARG; } #endif opt = vkFindOption( con->options, optString, '\0', singleDash ); if ( !opt && !singleDash ) { //printf("returning PERROR_BADOPT\n"); return PERROR_BADOPT; } } if ( !opt ) { con->os->nextCharArg = origOptString + 1; } else { shorty = 0; } } /* process next short option */ if ( con->os->nextCharArg ) { origOptString = con->os->nextCharArg; con->os->nextCharArg = NULL; opt = vkFindOption( con->options, NULL, *origOptString, 0 ); if ( !opt ) { return PERROR_BADOPT; } shorty = 1; origOptString++; if ( *origOptString != '\0' ) con->os->nextCharArg = origOptString; } if ( opt == NULL ) return PERROR_BADOPT; if ( opt->argType != VkOPTION::ARG_NONE ) { con->os->nextArg = (const char*)_free(con->os->nextArg); if ( longArg ) { longArg = vkExpandNextArg( longArg ); con->os->nextArg = longArg; } else if ( con->os->nextCharArg ) { longArg = vkExpandNextArg( con->os->nextCharArg); con->os->nextArg = longArg; con->os->nextCharArg = NULL; } else { while ( con->os->next == con->os->argc && con->os > con->optionStack ) { vkCleanOSE( con->os-- ); } if ( con->os->next == con->os->argc ) { /* FIX: con->os->argv not defined */ return PERROR_NOARG; con->os->nextArg = NULL; } else { if ( con->os->argv != NULL ) { /* watch out: subtle side-effects live here. */ longArg = con->os->argv[con->os->next++]; longArg = vkExpandNextArg( longArg ); con->os->nextArg = longArg; } } } longArg = NULL; /* store the argument value for checking */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -