001: /*
002: * ForeachCmd.java
003: *
004: * Copyright (c) 1997 Cornell University.
005: * Copyright (c) 1997 Sun Microsystems, Inc.
006: *
007: * See the file "license.terms" for information on usage and
008: * redistribution of this file, and for a DISCLAIMER OF ALL
009: * WARRANTIES.
010: *
011: * RCS: @(#) $Id: ForeachCmd.java,v 1.5 2005/11/08 05:20:53 mdejong Exp $
012: *
013: */
014:
015: package tcl.lang;
016:
017: /**
018: * This class implements the built-in "Foreach" command in Tcl.
019: */
020:
021: class ForeachCmd implements Command {
022: /**
023: * Tcl_ForeachObjCmd -> ForeachCmd.cmdProc
024: *
025: * This procedure is invoked to process the "foreach" Tcl command.
026: * See the user documentation for details on what it does.
027: *
028: * @param interp the current interpreter.
029: * @param objv command arguments.
030: * @exception TclException if script causes error.
031: */
032:
033: public void cmdProc(Interp interp, TclObject[] objv)
034: throws TclException {
035: if (objv.length < 4 || (objv.length % 2) != 0) {
036: throw new TclNumArgsException(interp, 1, objv,
037: "varList list ?varList list ...? command");
038: }
039:
040: // foreach {n1 n2} {1 2 3 4} {n3} {1 2} {puts $n1-$n2-$n3}
041: // name[0] = {n1 n2} value[0] = {1 2 3 4}
042: // name[1] = {n3} value[0] = {1 2}
043:
044: TclObject[] name = new TclObject[(objv.length - 2) / 2];
045: TclObject[] value = new TclObject[(objv.length - 2) / 2];
046:
047: int c, i, j, base;
048: int maxIter = 0;
049: TclObject command = objv[objv.length - 1];
050: boolean done = false;
051:
052: for (i = 0; i < objv.length - 2; i += 2) {
053: int x = i / 2;
054: name[x] = objv[i + 1];
055: value[x] = objv[i + 2];
056:
057: int nSize = TclList.getLength(interp, name[x]);
058: int vSize = TclList.getLength(interp, value[x]);
059:
060: if (nSize == 0) {
061: throw new TclException(interp,
062: "foreach varlist is empty");
063: }
064:
065: int iter = (vSize + nSize - 1) / nSize;
066: if (maxIter < iter) {
067: maxIter = iter;
068: }
069: }
070:
071: for (c = 0; !done && c < maxIter; c++) {
072: // Set up the variables
073:
074: for (i = 0; i < objv.length - 2; i += 2) {
075: int x = i / 2;
076: int nSize = TclList.getLength(interp, name[x]);
077: base = nSize * c;
078: for (j = 0; j < nSize; j++) {
079: try {
080: if (base + j >= TclList.getLength(interp,
081: value[x])) {
082: interp.setVar(TclList.index(interp,
083: name[x], j), TclString
084: .newInstance(""), 0);
085: } else {
086: interp.setVar(TclList.index(interp,
087: name[x], j), TclList.index(interp,
088: value[x], base + j), 0);
089: }
090: } catch (TclException e) {
091: throw new TclException(interp,
092: "couldn't set loop variable: \""
093: + TclList.index(interp,
094: name[x], j) + "\"");
095: }
096: }
097: }
098:
099: // Execute the script
100:
101: try {
102: interp.eval(command, 0);
103: } catch (TclException e) {
104: switch (e.getCompletionCode()) {
105: case TCL.BREAK:
106: done = true;
107: break;
108:
109: case TCL.CONTINUE:
110: continue;
111:
112: case TCL.ERROR:
113: interp.addErrorInfo("\n (\"foreach\" body line "
114: + interp.errorLine + ")");
115: throw e;
116:
117: default:
118: throw e;
119: }
120: }
121: }
122:
123: interp.resetResult();
124: }
125: }
|