001: package kawa;
002:
003: import gnu.mapping.*;
004: import gnu.expr.*;
005: import java.io.*;
006: import gnu.text.*;
007: import gnu.lists.*;
008:
009: /** Utility functions (static methods) for kawa.repl.
010: * Should probably be merged with kawa.repl. FIXME. */
011:
012: public class Shell {
013: private static Class[] noClasses = {};
014: private static Class[] boolClasses = { Boolean.TYPE };
015: private static Class[] xmlPrinterClasses = {
016: gnu.mapping.OutPort.class, java.lang.Object.class };
017: private static Class[] httpPrinterClasses = { gnu.mapping.OutPort.class };
018: private static Object portArg = "(port)";
019:
020: /** A table of names of known output formats.
021: * For each entry, the first Object is the format name.
022: * The next entries are a class name, the name of a static method in that
023: * class, and the parameter types (as a Class[] suitable for getMethod).
024: * The remain values are arguments (passed to invoke), except that if an
025: * argument is the spacial value portArg, it is replaced by the
026: * destination OutPort. */
027:
028: static Object[][] formats = {
029: { "scheme", "gnu.kawa.functions.DisplayFormat",
030: "getSchemeFormat", boolClasses, Boolean.FALSE },
031: { "readable-scheme", "gnu.kawa.functions.DisplayFormat",
032: "getSchemeFormat", boolClasses, Boolean.TRUE },
033: { "elisp", "gnu.kawa.functions.DisplayFormat",
034: "getEmacsLispFormat", boolClasses, Boolean.FALSE },
035: { "readable-elisp", "gnu.kawa.functions.DisplayFormat",
036: "getEmacsLispFormat", boolClasses, Boolean.TRUE },
037: { "clisp", "gnu.kawa.functions.DisplayFormat",
038: "getCommonLispFormat", boolClasses, Boolean.FALSE },
039: { "readable-clisp", "gnu.kawa.functions.DisplayFormat",
040: "getCommonLispFormat", boolClasses, Boolean.TRUE },
041: { "commonlisp", "gnu.kawa.functions.DisplayFormat",
042: "getCommonLispFormat", boolClasses, Boolean.FALSE },
043: { "readable-commonlisp",
044: "gnu.kawa.functions.DisplayFormat",
045: "getCommonLispFormat", boolClasses, Boolean.TRUE },
046: { "xml", "gnu.xml.XMLPrinter", "make", xmlPrinterClasses,
047: portArg, null },
048: { "html", "gnu.xml.XMLPrinter", "make", xmlPrinterClasses,
049: portArg, "html" },
050: { "xhtml", "gnu.xml.XMLPrinter", "make", xmlPrinterClasses,
051: portArg, "xhtml" },
052: { "cgi", "gnu.kawa.xml.HttpPrinter", "make",
053: httpPrinterClasses, portArg },
054: { "ignore", "gnu.lists.VoidConsumer", "getInstance",
055: noClasses }, { null } };
056:
057: public static String defaultFormatName;
058: public static Object[] defaultFormatInfo;
059: public static java.lang.reflect.Method defaultFormatMethod;
060:
061: /** Specify the default output format.
062: * @param name The name of the format, as an entry in the formats table.
063: */
064: public static void setDefaultFormat(String name) {
065: name = name.intern();
066: defaultFormatName = name;
067: for (int i = 0;; i++) {
068: Object[] info = formats[i];
069: Object iname = info[0];
070: if (iname == null) {
071: System.err.println("kawa: unknown output format '"
072: + name + "'");
073: System.exit(-1);
074: } else if (iname == name) {
075: defaultFormatInfo = info;
076: try {
077: Class formatClass = Class.forName((String) info[1]);
078: defaultFormatMethod = formatClass.getMethod(
079: (String) info[2], (Class[]) info[3]);
080:
081: } catch (Throwable ex) {
082: System.err.println("kawa: caught " + ex
083: + " while looking for format '" + name
084: + "'");
085: System.exit(-1);
086: }
087: break;
088: }
089: }
090: if (!defaultFormatInfo[1].equals("gnu.lists.VoidConsumer"))
091: ModuleBody.setMainPrintValues(true);
092: }
093:
094: /** Return a Consumer that formats using the appropriate format.
095: * The format is chosen depending on specified defaults.
096: * @param out The output where formatted output is sent to.
097: */
098: public static Consumer getOutputConsumer(OutPort out) {
099: Object[] info = defaultFormatInfo;
100: if (out == null)
101: return VoidConsumer.getInstance();
102: else if (info == null)
103: return Language.getDefaultLanguage().getOutputConsumer(out);
104: try {
105: Object args[] = new Object[info.length - 4];
106: System.arraycopy(info, 4, args, 0, args.length);
107: for (int i = args.length; --i >= 0;)
108: if (args[i] == portArg)
109: args[i] = out;
110: Object format = defaultFormatMethod.invoke(null, args);
111: if (format instanceof AbstractFormat) {
112: out.objectFormat = (AbstractFormat) format;
113: return out;
114: } else
115: return (Consumer) format;
116: } catch (Throwable ex) {
117: throw new RuntimeException("cannot get output-format '"
118: + defaultFormatName + "' - caught " + ex);
119: }
120: }
121:
122: public static void run(Language language, Environment env) {
123: InPort inp = InPort.inDefault();
124: if (inp instanceof TtyInPort) {
125: Procedure prompter = language.getPrompter();
126: if (prompter != null)
127: ((TtyInPort) inp).setPrompter(prompter);
128: }
129:
130: run(language, env, inp, OutPort.outDefault(), OutPort
131: .errDefault());
132: }
133:
134: public static void run(Language language, Environment env,
135: InPort inp, OutPort pout, OutPort perr) {
136: Consumer out;
137: AbstractFormat saveFormat = null;
138: if (pout != null)
139: saveFormat = pout.objectFormat;
140: out = getOutputConsumer(pout);
141: try {
142: run(language, env, inp, out, perr, null);
143: } finally {
144: if (pout != null)
145: pout.objectFormat = saveFormat;
146: }
147: }
148:
149: public static void run(Language language, Environment env,
150: InPort inp, Consumer out, OutPort perr, java.net.URL url) {
151: SourceMessages messages = new SourceMessages();
152: Language saveLanguage = Language.getDefaultLanguage();
153: Lexer lexer = language.getLexer(inp, messages);
154: // Wrong for the case of '-f' '-':
155: boolean interactive = inp instanceof TtyInPort;
156: lexer.setInteractive(interactive);
157: CallContext ctx = CallContext.getInstance();
158: Consumer saveConsumer = null;
159: if (out != null) {
160: saveConsumer = ctx.consumer;
161: ctx.consumer = out;
162: }
163: if (language != saveLanguage)
164: Language.setDefaultLanguage(language);
165: try {
166: for (;;) {
167: int opts = Language.PARSE_IMMEDIATE
168: | Language.PARSE_ONE_LINE;
169: try {
170: Compilation comp = language
171: .parse(lexer, opts, null);
172: boolean sawError = messages.checkErrors(perr, 20);
173: if (comp == null) // ??? end-of-file
174: break;
175: if (sawError)
176: continue;
177: comp.getModule().setName(
178: "atInteractiveLevel$"
179: + (++ModuleExp.interactiveCounter));
180:
181: // Skip whitespace, in case (read-char) or similar is called:
182: int ch;
183: for (;;) {
184: ch = inp.read();
185: if (ch < 0 || ch == '\r' || ch == '\n')
186: break;
187: if (ch != ' ' && ch != '\t') {
188: inp.unread();
189: break;
190: }
191: }
192:
193: if (!ModuleExp
194: .evalModule(env, ctx, comp, url, perr))
195: continue;
196: if (out instanceof Writer)
197: ((Writer) out).flush();
198: if (ch < 0)
199: break;
200: } catch (WrongArguments e) {
201: messages.printAll(perr, 20);
202: if (e.usage != null)
203: perr.println("usage: " + e.usage);
204: e.printStackTrace(perr);
205: } catch (java.lang.ClassCastException e) {
206: messages.printAll(perr, 20);
207: perr.println("Invalid parameter, was: "
208: + e.getMessage());
209: e.printStackTrace(perr);
210: } catch (java.io.IOException e) {
211: messages.printAll(perr, 20);
212: String msg = new SourceError(inp, 'e', "")
213: .toString();
214: msg = msg.substring(0, msg.length() - 2);
215: perr.println(msg
216: + " (or later): caught IOException");
217: e.printStackTrace(perr);
218: if (!interactive)
219: return;
220: } catch (Throwable e) {
221: SyntaxException se;
222: if (e instanceof SyntaxException
223: && (se = (SyntaxException) e).getMessages() == messages) {
224: se.printAll(perr, 20);
225: se.clear();
226: } else {
227: messages.printAll(perr, 20);
228: e.printStackTrace(perr);
229: }
230: if (!interactive)
231: return;
232: }
233: }
234: } finally {
235: if (out != null)
236: ctx.consumer = saveConsumer;
237: if (language != saveLanguage)
238: Language.setDefaultLanguage(saveLanguage);
239: }
240: }
241:
242: public static void runString(String str, Language language,
243: Environment env) {
244: run(language, env, new CharArrayInPort(str), ModuleBody
245: .getMainPrintValues() ? OutPort.outDefault() : null,
246: OutPort.errDefault());
247: }
248:
249: public static void runFile(String fname, int skipLines) {
250: Environment env = Environment.getCurrent();
251: try {
252: if (fname.equals("-")) {
253: InPort in = InPort.inDefault();
254: while (--skipLines >= 0)
255: in.skipRestOfLine();
256: kawa.standard.load.loadSource(in, env, null);
257: } else
258: kawa.standard.load.apply(Path.valueOf(fname), env,
259: false, skipLines);
260: } catch (gnu.text.SyntaxException e) {
261: e.printAll(OutPort.errDefault(), 20);
262: } catch (FileNotFoundException e) {
263: System.err.println("Cannot open file " + fname);
264: System.exit(1);
265: } catch (Throwable e) {
266: e.printStackTrace(System.err);
267: System.exit(1);
268: }
269: }
270:
271: }
|