001: /*=============================================================================
002: * Copyright Texas Instruments 2002. All Rights Reserved.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
019: */
020:
021: package oscript;
022:
023: import java.io.*;
024:
025: import oscript.data.Value;
026:
027: /**
028: * An extensible read-eval-print shell implementation. Splits the basic
029: * process of read, eval, print and handle errors into individual methods
030: * which can be overriden and extended as needed.
031: * <p>
032: * NOTE this could probably be split into an abstract base class which
033: * does not implement {@link #read} and {@link #print}, and hence has no
034: * knowledge of input/output/error streams.
035: *
036: * @author Rob Clark (rob@ti.com)
037: * <!--$Format: " * @version $Revision$"$-->
038: * @version 1.2
039: */
040: public class Shell {
041: private String prompt;
042: private BufferedReader in;
043: private PrintWriter out;
044: private PrintWriter err;
045:
046: /**
047: * Class Constructor.
048: *
049: * @param in input
050: * @param out output
051: */
052: public Shell(BufferedReader in, PrintWriter out) {
053: this (in, out, out);
054: }
055:
056: /**
057: * Class Constructor.
058: *
059: * @param in input
060: * @param out output
061: * @param err error output
062: */
063: public Shell(BufferedReader in, PrintWriter out, PrintWriter err) {
064: this ("os> ", in, out, err);
065: }
066:
067: /**
068: * Class Constructor.
069: *
070: * @param prompt the prompt to display before the read
071: * @param in input
072: * @param out output
073: * @param err error output
074: */
075: public Shell(String prompt, BufferedReader in, PrintWriter out,
076: PrintWriter err) {
077: this .prompt = prompt;
078: this .in = in;
079: this .out = out;
080: this .err = err;
081: }
082:
083: /**
084: * The entry point for the read-eval-print loop. This repeatedly calls
085: * {@link #prompt}, {@link #read}, and {@link #evalAndPrint}, which can
086: * each be overridden as needed.
087: */
088: public void run() throws IOException {
089: while (true) {
090: prompt();
091: String line = read();
092: if ((line == null) || line.equals(""))
093: continue;
094: else if (line.equals("exit"))
095: break;
096: else
097: evalAndPrint(line);
098: }
099: }
100:
101: /**
102: * Evaluate and print a line. This calls out to {@link #evalStr},
103: * {@link #print}, {@link #handleScriptException}, and
104: * {@link #handleParseException}, which can be overriden as needed.
105: *
106: * @param line the line of script
107: */
108: public void evalAndPrint(String line) {
109: try {
110: print(evalStr(line));
111: } catch (oscript.exceptions.PackagedScriptObjectException e) {
112: handleScriptException(e);
113: } catch (oscript.parser.ParseException e) {
114: handleParseException(e);
115: }
116: }
117:
118: /**
119: * Print the prompt shown to the user to indicate that we are ready for
120: * more input.
121: */
122: public void prompt() {
123: out.print(prompt);
124: out.flush();
125: }
126:
127: /**
128: * Read a line of input. This handles multi-line input (ie. lines ending
129: * with a <code>\</code>) by stripping out the backslash and reading the
130: * next line, until there is a line not terminated by a backslash. Also,
131: * as a convenience, this method appends a semicolon to the end of the
132: * input, if needed.
133: *
134: * @return the input
135: */
136: public String read() throws IOException {
137: String str = "";
138:
139: while (true) {
140: String line = in.readLine();
141:
142: if (line == null)
143: throw new EOFException();
144:
145: str += line.trim();
146:
147: if (str.length() == 0)
148: return null;
149:
150: char c = str.charAt(str.length() - 1);
151:
152: if (c == '\\') {
153: str = str.substring(0, str.length() - 1);
154: } else {
155: if ((c != ';') && (c != '}'))
156: str += ';';
157:
158: return str;
159: }
160: }
161: }
162:
163: /**
164: * Evaluate a string... calls out to the interpreter to perform the evaluate,
165: * and throws exceptions of there is a syntax or logical error in the code
166: * evaluated.
167: *
168: * @param line the script to evaluate
169: * @return the result of evaluating the string
170: */
171: public Value evalStr(String line)
172: throws oscript.parser.ParseException,
173: oscript.exceptions.PackagedScriptObjectException {
174: return OscriptInterpreter.eval(line);
175: }
176:
177: /**
178: * Print the result. This is called to print a result after successfully
179: * evaluating an input.
180: *
181: * @param val the result to print
182: */
183: public void print(Value val) {
184: if ((val != null) && (val != Value.NULL))
185: out.println("=> " + val);
186: }
187:
188: /**
189: * Called to handle script exceptions. A script exception may be a result
190: * of a logical error, in otherwise syntatically correct input.
191: *
192: * @param e the exception
193: */
194: public void handleScriptException(
195: oscript.exceptions.PackagedScriptObjectException e) {
196: err.println(e.val.castToString());
197: }
198:
199: /**
200: * Called to handle syntax exceptions. A syntax exception occurs in the
201: * case where the input is not syntatically correct.
202: *
203: * @param e the exception
204: */
205: public void handleParseException(oscript.parser.ParseException e) {
206: err.println("parse error: " + e.getMessage());
207: }
208: }
209:
210: /*
211: * Local Variables:
212: * tab-width: 2
213: * indent-tabs-mode: nil
214: * mode: java
215: * c-indentation-style: java
216: * c-basic-offset: 2
217: * eval: (c-set-offset 'substatement-open '0)
218: * eval: (c-set-offset 'case-label '+)
219: * eval: (c-set-offset 'inclass '+)
220: * eval: (c-set-offset 'inline-open '0)
221: * End:
222: */
|