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