uoptions.c revision b13da9df870a61b11249bf741347908dbea0edd8
1/* 2******************************************************************************* 3* 4* Copyright (C) 2000, 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 23U_CAPI int U_EXPORT2 24u_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 return -i; 64 } 65 } 66 } 67 } else { 68 /* process one or more short options */ 69 do { 70 /* search for the option letter */ 71 int j; 72 for(j=0; j<optionCount; ++j) { 73 if(c==options[j].shortName) { 74 option=options+j; 75 break; 76 } 77 } 78 if(option==NULL) { 79 /* no option matches */ 80 return -i; 81 } 82 option->doesOccur=1; 83 84 if(option->hasArg!=UOPT_NO_ARG) { 85 /* parse the argument for the option, if any */ 86 if(*arg!=0) { 87 /* argument following in the same argv[] */ 88 option->value=arg; 89 /* do not process the rest of this arg as option letters */ 90 break; 91 } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) { 92 /* argument in the next argv[], and there is not an option in there */ 93 option->value=argv[++i]; 94 /* this break is redundant because we know that *arg==0 */ 95 break; 96 } else if(option->hasArg==UOPT_REQUIRES_ARG) { 97 /* there is no argument, but one is required: return with error */ 98 return -i; 99 } 100 } 101 102 /* get the next option letter */ 103 option=NULL; 104 c=*arg++; 105 } while(c!=0); 106 } 107 108 if(option!=0 && option->optionFn!=0 && option->optionFn(option->context, option)<0) { 109 /* the option function was called and returned an error */ 110 return -i; 111 } 112 113 /* go to next argv[] */ 114 ++i; 115 } else { 116 /* move a non-option up in argv[] */ 117 argv[remaining++]=arg; 118 ++i; 119 } 120 } 121 return remaining; 122} 123