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