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