summaryrefslogtreecommitdiff
path: root/java/src/GetOpt.java
blob: 5060d7f8b94b8eb1dd31f0cc0487a2462dc1bb29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*************************************************
 *
 * = PACKAGE
 *    ACE.Misc
 *
 * = FILENAME
 *    GetOpt.java
 *
 *@author Prashant Jain
 *
 *************************************************/
package ACE.Misc;

import java.io.*;
import java.util.Hashtable;
import java.util.StringTokenizer;

/**
 * <hr>
 * <h2>SYNOPSIS</h2>
 *<blockquote>
 *     Iterator for parsing command-line arguments.
 *</blockquote>
 *
 * <h2>DESCRIPTION</h2>
 *<blockquote>
 *     This version of `get_opt' appears to the caller like standard
 *     Unix `get_opt' but it behaves differently for the user, since
 *     it allows the user to intersperse the options with the other
 *     arguments.
 * 
 * <p> As `get_opt' works, it permutes the elements of `argv' so that,
 *     when it is done, all the options precede everything else. Thus
 *     all application programs are extended to handle flexible argument
 *     order.
 *</blockquote>
 *
 */
public class GetOpt
{
  /** 
   * Constructor
   *@param args command line arguments
   *@param optstring string containing the legitimate option
   * characters. A colon in optstring means that the previous character
   * is an option that wants an argument which is then taken from the
   * rest of the current args-element. Here is an example of what
   * optstring might look like: "c:dP:p".
   */
  public GetOpt (String[] args, String optstring)
  {
    // Cache the arguments
    this.args_ = args;
    this.hasArg_ = false;

    // Build the arg hashtable
    this.buildArgTable (optstring);
  }
  
  /** 
   * Scan elements specified in optstring for next option flag.
   *@return The character corresponding to the next flag.
   */
  public int next ()
  {
    if (this.args_ == null)
      return -1;

    if (this.index_ < this.args_.length) 
      {
	String arg = this.args_[this.index_++];

	// Make sure flag starts with "-"
	if (!arg.startsWith ("-"))
	  return -1;
	
	// Check if there is more than one character specified as flag
	if (arg.length () > 2)
	  return -1;
	
	// So far so good
	// Check if the flag is in the arg_table and if it is get the
	// associated binding.
	Character c = (Character) this.argTable_.get (new Character (arg.charAt (1)));
	if (c == null)
	  return -1;

	if (c.charValue () == '#')
	  {
	    this.hasArg_ = false;
	    return arg.charAt (1);
	  }
	else if (c.charValue () == ':')
	  {
	    this.hasArg_ = true;
	    return arg.charAt (1);
	  }
	else   // This should not happen
	  return -1; 
      }
    return -1;
  }
  
  /**
   * Get the argument (if any) associated with the flag.
   *@return the argument associated with the flag.
   */
  public String optarg ()
  {
    if (this.hasArg_)
      return this.args_[this.index_++];
    else
      return null;
  }
  
  // Build the argument table
  private void buildArgTable (String s)
  {
    this.argTable_ = new Hashtable ();
    StringTokenizer tokens = new StringTokenizer (s, ":");
    while (tokens.hasMoreTokens ())
      {
	// Get the next token
	String t = tokens.nextToken ();

	// First add all flags except the one with ":" after it
	// Note "#" is an arbitrary character we use to distinguish
	// the two cases
	for (int i = 0; i < t.length () - 1; i++)
	  this.argTable_.put (new Character (t.charAt (i)),
			       new Character ('#'));

	// Now Add the flag just before ":" to the arg_table
	this.argTable_.put (new Character (t.charAt (t.length () - 1)),
			     new Character (':'));
      }
  }
  
  private String [] args_;
  // Copy of the args passed in
  
  private boolean hasArg_;
  // Indicator that the flag has an argument following it

  private int index_;
  // Index into the array of arguments

  private Hashtable argTable_;
  // Table of flags that take arguments after them
}