LCOV - code coverage report
Current view: top level - nsprpub/lib/libc/src - plgetopt.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 98 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             : ** File:          plgetopt.c
       8             : ** Description:   utilities to parse argc/argv
       9             : */
      10             : 
      11             : #include "prmem.h"
      12             : #include "prlog.h"
      13             : #include "prerror.h"
      14             : #include "plstr.h"
      15             : #include "plgetopt.h"
      16             : 
      17             : #include <string.h>
      18             : 
      19             : static char static_Nul = 0;
      20             : 
      21             : struct PLOptionInternal
      22             : {
      23             :     const char *options;        /* client options list specification */
      24             :     PRIntn argc;                /* original number of arguments */
      25             :     char **argv;                /* vector of pointers to arguments */
      26             :     PRIntn xargc;               /* which one we're processing now */
      27             :     const char *xargv;          /* where within *argv[xargc] */
      28             :     PRIntn minus;               /* do we already have the '-'? */
      29             :     const PLLongOpt *longOpts;  /* Caller's array */
      30             :     PRBool endOfOpts;           /* have reached a "--" argument */
      31             :     PRIntn optionsLen;          /* is strlen(options) */
      32             : };
      33             : 
      34             : /*
      35             : ** Create the state in which to parse the tokens.
      36             : **
      37             : ** argc        the sum of the number of options and their values
      38             : ** argv        the options and their values
      39             : ** options    vector of single character options w/ | w/o ':
      40             : */
      41             : PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
      42             :     PRIntn argc, char **argv, const char *options)
      43             : {
      44           0 :     return PL_CreateLongOptState( argc, argv, options, NULL);
      45             : }  /* PL_CreateOptState */
      46             : 
      47             : PR_IMPLEMENT(PLOptState*) PL_CreateLongOptState(
      48             :     PRIntn argc, char **argv, const char *options, 
      49             :     const PLLongOpt *longOpts)
      50             : {
      51           0 :     PLOptState *opt = NULL;
      52             :     PLOptionInternal *internal;
      53             : 
      54           0 :     if (NULL == options) 
      55             :     {
      56           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
      57           0 :         return opt;
      58             :     }
      59             : 
      60           0 :     opt = PR_NEWZAP(PLOptState);
      61           0 :     if (NULL == opt) 
      62             :     {
      63           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
      64           0 :         return opt;
      65             :     }
      66             : 
      67           0 :     internal = PR_NEW(PLOptionInternal);
      68           0 :     if (NULL == internal)
      69             :     {
      70           0 :         PR_DELETE(opt);
      71           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
      72           0 :         return NULL;
      73             :     }
      74             : 
      75           0 :     opt->option = 0;
      76           0 :     opt->value = NULL;
      77           0 :     opt->internal = internal;
      78           0 :     opt->longOption   =  0;
      79           0 :     opt->longOptIndex = -1;
      80             : 
      81           0 :     internal->argc = argc;
      82           0 :     internal->argv = argv;
      83           0 :     internal->xargc = 0;
      84           0 :     internal->xargv = &static_Nul;
      85           0 :     internal->minus = 0;
      86           0 :     internal->options = options;
      87           0 :     internal->longOpts = longOpts;
      88           0 :     internal->endOfOpts = PR_FALSE;
      89           0 :     internal->optionsLen = PL_strlen(options);
      90             : 
      91           0 :     return opt;
      92             : }  /* PL_CreateLongOptState */
      93             : 
      94             : /*
      95             : ** Destroy object created by CreateOptState()
      96             : */
      97             : PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
      98             : {
      99           0 :     PR_DELETE(opt->internal);
     100           0 :     PR_DELETE(opt);
     101           0 : }  /* PL_DestroyOptState */
     102             : 
     103             : PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
     104             : {
     105           0 :     PLOptionInternal *internal = opt->internal;
     106             : 
     107           0 :     opt->longOption   =  0;
     108           0 :     opt->longOptIndex = -1;
     109             :     /*
     110             :     ** If the current xarg points to nul, advance to the next
     111             :     ** element of the argv vector. If the vector index is equal
     112             :     ** to argc, we're out of arguments, so return an EOL.
     113             :     ** Note whether the first character of the new argument is
     114             :     ** a '-' and skip by it if it is.
     115             :     */
     116           0 :     while (0 == *internal->xargv)
     117             :     {
     118           0 :         internal->xargc += 1;
     119           0 :         if (internal->xargc >= internal->argc)
     120             :         {
     121           0 :             opt->option = 0;
     122           0 :             opt->value = NULL;
     123           0 :             return PL_OPT_EOL;
     124             :         }
     125           0 :         internal->xargv = internal->argv[internal->xargc];
     126           0 :         internal->minus = 0;
     127           0 :         if (!internal->endOfOpts && ('-' == *internal->xargv)) 
     128             :         {
     129           0 :             internal->minus++;
     130           0 :             internal->xargv++;  /* and consume */
     131           0 :             if ('-' == *internal->xargv && internal->longOpts) 
     132             :             {
     133           0 :                 internal->minus++;
     134           0 :                 internal->xargv++;
     135           0 :                 if (0 == *internal->xargv) 
     136             :                 {
     137           0 :                     internal->endOfOpts = PR_TRUE;
     138             :                 }
     139             :             }
     140             :         }
     141             :     }
     142             : 
     143             :     /*
     144             :     ** If we already have a '-' or '--' in hand, xargv points to the next
     145             :     ** option. See if we can find a match in the list of possible
     146             :     ** options supplied.
     147             :     */
     148           0 :     if (internal->minus == 2) 
     149             :     {
     150           0 :         char * foundEqual = strchr(internal->xargv,'=');
     151           0 :         PRIntn optNameLen = foundEqual ? (foundEqual - internal->xargv) :
     152           0 :                             strlen(internal->xargv);
     153           0 :         const PLLongOpt *longOpt = internal->longOpts;
     154           0 :         PLOptStatus result = PL_OPT_BAD;
     155             : 
     156           0 :         opt->option = 0;
     157           0 :         opt->value  = NULL;
     158             : 
     159           0 :         for (; longOpt->longOptName; ++longOpt) 
     160             :         {
     161           0 :             if (strncmp(longOpt->longOptName, internal->xargv, optNameLen))
     162           0 :                 continue;  /* not a possible match */
     163           0 :             if (strlen(longOpt->longOptName) != optNameLen)
     164           0 :                 continue;  /* not a match */
     165             :             /* option name match */
     166           0 :             opt->longOptIndex = longOpt - internal->longOpts;
     167           0 :             opt->longOption   = longOpt->longOption;
     168             :             /* value is part of the current argv[] element if = was found */
     169             :             /* note: this sets value even for long options that do not
     170             :              * require option if specified as --long=value */
     171           0 :             if (foundEqual) 
     172             :             {
     173           0 :                 opt->value = foundEqual + 1;
     174             :             }
     175           0 :             else if (longOpt->valueRequired)
     176             :             {
     177             :                 /* value is the next argv[] element, if any */
     178           0 :                 if (internal->xargc + 1 < internal->argc)
     179             :                 {
     180           0 :                     opt->value = internal->argv[++(internal->xargc)];
     181             :                 }
     182             :                 /* missing value */
     183             :                 else
     184             :                 {
     185           0 :                     break; /* return PL_OPT_BAD */
     186             :                 }
     187             :             }
     188           0 :             result = PL_OPT_OK;
     189           0 :             break;
     190             :         }
     191           0 :         internal->xargv = &static_Nul; /* consume this */
     192           0 :         return result;
     193             :     }
     194           0 :     if (internal->minus)
     195             :     {
     196             :         PRIntn cop;
     197           0 :         PRIntn eoo = internal->optionsLen;
     198           0 :         for (cop = 0; cop < eoo; ++cop)
     199             :         {
     200           0 :             if (internal->options[cop] == *internal->xargv)
     201             :             {
     202           0 :                 opt->option = *internal->xargv++;
     203           0 :                 opt->longOption = opt->option & 0xff;
     204             :                 /*
     205             :                 ** if options indicates that there's an associated
     206             :                 ** value, it must be provided, either as part of this
     207             :                 ** argv[] element or as the next one
     208             :                 */
     209           0 :                 if (':' == internal->options[cop + 1])
     210             :                 {
     211             :                     /* value is part of the current argv[] element */
     212           0 :                     if (0 != *internal->xargv)
     213             :                     {
     214           0 :                         opt->value = internal->xargv;
     215             :                     }
     216             :                     /* value is the next argv[] element, if any */
     217           0 :                     else if (internal->xargc + 1 < internal->argc)
     218             :                     {
     219           0 :                         opt->value = internal->argv[++(internal->xargc)];
     220             :                     }
     221             :                     /* missing value */
     222             :                     else
     223             :                     {
     224           0 :                         return PL_OPT_BAD;
     225             :                     }
     226             : 
     227           0 :                     internal->xargv = &static_Nul;
     228           0 :                     internal->minus = 0;
     229             :                 }
     230             :                 else 
     231           0 :                     opt->value = NULL; 
     232           0 :                 return PL_OPT_OK;
     233             :             }
     234             :         }
     235           0 :         internal->xargv += 1;  /* consume that option */
     236           0 :         return PL_OPT_BAD;
     237             :     }
     238             : 
     239             :     /*
     240             :     ** No '-', so it must be a standalone value. The option is nul.
     241             :     */
     242           0 :     opt->value = internal->argv[internal->xargc];
     243           0 :     internal->xargv = &static_Nul;
     244           0 :     opt->option = 0;
     245           0 :     return PL_OPT_OK;
     246             : }  /* PL_GetNextOpt */
     247             : 
     248             : /* plgetopt.c */

Generated by: LCOV version 1.13