static tSuccess
mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx );
static tSuccess
mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx );
static tSuccess
checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx );
static tSuccess
mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx )
{
switch (pOS->optType) {
case TOPT_SHORT:
if (*pzArg != NUL)
return SUCCESS;
break;
case TOPT_LONG:
if (pOS->pzOptArg != NULL)
return SUCCESS;
break;
default:
return FAILURE;
}
if (pOpts->curOptIdx >= pOpts->origArgCt)
return FAILURE;
ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
return SUCCESS;
}
static tSuccess
mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx )
{
switch (pOS->optType) {
case TOPT_SHORT:
if (*pzArg != NUL)
return SUCCESS;
break;
case TOPT_LONG:
if (pOS->pzOptArg != NULL)
return SUCCESS;
break;
default:
return FAILURE;
}
if (pOpts->curOptIdx >= pOpts->origArgCt)
return PROBLEM;
pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
if (*pzArg != '-')
ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
return SUCCESS;
}
static tSuccess
checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
char** ppzOpts, int* pOptsIdx )
{
while (*pzArg != NUL) {
if (FAILED( shortOptionFind( pOpts, (tAoUC)*pzArg, pOS )))
return FAILURE;
if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
pzArg++;
} else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
if (pzArg[1] != NUL)
return SUCCESS;
pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
if (*pzArg != '-')
ppzOpts[ (*pOptsIdx)++ ] =
pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
return SUCCESS;
} else {
if (pzArg[1] == NUL) {
if (pOpts->curOptIdx >= pOpts->origArgCt)
return FAILURE;
ppzOpts[ (*pOptsIdx)++ ] =
pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
}
return SUCCESS;
}
}
return SUCCESS;
}
LOCAL void
optionSort( tOptions* pOpts )
{
char** ppzOpts;
char** ppzOpds;
int optsIdx = 0;
int opdsIdx = 0;
tOptState os = OPTSTATE_INITIALIZER(DEFINED);
if ( (getenv( "POSIXLY_CORRECT" ) != NULL)
|| NAMED_OPTS(pOpts))
return;
ppzOpts = malloc( pOpts->origArgCt * sizeof( char* ));
if (ppzOpts == NULL)
goto exit_no_mem;
ppzOpds = malloc( pOpts->origArgCt * sizeof( char* ));
if (ppzOpds == NULL) {
free( ppzOpts );
goto exit_no_mem;
}
pOpts->curOptIdx = 1;
pOpts->pzCurOpt = NULL;
for (;;) {
char* pzArg;
tSuccess res;
if (pOpts->curOptIdx >= pOpts->origArgCt) {
errno = 0;
goto joinLists;
}
pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
if (*pzArg != '-') {
ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
continue;
}
switch (pzArg[1]) {
case NUL:
ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
continue;
case '-':
if (pzArg[2] == NUL) {
ppzOpts[ optsIdx++ ] =
pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
goto restOperands;
}
res = longOptionFind( pOpts, pzArg+2, &os );
break;
default:
if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) {
res = longOptionFind( pOpts, pzArg+1, &os );
} else {
res = shortOptionFind( pOpts, (tAoUC)pzArg[1], &os );
}
break;
}
if (FAILED( res )) {
errno = EINVAL;
goto freeTemps;
}
ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
if ( (os.optType == TOPT_SHORT)
&& FAILED( checkShortOpts( pOpts, pzArg+2, &os,
ppzOpts, &optsIdx )) ) {
errno = EINVAL;
goto freeTemps;
}
} else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) {
switch (mayHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
case FAILURE: errno = EIO; goto freeTemps;
case PROBLEM: errno = 0; goto joinLists;
}
} else {
switch (mustHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
case PROBLEM:
case FAILURE: errno = EIO; goto freeTemps;
}
}
}
restOperands:
while (pOpts->curOptIdx < pOpts->origArgCt)
ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
joinLists:
if (optsIdx > 0)
memcpy( pOpts->origArgVect + 1, ppzOpts, optsIdx * sizeof( char* ));
if (opdsIdx > 0)
memcpy( pOpts->origArgVect + 1 + optsIdx,
ppzOpds, opdsIdx * sizeof( char* ));
freeTemps:
free( ppzOpts );
free( ppzOpds );
return;
exit_no_mem:
errno = ENOMEM;
return;
}