001: /*
002: * TclIO.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: TclIO.java,v 1.10 2006/01/26 19:49:18 mdejong Exp $
011: *
012: */
013:
014: package tcl.lang;
015:
016: import java.util.*;
017: import java.io.*;
018:
019: class TclIO {
020:
021: static final int READ_ALL = 1;
022: static final int READ_LINE = 2;
023: static final int READ_N_BYTES = 3;
024:
025: static final int SEEK_SET = 1;
026: static final int SEEK_CUR = 2;
027: static final int SEEK_END = 3;
028:
029: static final int RDONLY = 1;
030: static final int WRONLY = 2;
031: static final int RDWR = 4;
032: static final int APPEND = 8;
033: static final int CREAT = 16;
034: static final int EXCL = 32;
035: static final int TRUNC = 64;
036:
037: static final int BUFF_FULL = 0;
038: static final int BUFF_LINE = 1;
039: static final int BUFF_NONE = 2;
040:
041: static final int TRANS_AUTO = 0;
042: static final int TRANS_BINARY = 1;
043: static final int TRANS_LF = 2;
044: static final int TRANS_CR = 3;
045: static final int TRANS_CRLF = 4;
046:
047: static int TRANS_PLATFORM;
048:
049: static {
050: if (Util.isWindows())
051: TRANS_PLATFORM = TRANS_CRLF;
052: else if (Util.isMac())
053: TRANS_PLATFORM = TRANS_CR;
054: else
055: TRANS_PLATFORM = TRANS_LF;
056: }
057:
058: /**
059: * Table of channels currently registered for all interps. The
060: * interpChanTable has "virtual" references into this table that
061: * stores the registered channels for the individual interp.
062: */
063:
064: private static StdChannel stdinChan = null;
065: private static StdChannel stdoutChan = null;
066: private static StdChannel stderrChan = null;
067:
068: static Channel getChannel(Interp interp, String chanName) {
069: return ((Channel) getInterpChanTable(interp).get(chanName));
070: }
071:
072: static void registerChannel(Interp interp, Channel chan) {
073:
074: if (interp != null) {
075: HashMap chanTable = getInterpChanTable(interp);
076: chanTable.put(chan.getChanName(), chan);
077: chan.refCount++;
078: }
079: }
080:
081: static void unregisterChannel(Interp interp, Channel chan) {
082: HashMap chanTable = getInterpChanTable(interp);
083: chanTable.remove(chan.getChanName());
084:
085: if (--chan.refCount <= 0) {
086: try {
087: chan.close();
088: } catch (IOException e) {
089: //e.printStackTrace(System.err);
090: throw new TclRuntimeError(
091: "TclIO.unregisterChannel() Error: IOException when closing "
092: + chan.getChanName() + ": "
093: + e.getMessage());
094: }
095: }
096: }
097:
098: static HashMap getInterpChanTable(Interp interp) {
099: Channel chan;
100:
101: if (interp.interpChanTable == null) {
102:
103: interp.interpChanTable = new HashMap();
104:
105: chan = getStdChannel(StdChannel.STDIN);
106: registerChannel(interp, chan);
107:
108: chan = getStdChannel(StdChannel.STDOUT);
109: registerChannel(interp, chan);
110:
111: chan = getStdChannel(StdChannel.STDERR);
112: registerChannel(interp, chan);
113: }
114:
115: return interp.interpChanTable;
116: }
117:
118: static Channel getStdChannel(int type) {
119: Channel chan = null;
120:
121: switch (type) {
122: case StdChannel.STDIN:
123: if (stdinChan == null) {
124: stdinChan = new StdChannel(StdChannel.STDIN);
125: }
126: chan = stdinChan;
127: break;
128: case StdChannel.STDOUT:
129: if (stdoutChan == null) {
130: stdoutChan = new StdChannel(StdChannel.STDOUT);
131: }
132: chan = stdoutChan;
133: break;
134: case StdChannel.STDERR:
135: if (stderrChan == null) {
136: stderrChan = new StdChannel(StdChannel.STDERR);
137: }
138: chan = stderrChan;
139: break;
140: default:
141: throw new TclRuntimeError("Invalid type for StdChannel");
142: }
143:
144: return (chan);
145: }
146:
147: /**
148: * Really ugly function that attempts to get the next available
149: * channelId name. In C the FD returned in the native open call
150: * returns this value, but we don't have that so we need to do
151: * this funky iteration over the HashMap.
152: *
153: * @param interp currrent interpreter.
154: * @return the next integer to use in the channelId name.
155: */
156:
157: static String getNextDescriptor(Interp interp, String prefix) {
158: int i;
159: HashMap htbl = getInterpChanTable(interp);
160:
161: // The first available file identifier in Tcl is "file3"
162: if (prefix.equals("file"))
163: i = 3;
164: else
165: i = 0;
166:
167: for (; (htbl.get(prefix + i)) != null; i++) {
168: // Do nothing...
169: }
170: return prefix + i;
171: }
172:
173: /*
174: * Return a string description for a translation id defined above.
175: */
176:
177: static String getTranslationString(int translation) {
178: switch (translation) {
179: case TRANS_AUTO:
180: return "auto";
181: case TRANS_CR:
182: return "cr";
183: case TRANS_CRLF:
184: return "crlf";
185: case TRANS_LF:
186: return "lf";
187: case TRANS_BINARY:
188: return "lf";
189: default:
190: throw new TclRuntimeError("bad translation id");
191: }
192: }
193:
194: /*
195: * Return a numerical identifier for the given -translation string.
196: */
197:
198: static int getTranslationID(String translation) {
199: if (translation.equals("auto"))
200: return TRANS_AUTO;
201: else if (translation.equals("cr"))
202: return TRANS_CR;
203: else if (translation.equals("crlf"))
204: return TRANS_CRLF;
205: else if (translation.equals("lf"))
206: return TRANS_LF;
207: else if (translation.equals("binary"))
208: return TRANS_LF;
209: else if (translation.equals("platform"))
210: return TRANS_PLATFORM;
211: else
212: return -1;
213: }
214:
215: /*
216: * Return a string description for a -buffering id defined above.
217: */
218:
219: static String getBufferingString(int buffering) {
220: switch (buffering) {
221: case BUFF_FULL:
222: return "full";
223: case BUFF_LINE:
224: return "line";
225: case BUFF_NONE:
226: return "none";
227: default:
228: throw new TclRuntimeError("bad buffering id");
229: }
230: }
231:
232: /*
233: * Return a numerical identifier for the given -buffering string.
234: */
235:
236: static int getBufferingID(String buffering) {
237: if (buffering.equals("full"))
238: return BUFF_FULL;
239: else if (buffering.equals("line"))
240: return BUFF_LINE;
241: else if (buffering.equals("none"))
242: return BUFF_NONE;
243: else
244: return -1;
245: }
246:
247: }
|