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