/* * $Id: Awk.java,v 1.21 2007/10/15 16:10:09 bacon Exp $ * * {License} */ package ase.awk; import java.io.*; import java.util.HashMap; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; public abstract class Awk { private HashMap functionTable; // mode for open_source & close_source public static final int SOURCE_READ = 1; public static final int SOURCE_WRITE = 2; // depth id public static final int DEPTH_BLOCK_PARSE = (1 << 0); public static final int DEPTH_BLOCK_RUN = (1 << 1); public static final int DEPTH_EXPR_PARSE = (1 << 2); public static final int DEPTH_EXPR_RUN = (1 << 3); public static final int DEPTH_REX_BUILD = (1 << 4); public static final int DEPTH_REX_MATCH = (1 << 5); // options public static final int OPTION_IMPLICIT = (1 << 0); public static final int OPTION_EXPLICIT = (1 << 1); public static final int OPTION_UNIQUEFN = (1 << 2); public static final int OPTION_SHADING = (1 << 3); public static final int OPTION_SHIFT = (1 << 4); public static final int OPTION_IDIV = (1 << 5); public static final int OPTION_STRCONCAT = (1 << 6); public static final int OPTION_EXTIO = (1 << 7); public static final int OPTION_COPROC = (1 << 8); public static final int OPTION_BLOCKLESS = (1 << 9); public static final int OPTION_ASEONE = (1 << 10); public static final int OPTION_STRIPSPACES = (1 << 11); public static final int OPTION_NEXTOFILE = (1 << 12); public static final int OPTION_CRLF = (1 << 13); public static final int OPTION_ARGSTOMAIN = (1 << 14); public static final int OPTION_RESET = (1 << 15); public static final int OPTION_MAPTOVAR = (1 << 16); public static final int OPTION_PABLOCK = (1 << 17); protected final static Reader stdin = new BufferedReader (new InputStreamReader (System.in)); protected final static Writer stdout = new BufferedWriter (new OutputStreamWriter (System.out)); private long awkid; public Awk () throws Exception { this.awkid = 0; this.functionTable = new HashMap (); open (); } /* == just in case == */ protected void finalize () throws Throwable { if (this.awkid != 0) close (); super.finalize (); } /* == native methods == */ private native void open () throws Exception; public native void close (); public native void parse () throws Exception; public native void run (String main, String[] args) throws Exception; public native void stop (); private native int getmaxdepth (int id); private native void setmaxdepth (int id, int depth); private native int getoption (); private native void setoption (int opt); private native boolean getdebug (); private native void setdebug (boolean debug); private native void setword (String ow, String nw); private native void addfunc ( String name, int min_args, int max_args) throws Exception; private native void delfunc (String name) throws Exception; native void setfilename ( long runid, String name) throws Exception; native void setofilename ( long runid, String name) throws Exception; private native Object strtonum ( long runid, String str) throws Exception; private native String valtostr ( long runid, Object obj) throws Exception; protected native String strftime (String fmt, long sec); protected native String strfgmtime (String fmt, long sec); protected native int system (String cmd); /* == simpler run methods == */ public void run (String main) throws Exception { run (main, null); } public void run (String[] args) throws Exception { run (null, args); } public void run () throws Exception { run (null, null); } /* == intrinsic functions == */ public void addFunction (String name, int min_args, int max_args) throws Exception { addFunction (name, min_args, max_args, name); } public void addFunction (String name, int min_args, int max_args, String method) throws Exception { if (functionTable.containsKey (name)) { throw new Exception ( "cannot add existing function '" + name + "'", Exception.EXIST); } functionTable.put (name, method); try { addfunc (name, min_args, max_args); } catch (Exception e) { functionTable.remove (name); throw e; } } public void deleteFunction (String name) throws Exception { delfunc (name); functionTable.remove (name); } protected Object handleFunction ( Context ctx, String name, Object args[]) throws java.lang.Exception { String mn = (String)functionTable.get(name); // name should always be found in this table. // otherwise, there is something wrong with this program. Class c = this.getClass (); Class[] a = { Context.class, String.class, Object[].class }; Method m = c.getMethod (mn, a); return m.invoke (this, /*new Object[] {*/ ctx, name, args/*}*/) ; } protected long builtinFunctionArgumentToLong ( Context ctx, Object obj) throws Exception { long n; if (obj == null) n = 0; else { if (obj instanceof String) obj = strtonum (ctx.getId(), (String)obj); if (obj instanceof Long) { n = ((Long)obj).longValue (); } else if (obj instanceof Double) { n = ((Double)obj).longValue (); } else if (obj instanceof Integer) { n = ((Integer)obj).longValue (); } else if (obj instanceof Short) { n = ((Short)obj).longValue (); } else if (obj instanceof Float) { n = ((Float)obj).longValue (); } else n = 0; } return n; } protected double builtinFunctionArgumentToDouble ( Context ctx, Object obj) throws Exception { double n; if (obj == null) n = 0.0; else { if (obj instanceof String) obj = strtonum (ctx.getId(), (String)obj); if (obj instanceof Long) { n = ((Long)obj).doubleValue (); } else if (obj instanceof Double) { n = ((Double)obj).doubleValue (); } else if (obj instanceof Integer) { n = ((Integer)obj).doubleValue (); } else if (obj instanceof Short) { n = ((Short)obj).doubleValue (); } else if (obj instanceof Float) { n = ((Float)obj).doubleValue (); } else n = 0.0; } return n; } protected String builtinFunctionArgumentToString ( Context ctx, Object obj) throws Exception { String str; if (obj == null) str = ""; else if (obj instanceof String) str = (String)obj; else str = valtostr (ctx.getId(), obj); return str; } /* == depth limiting == */ public int getMaxDepth (int id) { return getmaxdepth (id); } public void setMaxDepth (int ids, int depth) { setmaxdepth (ids, depth); } /* == option == */ public int getOption () { return getoption (); } public void setOption (int opt) { setoption (opt); } /* == debug == */ public boolean getDebug () { return getdebug (); } public void setDebug (boolean debug) { setdebug (debug); } public void setWord (String ow, String nw) { setword (ow, nw); } public void unsetWord (String ow) { setword (ow, null); } public void unsetAllWords () { setword (null, null); } /* == source code management == */ protected abstract int openSource (int mode); protected abstract int closeSource (int mode); protected abstract int readSource (char[] buf, int len); protected abstract int writeSource (char[] buf, int len); /* == external io interface == */ protected int openExtio (Extio extio) { switch (extio.getType()) { case Extio.TYPE_CONSOLE: { Console con = new Console (this, extio); int n = openConsole (con); extio.setHandle (con); return n; } case Extio.TYPE_FILE: { File file = new File (this, extio); int n = openFile (file); extio.setHandle (file); return n; } case Extio.TYPE_PIPE: { Pipe pipe = new Pipe (this, extio); int n = openPipe (pipe); extio.setHandle (pipe); return n; } } return -1; } protected int closeExtio (Extio extio) { switch (extio.getType()) { case Extio.TYPE_CONSOLE: return closeConsole ( (Console)extio.getHandle()); case Extio.TYPE_FILE: return closeFile ((File)extio.getHandle()); case Extio.TYPE_PIPE: return closePipe ((Pipe)extio.getHandle()); } return -1; } protected int readExtio (Extio extio, char[] buf, int len) { // this check is needed because 0 is used to indicate // the end of the stream. java streams can return 0 // if the data given is 0 bytes and it didn't reach // the end of the stream. if (len <= 0) return -1; switch (extio.getType()) { case Extio.TYPE_CONSOLE: { return readConsole ( (Console)extio.getHandle(), buf, len); } case Extio.TYPE_FILE: { return readFile ( (File)extio.getHandle(), buf, len); } case Extio.TYPE_PIPE: { return readPipe ( (Pipe)extio.getHandle(), buf, len); } } return -1; } protected int writeExtio (Extio extio, char[] buf, int len) { if (len <= 0) return -1; switch (extio.getType()) { case Extio.TYPE_CONSOLE: { return writeConsole ( (Console)extio.getHandle(), buf, len); } case Extio.TYPE_FILE: { return writeFile ( (File)extio.getHandle(), buf, len); } case Extio.TYPE_PIPE: { return writePipe ( (Pipe)extio.getHandle(), buf, len); } } return -1; } protected int flushExtio (Extio extio) { switch (extio.getType()) { case Extio.TYPE_CONSOLE: { return flushConsole ((Console)extio.getHandle()); } case Extio.TYPE_FILE: { return flushFile ((File)extio.getHandle()); } case Extio.TYPE_PIPE: { return flushPipe ((Pipe)extio.getHandle()); } } return -1; } protected int nextExtio (Extio extio) { int type = extio.getType (); switch (extio.getType()) { case Extio.TYPE_CONSOLE: { return nextConsole ((Console)extio.getHandle()); } } return -1; } protected abstract int openConsole (Console con); protected abstract int closeConsole (Console con); protected abstract int readConsole (Console con, char[] buf, int len); protected abstract int writeConsole (Console con, char[] buf, int len); protected abstract int flushConsole (Console con); protected abstract int nextConsole (Console con); protected abstract int openFile (File file); protected abstract int closeFile (File file); protected abstract int readFile (File file, char[] buf, int len); protected abstract int writeFile (File file, char[] buf, int len); protected abstract int flushFile (File file); protected abstract int openPipe (Pipe pipe); protected abstract int closePipe (Pipe pipe); protected abstract int readPipe (Pipe pipe, char[] buf, int len); protected abstract int writePipe (Pipe pipe, char[] buf, int len); protected abstract int flushPipe (Pipe pipe); /* TODO: ... protected void onRunStart (Context ctx) {} protected void onRunEnd (Context ctx) {} protected void onRunReturn (Context ctx) {} protected void onRunStatement (Context ctx) {} */ }