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