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