assorted-commits Mailing List for Assorted projects (Page 57)
Brought to you by:
yangzhang
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(9) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(86) |
Feb
(265) |
Mar
(96) |
Apr
(47) |
May
(136) |
Jun
(28) |
Jul
(57) |
Aug
(42) |
Sep
(20) |
Oct
(67) |
Nov
(37) |
Dec
(34) |
2009 |
Jan
(39) |
Feb
(85) |
Mar
(96) |
Apr
(24) |
May
(82) |
Jun
(13) |
Jul
(10) |
Aug
(8) |
Sep
(2) |
Oct
(20) |
Nov
(31) |
Dec
(17) |
2010 |
Jan
(16) |
Feb
(11) |
Mar
(17) |
Apr
(53) |
May
(31) |
Jun
(13) |
Jul
(3) |
Aug
(6) |
Sep
(11) |
Oct
(4) |
Nov
(17) |
Dec
(17) |
2011 |
Jan
(3) |
Feb
(19) |
Mar
(5) |
Apr
(17) |
May
(3) |
Jun
(4) |
Jul
(14) |
Aug
(3) |
Sep
(2) |
Oct
(1) |
Nov
(3) |
Dec
(2) |
2012 |
Jan
(3) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
(4) |
Aug
(5) |
Sep
(2) |
Oct
(3) |
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
(9) |
Apr
(5) |
May
|
Jun
(2) |
Jul
(1) |
Aug
(10) |
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
(3) |
Mar
(3) |
Apr
(1) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2016 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <yan...@us...> - 2008-02-25 06:59:48
|
Revision: 502 http://assorted.svn.sourceforge.net/assorted/?rev=502&view=rev Author: yangzhang Date: 2008-02-24 22:59:54 -0800 (Sun, 24 Feb 2008) Log Message: ----------- tweak Modified Paths: -------------- cpp-commons/trunk/README Modified: cpp-commons/trunk/README =================================================================== --- cpp-commons/trunk/README 2008-02-25 06:54:07 UTC (rev 501) +++ cpp-commons/trunk/README 2008-02-25 06:59:54 UTC (rev 502) @@ -24,7 +24,7 @@ License ------- -The C++ Commons is released under the [GNU GPL 3]. +The C++ Commons is released under the [GNU GPL3]. Contact ------- @@ -43,7 +43,7 @@ [libstdc++]: http://gcc.gnu.org/libstdc++/ [nmstl]: http://nmstl.sourceforge.net/ -[GNU GPL 3]: http://www.gnu.org/licenses/gpl-3.0.txt +[GNU GPL3]: http://www.gnu.org/licenses/gpl-3.0.txt [Yang Zhang]: http://www.mit.edu/~y_z/ [assorted.sf.net]: http://assorted.sourceforge.net/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-25 06:54:12
|
Revision: 501 http://assorted.svn.sourceforge.net/assorted/?rev=501&view=rev Author: yangzhang Date: 2008-02-24 22:54:07 -0800 (Sun, 24 Feb 2008) Log Message: ----------- added eclipse projects Added Paths: ----------- java-reactor/trunk/src/.classpath java-reactor/trunk/src/.project Added: java-reactor/trunk/src/.classpath =================================================================== --- java-reactor/trunk/src/.classpath (rev 0) +++ java-reactor/trunk/src/.classpath 2008-02-25 06:54:07 UTC (rev 501) @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path=""/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="output" path="out"/> +</classpath> Added: java-reactor/trunk/src/.project =================================================================== --- java-reactor/trunk/src/.project (rev 0) +++ java-reactor/trunk/src/.project 2008-02-25 06:54:07 UTC (rev 501) @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>java-reactor</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-25 06:54:02
|
Revision: 500 http://assorted.svn.sourceforge.net/assorted/?rev=500&view=rev Author: yangzhang Date: 2008-02-24 22:53:56 -0800 (Sun, 24 Feb 2008) Log Message: ----------- added javadoc Modified Paths: -------------- java-reactor/trunk/src/reactor/Reactor.java java-reactor/trunk/src/reactor/ReactorHandler.java java-reactor/trunk/src/reactor/ReactorTask.java java-reactor/trunk/src/reactor/ReactorTest.java java-reactor/trunk/src/reactor/Session.java Modified: java-reactor/trunk/src/reactor/Reactor.java =================================================================== --- java-reactor/trunk/src/reactor/Reactor.java 2008-02-24 22:40:15 UTC (rev 499) +++ java-reactor/trunk/src/reactor/Reactor.java 2008-02-25 06:53:56 UTC (rev 500) @@ -10,87 +10,152 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; - +/** + * A simple select-based reactor for event-based asynchronous IO programming. It + * supports scheduling of events. + * + * @author yang + * + */ public class Reactor { - private final Selector selector; - private final List<Session> sessions = new ArrayList<Session>(); - private boolean doShutdown = false; - private final PriorityQueue<ReactorTask> tasks = new PriorityQueue<ReactorTask>(); + private final Selector selector; + private final List<Session> sessions = new ArrayList<Session>(); + private boolean doShutdown = false; + private final PriorityQueue<ReactorTask> tasks = new PriorityQueue<ReactorTask>(); - public Reactor() throws Exception { - selector = Selector.open(); - } + public Reactor() throws Exception { + selector = Selector.open(); + } - public Session register(InetSocketAddress remoteSa, - InetSocketAddress localSa, ReactorHandler handler) { - Session session = new Session(remoteSa, localSa, handler, sessions - .size(), selector); - sessions.add(session); - return session; - } + /** + * Register a new session (i.e. socket). Currently, remoteSa is ignored. It + * was intended for creating restricted datagram sockets, which have better + * performance but occupy a file descriptor each. + * + * @param remoteSa + * Ignored. + * @param localSa + * The local address and port to send/receive messages on. + * @param handler + * The handler for events on this socket. + * @return + */ + public Session register(InetSocketAddress remoteSa, + InetSocketAddress localSa, ReactorHandler handler) { + Session session = new Session(remoteSa, localSa, handler, selector); + sessions.add(session); + return session; + } - public void react() throws Exception { - while (true) { - if (doShutdown) - break; + /** + * The main reactor loop. This runs until the shutdown method is called. + * + * @throws Exception + */ + public void react() throws Exception { + while (true) { + if (doShutdown) + break; - int updated; - if (tasks.isEmpty()) { - updated = selector.select(); - } else { - long t = tasks.peek().getDelay(TimeUnit.MILLISECONDS); - updated = t > 0 ? selector.select(t) : 0; - } + int updated; + if (tasks.isEmpty()) { + updated = selector.select(); + } else { + long t = tasks.peek().getDelay(TimeUnit.MILLISECONDS); + updated = t > 0 ? selector.select(t) : 0; + } - if (updated > 0) { - Set<SelectionKey> keys = selector.selectedKeys(); - for (SelectionKey key : keys) { - if (key.isValid()) { - if (key.isReadable()) { - ((Session) key.attachment()).read(key); - } else if (key.isWritable()) { - ((Session) key.attachment()).write(key); - } - } - } - keys.clear(); - } else { - // TODO impose limit on # things to run at once (perhaps even - // specify costs) - while (!tasks.isEmpty() - && tasks.peek().getDelay(TimeUnit.MILLISECONDS) == 0L) { - ReactorTask task = tasks.remove(); - task.run(); - } - } - } - selector.close(); - } + if (updated > 0) { + Set<SelectionKey> keys = selector.selectedKeys(); + for (SelectionKey key : keys) { + if (key.isValid()) { + if (key.isReadable()) { + ((Session) key.attachment()).read(key); + } else if (key.isWritable()) { + ((Session) key.attachment()).write(key); + } + } + } + keys.clear(); + } else { + // TODO impose limit on # things to run at once (perhaps even + // specify costs) + while (!tasks.isEmpty() + && tasks.peek().getDelay(TimeUnit.MILLISECONDS) == 0L) { + ReactorTask task = tasks.remove(); + task.run(); + } + } + } + selector.close(); + } - public ScheduledFuture<?> schedule(Runnable r, long delay, TimeUnit units) { - ReactorTask task = new ReactorTask(r, System.currentTimeMillis() - + units.toMillis(delay), this); - tasks.add(task); - return task; - } + /** + * Schedule a task to occur after a delay. + * + * @param r + * The Runnable to be executed. + * @param delay + * The delay to sleep before running the task. + * @param units + * The time units that the delay is in. + * @return A ScheduledFuture representing the newly created task. + */ + public ScheduledFuture<?> schedule(Runnable r, long delay, TimeUnit units) { + ReactorTask task = new ReactorTask(r, System.currentTimeMillis() + + units.toMillis(delay), this); + tasks.add(task); + return task; + } - public ScheduledFuture<?> scheduleWithFixedDelay(final Runnable r, - final long initialDelay, final long delay, final TimeUnit units) { - return schedule(new Runnable() { - public void run() { - r.run(); - Reactor.this.schedule(this, delay, units); - } - }, initialDelay, units); - } + /** + * Schedule a task with a fixed delay. + * + * @param r + * The Runnable to be repeatedly executed. + * @param initialDelay + * The initial delay before the task is first run. + * @param delay + * The regular delay to sleep before rerunning the task. + * @param units + * The time units that the initialDelay and delay tasks are + * expressed in. + * @return A ScheduledFuture representing the newly created task. + */ + public ScheduledFuture<?> scheduleWithFixedDelay(final Runnable r, + final long initialDelay, final long delay, final TimeUnit units) { + return schedule(new Runnable() { + public void run() { + r.run(); + Reactor.this.schedule(this, delay, units); + } + }, initialDelay, units); + } - public boolean cancel(ReactorTask task) { - return tasks.remove(task); - } + /** + * Cancel a task. This is used as a callback from ReactorTask. Removes a + * task from the tasks queue. + * + * TODO: remove the return value and assert that the return value of the + * remove call is the task itself? + * + * @param task + * The task to be canceled. + * @return The result of the queue removal (either the task itself, or null + * if there was nothing to remove - which should never be the case). + */ + boolean cancel(ReactorTask task) { + return tasks.remove(task); + } - public void shutdown() { - doShutdown = true; - } + /** + * Stop a running reactor. Note that this is <em>not</em> thread-safe; the + * caller is expected to be executing in the same thread as the reactor + * (i.e. one of the reactor's handlers or tasks). + */ + public void shutdown() { + doShutdown = true; + } } Modified: java-reactor/trunk/src/reactor/ReactorHandler.java =================================================================== --- java-reactor/trunk/src/reactor/ReactorHandler.java 2008-02-24 22:40:15 UTC (rev 499) +++ java-reactor/trunk/src/reactor/ReactorHandler.java 2008-02-25 06:53:56 UTC (rev 500) @@ -3,9 +3,25 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; - +/** + * Handler for events pertaining to a socket (session). Currently there is only + * a single event, which is the reception of a packet. + * + * @author yang + * + */ public interface ReactorHandler { - public void handle(Session session, InetSocketAddress src, ByteBuffer buf); + /** + * Handle a received packet. + * + * @param session + * The session (socket) at which the packet was received. + * @param src + * The sender's socket address. + * @param buf + * The received packet. + */ + public void handle(Session session, InetSocketAddress src, ByteBuffer buf); } Modified: java-reactor/trunk/src/reactor/ReactorTask.java =================================================================== --- java-reactor/trunk/src/reactor/ReactorTask.java 2008-02-24 22:40:15 UTC (rev 499) +++ java-reactor/trunk/src/reactor/ReactorTask.java 2008-02-25 06:53:56 UTC (rev 500) @@ -8,88 +8,94 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException; +/** + * A task that was scheduled for execution in a reactor. + * + * @author yang + * + */ public class ReactorTask implements ScheduledFuture<Void> { - private final Runnable r; - private final long time; - private final Reactor reactor; + private final Runnable r; + private final long time; + private final Reactor reactor; - private static enum TaskState { - WAITING, RUNNING, DONE, CANCELLED - }; + private static enum TaskState { + WAITING, RUNNING, DONE, CANCELLED + }; - private TaskState state = TaskState.WAITING; + private TaskState state = TaskState.WAITING; - public ReactorTask(Runnable r, long time, Reactor reactor) { - this.r = r; - this.time = time; - this.reactor = reactor; - } + ReactorTask(Runnable r, long time, Reactor reactor) { + this.r = r; + this.time = time; + this.reactor = reactor; + } - public void run() { - if (state != TaskState.CANCELLED) { - assert state == TaskState.WAITING; - state = TaskState.RUNNING; - try { - r.run(); - } catch (Exception ex) { - } - state = TaskState.DONE; - } - } + void run() { + if (state != TaskState.CANCELLED) { + assert state == TaskState.WAITING; + state = TaskState.RUNNING; + try { + r.run(); + } catch (Exception ex) { + } + state = TaskState.DONE; + } + } - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - if (state == TaskState.WAITING) { - state = TaskState.CANCELLED; - boolean b = reactor.cancel(this); - assert b; - return true; - } else { - return false; - } - } + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (state == TaskState.WAITING) { + state = TaskState.CANCELLED; + boolean b = reactor.cancel(this); + assert b; + return true; + } else { + return false; + } + } - @Override - public Void get() throws InterruptedException, ExecutionException { - // TODO is this correct? - return null; - } + @Override + public Void get() throws InterruptedException, ExecutionException { + // TODO is this correct? + return null; + } - @Override - public Void get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - throw new NotImplementedException(); - } + @Override + public Void get(long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, TimeoutException { + throw new NotImplementedException(); + } - @Override - public boolean isCancelled() { - return state == TaskState.CANCELLED; - } + @Override + public boolean isCancelled() { + return state == TaskState.CANCELLED; + } - @Override - public boolean isDone() { - return state == TaskState.DONE; - } + @Override + public boolean isDone() { + return state == TaskState.DONE; + } - @Override - public long getDelay(TimeUnit units) { - long delay = time - System.currentTimeMillis(); - return delay > 0 ? TimeUnit.MILLISECONDS.convert(delay, units) : 0; - } + @Override + public long getDelay(TimeUnit units) { + long delay = time - System.currentTimeMillis(); + return delay > 0 ? TimeUnit.MILLISECONDS.convert(delay, units) : 0; + } - @Override - public int compareTo(Delayed o) { - if (false && o instanceof ReactorTask) { - ReactorTask other = (ReactorTask) o; - System.out.println(time + " vs " + other.time + " " - + getDelay(TimeUnit.MILLISECONDS) + " vs " - + other.getDelay(TimeUnit.MILLISECONDS)); - return Long.valueOf(time).compareTo(other.time); - } else { - return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo( - o.getDelay(TimeUnit.MILLISECONDS)); - } - } + @Override + public int compareTo(Delayed o) { + if (false && o instanceof ReactorTask) { + ReactorTask other = (ReactorTask) o; + System.out.println(time + " vs " + other.time + " " + + getDelay(TimeUnit.MILLISECONDS) + " vs " + + other.getDelay(TimeUnit.MILLISECONDS)); + return Long.valueOf(time).compareTo(other.time); + } else { + return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo( + o.getDelay(TimeUnit.MILLISECONDS)); + } + } } Modified: java-reactor/trunk/src/reactor/ReactorTest.java =================================================================== --- java-reactor/trunk/src/reactor/ReactorTest.java 2008-02-24 22:40:15 UTC (rev 499) +++ java-reactor/trunk/src/reactor/ReactorTest.java 2008-02-25 06:53:56 UTC (rev 500) @@ -9,7 +9,11 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - +/** + * A simple test for the reactor.s + * @author yang + * + */ public class ReactorTest { ExecutorService e; Modified: java-reactor/trunk/src/reactor/Session.java =================================================================== --- java-reactor/trunk/src/reactor/Session.java 2008-02-24 22:40:15 UTC (rev 499) +++ java-reactor/trunk/src/reactor/Session.java 2008-02-25 06:53:56 UTC (rev 500) @@ -10,112 +10,160 @@ import java.util.ArrayList; import java.util.List; - +/** + * Represents a "session," which is probably a bad name for what is basically a + * wrapper around a datagram socket. + * + * @author yang + * + */ public class Session { - public final DatagramChannel channel; - public final ReactorHandler handler; - public final InetSocketAddress remoteSa, localSa; - public final int index; - // public final ByteBuffer readBuf = ByteBuffer.allocate(4096); - public final ByteBuffer readBuf = ByteBuffer.allocateDirect(4096); - public final List<ByteBuffer> pendingWrites = new ArrayList<ByteBuffer>(); + private final DatagramChannel channel; + private final ReactorHandler handler; + private final InetSocketAddress remoteSa; + private final ByteBuffer readBuf = ByteBuffer.allocateDirect(4096); + private final List<ByteBuffer> pendingWrites = new ArrayList<ByteBuffer>(); - public Session(InetSocketAddress remoteSa, InetSocketAddress localSa, - ReactorHandler handler, int index, Selector selector) { - this.handler = handler; - this.remoteSa = remoteSa; - this.localSa = localSa; - this.index = index; + /** + * Construct a new Session object. + * + * @param remoteSa + * Ignored. + * @param localSa + * The local socket address on which to send/receive packets. + * @param handler + * The handler for events on this socket. + * @param selector + * The selector that is used in the current reactor. + */ + Session(InetSocketAddress remoteSa, InetSocketAddress localSa, + ReactorHandler handler, Selector selector) { + this.handler = handler; + this.remoteSa = remoteSa; - try { - channel = DatagramChannel.open(); - channel.configureBlocking(false); - DatagramSocket socket = channel.socket(); - socket.setReuseAddress(true); - if (localSa != null) - socket.bind(localSa); - if (remoteSa != null) - channel.connect(remoteSa); + try { + channel = DatagramChannel.open(); + channel.configureBlocking(false); + DatagramSocket socket = channel.socket(); + socket.setReuseAddress(true); + if (localSa != null) + socket.bind(localSa); + if (remoteSa != null) + channel.connect(remoteSa); - channel.register(selector, SelectionKey.OP_READ, this); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } + channel.register(selector, SelectionKey.OP_READ, this); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } - // read messages is the priority - public void read(SelectionKey key) throws Exception { - while (true) { - try { - InetSocketAddress srcSa; + /** + * This is called by the reactor when there is a message to be received. + * Reading messages is the priority, so this is done before anything else. + * + * @param key + * The key into the selector's socket set representing our + * socket. + * @throws Exception + */ + void read(SelectionKey key) throws Exception { + while (true) { + try { + InetSocketAddress srcSa; - if (remoteSa == null) { - srcSa = (InetSocketAddress) channel.receive(readBuf); - } else { - int numRead = channel.read(readBuf); - if (numRead == -1) { - // Remote entity shut the socket down - // cleanly. - // Do - // the same from our end and cancel the - // channel. - key.channel().close(); - key.cancel(); - } - // TODO also handle numRead == 0 - srcSa = remoteSa; - } + if (remoteSa == null) { + srcSa = (InetSocketAddress) channel.receive(readBuf); + } else { + int numRead = channel.read(readBuf); + if (numRead == -1) { + // Remote entity shut the socket down + // cleanly. + // Do + // the same from our end and cancel the + // channel. + key.channel().close(); + key.cancel(); + } + // TODO also handle numRead == 0 + srcSa = remoteSa; + } - if (srcSa == null) { - break; - } + if (srcSa == null) { + break; + } - // after channel wrote to buf, set lim = pos, then pos = 0 - readBuf.flip(); - // callback - handler.handle(this, srcSa, readBuf); - // recycle buffer - readBuf.clear(); - } catch (IOException e) { - // The remote forcibly closed the connection, cancel - // the selection key and close the channel. - key.cancel(); - channel.close(); - } - } - } + // after channel wrote to buf, set lim = pos, then pos = 0 + readBuf.flip(); + // callback + handler.handle(this, srcSa, readBuf); + // recycle buffer + readBuf.clear(); + } catch (IOException e) { + // The remote forcibly closed the connection, cancel + // the selection key and close the channel. + key.cancel(); + channel.close(); + } + } + } - public void write(SelectionKey key) throws Exception { - // Write until there's not more data ... - while (!pendingWrites.isEmpty()) { - ByteBuffer buf = (ByteBuffer) pendingWrites.get(0); - channel.write(buf); - if (buf.remaining() > 0) { - // ... or the socket's buffer fills up - break; - } - pendingWrites.remove(0); - } + /** + * Handle the event where the socket is ready to be written. This is + * currently not used since the send() method blindly writes immediately to + * the socket - which is bad. + * + * @param key + * The key into the selector's socket set that represents our + * socket. + * @throws Exception + */ + void write(SelectionKey key) throws Exception { + // Write until there's not more data ... + while (!pendingWrites.isEmpty()) { + ByteBuffer buf = (ByteBuffer) pendingWrites.get(0); + channel.write(buf); + if (buf.remaining() > 0) { + // ... or the socket's buffer fills up + break; + } + pendingWrites.remove(0); + } - if (pendingWrites.isEmpty()) { - // We wrote away all data, so we're no longer - // interested - // in writing on this socket. Switch back to waiting - // for - // data. - key.interestOps(SelectionKey.OP_READ); - } - } + if (pendingWrites.isEmpty()) { + // We wrote away all data, so we're no longer + // interested + // in writing on this socket. Switch back to waiting + // for + // data. + key.interestOps(SelectionKey.OP_READ); + } + } - public void send(ByteBuffer writeBuf, InetSocketAddress dst) - throws Exception { - int bytes = channel.send(writeBuf, dst); - assert bytes == writeBuf.limit(); - } + /** + * Send messages from this socket. This does not enqueue anything onto the + * internal pendingWrites buffer if the socket's buffer is full, but instead + * triggers an assertion failure. + * + * @param writeBuf + * The packet to be sent. + * @param dst + * The destination socket address. + * @throws Exception + */ + public void send(ByteBuffer writeBuf, InetSocketAddress dst) + throws Exception { + int bytes = channel.send(writeBuf, dst); + assert bytes == writeBuf.limit(); + } - public void close() throws Exception { - channel.close(); - } + /** + * Close the underlying socket. + * + * @throws Exception + */ + public void close() throws Exception { + channel.close(); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 22:40:10
|
Revision: 499 http://assorted.svn.sourceforge.net/assorted/?rev=499&view=rev Author: yangzhang Date: 2008-02-24 14:40:15 -0800 (Sun, 24 Feb 2008) Log Message: ----------- minor updates to readme Modified Paths: -------------- simple-build/trunk/README Modified: simple-build/trunk/README =================================================================== --- simple-build/trunk/README 2008-02-24 20:48:14 UTC (rev 498) +++ simple-build/trunk/README 2008-02-24 22:40:15 UTC (rev 499) @@ -139,7 +139,9 @@ database came from here. - [CMake]: Cross-platform `make`. Uses its own quirky scripting language and - has quite a few features. I should probably target this. + has quite a few features. I should probably target this. ["Why the KDE + project switched to CMake"] is a nice article on CMake (vs. auto* and SCons). + I've been using CMake as well. - [WAF]: An even simpler/more barren build system. You actually write imperative scripts for each build you need. A bit scary. @@ -170,6 +172,7 @@ [YAML]: http://yaml.org/ [automatically generating dependencies]: http://make.paulandlesley.org/autodep.html ["Recursive Make Considered Harmful"]: http://miller.emu.id.au/pmiller/books/rmch/ +["Why the KDE project switched to CMake"]: http://lwn.net/Articles/188693/ [ANT]: http://ant.apache.org/ [Boost.Build]: http://boost.org/boost-build2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 20:48:10
|
Revision: 498 http://assorted.svn.sourceforge.net/assorted/?rev=498&view=rev Author: yangzhang Date: 2008-02-24 12:48:14 -0800 (Sun, 24 Feb 2008) Log Message: ----------- added a bunch of information to the readme Modified Paths: -------------- simple-build/trunk/README Modified: simple-build/trunk/README =================================================================== --- simple-build/trunk/README 2008-02-24 20:47:57 UTC (rev 497) +++ simple-build/trunk/README 2008-02-24 20:48:14 UTC (rev 498) @@ -1,12 +1,16 @@ +% SimpleBuild +% Yang Zhang + Overview -------- -Keep your builds as simple as possible. Never repeat yourself. Separation of -rules from declared goals. - Eventually aims to be a complete solution for software configuration, building, installation and distribution. +Some vague principles: keep your build configurations as tiny as possible. +Leverage/target existing build and package systems. Lots of features. +Extensibility. Portability. Cross-language. Cross-project. Etc. + Current features: - out-of-the-box support for C, C++, Java, Scala @@ -19,7 +23,49 @@ my case, the culprits are often C++ Commons, Scala Commons, etc.) - automatic library specification by checking headers against well-known header-to-library mappings +- in-place or out-of-place builds +Requirements +------------ + +- [JYaml] 1.3 + +Examples +-------- + +Say the directory `~/myapp/` contains two C++ programs: `client.cc` and +`server.cc`. To build these with SimpleBuild, create a file called `build` +containing the following [YAML] data: + + client: + srcs: [client.cc] + + server: + srcs: [server.cc] + libs: [pthread, profiler] + +Now running `simple-build` generates a `GNUmakefile` that can be used to +compile both programs in a variety of ways. We could alternatively keep the +source tree clean of generated files by changing to a different directory and +running `simple-build ~/myapp/build`. + +The `libs` field lists libraries that are to be linked with the application. +`simple-build` is also capable of inferring libraries by automatically +determining the headers included by your source files and then mapping these +onto library names. + +The `GNUmakefile` also contains a mechanism for [automatically generating +dependencies] from your source files. This mechanism relies on `gcc -M` and +some GNU `make` tricks. I also take other cues from Peter Miller's excellent +paper ["Recursive Make Considered Harmful"]. + +This automatic dependency generation is also available for Java and Scala; the +mechanism there relies on the compilers' verbose output, and has only been +tested with Sun's `javac`. + +Todo +---- + Planned features: - software deployment @@ -43,8 +89,100 @@ - DART/cmake for C/C++ - somehow merge with simple-setup (generate simple-setup files too?) - support on other platforms (e.g. pthread -> thr on BSD) +- look into: + - [precompiled headers] + - [lzz], [preprocess] + - [autodepend] +- selective target specification: enable configuration of rules (esp. `all`) to + build only certain targets that the user is interested in (currently all + configurations of all programs are built) -Requirements +Related Work ------------ -- jyaml-1.3.jar +The decision to write yet another build system was based on the empty-handed +outcome of a long (and depressing) quest. Here are brief commentaries of some +other build systems. + +- [autotools]: The de-facto standard for portable source distributions, but + writing portable, meaningful `configure.ac` scripts requires a lot of care, + which doesn't suit well the frequent one-off programs I write. Also, + `autotools` doesn't do much for Java or Scala. The aspiration for SimpleBuild + is to one day be able to generate `autotools` inputs (as well as other kinds + of software packaging). + +- [Boost.Build]: A system for building C++ projects. Documentation hints that + it is capable of discovering transitive dependencies as well. This seems like + the closest thing to what I wanted. + +- [GNU `make`]: Currently, SimpleBuild targets only `make`. + +- [ANT]: A portable, "cleaner" version of `make`. Where `make` relies on shell + commands for its actions, ANT relies on actions implemented in Java (either + built-in or provided by extensions). Also, ANT does not by default (i.e., + all targets are "phony"). It is also rid of other `make` idiosyncracies + (syntax, whitespace values, etc.). + +- [Maven]: Much more than a build system, Maven tries to cover everything + related to the general maintenance of software with attention to + cross-project maintenance, and is even a standard way of publishing and + obtaining software. A number of plug-ins (also automatically obtained) take + care of continuous builds, testing, and integration, all presented in a + cohesive dashboard interface. It requires the project follow certain + conventions (e.g. in file organization), but this turns out to be reasonable + for most projects. Again, Maven is not as meaningful for one-off Scala + scripts ([Scala Maven tools] do exist, BTW), but this is where I hope to take + `SimpleBuild` someday. + +- [clump]: A way to build C programs without any build configuration file + whatsoever. The idea of automatic library inference via a header-to-library + database came from here. + +- [CMake]: Cross-platform `make`. Uses its own quirky scripting language and + has quite a few features. I should probably target this. + +- [WAF]: An even simpler/more barren build system. You actually write + imperative scripts for each build you need. A bit scary. + +- [DART]: Somewhat like Maven but for C++, providing a tests/reports/dashboards + for monitoring the status of projects. From the same people behind CMake. + +- [SCons]: For building C, C++, Java, and more. Very minimalistic in its + approach, and imposes (even defines well) few abstractions. It doesn't have + many features. + +- [buildr]: A drop-in replacement for Maven written in Ruby. Supports Scala, + apparently. + +- [rake]: SCons in Ruby. + +- [rant]: Ant in Ruby. + +- [SAnt]: Ant in Scala (abandoned). + +[jyaml]: http://jyaml.sourceforge.net/ + +[precompiled headers]: http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html +[lzz]: http://www.lazycplusplus.com/ +[preprocess]: http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/ +[autodepend]: http://autodepend.sourceforge.net/ + +[YAML]: http://yaml.org/ +[automatically generating dependencies]: http://make.paulandlesley.org/autodep.html +["Recursive Make Considered Harmful"]: http://miller.emu.id.au/pmiller/books/rmch/ + +[ANT]: http://ant.apache.org/ +[Boost.Build]: http://boost.org/boost-build2/ +[CMake]: http://www.cmake.org/ +[DART]: http://www.itk.org/Dart/HTML/Index.html +[GNU `make`]: http://www.gnu.org/software/make/ +[Maven]: http://maven.apache.org/ +[SAnt]: http://code.google.com/p/sant/ +[SCons]: http://www.scons.org/ +[Scala Maven tools]: http://scala-tools.org/ +[WAF]: http://code.google.com/p/waf/ +[autotools]: http://sources.redhat.com/autobook/ +[buildr]: http://incubator.apache.org/buildr/ +[clump]: http://www.fexl.com/clump/ +[rake]: http://rake.rubyforge.org/ +[rant]: http://rant.rubyforge.org/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 20:47:52
|
Revision: 497 http://assorted.svn.sourceforge.net/assorted/?rev=497&view=rev Author: yangzhang Date: 2008-02-24 12:47:57 -0800 (Sun, 24 Feb 2008) Log Message: ----------- fixed some out-of-place build bugs Modified Paths: -------------- simple-build/trunk/src/SimpleBuild.scala simple-build/trunk/src/build-templates/cpp Modified: simple-build/trunk/src/SimpleBuild.scala =================================================================== --- simple-build/trunk/src/SimpleBuild.scala 2008-02-24 07:17:57 UTC (rev 496) +++ simple-build/trunk/src/SimpleBuild.scala 2008-02-24 20:47:57 UTC (rev 497) @@ -31,6 +31,8 @@ */ val basedir = System getenv "SIMPLEBUILD" + var srcdir: String = _ + /** * Mapping from file extensions to language IDs. */ @@ -119,7 +121,7 @@ object NativeEmitter extends MakeEmitter { def emitMake(target: YamlStr, attrs: YamlMap, aggs: MultiMap[String,String]) = { val srcs = attrs.m(YamlStr("srcs")).xs - val autolibs = autoscan(Set(srcs map (_.s):_*)) + val autolibs = autoscan(Set(srcs map (srcdir/_.s):_*)) val lang = ext2lang(srcs(0).s.extension) val template = loadTemplate("cpp") val struct = structs(lang) @@ -270,7 +272,7 @@ val rawfname = if (args.length > 0) args(0) else "build" val infile = new File(rawfname).getCanonicalFile val fname = infile.getPath - val srcdir = infile.getParent + srcdir = infile.getParent // Read build file. val contents = doOrDie { using (TextReader(fname)) (_.read) Modified: simple-build/trunk/src/build-templates/cpp =================================================================== --- simple-build/trunk/src/build-templates/cpp 2008-02-24 07:17:57 UTC (rev 496) +++ simple-build/trunk/src/build-templates/cpp 2008-02-24 20:47:57 UTC (rev 497) @@ -22,19 +22,19 @@ $(EXE): $(OBJS) $(COMPILER) $(LDFLAGS) -o $@ $^ -$(OBJDIR)/%.o: %.c +$(OBJDIR)/%.o: $(SRCDIR)/%.c mkdir -p $(@D) $(CC) $(CPPFLAGS) $(CFLAGS) -MD -c -o $@ $< -$(OBJDIR)/%.o: %.cc +$(OBJDIR)/%.o: $(SRCDIR)/%.cc mkdir -p $(@D) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< -$(OBJDIR)/%.o: %.cpp +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp mkdir -p $(@D) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< -$(OBJDIR)/%.o: %.cxx +$(OBJDIR)/%.o: $(SRCDIR)/%.cxx mkdir -p $(@D) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 07:17:54
|
Revision: 496 http://assorted.svn.sourceforge.net/assorted/?rev=496&view=rev Author: yangzhang Date: 2008-02-23 23:17:57 -0800 (Sat, 23 Feb 2008) Log Message: ----------- folded in sbw's .emacs Modified Paths: -------------- configs/trunk/src/emacs/yang.el Modified: configs/trunk/src/emacs/yang.el =================================================================== --- configs/trunk/src/emacs/yang.el 2008-02-24 07:00:01 UTC (rev 495) +++ configs/trunk/src/emacs/yang.el 2008-02-24 07:17:57 UTC (rev 496) @@ -259,6 +259,17 @@ ;; }}} +;; modes {{{ + +(defun linux-c-mode () + "C mode with adjusted defaults for use with the Linux kernel." + (interactive) + (c-mode) + (c-set-style "K&R") + (setq c-basic-offset 8)) + +;; }}} + ;; commands {{{ ;; TODO fill-line @@ -316,6 +327,31 @@ ;;; TODO how to fix this? ;;(global-set-key "\C-%" 'match-paren) +;; Silas' simple match-paren +;(defun match-paren (arg) +; "Go to the matching paren if on a paren" +; (interactive "p") +; (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1)) +; ((looking-at "\\s\)") (forward-char 1) (backward-list 1)) +; (t (message "no paren under cursor")))) + +(defun forward-open-curly () + (interactive) + (forward-char) (search-forward "{" nil t) (backward-char)) +(defun forward-closed-curly () + (interactive) + (forward-char) (search-forward "}" nil t) (backward-char)) +(defun backward-open-curly () + (interactive) + (backward-char) + (if (equal nil (search-backward "{" nil t)) + (forward-char))) +(defun backward-closed-curly () + (interactive) + (backward-char) + (if (equal nil (search-backward "}" nil t)) + (forward-char))) + ;; }}} ;; macros {{{ @@ -328,10 +364,27 @@ ;; key bindings {{{ +(global-set-key "C-xj" 'compile) (global-set-key [f5] 'goto-line) (global-set-key "\C-ha" 'apropos) (global-set-key (kbd "C-c j") 'join-lines) +;; Silas' key bindings + +;(global-set-key "\e[1;5A" 'backward-paragraph) ;; C-up +;(global-set-key "\e[1;5B" 'forward-paragraph) ;; C-down +;(global-set-key "\e[1;5C" 'forward-word) ;; C-right +;(global-set-key "\e[1;5D" 'backward-word) ;; C-left +; +;(global-set-key "\e[1;5H" 'backward-open-curly) ;; C-home +;(global-set-key "\e[5;5~" 'backward-closed-curly) ;; C-pageup +;(global-set-key "\e[1;5F" 'forward-open-curly) ;; C-pageup +;(global-set-key "\e[6;5~" 'forward-closed-curly) ;; C-pageup +;(global-set-key [f11] 'shrink-window-horizontally) +;(global-set-key [f12] 'enlarge-window-horizontally) +; +;(global-set-key "\e[2;5~" 'indent-relative-maybe) + ;; TODO make the following scroll without moving the cursor ;(defun scroll-up-one (arg) @@ -354,11 +407,10 @@ ;; options {{{ -;; TODO what's the default? ;; TODO make work in XEmacs ;; default to better frame titles -;(setq frame-title-format -; (concat "%b - emacs@" system-name)) +(setq frame-title-format + (concat "%b - emacs@" system-name)) ;; enable word wrapping (add-hook 'text-mode-hook 'turn-on-auto-fill) @@ -374,11 +426,22 @@ ;; expand tabs into spaces (setq-default indent-tabs-mode nil) +(setq-default fill-column 80) +;; auto fill +(setq-default auto-fill-function 'do-auto-fill) + +;; tab, indent dimensions +(setq-default c-basic-offset 4) +(setq-default tab-width 4) + +;; Make lines wrap automatically in text mode. +;;(add-hook 'text-mode-hook +;;'(lambda () (auto-fill-mode 1))) + ;; larger default font ;(set-face-font 'default "9x15") -;; TODO what does this do? ;; default to unified diffs (setq diff-switches "-u") @@ -477,6 +540,26 @@ +;; Silas' custom set variables + +;(custom-set-variables +; ;; custom-set-variables was added by Custom -- don't edit or cut/paste it! +; ;; Your init file should contain only one such instance. +; '(auto-compression-mode t nil (jka-compr)) +; '(case-fold-search t) +; '(current-language-environment "UTF-8") +; '(default-input-method "rfc1345") +; '(global-font-lock-mode t nil (font-lock)) +; '(hl-line-face (quote highlight)) +; '(show-paren-mode t nil (paren)) +; '(transient-mark-mode t)) +;(custom-set-faces +; ;; custom-set-faces was added by Custom -- don't edit or cut/paste it! +; ;; Your init file should contain only one such instance. +; '(highlight ((((type tty) (class color)) (:underline t))))) + + + ;;;(setq default-frame-alist '((background-color . "white")) ;;; font-lock-face-attributes ;;; '((font-lock-comment-face "Sienna") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:59:56
|
Revision: 495 http://assorted.svn.sourceforge.net/assorted/?rev=495&view=rev Author: yangzhang Date: 2008-02-23 23:00:01 -0800 (Sat, 23 Feb 2008) Log Message: ----------- minor note Modified Paths: -------------- simple-build/trunk/README Modified: simple-build/trunk/README =================================================================== --- simple-build/trunk/README 2008-02-24 06:57:52 UTC (rev 494) +++ simple-build/trunk/README 2008-02-24 07:00:01 UTC (rev 495) @@ -42,6 +42,7 @@ - maven for Java/Scala - DART/cmake for C/C++ - somehow merge with simple-setup (generate simple-setup files too?) +- support on other platforms (e.g. pthread -> thr on BSD) Requirements ------------ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:57:49
|
Revision: 494 http://assorted.svn.sourceforge.net/assorted/?rev=494&view=rev Author: yangzhang Date: 2008-02-23 22:57:52 -0800 (Sat, 23 Feb 2008) Log Message: ----------- cleanup Modified Paths: -------------- nano-httpd/trunk/src/nanohttpd.cc Modified: nano-httpd/trunk/src/nanohttpd.cc =================================================================== --- nano-httpd/trunk/src/nanohttpd.cc 2008-02-24 06:56:42 UTC (rev 493) +++ nano-httpd/trunk/src/nanohttpd.cc 2008-02-24 06:57:52 UTC (rev 494) @@ -1,17 +1,6 @@ -// Derived from: +// See also: // // http://www.jbox.dk/sanos/webserver.htm -// -// Example HTTP request -// -// GET / HTTP/1.1 -// User-Agent: Opera/9.25 (Windows NT 5.1; U; en) -// Host: harvard:8000 -// Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 -// Accept-Language: en-US,en;q=0.9 -// Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1 -// Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 -// Connection: Keep-Alive #define STANDALONE 1 @@ -63,22 +52,11 @@ void send_headers(int f, int status, char *title, char *extra, char *mime, int length, int date) { - //time_t now; - //char timebuf[128]; - nprintf(f, "%s %d %s\r\n", PROTOCOL, status, title); nprintf(f, "Server: %s\r\n", SERVER); - //now = time(NULL); - //strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); - //nprintf(f, "Date: %s\r\n", timebuf); if (extra) nprintf(f, "%s\r\n", extra); if (mime) nprintf(f, "Content-Type: %s\r\n", mime); if (length >= 0) nprintf(f, "Content-Length: %d\r\n", length); - //if (date != -1) - //{ - // strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&date)); - // nprintf(f, "Last-Modified: %s\r\n", timebuf); - //} nprintf(f, "Connection: close\r\n"); nprintf(f, "\r\n"); } @@ -92,26 +70,11 @@ nprintf(f, "</BODY></HTML>\r\n"); } -// XXX void send_file(int f, char *path) { char msg[] = "hello, world!\n"; send_headers(f, 200, "OK", NULL, "text/plain", sizeof(msg), -1); if (lwip_send(f, msg, sizeof(msg), 0) == -1) panic("XXX"); -// char data[4096]; -// int n; -// -// FILE *file = fopen(path, "r"); -// if (!file) -// send_error(f, 403, "Forbidden", NULL, "Access denied."); -// else -// { -// int length = S_ISREG(statbuf->st_mode) ? statbuf->st_size : -1; -// send_headers(f, 200, "OK", NULL, get_mime_type(path), length, statbuf->st_mtime); -// -// while ((n = fread(data, 1, sizeof(data), file)) > 0) fwrite(data, 1, n, f); -// fclose(file); -// } } int @@ -121,9 +84,6 @@ char *method; char *path; char *protocol; -// struct stat statbuf; -// char pathbuf[4096]; -// int len; if (lwip_recv(f, buf, sizeof(buf), 0) < 0) return -1; printf("URL: %s", buf); @@ -135,61 +95,6 @@ if (strcasecmp(method, "GET") != 0) send_error(f, 501, "Not supported", NULL, "Method is not supported."); -// else if (stat(path, &statbuf) < 0) -// send_error(f, 404, "Not Found", NULL, "File not found."); -// else if (S_ISDIR(statbuf.st_mode)) -// { -// len = strlen(path); -// if (len == 0 || path[len - 1] != '/') -// { -// snprintf(pathbuf, sizeof(pathbuf), "Location: %s/", path); -// send_error(f, 302, "Found", pathbuf, "Directories must end with a slash."); -// } -// else -// { -// snprintf(pathbuf, sizeof(pathbuf), "%sindex.html", path); -// if (stat(pathbuf, &statbuf) >= 0) -// send_file(f, pathbuf, &statbuf); -// else -// { -// DIR *dir; -// struct dirent *de; -// -// send_headers(f, 200, "OK", NULL, "text/html", -1, statbuf.st_mtime); -// nprintf(f, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\r\n<BODY>", path); -// nprintf(f, "<H4>Index of %s</H4>\r\n<PRE>\n", path); -// nprintf(f, "Name Last Modified Size\r\n"); -// nprintf(f, "<HR>\r\n"); -// if (len > 1) nprintf(f, "<A HREF=\"..\">..</A>\r\n"); -// -// dir = opendir(path); -// while ((de = readdir(dir)) != NULL) -// { -// char timebuf[32]; -// struct tm *tm; -// -// strcpy(pathbuf, path); -// strcat(pathbuf, de->d_name); -// -// stat(pathbuf, &statbuf); -// tm = gmtime(&statbuf.st_mtime); -// strftime(timebuf, sizeof(timebuf), "%d-%b-%Y %H:%M:%S", tm); -// -// nprintf(f, "<A HREF=\"%s%s\">", de->d_name, S_ISDIR(statbuf.st_mode) ? "/" : ""); -// nprintf(f, "%s%s", de->d_name, S_ISDIR(statbuf.st_mode) ? "/</A>" : "</A> "); -// if (de->d_namlen < 32) nprintf(f, "%*s", 32 - de->d_namlen, ""); -// -// if (S_ISDIR(statbuf.st_mode)) -// nprintf(f, "%s\r\n", timebuf); -// else -// nprintf(f, "%s %10d\r\n", timebuf, statbuf.st_size); -// } -// closedir(dir); -// -// nprintf(f, "</PRE>\r\n<HR>\r\n<ADDRESS>%s</ADDRESS>\r\n</BODY></HTML>\r\n", SERVER); -// } -// } -// } else send_file(f, path); // , &statbuf); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:56:36
|
Revision: 493 http://assorted.svn.sourceforge.net/assorted/?rev=493&view=rev Author: yangzhang Date: 2008-02-23 22:56:42 -0800 (Sat, 23 Feb 2008) Log Message: ----------- added mini test Added Paths: ----------- nano-httpd/trunk/src/test.bash Added: nano-httpd/trunk/src/test.bash =================================================================== --- nano-httpd/trunk/src/test.bash (rev 0) +++ nano-httpd/trunk/src/test.bash 2008-02-24 06:56:42 UTC (rev 493) @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +nc localhost 8000 << EOF +GET / HTTP/1.1 +User-Agent: Opera/9.25 (Windows NT 5.1; U; en) +Host: harvard:8000 +Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 +Accept-Language: en-US,en;q=0.9 +Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1 +Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 +Connection: Keep-Alive +EOF Property changes on: nano-httpd/trunk/src/test.bash ___________________________________________________________________ Name: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:56:19
|
Revision: 492 http://assorted.svn.sourceforge.net/assorted/?rev=492&view=rev Author: yangzhang Date: 2008-02-23 22:56:24 -0800 (Sat, 23 Feb 2008) Log Message: ----------- moved to simple-build Added Paths: ----------- nano-httpd/trunk/src/build Removed Paths: ------------- nano-httpd/trunk/src/Makefile Deleted: nano-httpd/trunk/src/Makefile =================================================================== --- nano-httpd/trunk/src/Makefile 2008-02-24 06:53:43 UTC (rev 491) +++ nano-httpd/trunk/src/Makefile 2008-02-24 06:56:24 UTC (rev 492) @@ -1,8 +0,0 @@ -all: nanohttpd -nanohttpd: nanohttpd.cc - g++ -Wall -g3 -o $@ $< -run: nanohttpd - ./nanohttpd -clean: - rm -f nanohttpd -.PHONY: clean run Added: nano-httpd/trunk/src/build =================================================================== --- nano-httpd/trunk/src/build (rev 0) +++ nano-httpd/trunk/src/build 2008-02-24 06:56:24 UTC (rev 492) @@ -0,0 +1,2 @@ +nanohttpd: + srcs: [nanohttpd.cc] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:53:38
|
Revision: 491 http://assorted.svn.sourceforge.net/assorted/?rev=491&view=rev Author: yangzhang Date: 2008-02-23 22:53:43 -0800 (Sat, 23 Feb 2008) Log Message: ----------- fixed simple-build Modified Paths: -------------- numa-bench/trunk/src/build Modified: numa-bench/trunk/src/build =================================================================== --- numa-bench/trunk/src/build 2008-02-24 06:52:53 UTC (rev 490) +++ numa-bench/trunk/src/build 2008-02-24 06:53:43 UTC (rev 491) @@ -1,6 +1,8 @@ malloc: srcs: [malloc.cc] + libs: [pthread] avail: srcs: [avail.cc] + libs: [pthread] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:52:49
|
Revision: 490 http://assorted.svn.sourceforge.net/assorted/?rev=490&view=rev Author: yangzhang Date: 2008-02-23 22:52:53 -0800 (Sat, 23 Feb 2008) Log Message: ----------- moved to simple-build Added Paths: ----------- numa-bench/trunk/src/build Removed Paths: ------------- numa-bench/trunk/src/Makefile Deleted: numa-bench/trunk/src/Makefile =================================================================== --- numa-bench/trunk/src/Makefile 2008-02-24 06:49:38 UTC (rev 489) +++ numa-bench/trunk/src/Makefile 2008-02-24 06:52:53 UTC (rev 490) @@ -1,34 +0,0 @@ -COMMONS := $(wildcard commons/*.h) -CXX = g++-4.2 -O3 -I. -lnuma -lpthread -o $@ $< - -# all: avail cache malloc threads -all: malloc - -avail: avail.cc $(COMMONS) - $(CXX) - -cache: cache.cc $(COMMONS) - $(CXX) - -malloc-dbg: malloc.cc $(COMMONS) - $(CXX) -g3 -O0 - -malloc: malloc.cc $(COMMONS) - $(CXX) - -threads: threads.cc $(COMMONS) - $(CXX) - -custom_alloc: custom_alloc.cc - $(CXX) - -openmp: openmp.cc - $(CXX) -fopenmp - -bthreads: bthreads.cc - $(CXX) -lboost_thread-gcc41-mt - -clean: - rm -f avail cache - -.PHONY: clean Added: numa-bench/trunk/src/build =================================================================== --- numa-bench/trunk/src/build (rev 0) +++ numa-bench/trunk/src/build 2008-02-24 06:52:53 UTC (rev 490) @@ -0,0 +1,6 @@ +malloc: + srcs: [malloc.cc] + +avail: + srcs: [avail.cc] + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:49:34
|
Revision: 489 http://assorted.svn.sourceforge.net/assorted/?rev=489&view=rev Author: yangzhang Date: 2008-02-23 22:49:38 -0800 (Sat, 23 Feb 2008) Log Message: ----------- moved to simple-build Modified Paths: -------------- hash-join/trunk/src/bench.bash Added Paths: ----------- hash-join/trunk/src/build Removed Paths: ------------- hash-join/trunk/src/Makefile Deleted: hash-join/trunk/src/Makefile =================================================================== --- hash-join/trunk/src/Makefile 2008-02-24 06:44:21 UTC (rev 488) +++ hash-join/trunk/src/Makefile 2008-02-24 06:49:38 UTC (rev 489) @@ -1,46 +0,0 @@ -TARGET := hashjoin -SRCS := hashjoin.cc -export TARGET - -### begin common makefrag - -CFLAGS := -I. -Wall -lpthread # -lprofiler - -CXX = g++ $(CFLAGS) -o $@ $< - -all: pg -dbg: $(TARGET)-dbg -opt: $(TARGET)-opt -pg: $(TARGET)-pg -pg-opt: $(TARGET)-pg-opt -goo: $(TARGET)-goo - -$(TARGET)-pg: $(SRCS) - $(CXX) -pg - -$(TARGET)-pg-opt: $(SRCS) - $(CXX) -pg -O3 - -$(TARGET)-dbg: $(SRCS) - $(CXX) -g3 - -$(TARGET)-opt: $(SRCS) - $(CXX) -g -O3 -fno-omit-frame-pointer - -$(TARGET)-goo: $(SRCS) - $(CXX) -lprofile - -doc: doc/html/index.html - -doc/html/index.html: $(SRCS) Doxyfile - doxygen - -clean: - rm -rf $(TARGET)-opt $(TARGET)-dbg $(TARGET)-pg doc - -.PHONY: clean dbg opt pg bench doc - -### end common makefrag - -bench: $(TARGET)-opt - ./bench.bash Modified: hash-join/trunk/src/bench.bash =================================================================== --- hash-join/trunk/src/bench.bash 2008-02-24 06:44:21 UTC (rev 488) +++ hash-join/trunk/src/bench.bash 2008-02-24 06:49:38 UTC (rev 489) @@ -9,6 +9,6 @@ for i in $configs ; do for j in {1..3} ; do - ./$TARGET-opt $i $MOVIEDATA/movies.dat $MOVIEDATA/actresses.dat + ./hashjoin-opt $i $MOVIEDATA/movies.dat $MOVIEDATA/actresses.dat done done >& log Added: hash-join/trunk/src/build =================================================================== --- hash-join/trunk/src/build (rev 0) +++ hash-join/trunk/src/build 2008-02-24 06:49:38 UTC (rev 489) @@ -0,0 +1,3 @@ +hashjoin: + srcs: [hashjoin.cc] + libs: [pthread] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:44:16
|
Revision: 488 http://assorted.svn.sourceforge.net/assorted/?rev=488&view=rev Author: yangzhang Date: 2008-02-23 22:44:21 -0800 (Sat, 23 Feb 2008) Log Message: ----------- added tests for overriding values and mixins Added Paths: ----------- sandbox/trunk/src/scala/Mixins.scala sandbox/trunk/src/scala/OverrideVals.scala Added: sandbox/trunk/src/scala/Mixins.scala =================================================================== --- sandbox/trunk/src/scala/Mixins.scala (rev 0) +++ sandbox/trunk/src/scala/Mixins.scala 2008-02-24 06:44:21 UTC (rev 488) @@ -0,0 +1,6 @@ +object Mixins extends Application { + case class A { def f = "hello" } + trait B extends A { override def f = "world" } + val x = new A with B + println(x.f) +} Added: sandbox/trunk/src/scala/OverrideVals.scala =================================================================== --- sandbox/trunk/src/scala/OverrideVals.scala (rev 0) +++ sandbox/trunk/src/scala/OverrideVals.scala 2008-02-24 06:44:21 UTC (rev 488) @@ -0,0 +1,5 @@ +object OverrideVals extends Application { + class A { val a = "a" } + class B extends A { override val a = "b" } + println(new B().a) +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:42:01
|
Revision: 487 http://assorted.svn.sourceforge.net/assorted/?rev=487&view=rev Author: yangzhang Date: 2008-02-23 22:42:08 -0800 (Sat, 23 Feb 2008) Log Message: ----------- added clean to backup makefile Modified Paths: -------------- simple-build/trunk/src/Makefile Modified: simple-build/trunk/src/Makefile =================================================================== --- simple-build/trunk/src/Makefile 2008-02-24 06:41:04 UTC (rev 486) +++ simple-build/trunk/src/Makefile 2008-02-24 06:42:08 UTC (rev 487) @@ -6,3 +6,6 @@ run: meta/SimpleBuild.class scala -cp meta:jyaml-1.3.jar SimpleBuild + +clean: + rm -rf meta This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:40:59
|
Revision: 486 http://assorted.svn.sourceforge.net/assorted/?rev=486&view=rev Author: yangzhang Date: 2008-02-23 22:41:04 -0800 (Sat, 23 Feb 2008) Log Message: ----------- updated documentation Modified Paths: -------------- simple-build/trunk/README Modified: simple-build/trunk/README =================================================================== --- simple-build/trunk/README 2008-02-24 06:40:00 UTC (rev 485) +++ simple-build/trunk/README 2008-02-24 06:41:04 UTC (rev 486) @@ -9,16 +9,19 @@ Current features: +- out-of-the-box support for C, C++, Java, Scala - automatic dependency tracking for C/C++ and Scala - only specify top-level source files - simple-build uses the compiler to generate dependency files that are included into the Makefile for fine-grained dependency tracking - - very useful for when you are working across multiple projects (in my case, - the culprits are often C++ Commons, Scala Commons, etc.) + - rebuilds occur only when necessary + - particularly useful for when you are working across multiple projects (in + my case, the culprits are often C++ Commons, Scala Commons, etc.) +- automatic library specification by checking headers against well-known + header-to-library mappings Planned features: -- out-of-the-box support for C, C++, Java, Scala - software deployment - installation - web publishing @@ -35,10 +38,10 @@ - setuptools/pypi for Python - sbaz for Scala - jars for Java -- continuous build and continuous testing +- continuous build, testing - maven for Java/Scala + - DART/cmake for C/C++ - somehow merge with simple-setup (generate simple-setup files too?) -- stronger inference (e.g. mainclass inference, library test inference) Requirements ------------ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:39:55
|
Revision: 485 http://assorted.svn.sourceforge.net/assorted/?rev=485&view=rev Author: yangzhang Date: 2008-02-23 22:40:00 -0800 (Sat, 23 Feb 2008) Log Message: ----------- some notes Modified Paths: -------------- simple-build/trunk/src/build-templates/java Modified: simple-build/trunk/src/build-templates/java =================================================================== --- simple-build/trunk/src/build-templates/java 2008-02-24 06:35:03 UTC (rev 484) +++ simple-build/trunk/src/build-templates/java 2008-02-24 06:40:00 UTC (rev 485) @@ -39,6 +39,11 @@ fi endif +# TODO: figure out a way to specify the actual set of updated files so as to +# deal with scalac's inability to invalidate class files that are older than +# their corresponding source files (GNU make has an auto-var that does this, +# but that would require adjusting the following dependencies) + $(JAR): $(SRCS) mkdir -p $(CLASSDIR) $(COMPILER) $< This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:34:59
|
Revision: 484 http://assorted.svn.sourceforge.net/assorted/?rev=484&view=rev Author: yangzhang Date: 2008-02-23 22:35:03 -0800 (Sat, 23 Feb 2008) Log Message: ----------- some notes Modified Paths: -------------- simple-build/trunk/notes Modified: simple-build/trunk/notes =================================================================== --- simple-build/trunk/notes 2008-02-24 06:34:44 UTC (rev 483) +++ simple-build/trunk/notes 2008-02-24 06:35:03 UTC (rev 484) @@ -12,3 +12,15 @@ C++ gprof { flags += -pg } C++ opt { flags += -O3 } } + +- look at experimental/ + +- another problem is that of *action* + - so far i have been focusing on compact structural descriptions that + minimize redundancy + - this information is eventually fed into some *behavioral* code (actions) + - eg: emit makefiles; emit ant files; etc. + - what are the rules governing what information goes to what actions? + +- this problem is too hard to focus so much time on for now + - solicit others' input/help This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:34:37
|
Revision: 483 http://assorted.svn.sourceforge.net/assorted/?rev=483&view=rev Author: yangzhang Date: 2008-02-23 22:34:44 -0800 (Sat, 23 Feb 2008) Log Message: ----------- updated tests Modified Paths: -------------- simple-build/trunk/test/cpp/build simple-build/trunk/test/scala/MyApp.scala Added Paths: ----------- simple-build/trunk/test/cpp/myapp2.cc Modified: simple-build/trunk/test/cpp/build =================================================================== --- simple-build/trunk/test/cpp/build 2008-02-24 06:34:03 UTC (rev 482) +++ simple-build/trunk/test/cpp/build 2008-02-24 06:34:44 UTC (rev 483) @@ -1,2 +1,5 @@ myapp: srcs: [myapp.cc] + +myapp2: + srcs: [myapp2.cc] Added: simple-build/trunk/test/cpp/myapp2.cc =================================================================== --- simple-build/trunk/test/cpp/myapp2.cc (rev 0) +++ simple-build/trunk/test/cpp/myapp2.cc 2008-02-24 06:34:44 UTC (rev 483) @@ -0,0 +1,10 @@ +#include <iostream> + +using namespace std; + +int +main() +{ + cout << "hello, world!" << endl; + return 0; +} Modified: simple-build/trunk/test/scala/MyApp.scala =================================================================== --- simple-build/trunk/test/scala/MyApp.scala 2008-02-24 06:34:03 UTC (rev 482) +++ simple-build/trunk/test/scala/MyApp.scala 2008-02-24 06:34:44 UTC (rev 483) @@ -1,5 +1,6 @@ +object MyApp2 { + def main(args: Array[String]) = println("goodbye, world!") +} object MyApp { - def main(args: Array[String]) { - println("hello, world!") - } + def main(args: Array[String]) = println("hello, world!") } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 06:33:58
|
Revision: 482 http://assorted.svn.sourceforge.net/assorted/?rev=482&view=rev Author: yangzhang Date: 2008-02-23 22:34:03 -0800 (Sat, 23 Feb 2008) Log Message: ----------- some important refactorings; support for c/c++; merged java/scala templates; still very hackish, sadly wasn't able to find the right abstractions after a long time exploring Modified Paths: -------------- simple-build/trunk/src/SimpleBuild.scala simple-build/trunk/src/build simple-build/trunk/src/build-templates/cpp simple-build/trunk/src/build-templates/java Removed Paths: ------------- simple-build/trunk/src/build-templates/Makefile simple-build/trunk/src/build-templates/common.mk simple-build/trunk/src/build-templates/scala simple-build/trunk/src/build-templates/scala.mk.part simple-build/trunk/src/build-templates/variant.mk Modified: simple-build/trunk/src/SimpleBuild.scala =================================================================== --- simple-build/trunk/src/SimpleBuild.scala 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/SimpleBuild.scala 2008-02-24 06:34:03 UTC (rev 482) @@ -9,15 +9,13 @@ import _root_.java.io.File object SimpleBuild { + + // + // Generic utils. + // + + def err(x: AnyRef) { Console.err println x } case class HandledException(e: Exception) extends Exception(e) - val ext2template = Map( - "c" -> "c", - "cc" -> "cpp", - "cpp" -> "cpp", - "java" -> "java", - "scala" -> "scala" - ) - def err(x: AnyRef) { Console.err println x } def doOrDie[a](f: => a)(mkmsg: Exception => String) = { try { f } catch { case e: Exception => { @@ -26,33 +24,155 @@ } } } - val structspec = """ - mainclass: required symbol - classpath: optional list of paths relative to srcdir joined by ':' default [] - srcs: required list of files relative to srcdir joined by ' ' - """ - val structs = Map( + val pwd = new File(System getProperty "user.dir").getCanonicalPath + + /** + * The directory where all global configuration files are stored. + */ + val basedir = System getenv "SIMPLEBUILD" + + /** + * Mapping from file extensions to language IDs. + */ + val ext2lang = Map( + "c" -> "c", + "C" -> "cpp", + "cc" -> "cpp", + "cpp" -> "cpp", + "cxx" -> "cpp", + "java" -> "java", + "scala" -> "scala" + ) + + /** + * AttrTypes that the struct definitions use; currently only the AttrList + * types are of any real use. + */ + abstract class AttrType + case class Sym extends AttrType + case class Str extends AttrType + abstract class AttrList extends AttrType { + def render(s: Seq[String]): String + } + case class PathList(glue: String, basedir: String) extends AttrList { + override def render(s: Seq[String]) = s map (rel2abs(basedir,_)) mkString glue + } + case class SymList(glue: String, prefix: String) extends AttrList { + override def render(s: Seq[String]) = s map (prefix + _) mkString glue + } + + /** + * "Struct definitions". Zero-information name. Basically, these describe the + * schema expected for each language. + */ + val structs: Map[String,Map[String,AttrType]] = Map( "scala" -> Map( - "mainclass" -> "symbol", - "classpath" -> "list|srcdir|:", - "srcs" -> "list|srcdir| " + "mainclass" -> Sym(), + "classpath" -> PathList(":", "$(SRCDIR)"), + "srcs" -> PathList(" ", "$(SRCDIR)") ), "java" -> Map( - "mainclass" -> "symbol", - "classpath" -> "list|srcdir|:", - "srcs" -> "list|srcdir| " + "mainclass" -> Sym(), + "classpath" -> PathList(":", "$(SRCDIR)"), + "srcs" -> PathList(" ", "$(SRCDIR)") + ), + "c" -> Map( + "srcs" -> PathList(" ", "$(SRCDIR)"), + "autolibs" -> SymList (" ", "-l"), + "libs" -> SymList (" ", "-l") + ), + "cpp" -> Map( + "srcs" -> PathList(" ", "$(SRCDIR)"), + "autolibs" -> SymList (" ", "-l"), + "libs" -> SymList (" ", "-l") ) ) + + /** + * Makefile emitters. + */ + abstract class MakeEmitter { + def emitMake(target: YamlStr, attrs: YamlMap, aggs: MultiMap[String,String]): String + } + object JavaEmitter extends MakeEmitter { + def emitMake(target: YamlStr, attrs: YamlMap, aggs: MultiMap[String,String]) = { + val srcs = attrs.m(YamlStr("srcs")).xs + val lang = ext2lang(srcs(0).s.extension) + val template = loadTemplate("java") + val struct = structs(lang) + val hdrs = ( + for ((k,v) <- attrs.m.elements ++ List( + (YamlStr("target"), target), + (YamlStr("lang"), YamlStr(lang)) + ) + if v.isInstanceOf[YamlStr] || v.isInstanceOf[YamlSeq]) + yield k.s.toUpperCase + " := " + (v match { + case YamlSeq(xs) => struct(k.s).asInstanceOf[AttrList].render(xs map (_.s)) + case YamlStr(s) => s + }) + ) mkString "\n" + val site = "PREFIX := /opt/" + target.s + "\nBINDIR := $(PREFIX)/bin\n" + val frag = instantiate(site + '\n' + hdrs + "\n\n" + template, aggs) + frag + } + } + object NativeEmitter extends MakeEmitter { + def emitMake(target: YamlStr, attrs: YamlMap, aggs: MultiMap[String,String]) = { + val srcs = attrs.m(YamlStr("srcs")).xs + val autolibs = autoscan(Set(srcs map (_.s):_*)) + val lang = ext2lang(srcs(0).s.extension) + val template = loadTemplate("cpp") + val struct = structs(lang) + val frags = for ((variant,xflags) <- List(("dbg", "-g3"), ("opt", "-O3"), ("gprof", "-pg"))) yield { + val hdrs = ( + for ((k,v) <- attrs.m.elements ++ List( + (YamlStr("origtarget"), target), + (YamlStr("autolibs"), YamlSeq(autolibs map YamlStr toList)), + (YamlStr("lang"), YamlStr(lang)), + (YamlStr("target"), YamlStr(target.s + "-" + variant)), + (YamlStr("flags"), YamlStr(xflags)) + ) + if v.isInstanceOf[YamlStr] || v.isInstanceOf[YamlSeq]) + yield k.s.toUpperCase + " := " + (v match { + case YamlSeq(xs) => struct(k.s).asInstanceOf[AttrList].render(xs map (_.s)) + case YamlStr(s) => s + }) + ) mkString "\n" + val site = "PREFIX := /opt/" + target.s + "\nBINDIR := $(PREFIX)/bin\n" + val frag = instantiate(site + '\n' + hdrs + "\n\n" + template, aggs) + frag + } + (frags mkString "\n") + """ +$(OUTDIR)/.deps: $(shell find $(OUTDIR) -name '*.d' 2> /dev/null || true) + mkdir -p $(OUTDIR) + [ "$^" ] && cat $^ > $@ + +-include $(OUTDIR)/.deps + +""" + } + } + val emitters: Map[String,MakeEmitter] = Map( + "scala" -> JavaEmitter, + "java" -> JavaEmitter, + "c" -> NativeEmitter, + "cpp" -> NativeEmitter + ) + + // + // Stuff related to processing the Makefile templates. + // + val ids = Iterator from 0 - val basedir = System getenv "SIMPLEBUILD" - val pwd = new File(System getProperty "user.dir").getCanonicalPath - def templateByFilename(s: String) = { - val name = ext2template(s split "\\." last) + def loadTemplate(name: String) = { val fname = basedir / "build-templates" / name val template = using (TextReader(fname)) (_ read) - val struct = structs(name) - (template, struct) + template } + + /** + * Instantiate a Makefile. + */ def instantiate(template: String, aggs: MultiMap[String,String]) = { val internalVars = new HashMap[String,String] val tid = ids.next @@ -63,7 +183,7 @@ val newLines0 = for (line <- template split "\n") yield { if (line contains " := ") { // Assignment. - val Seq(lhs, rhs) = line split " := " + val Seq(lhs, rhs) = ((line split " := ") ++ List(" ")) take 2 val newLhs = lhs.trim + "_" + tid val newRhs = substVars(rhs) internalVars += (lhs.trim -> newLhs) @@ -89,9 +209,6 @@ } newLines1 mkString "\n" } - def emitMakeFrag(target: String, rules: String) { - using (TextWriter(target + ".mk")) (_ println rules) - } implicit def node2map(n: YamlNode) = n.asInstanceOf[YamlMap] implicit def node2seq(n: YamlNode) = n.asInstanceOf[YamlSeq] implicit def node2str(n: YamlNode) = n.asInstanceOf[YamlStr] @@ -118,6 +235,36 @@ } r(Yaml.load(s)) } +// def includes(roots: Set[String]) = { +// val enqueued = new HashSet[String] +// val pattern = Pattern compile """#\s*include\s+<(.+)>""" +// def r(fs: Seq[String]): Stream[String] = { +// { +// for (f <- fs.toStream) yield { +// r(for (line <- using (TextReader(f)) (_.readLines.toArray); +// m = pattern matcher line; +// if m.matches; +// inc = m group 1; +// if !(enqueued contains inc)) +// yield inc +// ) +// } +// } flatMap (x => x) +// } +// r(roots toArray) +// } + val hdr2lib = Map( + // "pthread.h" -> "pthread", // TODO: Not sure how to deal with this, since pthread seems to always show up + "numa.h" -> "numa" + ) + def autoscan(roots: Set[String]) = { + val rules = run("gcc -M " + (roots mkString " "), "") + val deps = rules.replaceAll(" \\\n", " ").split("\n").map(_.split(": "). + last.split(" ")).flatMap(x=>x).map(_.basename) + val hs = Set(deps: _*) + val libs = for (opt <- hs map hdr2lib.get; if opt.isDefined) yield opt.get + libs + } def main(args: Array[String]) { try { val rawfname = if (args.length > 0) args(0) else "build" @@ -131,35 +278,29 @@ e => "could not open file: " + fname } val build = yaml(contents) + val aggs = multimap(List[(String,String)]()) + val frags = new ArrayBuffer[String] // For each target, emit a make frag. - val aggs = multimap(List[(String,String)]()) val targets = for ((target, attrs) <- build.m) yield { val srcs = attrs.m(YamlStr("srcs")).xs - val (template,struct) = templateByFilename(srcs(0).s) - val hdrs = ( - for ((k,v) <- attrs.m.elements ++ List((YamlStr("target"), target)) - if v.isInstanceOf[YamlStr] || v.isInstanceOf[YamlSeq]) - yield k.s.toUpperCase + " := " + (v match { - case YamlSeq(xs) => xs map (_.s) map (rel2abs(srcdir,_)) mkString (struct(k.s) split "|" last) - case YamlStr(s) => s - }) - ) mkString "\n" - val site = "PREFIX := /opt/" + target.s + "\nBINDIR := $(PREFIX)/bin\n" - val rules = instantiate(site + '\n' + hdrs + "\n\n" + template, aggs) - emitMakeFrag(target.s, rules) + frags += emitters(ext2lang(srcs(0).s.extension)).emitMake(target, attrs, aggs) target.s } + // TODO + val phonies = List[String]() // Makefiles. using (TextWriter("GNUmakefile")) { w => w println "OUTDIR := " + pwd / "out" w println "SRCDIR := " + srcdir w println "SRCPATH := " + srcdir w println ("all: " + (targets mkString " ")) - w println(targets map ("include "+_+".mk") mkString "\n") + w println (frags mkString "\n\n") w println ((for ((k,vs) <- aggs) yield (k + ": " + (vs mkString " "))) mkString "\n") - w println ("clean:\n\trm -rf out") - w println ("GNUmakefile: " + srcdir + "/build\n\tbuild.bash build") - w println (".PHONY: clean") + w println ("clean:\n\trm -rf $(OUTDIR)") + w println ("GNUmakefile: " + srcdir + "/build\n\tsimple-build") + w println ("clean-build:\n\trm GNUmakefile") + w println ("clean-all: clean clean-build") + w println (".PHONY: clean all clean-build clean-all " + (phonies mkString " ")) } } catch { // Catch-all for handled exceptions (the rest should be displayed in Modified: simple-build/trunk/src/build =================================================================== --- simple-build/trunk/src/build 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build 2008-02-24 06:34:03 UTC (rev 482) @@ -2,7 +2,3 @@ mainclass: SimpleBuild srcs: [SimpleBuild.scala] classpath: [jyaml-1.3.jar] - -#hashjoin: -# srcs: [hashjoin.cc] -# libs: [pthreads] Deleted: simple-build/trunk/src/build-templates/Makefile =================================================================== --- simple-build/trunk/src/build-templates/Makefile 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/Makefile 2008-02-24 06:34:03 UTC (rev 482) @@ -1,9 +0,0 @@ -TARGET := asdf -SRCS := src/asdf.c -OUTDIR := out -include common.mk - -TARGET := Asdf -SRCDIR := . -SRCS := Asdf.scala -include scala.mk Deleted: simple-build/trunk/src/build-templates/common.mk =================================================================== --- simple-build/trunk/src/build-templates/common.mk 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/common.mk 2008-02-24 06:34:03 UTC (rev 482) @@ -1,12 +0,0 @@ -VARIANT := dbg -VARIANT_CFLAGS := -g3 -include variant.mk - -VARIANT := opt -VARIANT_CFLAGS := -O3 -include variant.mk - -clean: - rm -rf $(OUTDIR) - -.PHONY: clean Modified: simple-build/trunk/src/build-templates/cpp =================================================================== --- simple-build/trunk/src/build-templates/cpp 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/cpp 2008-02-24 06:34:03 UTC (rev 482) @@ -1,7 +1,46 @@ -[instantiate variant.mk] - VARIANT := dbg - VARIANT_CFLAGS := -g3 +OBJDIR := $(OUTDIR)/$(TARGET)-obj +CFLAGS := $(CFLAGS) $(FLAGS) +CXXFLAGS := $(CXXFLAGS) $(FLAGS) +CPPFLAGS := $(CPPFLAGS) +LDFLAGS := $(LDFLAGS) $(LIBS) $(AUTOLIBS) +EXE := $(OUTDIR)/$(TARGET) -[instantiate variant.mk] - VARIANT := opt - VARIANT_CFLAGS := -O3 +OBJS := $(foreach ext, c cc cpp cxx, \ + $(patsubst $(SRCDIR)/%.$(ext), $(OBJDIR)/%.o, \ + $(filter %.$(ext), $(SRCS)))) + +CC := gcc +CXX := g++ +ifeq ($(LANG),c) + COMPILER := $(CC) +else + COMPILER := $(CXX) +endif + +$(TARGET): $(EXE) + +$(EXE): $(OBJS) + $(COMPILER) $(LDFLAGS) -o $@ $^ + +$(OBJDIR)/%.o: %.c + mkdir -p $(@D) + $(CC) $(CPPFLAGS) $(CFLAGS) -MD -c -o $@ $< + +$(OBJDIR)/%.o: %.cc + mkdir -p $(@D) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< + +$(OBJDIR)/%.o: %.cpp + mkdir -p $(@D) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< + +$(OBJDIR)/%.o: %.cxx + mkdir -p $(@D) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< + +clean: + rm -rf $(OBJDIR) $(EXE) + +$(ORIGTARGET): $(TARGET) + +.PHONY: $(ORIGTARGET) Modified: simple-build/trunk/src/build-templates/java =================================================================== --- simple-build/trunk/src/build-templates/java 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/java 2008-02-24 06:34:03 UTC (rev 482) @@ -1,30 +1,47 @@ # Output locations. -SCRIPT := $(OUTDIR)/$(TARGET) +SCRIPT := $(OUTDIR)/$(TARGET) ifeq (,$(VERSION)) - JAR := $(OUTDIR)/$(TARGET).jar + JAR := $(OUTDIR)/$(TARGET).jar else - JAR := $(OUTDIR)/$(TARGET)-$(VERSION).jar + JAR := $(OUTDIR)/$(TARGET)-$(VERSION).jar endif -CLASSDIR := $(OUTDIR)/$(TARGET)-classes +CLASSDIR := $(OUTDIR)/$(TARGET)-classes # Flags. -JAVACFLAGS:= -deprecation -unchecked -sourcepath $(SRCPATH) -d $(CLASSDIR) -cp $(CLASSPATH) -JAVAC := capture-javac-deps 2 $(JAR) $(OUTDIR)/.deps javac -verbose +SRCPATH := $(SRCPATH):$(SCALA_COMMONS_SRC) +SCALAC := capture-javac-deps 1 $(JAR) $(OUTDIR)/.deps fsc -verbose +SCALAFLAGS := -deprecation -unchecked -sourcepath $(SRCPATH) -d $(CLASSDIR) -cp $(CLASSPATH) +JAVAC := capture-javac-deps 2 $(JAR) $(OUTDIR)/.deps javac -verbose +JAVACFLAGS := -deprecation -sourcepath $(SRCPATH) -d $(CLASSDIR) -cp $(CLASSPATH) +ifeq ($(LANG),scala) + COMPILER := $(SCALAC) $(SCALAFLAGS) +else + COMPILER := $(JAVAC) $(JAVACFLAGS) +endif $(TARGET): $(SCRIPT) $(JAR) +ifeq ($(LANG),java) $(SCRIPT): $(MAKEFILE_LIST) mkdir -p $(@D) if [ ! -z "$(MAINCLASS)" ]; then \ - echo "#!/usr/bin/env bash\n\nJAVA_OPTS=\"$(JRUNFLAGS) \$${JAVA_OPTS:-}\" exec java -cp $(JAR):$(CLASSPATH) $(MAINCLASS) \"\$$@\"" > $(SCRIPT) ;\ + echo "#!/usr/bin/env bash\n\nexec java -cp $(JAR):$(CLASSPATH) $(JRUNFLAGS) $(MAINCLASS) \"\$$@\"" > $(SCRIPT) ;\ chmod +x $(SCRIPT) ;\ fi +else +$(SCRIPT): $(MAKEFILE_LIST) + mkdir -p $(@D) + if [ ! -z "$(MAINCLASS)" ]; then \ + echo "#!/usr/bin/env bash\n\nJAVA_OPTS=\"$(JRUNFLAGS) \$${JAVA_OPTS:-}\" exec scala -cp $(JAR):$(CLASSPATH) $(MAINCLASS) \"\$$@\"" > $(SCRIPT) ;\ + chmod +x $(SCRIPT) ;\ + fi +endif $(JAR): $(SRCS) mkdir -p $(CLASSDIR) - $(JAVAC) $(JAVACFLAGS) $< + $(COMPILER) $< jar cf $@ -C $(CLASSDIR) . -include $(OUTDIR)/.deps Deleted: simple-build/trunk/src/build-templates/scala =================================================================== --- simple-build/trunk/src/build-templates/scala 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/scala 2008-02-24 06:34:03 UTC (rev 482) @@ -1,40 +0,0 @@ -# Output locations. - -SCRIPT := $(OUTDIR)/$(TARGET) -ifeq (,$(VERSION)) - JAR := $(OUTDIR)/$(TARGET).jar -else - JAR := $(OUTDIR)/$(TARGET)-$(VERSION).jar -endif -CLASSDIR := $(OUTDIR)/$(TARGET)-classes - -# Flags. - -SRCPATH := $(SRCPATH):$(SCALA_COMMONS_SRC) -SFLAGS := -deprecation -unchecked -sourcepath $(SRCPATH) -d $(CLASSDIR) -cp $(CLASSPATH) -SCALAC := capture-javac-deps 1 $(JAR) $(OUTDIR)/.deps fsc -verbose - -$(TARGET): $(SCRIPT) $(JAR) - -$(SCRIPT): $(MAKEFILE_LIST) - mkdir -p $(@D) - if [ ! -z "$(MAINCLASS)" ]; then \ - echo "#!/usr/bin/env bash\n\nJAVA_OPTS=\"$(JRUNFLAGS) \$${JAVA_OPTS:-}\" exec scala -cp $(JAR):$(CLASSPATH) $(MAINCLASS) \"\$$@\"" > $(SCRIPT) ;\ - chmod +x $(SCRIPT) ;\ - fi - -$(JAR): $(SRCS) - mkdir -p $(CLASSDIR) - $(SCALAC) $(SFLAGS) $< - jar cf $@ -C $(CLASSDIR) . - --include $(OUTDIR)/.deps - -install: $(TARGET) - mkdir -p $(BINDIR) - cp $(SCRIPT) $(BINDIR) - -clean: - rm -rf $(SCRIPT) $(JAR) $(CLASSDIR) - -.PHONY: $(TARGET) clean Deleted: simple-build/trunk/src/build-templates/scala.mk.part =================================================================== --- simple-build/trunk/src/build-templates/scala.mk.part 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/scala.mk.part 2008-02-24 06:34:03 UTC (rev 482) @@ -1,14 +0,0 @@ -# Global environment variable (if missing, then Scala Commons should be -# available on the classpath). - -SCALA_COMMONS_SRC := ~/scom - -# Project settings. - -TARGET := myapp -MAINCLASS := myapp.MyApp -OUTDIR := out -SRCPATH := . -SRCS := MyApp.scala Other.scala -JRUNFLAGS := -Xmx512M -CLASSPATH := Deleted: simple-build/trunk/src/build-templates/variant.mk =================================================================== --- simple-build/trunk/src/build-templates/variant.mk 2008-02-24 01:11:46 UTC (rev 481) +++ simple-build/trunk/src/build-templates/variant.mk 2008-02-24 06:34:03 UTC (rev 482) @@ -1,34 +0,0 @@ -OUTDIR := $(OUTDIR)/$(VARIANT) -CFLAGS := $(CFLAGS) $(CFLAGS) -CXXFLAGS := $(CXXFLAGS) $(CXXFLAGS) -CPPFLAGS := $(CPPFLAGS) -LDFLAGS := $(LDFLAGS) $(LIBS) - -OBJS := $(foreach src,$(SRCS),$(OUTDIR)/$(patsubst %.c,%.o,$(src))) - -CC := gcc -CXX := g++ - -$(VARIANT): $(OUTDIR)/$(TARGET) - -$(OUTDIR)/$(TARGET): $(OBJS) - $(CC) $(LDFLAGS) -o $@ $^ - -$(OUTDIR)/%.o: %.c - mkdir -p $(@D) - $(CC) $(CPPFLAGS) $(CFLAGS) -MD -c -o $@ $< - -$(OUTDIR)/%.o: %.cc - mkdir -p $(@D) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c -o $@ $< - -$(OUTDIR)/.deps: $(shell find $(OUTDIR) -name '*.d' 2> /dev/null || true) - mkdir -p $(OUTDIR) - [ "$^" ] && cat $^ > $@ - --include $(OUTDIR)/.deps - -clean: - rm -rf $(OUTDIR) - -.PHONY: clean This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-24 01:11:46
|
Revision: 481 http://assorted.svn.sourceforge.net/assorted/?rev=481&view=rev Author: yangzhang Date: 2008-02-23 17:11:46 -0800 (Sat, 23 Feb 2008) Log Message: ----------- exploratory code Added Paths: ----------- simple-build/trunk/experimental/ simple-build/trunk/experimental/Schema1.scala simple-build/trunk/experimental/Schema2 Added: simple-build/trunk/experimental/Schema1.scala =================================================================== --- simple-build/trunk/experimental/Schema1.scala (rev 0) +++ simple-build/trunk/experimental/Schema1.scala 2008-02-24 01:11:46 UTC (rev 481) @@ -0,0 +1,166 @@ +// +// Attribute types +// + +class Void +object Null extends Void + +abstract class Attr { + def valid: Boolean +} +case class Str extends Attr { + var value: Option[String] = None + var isSet = false + def :=(n: Void) = { + value = None + isSet = true + this + } + def :=(s: String) = { + value = Some(s) + isSet = true + this + } + override def valid = isSet + def get = { + if (!valid) throw new Exception("unset!") + value.get + } + override def toString = getClass.getName + "(" + value + ")" +} +case class Sym extends Str +case class Path(val baseDir: String) extends Str +case class AttrList extends Attr { + import scala.collection.mutable.ArrayBuffer + var values: Option[ArrayBuffer[String]] = None + def :=(n: Void) = { + values = Some(new ArrayBuffer) + this + } + def :=(xs: Seq[String]) = { + if (values == None) values = Some(new ArrayBuffer) + values.get ++= xs + this + } + def +=(x: String) = { + if (values == None) values = Some(new ArrayBuffer) + values.get += x + this + } + def valid = !values.isEmpty + def get = values.get mkString "," + override def toString = + getClass.getName + "(" + (values map (_ mkString ",")) + ")" +} +case class PathList(val baseDir: String) extends AttrList +case class SymList extends AttrList +object Implicits { + implicit def Str2String(s: Str) = s.get + implicit def AttrList2String(xs: AttrList) = xs.get +} +import Implicits._ + +// +// Target types +// + +trait Target { + val name = Sym() + val version = Str() := Null + val descrip = Str() := Null + val srcs = PathList(srcdir) + val compiler = Str() + def emit: String + def valid = true + // XXX +// def valid = { +// this.getClass.getMethods map ( +// _.get(this)) filter ( +// _.isInstanceOf[Attr]) forall ( +// _.asInstanceOf[Attr]valid) +// } +} + +trait JavaPlatformTarget extends Target { + val classpath = PathList(srcdir) := Null + override def emit = <p> + name {name} + version {version} + descrip {descrip} + srcs {srcs} + compiler {compiler} + classpath {classpath} + </p>.text +} +trait JavaPlatformLibrary extends JavaPlatformTarget +trait JavaPlatformProgram extends JavaPlatformTarget { + val mainclass = Sym() + val runner = Str() +} + +trait JavaLanguageMixin extends Target { + compiler := "javac" +} +case class JavaLanguageLibrary extends JavaPlatformLibrary with JavaLanguageMixin +case class JavaLanguageProgram extends JavaPlatformProgram with JavaLanguageMixin { + runner := "java" +} + +trait ScalaMixin extends Target { + compiler := "fsc" +} +case class ScalaLibrary extends JavaPlatformLibrary with ScalaMixin +case class ScalaProgram extends JavaPlatformProgram with ScalaMixin { + runner := "scala" +} + +trait NativeTarget extends Target { + val libs = SymList() := Null + val libpaths = PathList(srcdir) := Null + val ldflags = Str() := Null + override def emit = <p> + name {name} + version {version} + descrip {descrip} + srcs {srcs} + compiler {compiler} + libs {libs} + libpaths {libpaths} + ldflags {ldflags} + </p>.text +} + +trait NativeProgram extends NativeTarget +trait NativeLibrary extends NativeTarget + +trait CMixin extends Target { + compiler := "gcc" + val cflags = Str() := Null +} +trait CppMixin extends Target { + compiler := "g++" + val cxxflags = Str() := Null +} + +trait CProgram extends NativeProgram with CMixin +trait CLibrary extends NativeLibrary with CMixin + +case class CppProgram extends NativeProgram with CppMixin +case class CppLibrary extends NativeLibrary with CppMixin + +// +// Test +// + +object SchemaTest extends Application { + val cpp = new CppProgram { + name := "hello" + srcs := List("hello.cc") + } + println(cpp.emit) + val java = new JavaLanguageProgram { + name := "Hello" + srcs := List("Hello.java") + } + println(java.emit) +} Added: simple-build/trunk/experimental/Schema2 =================================================================== --- simple-build/trunk/experimental/Schema2 (rev 0) +++ simple-build/trunk/experimental/Schema2 2008-02-24 01:11:46 UTC (rev 481) @@ -0,0 +1,101 @@ +target: + fields: + name: sym + version: str + descrip: str + srcs: pathlist + compiler: str + overrides: + version: + descrip: + +java platform target: + extends: + target + fields: + classpath: pathlist + +java platform program: + extends: + java platform target + fields: + mainclass: sym + runner: str + +java language: + extends: + target + overrides: + compiler: "javac" + applies to: java platform + +java program: + extends: + java platform program + java language + overrides: + runner: "java" + +scala language: + extends: [target] + overrides: + compiler: "javac" + applies to: java platform + +scala program: + extends: + java platform program + scala language + name: Hello + runner: scala + +native target: + extends: + target + fields: + flags: strlist + overrides: + flags: [] + +c++: + extends: + native target + overrides: + compiler: g++ + applies to: native target + +c: + extends: + native target + overrides: + compiler: gcc + applies to: native target + +complete native: + extends: + native target: + name: name + "-gprof" // TODO how to do this? + flags: [-pg] + native target: + name: name + "-opt" + flags: [-O3] + native target: + name: name + "-dbg" + flags: [-g3] + +c++ program: + extends: + complete native + c++ + +c program: + extends: + complete native + c + +===== + +java program: + name: Hello + version: 0.1 + srcs: [Hello.java] + +c++ program: + name: hello + srcs: [hello.cc] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-23 23:46:12
|
Revision: 480 http://assorted.svn.sourceforge.net/assorted/?rev=480&view=rev Author: yangzhang Date: 2008-02-23 15:46:11 -0800 (Sat, 23 Feb 2008) Log Message: ----------- Added Paths: ----------- simple-build/trunk/notes Added: simple-build/trunk/notes =================================================================== --- simple-build/trunk/notes (rev 0) +++ simple-build/trunk/notes 2008-02-23 23:46:11 UTC (rev 480) @@ -0,0 +1,14 @@ +- mixins are helpful (for both the interface and implementation) +- don't use subclassing + - you can only inherit a single class + - eg "c++ complete program" should generate multiple "c++ programs" variants + - program is too dynamic for that + - eg validation requires reflection trickery + - eg validation requires +- but parameterization is repetitive +- use something like this? (should this be merged into the same layer of abstraction, or separated?) + C++ complete { + C++ dbg { flags += -g3 } + C++ gprof { flags += -pg } + C++ opt { flags += -O3 } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-22 23:44:41
|
Revision: 479 http://assorted.svn.sourceforge.net/assorted/?rev=479&view=rev Author: yangzhang Date: 2008-02-22 15:44:41 -0800 (Fri, 22 Feb 2008) Log Message: ----------- added a test Added Paths: ----------- scala-commons/trunk/src/test/All.scala scala-commons/trunk/src/test/build Added: scala-commons/trunk/src/test/All.scala =================================================================== --- scala-commons/trunk/src/test/All.scala (rev 0) +++ scala-commons/trunk/src/test/All.scala 2008-02-22 23:44:41 UTC (rev 479) @@ -0,0 +1,15 @@ +import commons._ +import commons.Collections._ +import commons.Control._ +import commons.Debug._ +import commons.English._ +import commons.Hash._ +import commons.Io._ +import commons.Misc._ +import commons.Path._ +import commons.Plotting._ +import commons.Repl._ +/** + * Includes everything. Simply ensures that the library builds. + */ +object All extends Application Added: scala-commons/trunk/src/test/build =================================================================== --- scala-commons/trunk/src/test/build (rev 0) +++ scala-commons/trunk/src/test/build 2008-02-22 23:44:41 UTC (rev 479) @@ -0,0 +1,3 @@ +all: + srcs: [All.scala] + mainclass: All This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2008-02-22 23:44:38
|
Revision: 478 http://assorted.svn.sourceforge.net/assorted/?rev=478&view=rev Author: yangzhang Date: 2008-02-22 15:44:36 -0800 (Fri, 22 Feb 2008) Log Message: ----------- added more documentation, some cleaning and reorganization Modified Paths: -------------- scala-commons/trunk/src/commons/Collections.scala scala-commons/trunk/src/commons/Control.scala scala-commons/trunk/src/commons/Debug.scala scala-commons/trunk/src/commons/Hash.scala scala-commons/trunk/src/commons/Io.scala scala-commons/trunk/src/commons/Misc.scala scala-commons/trunk/src/commons/Path.scala scala-commons/trunk/src/commons/Repl.scala Added Paths: ----------- scala-commons/trunk/src/commons/English.scala Removed Paths: ------------- scala-commons/trunk/src/commons/ExtractorObject.scala Modified: scala-commons/trunk/src/commons/Collections.scala =================================================================== --- scala-commons/trunk/src/commons/Collections.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Collections.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -11,6 +11,29 @@ object Collections { + // + // Tuples + // + + /** + * Swap the elements of a tuple. + */ + def swap[a,b](p: (a,b)) = (p._2, p._1) + + implicit def pair2xpair(p: (Int,Int)) = new XPair(p._1,p._2) + implicit def xpair2pair(p: XPair) = (p.x,p.y) + + case class XPair(x: Int, y: Int) { + /** + * Add a pair of Ints. + */ + def +(p: (Int, Int)) = Pair(x+p.x, y+p.y) + } + + // + // Strings + // + // TODO: Make faster. /** * Split a String into words. Use this when possible, since its @@ -19,8 +42,36 @@ */ def words(x: String) = x.trim.split("\\s+") + /** + * Convert camel case to lower case with the given inter-word glue string. + * <p> + * <code>camelToLower("helloWorld", "_") == "hello_world"</code> + * <p> + * <code>camelToLower("HelloWorld", "_") == "_hello_world"</code> + */ + def camelToLower(s: String, sep: String) = { + val xs = + for (c <- s) + yield if (c.isUpperCase) sep + c.toLowerCase else c + xs mkString "" + } + def camelToUnder(s: String) = camelToLower(s, "_") + def camelToHyphen(s: String) = camelToLower(s, "-") + def camelToSpaced(s: String) = camelToLower(s, " ") + + /** + * Convert a spaced word to a hyphenated word. + */ + def spacedToHyphen(s: String) = s replaceAll (" ", "-") + + /** + * Rot-n-encode a string, but where all characters are rotated, not just + * alphabetical characters. + */ + def rot(n: Int, s: String) = s map (_ + n toChar) mkString + // - // Views + // Views of sequences // // TODO: Is there a way to "chain" views? Then Iterable2FilterMap is @@ -61,16 +112,6 @@ } } - implicit def pair2xpair(p: (Int,Int)) = new XPair(p._1,p._2) - implicit def xpair2pair(p: XPair) = (p.x,p.y) - - case class XPair(x: Int, y: Int) { - /** - * Add a pair of Ints. - */ - def +(p: (Int, Int)) = Pair(x+p.x, y+p.y) - } - implicit def MapToRichMap[k,v](m: Map[k,v]) = new RichMap(m) implicit def RichMapToMap[k,v](m: RichMap[k,v]) = m.m @@ -119,8 +160,6 @@ // Simple statistics // - import scala.util.Sorting - def sum(xs: Iterator[Int]) = xs.foldLeft(0)(_+_) def sum(xs: Seq[Double]) = xs reduceLeft ((x:Double,y:Double)=>x+y) def sum(xs: Iterator[Double]) = xs reduceLeft ((_:Double)+(_:Double)) @@ -128,6 +167,8 @@ def mean(xs: Seq[Double]) = sum(xs.elements) / xs.size def median(xs: Seq[Long]) = xs(xs.length / 2) + import scala.util.Sorting + /** * Destructively sort the array, and returns a tuple of the (mean, median, * standard deviation, variance, minimum, and maximum) of a list. @@ -151,7 +192,7 @@ // TODO: Can I write functions that are generic over n-tuples? /** - * Returns the two smallest elements. + * Return the two smallest elements. */ def mins(xs: Iterable[Long]) = { var min1 = java.lang.Long.MAX_VALUE // smallest @@ -226,6 +267,100 @@ // /** + * Return pairs of elements. + * <p> + * <code> + * pairs([a,b,c,d]) == [(a,b),(c,d)] + * <p> + * pairs([a,b,c,d,e]) == [(a,b),(c,d)] + * </code> + */ + def pairs[a](xs: Seq[a]): Stream[(a,a)] = { + xs match { + case Seq() => Stream empty + case Seq(a, b, rest @ _*) => Stream cons ((a,b), pairs(rest)) + } + } + + /** + * Return an iterator that yields invocations of f until it returns null. + * Useful for, e.g., Java's IO stream abstractions. + */ + def untilNull[a](f: => a) = new Iterator[a] { + var upcoming = f + override def hasNext = upcoming != null + override def next = { + val emit = upcoming + upcoming = f + emit + } + } + + /** + * For each x in xs, if p(x), then x is a header, and it owns all the xs + * after it until the next x for which p(x) holds. The return value is the + * header and its body. + * <p> + * <code> + * groupByHeaders([1,2,3,4,5,6,7,8,9])(_%3==0) == [[3,4,5],[6,7,8],[9]] + * </code> + */ + def groupByHeaders[a](xs: Seq[a])(p: a => Boolean) = { + val ys = new mut.ArrayBuffer[mut.ArrayBuffer[a]] + for (x <- xs) { + if (p(x)) ys += new mut.ArrayBuffer[a] + if (!ys.isEmpty) ys.last += x + } + ys + } + + /** + * Given a list of sublists, return pairs of the first element of each + * sublist along with the remaining elements. Empty sublists are ignored. + * <p> + * <code> + * separateHeads([[a,b,c],[d,e,f,g],[],[h]]) + * == [(a,[b,c]),(d,[e,f,g]),(h,[])] + * </code> + */ + def separateHeads[a](xss: Seq[Seq[a]]) = + for (xs <- xss; if !xs.isEmpty; (Seq(a),b) = span(1)(xs)) yield (a,b) + + /** + * Construct a multimap out of the given key-value pairs; the result maps + * keys to sets of values. + */ + def multimap[a,b](xs: Iterable[(a,b)]) = { + val h = new mut.HashMap[a,mut.Set[b]] with mut.MultiMap[a,b] { + override def makeSet = new mut.HashSet[b] + } + for ((k,v) <- xs) { + h add (k,v) + } + h + } + + /** + * Construct a multimap out of xs, preserving the order of values as they + * were input. + */ + def orderedMultimap[a,b](xs: List[(a,b)]) = { + val h = new mut.HashMap[a, mut.ArrayBuffer[b]] { + override def default(k: a) = { + this(k) = new mut.ArrayBuffer[b] + this(k) + } + } + for ((k,v) <- xs) h(k) += v + h + } + + /** + * Convert an iterator to array. + */ + def iterator2array[a](xs: Iterator[a]) = xs.toList.toArray + + /** * A combination of take and drop. * <p> * <code>span(3)([a,b,c,d,e]) == ([a,b,c],[d,e])</code> @@ -235,7 +370,7 @@ /** * Same as span but for Strings, which are treated as an array of chars. * <p> - * <code>spanstr(3)("abcde") == ("abc","de") + * <code>spanstr(3)("abcde") == ("abc","de")</code> */ def spanstr[a](n: Int)(xs: String) = (xs take n mkString ("","",""), xs drop n mkString ("","","")) @@ -257,6 +392,10 @@ * <p> * <code> * splitBy([1..10], (_ % 4 < 2)) == [[2,3],[6,7],[8,9]] + * <p> + * [1,3,5,6,7,8] odd == ([1,3,5],[6,7,8]) + * <p> + * [] _ == ([],[]) * </code> */ def splitBy[a](xs: Seq[a])(pred: a => Boolean): Stream[Seq[a]] = { @@ -279,11 +418,11 @@ def groupBy[a](xs: Seq[a])(pred: a => Boolean): Stream[Seq[a]] = splitBy(xs)(not(pred)) - // TODO: these was renamed from slices. Make sure nothing was broken. + // TODO: this was renamed from slices. Make sure nothing was broken. /** * Return all length-n "chunks" of xs as a stream. * <p> - * <code>chunks([a..h], 3) == [[a,b,c],[d,e,f],[g,h]]</code> + * <code>chunks(3)([a..h]) == [[a,b,c],[d,e,f],[g,h]]</code> */ def chunks[a](n: Int)(xs: Seq[a]): Stream[Seq[a]] = { if (xs.length == 0) Stream.empty @@ -300,11 +439,13 @@ 0 to (xs.length - n) map { i => xs slice (i,i+n) } /** - * Same as slices(_,2) but yields tuples. + * Same as <code>slices(_,2)</code> but yields tuples. * <p> * <code> * pairwise([a,b,c]) == [(a,b),(c,d)] + * <p> * pairwise([a]) == [] + * <p> * pairwise([]) == [] * </code> */ @@ -338,10 +479,11 @@ /** * Return a stream of n elements, where each element is an evaluation of gen. - * Note that gen may be evaluated more than n times. See: - * + * <p> + * Note that gen may be evaluated more than n times. See + * <a href="http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.ps"> * "How to add laziness to a strict language, without even being odd" - * http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.ps + * </a> */ def replicate[a](n: Int, gen: => a): Stream[a] = repeat(gen) take n @@ -385,29 +527,51 @@ } /** - * Note that this operates by duplicating the iterator and traversing each - * copy. + * Given an Iterator of pairs, return two Iterators over the first and second + * elements of the pairs. Note that this operates by duplicating the + * iterator and traversing each copy. */ def unzip[a,b](pairs: Iterator[(a,b)]): (Iterator[a],Iterator[b]) = { val (i,j) = pairs.duplicate (i map (_._1), j map (_._2)) } + /** + * Given a Stream of pairs, return two Streams over the first and second + * elements of the pairs. + */ def unzip[a,b](pairs: Stream[(a,b)]): (Stream[a],Stream[b]) = (pairs map (_._1), pairs map (_._2)) /** * Indexes the result of groupBy. * <p> - // 0 1 2 3 4 5 6 7 8 9 - // [a,b,c,c,c,d,d,e,f,f] -> [[0],[1],[2,3,4],[5,6],[7],[8,9]] - // [] -> [] + * <code> + * <p> + * [0 1 2 3 4 5 6 7 8 9] + * <br> + * [a,b,c,c,c,d,d,e,f,f] == [[0],[1],[2,3,4],[5,6],[7],[8,9]] + * <p> + * [] == [] + * </code> */ def indexGroups[a,b](xs: Seq[a])(f: a => b) = { val i = Iterator from 0 Stream fromIterator xs.elements groupBy f map (_ map (x => i.next)) } + /** + * Zip or unzip some lists (the zip width is dynamic, so no tuples). The + * length of the resulting list is the length of the shortest input list. + * <p> + * <code> + * zipx([[a,b,c,d,e],[f,g,h,i,j],[k,l,m,n]]) + * == [[a,f,k],[b,g,l],[c,h,m],[d,i,n]] + * <p> + * unzipx([[a,f,k],[b,g,l],[c,h,m],[d,i,n]]) + * == [[a,b,c,d],[f,g,h,i],[k,l,m,n]] + * </code> + */ def zipx[a](xss: Seq[Iterable[a]]): Stream[Seq[a]] = { val is = xss map (_.elements) def rec: Stream[Seq[a]] = @@ -415,7 +579,12 @@ else Stream.empty rec } - def unzipx[a](xss: Iterable[Seq[a]]) = { + + /** + * Zip or unzip some lists (the zip width is dynamic, so no tuples). The + * length of the resulting list is the length of the shortest input list. + */ + def zipx[a](xss: Iterable[Seq[a]]) = { val width = xss.elements.next.length val iters = for (i <- 0 until width) @@ -423,6 +592,62 @@ List(iters: _*) } + /** + * Concatenate iterators. + */ + def concat[a](iters: Seq[Iterator[a]]) = + iters reduceLeft ((x: Iterator[a], y: Iterator[a]) => x ++ y) + + /** + * Eliminate consecutive duplicates. + */ + def uniq[a](xs: Seq[a]) = groupPairwiseBy(xs)(_==_) map (_.head) + + /** + * A specialization of argmin that uses the identity function as the + * comparison key. + * <p> + * <code> + * argminId([b,a,c]) == (a,1) + * <p> + * argminId([]) == error + * </code> + */ + def argminId[a <: Ordered[a]](xs: Iterator[a]) = argmin(xs)(x => x) + def argmin[a, b <: Ordered[b]](xs: Iterator[a])(f: a => b) = { + val i = Iterator from 0 + val first = xs.next + ((first, f(first), i.next) /: xs) { (p:(a,b,Int),y:a) => + val fy = f(y) + val iy = i.next + if (p._2 < fy) p else (y,fy,iy) + } + } + + /** + * Sort-merge streams. Assumes that the stream are each sorted already. + */ + def merge[a, b <: Ordered[b]](streams: Seq[BufferedIterator[a]])(f: a => b): Stream[a] = { + def loop: Stream[a] = { + val nonempty = streams filter (_ hasNext) + if (nonempty isEmpty) { + Stream empty + } else { + val (miniter,minvalue,minindex) = argmin( nonempty )( x => f(x head) ) + val p = miniter.head + nonempty(minindex).next + Stream cons (p, loop) + } + } + loop + } + + /** + * Get the i-th element of a flatten list of lists. + * <p> + * <code>coord(7, [[a,b],[],[c,d,e],[f],[g,h,i],[j,k]]) == h</code> + * @deprecated Use instead: <code>xss.flatMap(x=>x)(0)</code>. + */ def coord[a](i: Int, xss: Iterable[Seq[a]]): (Int, Int) = { var x = i var y = 0 @@ -435,35 +660,47 @@ /** * Convenience constructor for converting an Iterator into an ArrayBuffer. + * @deprecated Use instead: <code>xs.toElements</code>. */ def newArrayBuffer[a](xs: Iterator[a]) = { val buf = new mut.ArrayBuffer[a] buf ++= xs buf } + + // + // Trees + // + /** - * Swap the elements of a tuple. + * A simple tree class where each node (Tree) is a Leaf or a Branch, and each + * Branch contains a list of other Trees. */ - def swap[a,b](p: (a,b)) = (p._2, p._1) - object Tree { + /** + * A simple tree class where each node (Tree) is a Leaf or a Branch, and each + * Branch contains a list of other Trees. + */ abstract class Tree[a] { /** * Show the tree as a string. + * <code> + * <p> + * Leaf("a") -><p> + * a<p> + * <p> + * Branch(List(Leaf("a"), Leaf("b"))) -><p> + * a<p> + * b<p> + * <p> + * Branch(List(Leaf("a"), Branch(List(Leaf("b"), Leaf("c"))), Leaf("d")))<p> + * -><p> + * a<p> + * b<p> + * c<p> + * d<p> + * </code> */ - // Leaf("a") -> - // a - // - // Branch(List(Leaf("a"), Leaf("b"))) -> - // a - // b - // - // Branch(List(Leaf("a"), Branch(List(Leaf("b"), Leaf("c"))), Leaf("d"))) - // -> - // a - // b - // c - // d def show(showLeaf: a => String): String = { def r(t: Tree[a]): Stream[String] = t match { case Branch(ts) => Stream concat (ts map r) map (" " + _) @@ -514,6 +751,10 @@ } } + /** + * A boolean expression tree contains nodes corresponding to And, Or, Not, + * and Leaf. And, Or contain any number of children. + */ abstract class BoolTree[a] { def sat(f: a => Boolean): Boolean = this match { case And(ts) => ts forall (_ sat f) @@ -533,8 +774,10 @@ case Not(t) => t flatten f case Leaf(x) => Stream cons (f(x), Stream empty) } - // TODO this looks a candidate for some nicer monadic-style sum - // f returns false if the leaf is to be pruned out, and true otherwise + // TODO: this looks a candidate for some nicer monadic-style sum. + /** + * f returns false if the leaf is to be pruned out, and true otherwise. + */ def prune[b](f: a => Option[b]): Option[BoolTree[b]] = this match { case And(ts) => { @@ -560,51 +803,9 @@ case class Not[a](t: BoolTree[a]) extends BoolTree[a] case class Leaf[a](x: a) extends BoolTree[a] - def uniq[a](xs: Seq[a]) = groupPairwiseBy(xs)(_==_) map (_.head) - - // [b,a,c] -> (a,1) - // [] -> error - def argminId[a <: Ordered[a]](xs: Iterator[a]) = argmin(xs)(x => x) - def argmin[a, b <: Ordered[b]](xs: Iterator[a])(f: a => b) = { - val i = Iterator from 0 - val first = xs.next - ((first, f(first), i.next) /: xs) { (p:(a,b,Int),y:a) => - val fy = f(y) - val iy = i.next - if (p._2 < fy) p else (y,fy,iy) - } - } -// def merge[a, b <: Ordered[b]](streams: Seq[Stream[a]])(f: a => b): Stream[a] = { -// val nonempty = streams filter (!_.isEmpty) -// if (nonempty isEmpty) { -// Stream empty -// } else { -// val (minvalue,minindex) = argmin( nonempty map f(_ head) ) -// val remaining = for ((s,i) <- nonempty zipWithIndex) -// yield if (i == minindex) s.tail else s -// Stream cons (minvalue, merge(remaining)) -// } -// } -// def mergeId[a <: Ordered[a]](streams: Seq[Stream[a]]): Stream[a] = -// merge(streams)(x => x) - def concat[a](iters: Seq[Iterator[a]]) = - iters reduceLeft ((x: Iterator[a], y: Iterator[a]) => x ++ y) - def merge[a, b <: Ordered[b]](streams: Seq[BufferedIterator[a]])(f: a => b): Stream[a] = { - def loop: Stream[a] = { - val nonempty = streams filter (_ hasNext) - if (nonempty isEmpty) { - Stream empty - } else { - val (miniter,minvalue,minindex) = argmin( nonempty )( x => f(x head) ) - val p = miniter.head - nonempty(minindex).next - Stream cons (p, loop) - } - } - loop - } - + // // Performance work-arounds. + // /** * The standard library Iterator.dropWhile is inefficient and non-scalable, @@ -633,51 +834,12 @@ dst } - def orderedMultimap[a,b](xs: List[(a,b)]) = { - val h = new mut.HashMap[a, mut.ArrayBuffer[b]] { - override def default(k: a) = { - this(k) = new mut.ArrayBuffer[b] - this(k) - } - } - for ((k,v) <- xs) h(k) += v - h - } - def iterator2array[a](xs: Iterator[a]) = xs.toList.toArray - - // TODO where does this go??? // - // [1,3,5,6,7,8] odd -> ([1,3,5],[6,7,8]) - // [] _ -> ([],[]) + // Misc // - def camelToLower(s: String, sep: String) = { - val xs = - for (c <- s) - yield if (c.isUpperCase) sep + c.toLowerCase else c - xs mkString "" - } - def camelToUnder(s: String) = camelToLower(s, "_") - def camelToHyphen(s: String) = camelToLower(s, "-") - def camelToSpaced(s: String) = camelToLower(s, " ") - - def spacedToHyphen(s: String) = s replaceAll (" ", "-") - - // TODO: this isn't really rot encoding - def rot(n: Int, s: String) = s map (_ + n toChar) mkString - - def untilNull[a](f: => a) = new Iterator[a] { - var upcoming = f - override def hasNext = upcoming != null - override def next = { - val emit = upcoming - upcoming = f - emit - } - } - /** - * Returns the positive (unsigned int) modulo. + * Return the positive (unsigned int) modulo. */ def mod(n: Int, m: Int) = { val r = n % m @@ -685,23 +847,8 @@ } /** - * Returns pairs of elements. - * <p> - * <code> - * pairs([a,b,c,d]) == [(a,b),(c,d)] - * pairs([a,b,c,d,e]) == [(a,b),(c,d)] - * </code> + * Return a map that assigns unique IDs to distinct objects. */ - def pairs[a](xs: Seq[a]): Stream[(a,a)] = { - xs match { - case Seq() => Stream empty - case Seq(a, b, rest @ _*) => Stream cons ((a,b), pairs(rest)) - } - } - - /** - * Maps unique IDs to distinct objects. - */ class IdMapper[a] extends mut.HashMap[a,Int] { val i = Iterator from 0 override def default(k: a) = { @@ -721,56 +868,4 @@ (i >>> 16) & 0xff, (i >>> 24) & 0xff ).map(_.toChar).mkString - - /** - * For each x in xs, if p(x), then x is a header, and it owns all the xs - * after it until the next x for which p(x) holds. The return value is the - * header and its body. - * <p> - * <code> - * groupByHeaders([1,2,3,4,5,6,7,8,9])(_%3==0) == [[3,4,5],[6,7,8],[9]] - * </code> - */ - def groupByHeaders[a](xs: Seq[a])(p: a => Boolean) = { - val ys = new mut.ArrayBuffer[mut.ArrayBuffer[a]] - for (x <- xs) { - if (p(x)) ys += new mut.ArrayBuffer[a] - if (!ys.isEmpty) ys.last += x - } - ys - } -// def groupByHeaders[a](xs: Seq[a])(p: a => Boolean) = { -// def r(seq: Seq[a]): Stream[List[a]] = seq match { -// case Seq() => Stream.empty -// case Seq(y,ys@_*) => { -// val (as,bs) = spanBy(ys)(not(p)) -// Stream.cons(y :: as.toList, r(bs)) -// } -// } -// r(xs dropWhile (not(p))) -// } - - /** - * <code> - * separateHeads([[a,b,c],[d,e,f,g],[],[h]]) - * == [(a,[b,c]),(d,[e,f,g]),(h,[])] - * </code> - */ - def separateHeads[a](xss: Seq[Seq[a]]) = - for (xs <- xss; (Seq(a),b) = span(1)(xs)) yield (a,b) - - - /** - * Construct a multimap out of the given key-value pairs; the result maps - * keys to sets of values. - */ - def multimap[a,b](xs: Iterable[(a,b)]) = { - val h = new mut.HashMap[a,mut.Set[b]] with mut.MultiMap[a,b] { - override def makeSet = new mut.HashSet[b] - } - for ((k,v) <- xs) { - h add (k,v) - } - h - } } Modified: scala-commons/trunk/src/commons/Control.scala =================================================================== --- scala-commons/trunk/src/commons/Control.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Control.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -4,29 +4,57 @@ import Misc._ object Control { - /* - trait Disposeable { - def dispose: Unit; - } - def using[a <% Disposeable, b](x: a)(f: a => b) = - try { f(x) } - finally { x.dispose; } - */ + + /** + * Close streams. + */ def using[a <% Closeable, b](x: a)(f: a => b) = try { f(x) } finally { x.close } + + /** + * Time some code. + */ def time(f: =>Any): Long = { val start = System.currentTimeMillis f val stop = System.currentTimeMillis stop - start } + + /** + * Return Some(f) if the function succeeded, or None if there was an + * Exception. + */ def optionize[a](f: => a) = try { Some(f) } catch { case _ => None } + + /** + * Return true if the function succeeded, or false if there was an Exception. + */ def success(f: => Any) = try { f; true } catch { case _ => false } + + /** + * Invoke f forever. + */ def loop[a](f: => a) { loop(const(f)) } + + /** + * Invoke f(i) for all i from 0 on. + */ def loop[a](f: Int => a) = for (val x <- Stream from 0) f(x) + + /** + * Stream the repetition of f. + * + * @deprecated Use {@link commons.Collections.repeat} instead. + */ def lazyLoop[a](f: => a): Stream[a] = lazyLoop(const(f)) + + /** + * Stream f(i) for all i from 0 on. + */ def lazyLoop[a](f: Int => a): Stream[a] = Stream from 0 map f + } Modified: scala-commons/trunk/src/commons/Debug.scala =================================================================== --- scala-commons/trunk/src/commons/Debug.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Debug.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -5,7 +5,8 @@ import Misc._ import Io._ -// TODO use jakarta commons logging and/or log4j +// TODO Use jakarta commons logging and/or log4j. +// TODO Redo this whole forsaken thing. /* object Logger { @@ -26,10 +27,15 @@ */ object Debug { + + /** + * Output a labeled value, and return the value. Similar to Haskell's trace. + */ def trace[a](label: String, x: a) = { println(label + x) x } + val logFile = TextWriter("log") type Level = Int object Levels { @@ -126,6 +132,5 @@ // extends LogRoot(label + "." + label2, indent + 3) // } // class Log(label: String) extends LogRoot(label, 0) + } - -import Debug._ Added: scala-commons/trunk/src/commons/English.scala =================================================================== --- scala-commons/trunk/src/commons/English.scala (rev 0) +++ scala-commons/trunk/src/commons/English.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -0,0 +1,64 @@ +package commons + +import Collections._ +import Misc._ +import java.util.regex.Pattern + +object English { + val consonants = "bcdfghjklmnpqrstvwxz" + val singularizePattern = Pattern.compile("[%s]ies" % consonants) + implicit def str2english(s: String): EnglishText = EnglishText(s) + implicit def english2str(s: EnglishText): String = s.s + case class EnglishText(val s: String) { + /** + * Return the singular of s (if it's plural). + */ + def singularize = { + val lowered = s.toLowerCase + if (Array("ches", "shes", "sses") exists (lowered endsWith _)) { + s truncate 2 + } else if (singularizePattern matcher lowered find) { + (s truncate 3) + "y" + } else if (lowered endsWith "s") { + s truncate 1 + } else { + s + } + } + } + + /** + * Return true if and only if the target contains the query phrase, using + * search engine phrase search semantics. + */ + def phraseSearch(query: String, target: String) = { + val qs = tokenize(query) toArray; + val ts = tokenize(target) toArray; + // TODO this should really take an equalsWith (but I don't like the extra f) + slices(ts, qs.length) exists { slice => seqsEqual(slice,qs) } + } + + /** + * Shallow comparison of two sequences. + */ + def seqsEqual[a](xs: Seq[a], ys: Seq[a]) = + xs.length == ys.length && ( (xs zip ys) forall { case (x,y) => x == y }) + + /** + * The delimiters for the tokenizer. + */ + val delims = " \r\n\t,./;[]\\<>?:\"{}|`~!@#$%^&*()-=+'" + + /** + * Tokenize things, with special dropping of apostrophes/single-quotes. + */ + def tokenize( s: String ) = { + import java.util.StringTokenizer + val t = new StringTokenizer( s, delims, false ) + def recur: Stream[String] = + if ( ! t.hasMoreElements ) Stream.empty + else Stream.cons( t.nextToken, recur ) + recur + } + +} Deleted: scala-commons/trunk/src/commons/ExtractorObject.scala =================================================================== --- scala-commons/trunk/src/commons/ExtractorObject.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/ExtractorObject.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -1,67 +0,0 @@ -package commons - -/** - * From http://users.utu.fi/hvkhut/scalad/extractorobject.htm. - * Copyright Henrik Huttunen. - */ - -object ExtractorObject{ - // from http://users.utu.fi/hvkhut/scalad/extractorobject.htm - implicit def seqCharToString(seq: scala.Seq[Char]): String - = seq.foldLeft("")((b, a) => b + a) - private def rotateRight(char: Char, amount: Int) - = (char.toInt + amount).toChar - private def rotateLeft(char: Char, amount: Int) - = (char.toInt - amount).toChar - private def rotate(x: String, amount: Int, - rotateChar: (Char, Int) => Char): String - = x.map(char => rotateChar(char, amount)) - class FixedString(string: String) { - import collection.mutable.ArrayBuffer - def dropFixed(n: Int): Seq[Char] - = new ArrayBuffer[Char] ++ string.elements.drop(n) - } - implicit def string2FixedString(x: String): FixedString - = new FixedString(x) - object BinaryNumberWord{ - val Zero = "zero" - val One = "one" - def apply(x: Int) = x match { - case 0 => Zero - case 1 => One - case _ => error("Not legal number: " + x) - } - def unapply(x: String) = x match { - case Zero => Some(0) - case One => Some(1) - case _ => None - } - } - object EncodedString{ - private val times = 13 - private val header = "[rot]" - def apply(x: String) = header + rotate(x, times, rotateRight) - def unapply(x: String) = { - val front: String = x.take(header.length) - //val front = x.take(header.length) - if(front == header){ - val dropped = x.dropFixed(header.length) - Some(rotate(dropped, times, rotateLeft)) - } - else None - } - } - def test(x: String) = x match { - case EncodedString(decoded) => x + " is as decoded: " + decoded - case BinaryNumberWord(number) => x + " is as word: " + number - case _ => x + " is unknown" - } - def example = { - import Console.println - println(test(EncodedString("classified information"))) - println(test(BinaryNumberWord(0))) - println(test(BinaryNumberWord(1))) - } -} - -import ExtractorObject._ Modified: scala-commons/trunk/src/commons/Hash.scala =================================================================== --- scala-commons/trunk/src/commons/Hash.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Hash.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -1,5 +1,8 @@ package commons +/** + * Various hash functions. + */ object Hash { /** Modified: scala-commons/trunk/src/commons/Io.scala =================================================================== --- scala-commons/trunk/src/commons/Io.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Io.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -11,17 +11,33 @@ // TODO see also: Source // Source.fromInputStream(System.in).getLines.foreach { line => etc... } -// TODO fix the followin +object Io { -object Io { + // + // Views + // + implicit def InputStream2BinaryReader(is: InputStream) = BinaryReader(is) implicit def BinaryReader2InputStream(br: BinaryReader) = br.in implicit def Reader2TextReader(r: Reader) = TextReader(r) implicit def TextReader2Reader(tr: TextReader) = tr.in - //implicit def os2xos[os <: OutputStream](os: os) = new XOutputStream(os) - //implicit def xos2os[os <: OutputStream](xos: XOutputStream) = xos.stream + + // + // Files + // + + /** + * @deprecated + */ def fileExists(fname: String) = new File(fname).exists + // + // IO streams + // + + /** + * A reader for streams of binary data. + */ class BinaryReader(val in: InputStream) extends AnyRef with Closeable { def read = { val chunks = new ArrayBuffer[Array[Byte]]() @@ -36,11 +52,17 @@ def close = in.close } + /** + * Constructors. + */ object BinaryReader { def apply(in: InputStream) = new BinaryReader(in) def apply(fname: String) = new BinaryReader(new FileInputStream(fname)) } + /** + * A reader for text streams. + */ class TextReader(val in: BufferedReader) extends AnyRef with Closeable { def readLine = in.readLine def readLines: Stream[String] = { @@ -52,6 +74,9 @@ def close = in.close } + /** + * Constructors. + */ object TextReader { def apply(is: InputStream): TextReader = apply(new InputStreamReader(is)) @@ -61,15 +86,24 @@ apply(new FileReader(fname)) } + /** + * A writer for streams of binary data. + */ class BinaryWriter(out: OutputStream) extends Closeable { def write(x: Array[Byte]) = out.write(x) def close = out.close } + /** + * Constructors. + */ object BinaryWriter { def apply(fname: String) = new BinaryWriter(new FileOutputStream(fname)) } + /** + * Constructors. + */ object TextWriter { def apply(fname: String) = new PrintWriter(new FileOutputStream(fname), true) @@ -77,16 +111,35 @@ new PrintWriter(out) } + // + // Serialization + // + + /** + * Read a Java serialization object from a file. + */ def readObject(fname: String) = { val bytes = using (BinaryReader(fname)) (_ read) using (new ObjectInputStream(new ByteArrayInputStream(bytes))) (_ readObject) } + + /** + * Write an object to a file using Java serialization. + */ def writeObject(fname: String, x: AnyRef) { val bytes = new ByteArrayOutputStream using (new ObjectOutputStream(bytes)) (_ writeObject x) using (BinaryWriter(fname)) (_ write bytes.toByteArray) } + // + // Processes + // + + /** + * Run a command, providing the given input to stdin. On success, return + * stdout; on error, print stderr to stderr and raise an exception. + */ def run(cmd: String, input: String) = { val proc = Runtime.getRuntime.exec(cmd) using (TextWriter(proc.getOutputStream)) (_ println input) @@ -101,4 +154,3 @@ } } -import Io._ Modified: scala-commons/trunk/src/commons/Misc.scala =================================================================== --- scala-commons/trunk/src/commons/Misc.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Misc.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -1,10 +1,12 @@ package commons -import java.util.regex.Pattern - import Collections._ object Misc { + + /** + * @deprecated Use {@link Iterator.from} instead. + */ @serializable class Uniq(var x: Int) { def next = { @@ -12,112 +14,84 @@ x - 1 } } + + // TODO: Better name? + /** + * Funnel a value into the range [0,max]. + */ def bounds(max: Int, x: Int): Int = bounds(0, max, x) + + /** + * Funnel a value into the range [min,max]. + */ def bounds(min: Int, max: Int, x: Int) = Math.max(min, Math.min(max-1, x)) - def wrapMod(x: Int, mod: Int) = if (x < 0) mod + x % mod else x % mod + + // TODO: Better name? + /** + * Return the positive modulus x mod m. + */ + def wrapMod(x: Int, m: Int) = if (x < 0) m + x % m else x % m + def succ(x: Int) = x + 1 def pred(x: Int) = x - 1 def const[a](f: => a): Any => a = ((x: Any) => f) + + // TODO: move this to the same place as optionize and success in Control. + /** + * Return the result of f on success or null if there was an exception. + */ def nullifyExceptions[a >: Null](f: => a): a = try { f } catch { case e => null } + + /** + * "Simplify" a String by trimming and lower-casing it. + */ def simplify(s: String) = s.trim.toLowerCase + + /** + * Rich string view. + */ case class XString(val s: String) { + /** + * Case-insensitive comparator. + */ def ===(that: String) = s equalsIgnoreCase that + /** + * Case-insensitive comparator. + */ def !==(that: String) = !(===(that)) + /** + * Repeat the string n times. + */ def *(n: Int) = repeat(s) take n mkString ("", "", "") + /** + * Truncate a string to be of length n. + */ def truncate(n: Int) = s substring (0, s.length - n) + /** + * String interpolator. + */ def %[A](s: A*): String = format(s.map(_.asInstanceOf[AnyRef]).toArray) + /** + * String interpolator. + */ def format(a: Array[AnyRef]) = String.format(s, a) } implicit def str2xstr(s: String): XString = XString(s) implicit def xstr2str(s: XString): String = s.s + + /** + * Identity function. + */ def id[a](x: a) = x - // aka symbol generator + /** + * Generate Strings that are the given base string with a unique integer + * appended. + */ class HandleGenerator(base: String) extends Iterator[String] { val i = Iterator from 0 override def next = base + i.next override def hasNext = i.hasNext } -// class OrderedPair[a <: Ordered[a], b](x:a,y:b) extends GPair[a,b](x,y) with Ordered[OrderedPair[a,b]] { -// override def compare(o: OrderedPair[a,b]) = x compare o._1 -// } -// class OrderedPair[a <: Ordered[a], b](val x:a,val y:b) extends Ordered[Tuple2[a,b]] { -// override def compare(o: Tuple2[a,b]) = x compare o._1 -// } } - -import Misc._ - -object English { - val consonants = "bcdfghjklmnpqrstvwxz" - val singularizePattern = Pattern.compile("[%s]ies" % consonants) - implicit def str2english(s: String): EnglishText = EnglishText(s) - implicit def english2str(s: EnglishText): String = s.s - case class EnglishText(val s: String) { - // Returns the singular of s - def singularize = { - val lowered = s.toLowerCase - if (Array("ches", "shes", "sses") exists (lowered endsWith _)) { - s truncate 2 - } else if (singularizePattern matcher lowered find) { - (s truncate 3) + "y" - } else if (lowered endsWith "s") { - s truncate 1 - } else { - s - } -// if lowered in plurals: -// def matchCase(s1, s2): -// """Matches the case of s1 in s2""" -// if s1.isupper(): -// return s2.upper() -// else: -// L = list(s2) -// for (i, char) in enumerate(s1[:len(s2)]): -// if char.isupper(): -// L[i] = L[i].upper() -// return ''.join(L) -// return matchCase(s, plurals[lowered]) -// elif any(lowered.endswith, ['ches', 'shes', 'sses']): -// return s[:-2] -// elif re.search(depluralizeRegex, lowered): -// return s[:-3] + 'y' -// else: -// if lowered.endswith('s'): -// return s[:-1] # Chop off 's'. -// else: -// return s # Don't know what to do. - } - } - // similar to a search engine's phrase search semantics - // returns true iff we can the target contains the query phrase - // XXX 2.6.0 required -// def phraseSearch(query: String, target: String) = { -// val qs = List(tokenize(query):_*); -// val ts = List(tokenize(target):_*); -// // TODO this should really be an equalsWith (but I don't like the extra f) -// slices(ts, qs.length) exists (_ startsWith qs) -// } - def seqsEqual[a](xs: Seq[a], ys: Seq[a]) = - xs.length == ys.length && ( (xs zip ys) forall { case (x,y) => x == y }) - def phraseSearch(query: String, target: String) = { - val qs = tokenize(query) toArray; - val ts = tokenize(target) toArray; - // TODO this should really be an equalsWith (but I don't like the extra f) - slices(ts, qs.length) exists { slice => seqsEqual(slice,qs) } - } - // the delimiters for the tokenizer - val delims = " \r\n\t,./;[]\\<>?:\"{}|`~!@#$%^&*()-=+'" - // tokenize things, with special dropping of apostrophes/single-quotes - def tokenize( s: String ) = { - import java.util.StringTokenizer - val t = new StringTokenizer( s, delims, false ) - def recur: Stream[String] = - if ( ! t.hasMoreElements ) Stream.empty - else Stream.cons( t.nextToken, recur ) - recur - } -} - -import English._ Modified: scala-commons/trunk/src/commons/Path.scala =================================================================== --- scala-commons/trunk/src/commons/Path.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Path.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -1,14 +1,23 @@ package commons + import java.io.File + object Path { implicit def StringToPathString(s: String) = PathString(s) implicit def PathStringToString(p: PathString) = p.path val sep = File.separatorChar case class PathString(path: String) { + /** + * Join two paths without adding redundant path separators. + */ def /(relpath: String) = if (path.last == sep) path + relpath else path + sep + relpath } + + /** + * Return path if it's already an absolute path, and dir/path otherwise. + */ def rel2abs(dir: String, path: String) = if (path startsWith "/") path else dir / path } Modified: scala-commons/trunk/src/commons/Repl.scala =================================================================== --- scala-commons/trunk/src/commons/Repl.scala 2008-02-22 19:25:34 UTC (rev 477) +++ scala-commons/trunk/src/commons/Repl.scala 2008-02-22 23:44:36 UTC (rev 478) @@ -1,5 +1,8 @@ package commons +/** + * Things that may be helpful in a Scala REPL. + */ object Repl { case class Introspecter[a<:AnyRef](x:a) { def ? = m ++ f // p(x.getClass.getMethods.toList) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |