home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / libc / src / plgetopt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  5.1 KB  |  166 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20. ** File:          plgetopt.c
  21. ** Description:   utilities to parse argc/argv
  22. */
  23.  
  24. #include "prmem.h"
  25. #include "prlog.h"
  26. #include "prerror.h"
  27. #include "plstr.h"
  28. #include "plgetopt.h"
  29.  
  30. #include <string.h>
  31.  
  32. static char static_Nul = 0;
  33.  
  34. struct PLOptionInternal
  35. {
  36.     const char *options;        /* client options list specification */
  37.     PRIntn argc;                /* original number of arguments */
  38.     char **argv;                /* vector of pointers to arguments */
  39.     PRIntn xargc;               /* which one we're processing now */
  40.     const char *xargv;          /* where within *argv[xargc] */
  41.     PRBool minus;               /* do we already have the '-'? */
  42. };
  43.  
  44. /*
  45. ** Create the state in which to parse the tokens.
  46. **
  47. ** argc        the sum of the number of options and their values
  48. ** argv        the options and their values
  49. ** options    vector of single character options w/ | w/o ':
  50. */
  51. PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
  52.     PRIntn argc, char **argv, const char *options)
  53. {
  54.     PLOptState *opt = NULL;
  55.     if (NULL == options)
  56.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  57.     else
  58.     {
  59.         opt = PR_NEWZAP(PLOptState);
  60.         if (NULL == opt)
  61.             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  62.         else
  63.         {
  64.             PLOptionInternal *internal = PR_NEW(PLOptionInternal);
  65.             if (NULL == internal)
  66.             {
  67.                 PR_DELETE(opt);
  68.                 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  69.             }
  70.             else
  71.             {
  72.                 opt->option = 0;
  73.                 opt->value = NULL;
  74.                 opt->internal = internal;
  75.  
  76.                 internal->argc = argc;
  77.                 internal->argv = argv;
  78.                 internal->xargc = 0;
  79.                 internal->xargv = &static_Nul;
  80.                 internal->minus = PR_FALSE;
  81.                 internal->options = options;
  82.             }
  83.         }
  84.     }
  85.     return opt;
  86. }  /* PL_CreateOptState */
  87.  
  88. /*
  89. ** Destroy object created by CreateOptState()
  90. */
  91. PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
  92. {
  93.     PR_DELETE(opt->internal);
  94.     PR_DELETE(opt);
  95. }  /* PL_DestroyOptState */
  96.  
  97. PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
  98. {
  99.     PLOptionInternal *internal = opt->internal;
  100.     PRIntn cop, eoo = PL_strlen(internal->options);
  101.  
  102.     /*
  103.     ** If the current xarg points to nul, advance to the next
  104.     ** element of the argv vector. If the vector index is equal
  105.     ** to argc, we're out of arguments, so return an EOL.
  106.     ** Note whether the first character of the new argument is
  107.     ** a '-' and skip by it if it is.
  108.     */
  109.     while (0 == *internal->xargv)
  110.     {
  111.         internal->xargc += 1;
  112.         if (internal->xargc >= internal->argc)
  113.         {
  114.             opt->option = 0;
  115.             opt->value = NULL;
  116.             return PL_OPT_EOL;
  117.         }
  118.         internal->xargv = internal->argv[internal->xargc];
  119.         internal->minus = ('-' == *internal->xargv ? PR_TRUE : PR_FALSE);  /* not it */
  120.         if (internal->minus) internal->xargv += 1;  /* and consume */
  121.     }
  122.  
  123.     /*
  124.     ** If we already have a '-' in hand, xargv points to the next
  125.     ** option. See if we can find a match in the list of possible
  126.     ** options supplied.
  127.     */
  128.  
  129.     if (internal->minus)
  130.     {
  131.         for (cop = 0; cop < eoo; ++cop)
  132.         {
  133.             if (internal->options[cop] == *internal->xargv)
  134.             {
  135.                 opt->option = *internal->xargv;
  136.                 internal->xargv += 1;
  137.                 /*
  138.                 ** if options indicates that there's an associated
  139.                 ** value, this argv is finished and the next is the
  140.                 ** option's value.
  141.                 */
  142.                 if (':' == internal->options[cop + 1])
  143.                 {
  144.                     PR_ASSERT(0 == *internal->xargv);
  145.                     opt->value = internal->argv[++(internal->xargc)];
  146.                     internal->xargv = &static_Nul;
  147.                     internal->minus = PR_FALSE;
  148.                 }
  149.                 else opt->value = NULL;
  150.                 return PL_OPT_OK;
  151.             }
  152.         }
  153.         internal->xargv += 1;  /* consume that option */
  154.         return PL_OPT_BAD;
  155.     }
  156.     /*
  157.     ** No '-', so it must be a standalone value. The option is nul.
  158.     */
  159.     opt->value = internal->argv[(internal->xargc)++];
  160.     internal->xargv = &static_Nul;
  161.     opt->option = 0;
  162.     return PL_OPT_OK;
  163. }  /* PL_GetNextOpt */
  164.  
  165. /* plgetopt.c */
  166.