• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
u_parseArgs(int argc,char * argv[],int optionCount,UOption options[])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