001: /*
002: * ReadCmd.java --
003: *
004: * Copyright (c) 1997 Sun Microsystems, Inc.
005: *
006: * See the file "license.terms" for information on usage and
007: * redistribution of this file, and for a DISCLAIMER OF ALL
008: * WARRANTIES.
009: *
010: * RCS: @(#) $Id: ReadCmd.java,v 1.8 2003/03/08 03:42:44 mdejong Exp $
011: *
012: */
013:
014: package tcl.lang;
015:
016: import java.util.*;
017: import java.io.*;
018:
019: /**
020: * This class implements the built-in "read" command in Tcl.
021: */
022:
023: class ReadCmd implements Command {
024:
025: /**
026: * This procedure is invoked to process the "read" Tcl command.
027: * See the user documentation for details on what it does.
028: *
029: * @param interp the current interpreter.
030: * @param argv command arguments.
031: */
032:
033: public void cmdProc(Interp interp, TclObject argv[])
034: throws TclException {
035:
036: Channel chan; // The channel being operated on this
037: // method
038: int i = 1; // Index to the next arg in argv
039: int toRead = 0; // Number of bytes or chars to read from channel
040: int charactersRead; // Number of bytes or chars read from channel
041: boolean readAll = true; // If true read-all else toRead
042: boolean noNewline = false; // If true, strip the newline if there
043: TclObject result;
044:
045: if ((argv.length != 2) && (argv.length != 3)) {
046: errorWrongNumArgs(interp, argv[0].toString());
047: }
048:
049: if (argv[i].toString().equals("-nonewline")) {
050: noNewline = true;
051: i++;
052: }
053:
054: if (i == argv.length) {
055: errorWrongNumArgs(interp, argv[0].toString());
056: }
057:
058: chan = TclIO.getChannel(interp, argv[i].toString());
059: if (chan == null) {
060: throw new TclException(interp,
061: "can not find channel named \""
062: + argv[i].toString() + "\"");
063: }
064:
065: // Consumed channel name.
066:
067: i++;
068:
069: // Compute how many bytes or chars to read, and see whether the final
070: // noNewline should be dropped.
071:
072: if (i < argv.length) {
073: String arg = argv[i].toString();
074:
075: if (Character.isDigit(arg.charAt(0))) {
076: toRead = TclInteger.get(interp, argv[i]);
077: readAll = false;
078: } else if (arg.equals("nonewline")) {
079: noNewline = true;
080: } else {
081: throw new TclException(interp, "bad argument \"" + arg
082: + "\": should be \"nonewline\"");
083: }
084: }
085:
086: try {
087: if (chan.getEncoding() == null) {
088: result = TclByteArray.newInstance();
089: } else {
090: result = TclString.newInstance(new StringBuffer(64));
091: }
092: if (readAll) {
093: charactersRead = chan.read(interp, result,
094: TclIO.READ_ALL, 0);
095:
096: // If -nonewline was specified, and we have not hit EOF
097: // and the last char is a "\n", then remove it and return.
098:
099: if (noNewline) {
100: String inStr = result.toString();
101: if ((charactersRead > 0)
102: && (inStr.charAt(charactersRead - 1) == '\n')) {
103: interp.setResult(inStr.substring(0,
104: (charactersRead - 1)));
105: return;
106: }
107: }
108: } else {
109: // FIXME: Bug here, the -nonewline flag must be respected
110: // when reading a set number of bytes
111: charactersRead = chan.read(interp, result,
112: TclIO.READ_N_BYTES, toRead);
113: }
114:
115: /*
116: // FIXME: Port this -nonewline logic from the C code.
117: if (charactersRead < 0) {
118: Tcl_ResetResult(interp);
119: Tcl_AppendResult(interp, "error reading \"", name, "\": ",
120: Tcl_PosixError(interp), (char *) NULL);
121: Tcl_DecrRefCount(resultPtr);
122: return TCL_ERROR;
123: }
124:
125: // If requested, remove the last newline in the channel if at EOF.
126:
127: if ((charactersRead > 0) && (newline != 0)) {
128: char *result;
129: int length;
130:
131: result = Tcl_GetStringFromObj(resultPtr, &length);
132: if (result[length - 1] == '\n') {
133: Tcl_SetObjLength(resultPtr, length - 1);
134: }
135: }
136:
137: */
138:
139: interp.setResult(result);
140:
141: } catch (IOException e) {
142: throw new TclRuntimeError(
143: "ReadCmd.cmdProc() Error: IOException when reading "
144: + chan.getChanName());
145: }
146: }
147:
148: /**
149: * A unique error msg is printed for read, therefore dont call this
150: * instead of the standard TclNumArgsException().
151: *
152: * @param interp the current interpreter.
153: * @param cmd the name of the command (extracted form argv[0] of cmdProc)
154: */
155:
156: private void errorWrongNumArgs(Interp interp, String cmd)
157: throws TclException {
158: throw new TclException(interp, "wrong # args: should be \""
159: + "read channelId ?numChars?\" "
160: + "or \"read ?-nonewline? channelId\"");
161: }
162:
163: }
|