static tSuccess
must_arg(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx);
static tSuccess
maybe_arg(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx);
static tSuccess
short_opt_ck(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx);
static tSuccess
must_arg(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx)
{
switch (pOS->optType) {
case TOPT_SHORT:
if (*arg_txt != NUL)
return SUCCESS;
break;
case TOPT_LONG:
if (pOS->pzOptArg != NULL)
return SUCCESS;
break;
default:
return FAILURE;
}
if (opts->curOptIdx >= opts->origArgCt)
return FAILURE;
opt_txt[ (*opt_idx)++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
return SUCCESS;
}
static tSuccess
maybe_arg(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx)
{
switch (pOS->optType) {
case TOPT_SHORT:
if (*arg_txt != NUL)
return SUCCESS;
break;
case TOPT_LONG:
if (pOS->pzOptArg != NULL)
return SUCCESS;
break;
default:
return FAILURE;
}
if (opts->curOptIdx >= opts->origArgCt)
return PROBLEM;
arg_txt = opts->origArgVect[ opts->curOptIdx ];
if (*arg_txt != '-')
opt_txt[ (*opt_idx)++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
return SUCCESS;
}
static tSuccess
short_opt_ck(tOptions * opts, char * arg_txt, tOptState * pOS,
char ** opt_txt, uint32_t * opt_idx)
{
while (*arg_txt != NUL) {
if (FAILED(opt_find_short(opts, (uint8_t)*arg_txt, pOS)))
return FAILURE;
if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
arg_txt++;
} else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
if (arg_txt[1] != NUL)
return SUCCESS;
arg_txt = opts->origArgVect[ opts->curOptIdx ];
if (*arg_txt != '-')
opt_txt[ (*opt_idx)++ ] =
opts->origArgVect[ (opts->curOptIdx)++ ];
return SUCCESS;
} else {
if (arg_txt[1] == NUL) {
if (opts->curOptIdx >= opts->origArgCt)
return FAILURE;
opt_txt[ (*opt_idx)++ ] =
opts->origArgVect[ (opts->curOptIdx)++ ];
}
return SUCCESS;
}
}
return SUCCESS;
}
LOCAL void
optionSort(tOptions * opts)
{
char ** opt_txt;
char ** ppzOpds;
uint32_t optsIdx = 0;
uint32_t opdsIdx = 0;
tOptState os = OPTSTATE_INITIALIZER(DEFINED);
if ( (getenv("POSIXLY_CORRECT") != NULL)
|| NAMED_OPTS(opts))
return;
opt_txt = malloc(opts->origArgCt * sizeof(char *));
if (opt_txt == NULL)
goto exit_no_mem;
ppzOpds = malloc(opts->origArgCt * sizeof(char *));
if (ppzOpds == NULL) {
free(opt_txt);
goto exit_no_mem;
}
opts->curOptIdx = 1;
opts->pzCurOpt = NULL;
for (;;) {
char * arg_txt;
tSuccess res;
if (opts->curOptIdx >= opts->origArgCt) {
errno = 0;
goto joinLists;
}
arg_txt = opts->origArgVect[ opts->curOptIdx ];
if (*arg_txt != '-') {
ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
continue;
}
switch (arg_txt[1]) {
case NUL:
ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
continue;
case '-':
if (arg_txt[2] == NUL) {
opt_txt[ optsIdx++ ] =
opts->origArgVect[ (opts->curOptIdx)++ ];
goto restOperands;
}
res = opt_find_long(opts, arg_txt+2, &os);
break;
default:
if ((opts->fOptSet & OPTPROC_SHORTOPT) == 0) {
res = opt_find_long(opts, arg_txt+1, &os);
} else {
res = opt_find_short(opts, (uint8_t)arg_txt[1], &os);
}
break;
}
if (FAILED(res)) {
errno = EINVAL;
goto freeTemps;
}
opt_txt[ optsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
if ( (os.optType == TOPT_SHORT)
&& FAILED(short_opt_ck(opts, arg_txt+2, &os, opt_txt,
&optsIdx)) ) {
errno = EINVAL;
goto freeTemps;
}
} else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) {
switch (maybe_arg(opts, arg_txt+2, &os, opt_txt, &optsIdx)) {
case FAILURE: errno = EIO; goto freeTemps;
case PROBLEM: errno = 0; goto joinLists;
}
} else {
switch (must_arg(opts, arg_txt+2, &os, opt_txt, &optsIdx)) {
case PROBLEM:
case FAILURE: errno = EIO; goto freeTemps;
}
}
}
restOperands:
while (opts->curOptIdx < opts->origArgCt)
ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ];
joinLists:
if (optsIdx > 0)
memcpy(opts->origArgVect + 1, opt_txt,
(size_t)optsIdx * sizeof(char *));
if (opdsIdx > 0)
memcpy(opts->origArgVect + 1 + optsIdx, ppzOpds,
(size_t)opdsIdx * sizeof(char *));
freeTemps:
free(opt_txt);
free(ppzOpds);
return;
exit_no_mem:
errno = ENOMEM;
return;
}