1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: GetOpt.java,v 1.5 2004/02/16 21:21:06 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt;
  20. import java.util.ArrayList;
  21. import java.util.List;
  22. import java.util.ListIterator;
  23. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  24. /**
  25. * GetOpt is a Java equivalent to the C getopt() library function
  26. * discussed in man page getopt(3C). It provides command line
  27. * parsing for Java applications. It supports the most rules of the
  28. * command line standard (see man page intro(1)) including stacked
  29. * options such as '-sxm' (which is equivalent to -s -x -m); it
  30. * handles special '--' option that signifies the end of options.
  31. * Additionally this implementation of getopt will check for
  32. * mandatory arguments to options such as in the case of
  33. * '-d <file>' it will throw a MissingOptArgException if the
  34. * option argument '<file>' is not included on the commandline.
  35. * getopt(3C) does not check for this.
  36. * @author G Todd Miller
  37. */
  38. public class GetOpt{
  39. public GetOpt(String[] args, String optString){
  40. theOptions = new ArrayList();
  41. int currOptIndex = 0;
  42. theCmdArgs = new ArrayList();
  43. theOptionMatcher = new OptionMatcher(optString);
  44. // fill in the options list
  45. for(int i=0; i<args.length; i++){
  46. String token = args[i];
  47. int tokenLength = token.length();
  48. if(token.equals("--")){ // end of opts
  49. currOptIndex = i+1; // set index of first operand
  50. break; // end of options
  51. }
  52. else if(token.startsWith("-") && tokenLength == 2){
  53. // simple option token such as '-s' found
  54. theOptions.add(new Option(token.charAt(1)));
  55. }
  56. else if(token.startsWith("-") && tokenLength > 2){
  57. // stacked options found, such as '-shm'
  58. // iterate thru the tokens after the dash and
  59. // add them to theOptions list
  60. for(int j=1; j<tokenLength; j++){
  61. theOptions.add(new Option(token.charAt(j)));
  62. }
  63. }
  64. else if(!token.startsWith("-")){
  65. // case 1- there are not options stored yet therefore
  66. // this must be an command argument, not an option argument
  67. if(theOptions.size() == 0){
  68. currOptIndex = i;
  69. break; // stop processing options
  70. }
  71. else {
  72. // case 2-
  73. // there are options stored, check to see if
  74. // this arg belong to the last arg stored
  75. int indexoflast=0;
  76. indexoflast = theOptions.size()-1;
  77. Option op = (Option)theOptions.get(indexoflast);
  78. char opLetter = op.getArgLetter();
  79. if(!op.hasArg() && theOptionMatcher.hasArg(opLetter)){
  80. op.setArg(token);
  81. }
  82. else{
  83. // case 3 -
  84. // the last option stored does not take
  85. // an argument, so again, this argument
  86. // must be a command argument, not
  87. // an option argument
  88. currOptIndex = i;
  89. break; // end of options
  90. }
  91. }
  92. }// end option does not start with "-"
  93. } // end for args loop
  94. // attach an iterator to list of options
  95. theOptionsIterator = theOptions.listIterator();
  96. // options are done, now fill out cmd arg list with remaining args
  97. for(int i=currOptIndex; i<args.length; i++){
  98. String token = args[i];
  99. theCmdArgs.add(token);
  100. }
  101. }
  102. /**
  103. * debugging routine to print out all options collected
  104. */
  105. public void printOptions(){
  106. for(ListIterator it=theOptions.listIterator(); it.hasNext();){
  107. Option opt = (Option)it.next();
  108. System.out.print("OPT =" + opt.getArgLetter());
  109. String arg = opt.getArgument();
  110. if(arg != null){
  111. System.out.print(" " + arg);
  112. }
  113. System.out.println();
  114. }
  115. }
  116. /**
  117. * gets the next option found in the commandline. Distinguishes
  118. * between two bad cases, one case is when an illegal option
  119. * is found, and then other case is when an option takes an
  120. * argument but no argument was found for that option.
  121. * If the option found was not declared in the optString, then
  122. * an IllegalArgumentException will be thrown (case 1).
  123. * If the next option found has been declared to take an argument,
  124. * and no such argument exists, then a MissingOptArgException
  125. * is thrown (case 2).
  126. * @param none
  127. * @return int - the next option found.
  128. * @throws IllegalArgumentException, MissingOptArgException.
  129. */
  130. public int getNextOption() throws IllegalArgumentException,
  131. MissingOptArgException
  132. {
  133. int retval = -1;
  134. if(theOptionsIterator.hasNext()){
  135. theCurrentOption = (Option)theOptionsIterator.next();
  136. char c = theCurrentOption.getArgLetter();
  137. boolean shouldHaveArg = theOptionMatcher.hasArg(c);
  138. String arg = theCurrentOption.getArgument();
  139. if(!theOptionMatcher.match(c)) {
  140. ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_CMDLINE_OPTION_ERR,
  141. new Character(c));
  142. throw (new IllegalArgumentException(msg.toString()));
  143. }
  144. else if(shouldHaveArg && (arg == null)) {
  145. ErrorMsg msg = new ErrorMsg(ErrorMsg.CMDLINE_OPT_MISSING_ARG_ERR,
  146. new Character(c));
  147. throw (new MissingOptArgException(msg.toString()));
  148. }
  149. retval = c;
  150. }
  151. return retval;
  152. }
  153. /**
  154. * gets the argument for the current parsed option. For example,
  155. * in case of '-d <file>', if current option parsed is 'd' then
  156. * getOptionArg() would return '<file>'.
  157. * @param none
  158. * @return String - argument for current parsed option.
  159. */
  160. public String getOptionArg(){
  161. String retval = null;
  162. String tmp = theCurrentOption.getArgument();
  163. char c = theCurrentOption.getArgLetter();
  164. if(theOptionMatcher.hasArg(c)){
  165. retval = tmp;
  166. }
  167. return retval;
  168. }
  169. /**
  170. * gets list of the commandline arguments. For example, in command
  171. * such as 'cmd -s -d file file2 file3 file4' with the usage
  172. * 'cmd [-s] [-d <file>] <file>...', getCmdArgs() would return
  173. * the list {file2, file3, file4}.
  174. * @params none
  175. * @return String[] - list of command arguments that may appear
  176. * after options and option arguments.
  177. */
  178. public String[] getCmdArgs(){
  179. String[] retval = new String[theCmdArgs.size()];
  180. int i=0;
  181. for(ListIterator it=theCmdArgs.listIterator(); it.hasNext();){
  182. retval[i++] = (String)it.next();
  183. }
  184. return retval;
  185. }
  186. private Option theCurrentOption = null;
  187. private ListIterator theOptionsIterator;
  188. private List theOptions = null;
  189. private List theCmdArgs = null;
  190. private OptionMatcher theOptionMatcher = null;
  191. ///////////////////////////////////////////////////////////
  192. //
  193. // Inner Classes
  194. //
  195. ///////////////////////////////////////////////////////////
  196. // inner class to model an option
  197. class Option{
  198. private char theArgLetter;
  199. private String theArgument = null;
  200. public Option(char argLetter) { theArgLetter = argLetter; }
  201. public void setArg(String arg) {
  202. theArgument = arg;
  203. }
  204. public boolean hasArg() { return (theArgument != null); }
  205. public char getArgLetter() { return theArgLetter; }
  206. public String getArgument() { return theArgument; }
  207. } // end class Option
  208. // inner class to query optString for a possible option match,
  209. // and whether or not a given legal option takes an argument.
  210. //
  211. class OptionMatcher{
  212. public OptionMatcher(String optString){
  213. theOptString = optString;
  214. }
  215. public boolean match(char c){
  216. boolean retval = false;
  217. if(theOptString.indexOf(c) != -1){
  218. retval = true;
  219. }
  220. return retval;
  221. }
  222. public boolean hasArg(char c){
  223. boolean retval = false;
  224. int index = theOptString.indexOf(c)+1;
  225. if (index == theOptString.length()){
  226. // reached end of theOptString
  227. retval = false;
  228. }
  229. else if(theOptString.charAt(index) == ':'){
  230. retval = true;
  231. }
  232. return retval;
  233. }
  234. private String theOptString = null;
  235. } // end class OptionMatcher
  236. }// end class GetOpt