Home | History | Annotate | Download | only in toolutil
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2000-2015, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *   file name:  uoptions.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2000apr17
     14 *   created by: Markus W. Scherer
     15 *
     16 *   This file provides a command line argument parser.
     17 */
     18 
     19 #include "unicode/utypes.h"
     20 #include "cstring.h"
     21 #include "uoptions.h"
     22 
     23 U_CAPI int U_EXPORT2
     24 u_parseArgs(int argc, char* argv[],
     25             int optionCount, UOption options[]) {
     26     char *arg;
     27     int i=1, remaining=1;
     28     char c, stopOptions=0;
     29 
     30     while(i<argc) {
     31         arg=argv[i];
     32         if(!stopOptions && *arg=='-' && (c=arg[1])!=0) {
     33             /* process an option */
     34             UOption *option=NULL;
     35             arg+=2;
     36             if(c=='-') {
     37                 /* process a long option */
     38                 if(*arg==0) {
     39                     /* stop processing options after "--" */
     40                     stopOptions=1;
     41                 } else {
     42                     /* search for the option string */
     43                     int j;
     44                     for(j=0; j<optionCount; ++j) {
     45                         if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) {
     46                             option=options+j;
     47                             break;
     48                         }
     49                     }
     50                     if(option==NULL) {
     51                         /* no option matches */
     52                         return -i;
     53                     }
     54                     option->doesOccur=1;
     55 
     56                     if(option->hasArg!=UOPT_NO_ARG) {
     57                         /* parse the argument for the option, if any */
     58                         if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
     59                             /* argument in the next argv[], and there is not an option in there */
     60                             option->value=argv[++i];
     61                         } else if(option->hasArg==UOPT_REQUIRES_ARG) {
     62                             /* there is no argument, but one is required: return with error */
     63                             option->doesOccur=0;
     64                             return -i;
     65                         }
     66                     }
     67 
     68                     if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) {
     69                         /* the option function was called and returned an error */
     70                         option->doesOccur=0;
     71                         return -i;
     72                     }
     73                 }
     74             } else {
     75                 /* process one or more short options */
     76                 do {
     77                     /* search for the option letter */
     78                     int j;
     79                     for(j=0; j<optionCount; ++j) {
     80                         if(c==options[j].shortName) {
     81                             option=options+j;
     82                             break;
     83                         }
     84                     }
     85                     if(option==NULL) {
     86                         /* no option matches */
     87                         return -i;
     88                     }
     89                     option->doesOccur=1;
     90 
     91                     if(option->hasArg!=UOPT_NO_ARG) {
     92                         /* parse the argument for the option, if any */
     93                         if(*arg!=0) {
     94                             /* argument following in the same argv[] */
     95                             option->value=arg;
     96                             /* do not process the rest of this arg as option letters */
     97                             break;
     98                         } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
     99                             /* argument in the next argv[], and there is not an option in there */
    100                             option->value=argv[++i];
    101                             /* this break is redundant because we know that *arg==0 */
    102                             break;
    103                         } else if(option->hasArg==UOPT_REQUIRES_ARG) {
    104                             /* there is no argument, but one is required: return with error */
    105                             option->doesOccur=0;
    106                             return -i;
    107                         }
    108                     }
    109 
    110                     if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) {
    111                         /* the option function was called and returned an error */
    112                         option->doesOccur=0;
    113                         return -i;
    114                     }
    115 
    116                     /* get the next option letter */
    117                     option=NULL;
    118                     c=*arg++;
    119                 } while(c!=0);
    120             }
    121 
    122             /* go to next argv[] */
    123             ++i;
    124         } else {
    125             /* move a non-option up in argv[] */
    126             argv[remaining++]=arg;
    127             ++i;
    128         }
    129     }
    130     return remaining;
    131 }
    132