xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/util/Getopt.java (revision ff44f24ac10337e272510634599e287cb25d0e9c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
22  */
23 package org.opengrok.indexer.util;
24 
25 import java.text.ParseException;
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * A simple implementation of the getopt(3c). It does just implement what I
31  * need ;-) Please note that I dislike the way GNU getopt allows mixing of
32  * options and arguments, so this version will stop processing options as soon
33  * as it encounters an argument.
34  */
35 public class Getopt {
36     private static class Option {
37         char option;
38         String argument;
39     }
40 
41     private final List<Option> options;
42     private int current;
43     private int optind;
44     private final String[] argv;
45     private final String opts;
46 
47     /**
48      * Creates a new instance of Getopt.
49      * @param argv argument vector
50      * @param opts the list of allowed options
51      */
Getopt(String[] argv, String opts)52     public Getopt(String[] argv, String opts) {
53         options = new ArrayList<>();
54         current = -1;
55         optind = -1;
56         this.argv = argv.clone();
57         this.opts = opts;
58     }
59 
60     /**
61      * Parse the command line options.
62      * @throws ParseException if an illegal argument is passed
63      */
parse()64     public void parse() throws ParseException {
65 
66         int ii = 0;
67         while (ii < argv.length) {
68             char[] chars = argv[ii].toCharArray();
69             if (chars.length > 0 && chars[0] == '-') {
70                 if (argv[ii].equals("--")) {
71                     // End of command line options ;)
72                     optind = ii + 1;
73                     break;
74                 }
75 
76                 for (int jj = 1; jj < chars.length; ++jj) {
77                     int idx = opts.indexOf(chars[jj]);
78                     if (idx == -1) {
79                         throw new ParseException("Unknown argument: " + argv[ii].substring(jj), ii);
80                     }
81 
82                     Option option = new Option();
83                     option.option = chars[jj];
84                     options.add(option);
85                     // does this option take an argument?
86                     if ((idx + 1) < opts.length() && (opts.charAt(idx + 1) == ':')) {
87                         // next should be an argument
88                         if ((jj + 1) < chars.length) {
89                             // Rest of this is the argument
90                             option.argument = argv[ii].substring(jj + 1);
91                             break;
92                         }
93                         // next argument vector contains the argument
94                         ++ii;
95                         if (ii < argv.length) {
96                             option.argument = argv[ii];
97                         } else {
98                             throw new ParseException("Option " + chars[jj] + " requires an argument", ii);
99                         }
100                     }
101                 }
102                 ++ii;
103             } else {
104                 // End of options
105                 optind = ii;
106                 break;
107             }
108         }
109     }
110 
111     /**
112      * Get the next option in the options string.
113      * @return the next valid option, or -1 if all options are processed
114      */
getOpt()115     public int getOpt() {
116         int ret = -1;
117 
118         ++current;
119         if (current < options.size()) {
120             ret = options.get(current).option;
121         }
122 
123         return ret;
124     }
125 
126     /**
127      * Reset the current pointer so we may traverse all the options again.
128      */
reset()129     public void reset() {
130         current = -1;
131     }
132 
133     /**
134      * Get the argument to the current option.
135      * @return the argument or null if none present (or allowed)
136      */
getOptarg()137     public String getOptarg() {
138         String ret = null;
139 
140         if (current < options.size()) {
141             ret = options.get(current).argument;
142         }
143         return ret;
144     }
145 
146     /**
147      * Get the index of the first argument.
148      * @return the index of the first argument in the original array
149      */
getOptind()150     public int getOptind() {
151         return optind;
152     }
153 }
154