001: /*
002: * TclIndex.java
003: *
004: * This file implements objects of type "index". This object type
005: * is used to lookup a keyword in a table of valid values and cache
006: * the index of the matching entry.
007: *
008: * Copyright (c) 1997 Sun Microsystems, Inc.
009: *
010: * See the file "license.terms" for information on usage and
011: * redistribution of this file, and for a DISCLAIMER OF ALL
012: * WARRANTIES.
013: *
014: * RCS: @(#) $Id: TclIndex.java,v 1.6 2005/10/11 20:03:23 mdejong Exp $
015: */
016:
017: package tcl.lang;
018:
019: public class TclIndex implements InternalRep {
020:
021: /**
022: * The variable slots for this object.
023: */
024: private int index;
025:
026: /**
027: * Table of valid options.
028: */
029:
030: private String[] table;
031:
032: /**
033: * Construct a TclIndex representation with the given index & table.
034: */
035: private TclIndex(int i, String[] tab) {
036: index = i;
037: table = tab;
038: }
039:
040: /**
041: * Returns a dupilcate of the current object.
042: * @param obj the TclObject that contains this internalRep.
043: */
044: public InternalRep duplicate() {
045: return new TclIndex(index, table);
046: }
047:
048: /**
049: * Implement this no-op for the InternalRep interface.
050: */
051:
052: public void dispose() {
053: }
054:
055: /**
056: * Called to query the string representation of the Tcl object. This
057: * method is called only by TclObject.toString() when
058: * TclObject.stringRep is null.
059: *
060: * @return the string representation of the Tcl object.
061: */
062: public String toString() {
063: return table[index];
064: }
065:
066: /**
067: * Tcl_GetIndexFromObj -> get
068: *
069: * Gets the index into the table of the object. Generate an error
070: * it it doesn't occur. This also converts the object to an index
071: * which should catch the lookup for speed improvement.
072: *
073: * @param interp the interperter or null
074: * @param tobj the object to operate on.
075: * @paran table the list of commands
076: * @paran msg used as part of any error messages
077: * @paran flags may be TCL.EXACT.
078: */
079:
080: public static int get(Interp interp, TclObject tobj,
081: String[] table, String msg, int flags) throws TclException {
082: InternalRep rep = tobj.getInternalRep();
083:
084: if (rep instanceof TclIndex) {
085: if (((TclIndex) rep).table == table) {
086: return ((TclIndex) rep).index;
087: }
088: }
089:
090: String str = tobj.toString();
091: int strLen = str.length();
092: int tableLen = table.length;
093: int index = -1;
094: int numAbbrev = 0;
095:
096: checking: {
097: if (strLen > 0) {
098:
099: for (int i = 0; i < tableLen; i++) {
100: String option = table[i];
101:
102: if (((flags & TCL.EXACT) == TCL.EXACT)
103: && (option.length() != strLen)) {
104: continue;
105: }
106: if (option.equals(str)) {
107: // Found an exact match already. Return it.
108:
109: index = i;
110: break checking;
111: }
112: if (option.startsWith(str)) {
113: numAbbrev++;
114: index = i;
115: }
116: }
117: }
118: if (numAbbrev != 1) {
119: StringBuffer sbuf = new StringBuffer();
120: if (numAbbrev > 1) {
121: sbuf.append("ambiguous ");
122: } else {
123: sbuf.append("bad ");
124: }
125: sbuf.append(msg);
126: sbuf.append(" \"");
127: sbuf.append(str);
128: sbuf.append("\"");
129: sbuf.append(": must be ");
130: sbuf.append(table[0]);
131: for (int i = 1; i < tableLen; i++) {
132: if (i == (tableLen - 1)) {
133: sbuf.append((i > 1) ? ", or " : " or ");
134: } else {
135: sbuf.append(", ");
136: }
137: sbuf.append(table[i]);
138: }
139: throw new TclException(interp, sbuf.toString());
140: }
141: }
142:
143: // Create a new index object.
144:
145: tobj.setInternalRep(new TclIndex(index, table));
146: return index;
147: }
148:
149: /**
150: * Invoked only when testing the TclIndex implementation in TestObjCmd.java
151: */
152: void testUpdateIndex(int index) {
153: this.index = index;
154: }
155:
156: }
|