| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 | 
							
- /*
 
-  *  sort.c  $Id: sort.c,v 4.5 2005/03/13 19:51:59 bkorb Exp $
 
-  * Time-stamp:      "2005-02-20 17:18:41 bkorb"
 
-  *
 
-  *  This module implements argument sorting.
 
-  */
 
- /*
 
-  *  Automated Options copyright 1992-2005 Bruce Korb
 
-  *
 
-  *  Automated Options is free software.
 
-  *  You may redistribute it and/or modify it under the terms of the
 
-  *  GNU General Public License, as published by the Free Software
 
-  *  Foundation; either version 2, or (at your option) any later version.
 
-  *
 
-  *  Automated Options is distributed in the hope that it will be useful,
 
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
-  *  GNU General Public License for more details.
 
-  *
 
-  *  You should have received a copy of the GNU General Public License
 
-  *  along with Automated Options.  See the file "COPYING".  If not,
 
-  *  write to:  The Free Software Foundation, Inc.,
 
-  *             59 Temple Place - Suite 330,
 
-  *             Boston,  MA  02111-1307, USA.
 
-  *
 
-  * As a special exception, Bruce Korb gives permission for additional
 
-  * uses of the text contained in his release of AutoOpts.
 
-  *
 
-  * The exception is that, if you link the AutoOpts library with other
 
-  * files to produce an executable, this does not by itself cause the
 
-  * resulting executable to be covered by the GNU General Public License.
 
-  * Your use of that executable is in no way restricted on account of
 
-  * linking the AutoOpts library code into it.
 
-  *
 
-  * This exception does not however invalidate any other reasons why
 
-  * the executable file might be covered by the GNU General Public License.
 
-  *
 
-  * This exception applies only to the code released by Bruce Korb under
 
-  * the name AutoOpts.  If you copy code from other sources under the
 
-  * General Public License into a copy of AutoOpts, as the General Public
 
-  * License permits, the exception does not apply to the code that you add
 
-  * in this way.  To avoid misleading anyone as to the status of such
 
-  * modified files, you must delete this exception notice from them.
 
-  *
 
-  * If you write modifications of your own for AutoOpts, it is your choice
 
-  * whether to permit this exception to apply to your modifications.
 
-  * If you do not wish that, delete this exception notice.
 
-  */
 
- /* = = = START-STATIC-FORWARD = = = */
 
- /* static forward declarations maintained by :mkfwd */
 
- 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 );
 
- /* = = = END-STATIC-FORWARD = = = */
 
- /*
 
-  *  "mustHandleArg" and "mayHandleArg" are really similar.  The biggest
 
-  *  difference is that "may" will consume the next argument only if it
 
-  *  does not start with a hyphen and "must" will consume it, hyphen or not.
 
-  */
 
- static tSuccess
 
- mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
 
-                char** ppzOpts, int* pOptsIdx )
 
- {
 
-     /*
 
-      *  An option argument is required.  Long options can either have
 
-      *  a separate command line argument, or an argument attached by
 
-      *  the '=' character.  Figure out which.
 
-      */
 
-     switch (pOS->optType) {
 
-     case TOPT_SHORT:
 
-         /*
 
-          *  See if an arg string follows the flag character.  If not,
 
-          *  the next arg must be the option argument.
 
-          */
 
-         if (*pzArg != NUL)
 
-             return SUCCESS;
 
-         break;
 
-     case TOPT_LONG:
 
-         /*
 
-          *  See if an arg string has already been assigned (glued on
 
-          *  with an `=' character).  If not, the next is the opt arg.
 
-          */
 
-         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 )
 
- {
 
-     /*
 
-      *  An option argument is optional.
 
-      */
 
-     switch (pOS->optType) {
 
-     case TOPT_SHORT:
 
-         /*
 
-          *  IF nothing is glued on after the current flag character,
 
-          *  THEN see if there is another argument.  If so and if it
 
-          *  does *NOT* start with a hyphen, then it is the option arg.
 
-          */
 
-         if (*pzArg != NUL)
 
-             return SUCCESS;
 
-         break;
 
-     case TOPT_LONG:
 
-         /*
 
-          *  Look for an argument if we don't already have one (glued on
 
-          *  with a `=' character)
 
-          */
 
-         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;
 
- }
 
- /*
 
-  *  Process a string of short options glued together.  If the last one
 
-  *  does or may take an argument, the do the argument processing and leave.
 
-  */
 
- static tSuccess
 
- checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
 
-                 char** ppzOpts, int* pOptsIdx )
 
- {
 
-     while (*pzArg != NUL) {
 
-         if (FAILED( shortOptionFind( pOpts, *pzArg, pOS )))
 
-             return FAILURE;
 
-         /*
 
-          *  See if we can have an arg.
 
-          */
 
-         if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
 
-             pzArg++;
 
-         } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
 
-             /*
 
-              *  Take an argument if it is not attached and it does not
 
-              *  start with a hyphen.
 
-              */
 
-             if (pzArg[1] != NUL)
 
-                 return SUCCESS;
 
-             pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
 
-             if (*pzArg != '-')
 
-                 ppzOpts[ (*pOptsIdx)++ ] =
 
-                     pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
 
-             return SUCCESS;
 
-         } else {
 
-             /*
 
-              *  IF we need another argument, be sure it is there and
 
-              *  take it.
 
-              */
 
-             if (pzArg[1] == NUL) {
 
-                 if (pOpts->curOptIdx >= pOpts->origArgCt)
 
-                     return FAILURE;
 
-                 ppzOpts[ (*pOptsIdx)++ ] =
 
-                     pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
 
-             }
 
-             return SUCCESS;
 
-         }
 
-     }
 
-     return SUCCESS;
 
- }
 
- /*
 
-  *  If the program wants sorted options (separated operands and options),
 
-  *  then this routine will to the trick.
 
-  */
 
- LOCAL void
 
- optionSort( tOptions* pOpts )
 
- {
 
-     char** ppzOpts;
 
-     char** ppzOpds;
 
-     int    optsIdx = 0;
 
-     int    opdsIdx = 0;
 
-     tOptState os = OPTSTATE_INITIALIZER(DEFINED);
 
-     /*
 
-      *  Disable for POSIX conformance
 
-      */
 
-     if (getenv( "POSIXLY_CORRECT" ) != NULL) {
 
-         errno = 0;
 
-         return;
 
-     }
 
-     errno = ENOENT;
 
-     /*
 
-      *  If all arguments are named, we can't sort 'em.  There are no operands.
 
-      */
 
-     if (NAMED_OPTS(pOpts))
 
-         return;
 
-     /*
 
-      *  Make sure we can allocate two full-sized arg vectors.
 
-      */
 
-     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;
 
-     /*
 
-      *  Now, process all the options from our current position onward.
 
-      *  (This allows interspersed options and arguments for the few
 
-      *  non-standard programs that require it.)
 
-      */
 
-     for (;;) {
 
-         char* pzArg;
 
-         tSuccess res;
 
-         /*
 
-          *  If we're out of arguments, we're done.  Join the option and
 
-          *  operand lists into the original argument vector.
 
-          */
 
-         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:
 
-             /*
 
-              *  A regular option.  Put it on the operand list.
 
-              */
 
-             ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
 
-             continue;
 
-         case '-':
 
-             /*
 
-              *  Two consecutive hypens.  Put them on the options list and then
 
-              *  _always_ force the remainder of the arguments to be operands.
 
-              */
 
-             if (pzArg[2] == NUL) {
 
-                 ppzOpts[ optsIdx++ ] =
 
-                     pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
 
-                 goto restOperands;
 
-             }
 
-             res = longOptionFind( pOpts, pzArg+2, &os );
 
-             break;
 
-         default:
 
-             /*
 
-              *  If short options are not allowed, then do long
 
-              *  option processing.  Otherwise the character must be a
 
-              *  short (i.e. single character) option.
 
-              */
 
-             if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) {
 
-                 res = longOptionFind( pOpts, pzArg+1, &os );
 
-             } else {
 
-                 res = shortOptionFind( pOpts, pzArg[1], &os );
 
-             }
 
-             break;
 
-         }
 
-         if (FAILED( res )) {
 
-             errno = EIO;
 
-             goto freeTemps;
 
-         }
 
-         /*
 
-          *  We've found an option.  Add the argument to the option list.
 
-          *  Next, we have to see if we need to pull another argument to be
 
-          *  used as the option argument.
 
-          */
 
-         ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
 
-         if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
 
-             /*
 
-              *  No option argument.  If we have a short option here,
 
-              *  then scan for short options until we get to the end
 
-              *  of the argument string.
 
-              */
 
-             if (  (os.optType == TOPT_SHORT)
 
-                && FAILED( checkShortOpts( pOpts, pzArg+2, &os,
 
-                                           ppzOpts, &optsIdx )) )  {
 
-                 errno = EIO;
 
-                 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;
 
-             }
 
-         }
 
-     } /* for (;;) */
 
-  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;
 
- }
 
- /*
 
-  * Local Variables:
 
-  * mode: C
 
-  * c-file-style: "stroustrup"
 
-  * tab-width: 4
 
-  * indent-tabs-mode: nil
 
-  * End:
 
-  * end of autoopts/sort.c */
 
 
  |