/* ******************************************************************************* * * Copyright (C) 2000-2015, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: uoptions.c * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 2000apr17 * created by: Markus W. Scherer * * This file provides a command line argument parser. */ #include "unicode/utypes.h" #include "cstring.h" #include "uoptions.h" U_CAPI int U_EXPORT2 u_parseArgs(int argc, char* argv[], int optionCount, UOption options[]) { char *arg; int i=1, remaining=1; char c, stopOptions=0; while(i<argc) { arg=argv[i]; if(!stopOptions && *arg=='-' && (c=arg[1])!=0) { /* process an option */ UOption *option=NULL; arg+=2; if(c=='-') { /* process a long option */ if(*arg==0) { /* stop processing options after "--" */ stopOptions=1; } else { /* search for the option string */ int j; for(j=0; j<optionCount; ++j) { if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) { option=options+j; break; } } if(option==NULL) { /* no option matches */ return -i; } option->doesOccur=1; if(option->hasArg!=UOPT_NO_ARG) { /* parse the argument for the option, if any */ if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) { /* argument in the next argv[], and there is not an option in there */ option->value=argv[++i]; } else if(option->hasArg==UOPT_REQUIRES_ARG) { /* there is no argument, but one is required: return with error */ option->doesOccur=0; return -i; } } if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) { /* the option function was called and returned an error */ option->doesOccur=0; return -i; } } } else { /* process one or more short options */ do { /* search for the option letter */ int j; for(j=0; j<optionCount; ++j) { if(c==options[j].shortName) { option=options+j; break; } } if(option==NULL) { /* no option matches */ return -i; } option->doesOccur=1; if(option->hasArg!=UOPT_NO_ARG) { /* parse the argument for the option, if any */ if(*arg!=0) { /* argument following in the same argv[] */ option->value=arg; /* do not process the rest of this arg as option letters */ break; } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) { /* argument in the next argv[], and there is not an option in there */ option->value=argv[++i]; /* this break is redundant because we know that *arg==0 */ break; } else if(option->hasArg==UOPT_REQUIRES_ARG) { /* there is no argument, but one is required: return with error */ option->doesOccur=0; return -i; } } if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) { /* the option function was called and returned an error */ option->doesOccur=0; return -i; } /* get the next option letter */ option=NULL; c=*arg++; } while(c!=0); } /* go to next argv[] */ ++i; } else { /* move a non-option up in argv[] */ argv[remaining++]=arg; ++i; } } return remaining; }