\r
+ listener/plugin:\r
\r
-- extract word in wrong place\r
- accept multi-line input in listener\r
- don't show listener on certain commands\r
- NPE in ErrorHighlight\r
<!DOCTYPE ACTIONS SYSTEM "actions.dtd">
<ACTIONS>
+ <ACTION NAME="factor-restart">
+ <CODE>
+ FactorPlugin.stopExternalInstance();
+ FactorPlugin.getExternalInstance();
+ </CODE>
+ </ACTION>
<ACTION NAME="factor-eval-selection">
<CODE>
sel = textArea.selectedText;
! Graphical mandelbrot fractal renderer.
! To run this code, start your interpreter like so:
!
-! ./f -library:sdl=libSDL.so -library:sdl-gfx=libSDL_gfx.so
+! ./f -libraries:sdl=libSDL.so -libraries:sdl-gfx=libSDL_gfx.so
!
! Then, enter this at the interpreter prompt:
!
ParseState state = getCurrentState();
if(state.start != start)
scanner.error(end + " does not close " + state.start);
- else
- states = states.next();
+ states = states.next();
return state;
} //}}}
--- /dev/null
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.FactorInterpreter;
+import java.io.*;
+import java.net.Socket;
+import java.util.*;
+import org.gjt.sp.util.Log;
+
+/**
+ * Encapsulates a connection to an external Factor instance.
+ */
+public class ExternalFactor
+{
+ //{{{ ExternalFactor constructor
+ /**
+ * We are given two streams that point to a bare REPL.
+ */
+ public ExternalFactor(FactorInterpreter interp, InputStream in, OutputStream out)
+ throws IOException
+ {
+ this.interp = interp;
+ this.in = new DataInputStream(in);
+ this.out = new DataOutputStream(out);
+
+ out.write("USE: jedit wire-server\n".getBytes("ASCII"));
+ out.flush();
+
+ waitForAck();
+
+ /* Start stream server */
+ streamServer = 9999;
+ eval("USE: telnetd [ 9999 telnetd ] in-thread");
+ } //}}}
+
+ //{{{ waitForAck() method
+ private void waitForAck() throws IOException
+ {
+ sendEval("\"ACK\" write flush\n");
+
+ /* Read everything until wire header */
+ String discardStr = "";
+
+ while(!discardStr.endsWith("ACK"))
+ {
+ byte[] discard = new byte[2048];
+ int len = in.read(discard,0,discard.length);
+ discardStr = new String(discard,0,len);
+ }
+ } //}}}
+
+ //{{{ sendEval() method
+ private void sendEval(String cmd) throws IOException
+ {
+ byte[] bytes = cmd.getBytes("ASCII");
+ out.writeInt(bytes.length);
+ out.write(bytes,0,bytes.length);
+ out.flush();
+ } //}}}
+
+ //{{{ eval() method
+ /**
+ * Send a command to the inferior Factor, and return the string output.
+ */
+ public synchronized String eval(String cmd) throws IOException
+ {
+ waitForAck();
+
+ sendEval(cmd);
+
+ int responseLength = in.readInt();
+ byte[] response = new byte[responseLength];
+ in.readFully(response);
+
+ return new String(response,"ASCII");
+ } //}}}
+
+ //{{{ openStream() method
+ /**
+ * Return a listener stream.
+ */
+ public FactorStream openStream() throws IOException
+ {
+ Socket client = new Socket("localhost",streamServer);
+ return new FactorStream(client,interp);
+ } //}}}
+
+ //{{{ close() method
+ /**
+ * Close communication session. Factor will then exit.
+ */
+ public synchronized void close()
+ {
+ try
+ {
+ /* don't care about response */
+ sendEval("0 exit*");
+ in.close();
+ out.close();
+ }
+ catch(Exception e)
+ {
+ // We don't care...
+ Log.log(Log.DEBUG,this,e);
+ }
+ } //}}}
+
+ //{{{ Private members
+ private FactorInterpreter interp;
+ private DataInputStream in;
+ private DataOutputStream out;
+
+ private int streamServer;
+ //}}}
+}
package factor.jedit;
import factor.*;
-import java.io.InputStreamReader;
+import java.io.*;
import java.util.*;
import org.gjt.sp.jedit.gui.*;
import org.gjt.sp.jedit.textarea.*;
public class FactorPlugin extends EditPlugin
{
private static FactorInterpreter interp;
+ private static ExternalFactor external;
+ //{{{ getPluginPath() method
+ private String getPluginPath()
+ {
+ return MiscUtilities.getParentOfPath(
+ jEdit.getPlugin("factor.jedit.FactorPlugin")
+ .getPluginJAR().getPath())
+ + "Factor";
+ } //}}}
+
//{{{ start() method
public void start()
{
BeanShell.eval(null,BeanShell.getNameSpace(),
"import factor.*;\nimport factor.jedit.*;\n");
+ String program = jEdit.getProperty("factor.external.program");
+ String image = jEdit.getProperty("factor.external.image");
+ if(program == null || image == null
+ || program.length() == 0 || image.length() == 0)
+ {
+ jEdit.setProperty("factor.external.program",
+ MiscUtilities.constructPath(getPluginPath(),"f"));
+ jEdit.setProperty("factor.external.image",
+ MiscUtilities.constructPath(getPluginPath(),"factor.image"));
+ }
+ } //}}}
+
+ //{{{ stop() method
+ public void stop()
+ {
+ stopExternalInstance();
} //}}}
+ //{{{ getExternalInstance() method
+ /**
+ * Returns the object representing a connection to an external Factor instance.
+ * It will start the interpreter if it's not already running.
+ */
+ public static ExternalFactor getExternalInstance()
+ throws IOException, UnsupportedEncodingException
+ {
+ if(external == null)
+ {
+ Process p = Runtime.getRuntime().exec(
+ new String[] {
+ jEdit.getProperty("factor.external.program"),
+ jEdit.getProperty("factor.external.image"),
+ "-no-ansi",
+ "-jedit"
+ });
+ p.getErrorStream().close();
+
+ external = new ExternalFactor(
+ getInterpreter(),
+ p.getInputStream(),
+ p.getOutputStream());
+ }
+
+ return external;
+ } //}}}
+
+ //{{{ stopExternalInstance() method
+ /**
+ * Stops the external interpreter. It will probably be restarted soon after.
+ */
+ public static void stopExternalInstance()
+ {
+ ((FactorShell)ServiceManager.getService("console.Shell","Factor"))
+ .closeStreams();
+
+ if(external != null)
+ {
+ external.close();
+ external = null;
+ }
+ } //}}}
+
//{{{ newInterpreter() method
private static FactorInterpreter newInterpreter(String[] args)
{
{
if(interp == null)
{
- interp = newInterpreter(new String[] { "-jedit" });
+ interp = newInterpreter(new String[] { "-jedit", "-no-compile" });
}
return interp;
### Plugin properties
-
plugin.factor.jedit.FactorPlugin.activate=startup
plugin.factor.jedit.FactorPlugin.name=Factor
plugin.factor.jedit.FactorPlugin.depend.2=plugin sidekick.SideKickPlugin 0.3.1
plugin.factor.jedit.FactorPlugin.depend.3=plugin console.ConsolePlugin 4.0.1
+#! Menu
plugin.factor.jedit.FactorPlugin.menu=factor-run-file \
factor-eval-selection \
- \
factor-see \
factor-usages \
- \
- factor-extract-word
+ factor-extract-word \
+ - \
+ factor-restart
factor-run-file.label=Run current file
factor-eval-selection.label=Evaluate selection
factor-edit-dialog.label=Edit word...
factor-usages.label=Word usages at caret
factor-extract-word.label=Extract word...
+factor-restart.label=Restart Factor
+# SideKick stuff
sidekick.parser.factor.label=Factor
mode.factor.sidekick.parser=factor
factor.completion.shuffle=~<< <b>{0}</b> {1} >>~
factor.completion.symbol=SYMBOL: <b>{0}</b>
+# Dialog boxes
factor.status.inserted-use=Inserted {0}
factor.status.already-used=Already used {0}
factor.extract-word-where.title=Cannot Extract Here
factor.extract-word-where.message=This command can only be used inside a word definition.
+
+# Shell
+factor.shell.opening=Opening listener connection
+factor.shell.closing=Closing listener connection
+factor.shell.not-waiting=Not accepting input at this time
+
+# Option pane
+plugin.factor.jedit.FactorPlugin.option-pane=factor
+
+options.factor.label=Factor
+options.factor.code=new factor.jedit.FactorOptionPane();
+options.factor.program=Factor runtime executable:
+options.factor.image=Factor image:
+options.factor.choose=Choose file...
import console.*;
import factor.*;
import javax.swing.text.AttributeSet;
+import java.io.IOException;
+import java.util.Iterator;
import java.util.WeakHashMap;
+import org.gjt.sp.jedit.jEdit;
import org.gjt.sp.jedit.ServiceManager;
+import org.gjt.sp.util.Log;
public class FactorShell extends Shell
{
- //{{{ readLine() method
- /**
- * Helper static method to simplify Factor code.
- */
- public static void readLine(Cons continuation, Console console)
- {
- FactorShell shell = (FactorShell)ServiceManager.getService(
- "console.Shell","Factor");
- ConsoleState state = shell.getConsoleState(console);
- state.readLineContinuation = continuation;
- } //}}}
-
//{{{ FactorShell constructor
public FactorShell()
{
super("Factor");
- interp = FactorPlugin.getInterpreter();
consoles = new WeakHashMap();
} //}}}
*/
public void printPrompt(Console console, Output output)
{
- getConsoleState(console);
+ try
+ {
+ getConsoleState(console).packetLoop(output);
+ }
+ catch(Exception e)
+ {
+ output.print(console.getErrorColor(),e.toString());
+ Log.log(Log.ERROR,this,e);
+ }
} //}}}
//{{{ execute() method
public void execute(Console console, String input,
Output output, Output error, String command)
{
- ConsoleState state = getConsoleState(console);
- Cons quot = new Cons(command,state.readLineContinuation);
- eval(quot);
- output.commandDone();
- error.commandDone();
+ try
+ {
+ getConsoleState(console).readResponse(output,command);
+ }
+ catch(Exception e)
+ {
+ output.print(console.getErrorColor(),e.toString());
+ Log.log(Log.ERROR,this,e);
+ }
+ finally
+ {
+ output.commandDone();
+ error.commandDone();
+ }
} //}}}
//{{{ stop() method
public void stop(Console console)
{
} //}}}
-
+
+ //{{{ closeStreams() method
+ /**
+ * Close all listener connections. Should be called before Factor is restarted.
+ */
+ public void closeStreams()
+ {
+ Iterator iter = consoles.values().iterator();
+ while(iter.hasNext())
+ {
+ ConsoleState state = (ConsoleState)iter.next();
+ state.closeStream();
+ }
+ } //}}}
+
//{{{ Private members
- private FactorInterpreter interp;
private WeakHashMap consoles;
//{{{ getConsoleState() method
private ConsoleState getConsoleState(Console console)
+ throws IOException
{
ConsoleState state = (ConsoleState)consoles.get(console);
if(state == null)
{
state = new ConsoleState(console);
consoles.put(console,state);
-
- eval(new Cons(console,
- new Cons(interp.searchVocabulary(
- "console","console-hook"),
- null)));
}
return state;
} //}}}
- //{{{ eval() method
- private void eval(Cons cmd)
- {
- try
- {
- interp.call(cmd);
- interp.run();
- }
- catch(Exception e)
- {
- System.err.println("Failed to eval " + cmd + ":");
- e.printStackTrace();
- }
- } //}}}
-
//}}}
//{{{ ConsoleState class
class ConsoleState
{
private Console console;
- Cons readLineContinuation;
+ private FactorStream stream;
+ private boolean waitingForInput;
ConsoleState(Console console)
{
this.console = console;
}
+
+ void openStream(Output output) throws Exception
+ {
+ if(stream == null)
+ {
+ output.print(console.getInfoColor(),
+ jEdit.getProperty("factor.shell.opening"));
+ stream = FactorPlugin.getExternalInstance().openStream();
+ }
+ }
+
+ void closeStream()
+ {
+ try
+ {
+ if(stream != null)
+ {
+ waitingForInput = false;
+ console.print(console.getInfoColor(),
+ jEdit.getProperty("factor.shell.closing"));
+ stream.close();
+ stream = null;
+ }
+ }
+ catch(IOException e)
+ {
+ /* We don't care */
+ Log.log(Log.ERROR,this,e);
+ }
+ }
+
+ void packetLoop(Output output) throws Exception
+ {
+ if(waitingForInput)
+ return;
+
+ openStream(output);
+
+ FactorStream.Packet p;
+ while((p = stream.nextPacket()) != null)
+ {
+ if(p instanceof FactorStream.ReadLinePacket)
+ {
+ waitingForInput = true;
+ break;
+ }
+ else if(p instanceof FactorStream.WritePacket)
+ {
+ FactorStream.WritePacket w
+ = (FactorStream.WritePacket)p;
+ output.writeAttrs(w.getAttributes(),w.getText());
+ }
+ }
+ }
+
+ void readResponse(Output output, String command) throws Exception
+ {
+ if(waitingForInput)
+ {
+ openStream(output);
+
+ stream.readResponse(command);
+ waitingForInput = false;
+ packetLoop(output);
+ }
+ else
+ {
+ console.print(console.getErrorColor(),
+ jEdit.getProperty("factor.shell.not-waiting"));
+ }
+ }
} //}}}
}
--- /dev/null
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.Cons;
+import factor.FactorInterpreter;
+import factor.FactorReader;
+import javax.swing.text.AttributeSet;
+import java.io.*;
+import java.net.Socket;
+import java.util.*;
+
+/**
+ * Encapsulates a Factor listener connection.
+ */
+public class FactorStream
+{
+ //{{{ FactorStream constructor
+ /**
+ * We are given a socket that points to a bare REPL.
+ */
+ public FactorStream(Socket socket, FactorInterpreter interp) throws IOException
+ {
+ this.interp = interp;
+ this.socket = socket;
+ this.in = new DataInputStream(socket.getInputStream());
+ this.out = new DataOutputStream(socket.getOutputStream());
+
+ out.write("\"\\0\" write flush USE: jedit stream-server\n".getBytes("ASCII"));
+ out.flush();
+
+ /* Read everything until prompt */
+ int b = -2;
+ while(b != '\0' && b != -1)
+ b = in.read();
+ } //}}}
+
+ //{{{ nextPacket() method
+ /**
+ * @return null on EOF.
+ */
+ public Packet nextPacket() throws Exception
+ {
+ int ch = in.read();
+ switch(ch)
+ {
+ case 'r':
+ return new ReadLinePacket();
+ case 'f':
+ return new FlushPacket();
+ case 'w':
+ int len = in.readInt();
+ byte[] request = new byte[len];
+ in.readFully(request);
+ return new WritePacket(new String(request,0,len),interp);
+ case -1:
+ return null;
+ default:
+ throw new IOException("Bad stream packet type: " + ch);
+ }
+ } //}}}
+
+ //{{{ readResponse() method
+ /**
+ * This must only be called if the last packet received was a read request.
+ */
+ public void readResponse(String input) throws IOException
+ {
+ int len = input.length();
+ out.writeInt(len);
+ out.write(input.getBytes("ASCII"),0,len);
+ out.flush();
+ } //}}}
+
+ //{{{ close() method
+ /**
+ * Close communication session. Factor will then exit.
+ */
+ public void close() throws IOException
+ {
+ socket.close();
+ in.close();
+ out.close();
+ } //}}}
+
+ //{{{ Private members
+ private Socket socket;
+ private DataInputStream in;
+ private DataOutputStream out;
+ private FactorInterpreter interp;
+ //}}}
+
+ //{{{ Packet class
+ public static abstract class Packet {}
+ //}}}
+
+ //{{{ ReadLinePacket class
+ public static class ReadLinePacket extends Packet {}
+ //}}}
+
+ //{{{ FlushPacket class
+ public static class FlushPacket extends Packet {}
+ //}}}
+
+ //{{{ WritePacket class
+ public static class WritePacket extends Packet
+ {
+ public WritePacket(String input, FactorInterpreter interp)
+ throws Exception
+ {
+ FactorReader parser = new FactorReader(
+ "parseObject()",
+ new BufferedReader(new StringReader(input)),
+ true,false,interp);
+ Cons pair = parser.parse();
+
+ this.write = (String)pair.car;
+ this.attrs = new ListenerAttributeSet((Cons)pair.next().car);
+ }
+
+ public String getText()
+ {
+ return write;
+ }
+
+ public AttributeSet getAttributes()
+ {
+ return attrs;
+ }
+
+ private String write;
+ private AttributeSet attrs;
+ } //}}}
+}
--- /dev/null
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import javax.swing.text.*;
+import java.awt.Color;
+import factor.Cons;
+
+public class ListenerAttributeSet extends SimpleAttributeSet
+{
+ //{{{ ListenerAttributeSet constructor
+ ListenerAttributeSet(Cons alist)
+ {
+ while(alist != null)
+ {
+ Cons pair = (Cons)alist.car;
+ handleAttribute(pair.car,pair.cdr);
+ alist = alist.next();
+ }
+ } //}}}
+
+ //{{{ handleAttribute() method
+ private void handleAttribute(Object key, Object value)
+ {
+ if("bold".equals(key))
+ addAttribute(StyleConstants.Bold,Boolean.TRUE);
+ else if("italics".equals(key))
+ addAttribute(StyleConstants.Italic,Boolean.TRUE);
+ else if("underline".equals(key))
+ addAttribute(StyleConstants.Underline,Boolean.TRUE);
+ else if("fg".equals(key))
+ addAttribute(StyleConstants.Foreground,toColor((Cons)value));
+ else if("bg".equals(key))
+ addAttribute(StyleConstants.Background,toColor((Cons)value));
+ else if("font".equals(key))
+ addAttribute(StyleConstants.FontFamily,value);
+ else if("size".equals(key))
+ addAttribute(StyleConstants.FontSize,value);
+ } //}}}
+
+ //{{{ toColor() method
+ private Color toColor(Cons color)
+ {
+ Number r = (Number)color.car;
+ Number g = (Number)color.next().car;
+ Number b = (Number)color.next().next().car;
+ return new Color(r.intValue(),g.intValue(),b.intValue());
+ } //}}}
+}
--- /dev/null
+! :folding=indent:collapseFolds=1:
+
+! $Id$
+!
+! Copyright (C) 2004 Slava Pestov.
+!
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+!
+! 1. Redistributions of source code must retain the above copyright notice,
+! this list of conditions and the following disclaimer.
+!
+! 2. Redistributions in binary form must reproduce the above copyright notice,
+! this list of conditions and the following disclaimer in the documentation
+! and/or other materials provided with the distribution.
+!
+! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+IN: parser
+USE: errors
+USE: stack
+USE: combinators
+USE: stdio
+
+: eval-catch ( str -- )
+ [ eval ] [ [ default-error-handler drop ] when* ] catch ;
+
+: eval>string ( in -- out )
+ [ eval-catch ] with-string ;
: eval ( "X" -- X )
parse call ;
+: eval-catch ( str -- )
+ [ eval ] [ [ default-error-handler drop ] when* ] catch ;
+
: parse-number* ( str base -- num )
#! Convert a string to a number. Return f if conversion
#! fails.
"/library/platform/native/prettyprint.factor"
"/library/platform/native/files.factor"
"/library/files.factor"
+ "/library/eval-catch.factor"
"/library/tools/listener.factor"
"/library/tools/inspector.factor"
"/library/tools/word-tools.factor"
"/library/ansi.factor"
"/library/tools/telnetd.factor"
"/library/tools/inferior.factor"
+ "/library/tools/jedit-wire.factor"
"/library/platform/native/profiler.factor"
"/library/platform/native/heap-stats.factor"
"/library/platform/native/gensym.factor"
#! I/O or an explicit call to 'yield'.
[
schedule-thread
+ ! Clear stacks since we never go up from this point
+ { } set-catchstack
+ { } set-callstack
[
call
] [
"/library/test/io/binary.txt" <resource-stream>
[ read1 ] with-stream >fixnum
] unit-test
+
+! Make sure we use correct to_c_string form when writing
+[ ] [ "\0" write ] unit-test
! Test EOL comments in multiline strings.
[ [ "Hello" ] ] [ "#! This calls until-eol.\n\"Hello\"" parse ] unit-test
+
+[ 4 ] [ "2 2 +" eval-catch ] unit-test
+[ "4\n" ] [ "2 2 + ." eval>string ] unit-test
+[ ] [ "fdafdf" eval-catch ] unit-test
: exit ( -- )
"quit-flag" on ;
-: eval-catch ( str -- )
- [ eval ] [ [ default-error-handler drop ] when* ] catch ;
-
: listener-step ( -- )
print-prompt read [ eval-catch ] [ exit ] ifte* ;
/* untagged */
BYTE* to_c_string(STRING* s)
{
- STRING* _c_str = allot_string(s->capacity / CHARS + 1);
CELL i;
- BYTE* c_str = (BYTE*)(_c_str + 1);
-
for(i = 0; i < s->capacity; i++)
{
CHAR ch = string_nth(s,i);
if(ch == '\0' || ch > 255)
general_error(ERROR_C_STRING,tag_object(s));
- c_str[i] = string_nth(s,i);
}
+ return to_c_string_unchecked(s);
+}
+
+/* untagged */
+BYTE* to_c_string_unchecked(STRING* s)
+{
+ STRING* _c_str = allot_string(s->capacity / CHARS + 1);
+ CELL i;
+
+ BYTE* c_str = (BYTE*)(_c_str + 1);
+
+ for(i = 0; i < s->capacity; i++)
+ c_str[i] = string_nth(s,i);
+
c_str[s->capacity] = '\0';
return c_str;
void rehash_string(STRING* str);
STRING* grow_string(STRING* string, FIXNUM capacity, CHAR fill);
BYTE* to_c_string(STRING* s);
+BYTE* to_c_string_unchecked(STRING* s);
void box_c_string(const BYTE* c_string);
STRING* from_c_string(const BYTE* c_string);
BYTE* unbox_c_string(void);
if(!can_write(port,str->capacity))
io_error(__FUNCTION__);
- c_str = to_c_string(str);
+ c_str = to_c_string_unchecked(str);
write_string_raw(port,c_str,str->capacity);
}