import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; public class main { // adapters are immutable! (plus returns a modified clone) abstract static class Adapter { abstract boolean canMatch(String in, String out); Adapter plus(String in, String out) { return this; } String get(String in) { return in; } double size() { return 0; } } static class WordAdapter extends Adapter { Map wordMap = new TreeMap(); List tok(String s) { return nlTok2(dropPunctuation2(s)); } boolean canMatch(String in, String out) { List t1 = tok(in), t2 = tok(out); return l(t1) == l(t2); } Adapter plus(String in, String out) { List t1 = tok(in), t2 = tok(out); if (l(t1) != l(t2)) return this; WordAdapter a = (WordAdapter) ( nuObject(getClass())); a.wordMap = cloneMap(wordMap); for (int i = 1; i < l(t1); i += 2) { String w1 = t1.get(i), w2 = t2.get(i); if (!eqic(w1, w2)) // just overwrite - be flexible! a.wordMap.put(w1.toLowerCase(), w2.toLowerCase()); } return a; } String get(String s) { List tok = nlTok2(s); for (int i = 1; i < l(tok); i += 2) { String w = lookupToken(tok.get(i)); if (nempty(w)) tok.set(i, w); } return join(tok); } String lookupToken(String s) { return wordMap.get(s.toLowerCase()); } double size() { return l(wordMap); } public String toString() { return structure(wordMap); } } // WordAdapter static boolean adapt_debug; // put func {}'s returning a string in there // not using _log parameter anymore static void makeGenerators(List l, List _log) { gen(l, new Object() { Object get() { return "3" ; } public String toString() { return "\"3\""; }}); gen(l, "plus1", new Object() { Object get() { return parseLong(gI())+1 ; } public String toString() { return "parseLong(gI())+1"; }}); gen(l, "delta", new Object() { Object get() { return parseLong(g0())*2-parseLong(g1()) ; } public String toString() { return "parseLong(g0())*2-parseLong(g1())"; }}); gen(l, "delta unicode", new Object() { Object get() { String a = g1(), b = g0(); if (l(a) == 1 && l(b) == 1) return intToChar(charToInt(b)*2-charToInt(a)); return null; } public String toString() { return "S a = g1(), b = g0();\n if (l(a) == 1 && l(b) == 1)\n ret intToChar(charToInt(b)*2-charToInt(a));\n null;"; }}); gen(l, "exponential", new Object() { Object get() { return sqr(parseLong(g0()))/parseLong(g1()) ; } public String toString() { return "sqr(parseLong(g0()))/parseLong(g1())"; }}); gen(l, "assoc", gOneAssoc()); gen(l, "adjective magic", new Object() { Object get() { return lineAbove(findAdjectiveComment(findAdjective())) ; } public String toString() { return "lineAbove(findAdjectiveComment(findAdjective()))"; }}); gen(l, "complete line", new Object() { Object get() { return gSearchNeqNoSystem(new Object() { Object get(String s) { return startsWithIgnoreCase(s, gI()) ; } public String toString() { return "startsWithIgnoreCase(s, gI())"; }}) ; } public String toString() { return "gSearchNeqNoSystem(new O { O get(S s) { ret startsWithIgnoreCase(s, gI()) ; }\n public S toString() { ret \"startsWithIgnoreCase(s, gI())\"; }})"; }}); gen(l, "longest prefix match -> answer", new Object() { Object get() { return lineBelow(gLongestPrefixMatchNeqIdx(gI())) ; } public String toString() { return "lineBelow(gLongestPrefixMatchNeqIdx(gI()))"; }}); gen(l, "word search", new Object() { Object get() { return gSearchNeqNoSystem(new Object() { Object get(String s) { return match(gI(), s) ; } public String toString() { return "match(gI(), s)"; }}) ; } public String toString() { return "gSearchNeqNoSystem(new O { O get(S s) { ret match(gI(), s) ; }\n public S toString() { ret \"match(gI(), s)\"; }})"; }}); gen(l, "raw string search", new Object() { Object get() { return gSearchNeqNoSystem(new Object() { Object get(String s) { return containsIgnoreCase(s, gI()) ; } public String toString() { return "containsIgnoreCase(s, gI())"; }}) ; } public String toString() { return "gSearchNeqNoSystem(new O { O get(S s) { ret containsIgnoreCase(s, gI()) ; }\n public S toString() { ret \"containsIgnoreCase(s, gI())\"; }})"; }}); gen(l, "raw string search (!java)", new Object() { Object get() { return gSearchNeqNoSystem(new Object() { Object get(String s) { return s.startsWith("!java") && containsIgnoreCase(s, gI()) ; } public String toString() { return "s.startsWith(\"!java\") && containsIgnoreCase(s, gI())"; }}) ; } public String toString() { return "gSearchNeqNoSystem(new O { O get(S s) { ret s.startsWith(\"!java\") && containsIgnoreCase(s, gI()) ; }\n public S toString() { ret \"s.startsWith(\\\"!java\\\") && containsIgnoreCase(s, gI())\"; }})"; }}); gen(l, "yes/no from java", new Object() { Object get() { List tok = javaTok(gI()); if (contains(tok, "t")) return "yes"; if (contains(tok, "f")) return "no"; return null; } public String toString() { return "L tok = javaTok(gI());\n if (contains(tok, \"t\")) ret \"yes\";\n if (contains(tok, \"f\")) ret \"no\";\n null;"; }}); gen(l, "learned", new Object() { Object get() { for (List learn : gLearns()) { if (l(learn) >= 2 && match(first(learn), gI())) { String _a_1 = lastNonSystemLine(learn); if (!empty(_a_1)) return _a_1; } } return null; } public String toString() { return "for (L learn : gLearns()) {\n if (l(learn) >= 2 && match(first(learn), gI()))\n try answer lastNonSystemLine(learn);\n }\n null;"; }}); gen(l, "learned (single step)", new Object() { Object get() { for (List learn : gLearns()) { for (int i = 0; i < l(learn)-1; i++) if (match(learn.get(i), gI())) return learn.get(i+1); } return null; } public String toString() { return "for (L learn : gLearns()) {\n for (int i = 0; i < l(learn)-1; i++)\n if (match(learn.get(i), gI()))\n ret learn.get(i+1);\n }\n null;"; }}); gen(l, "learned (single step 2)", new Object() { Object get() { thislearn: for (List learn : gLearns()) { List log = gLog(); int j = l(log)-l(learn)+1; // TODO: wrong logic if (j < 0) return null; for (int i = 0; i < l(learn)-1; i++) if (!match(learn.get(i), log.get(j+i))) break thislearn; return last(learn); // all entries match } return null; } public String toString() { return "thislearn: for (L learn : gLearns()) {\n L log = gLog();\n int j = l(log)-l(learn)+1; // TODO: wrong logic\n if (j < 0) null;\n for (int i = 0; i < l(learn)-1; i++)\n if (!match(learn.get(i), log.get(j+i)))\n break thislearn;\n ret last(learn); // all entries match\n }\n null;"; }}); gen(l, "learned (single step 2, with adapter)", new Object() { Object get() { List log = gLog(); String bestResult = null; double bestValue = 0; thislearn: for (List learn : gLearns()) { if (adapt_debug) print("Testing learn: " + struct(learn)); // j is starting point of match in log j: for (int j = l(log)-l(learn)+1; j < l(log); j++) try { if (adapt_debug) print("\nl(log)=" + l(log) + ", j=" + j); Adapter adapter = new WordAdapter(); int k; for (k = j; k < l(log); k++) { String in = learn.get(k-j), out = log.get(k); if (adapt_debug) print(in + " => " + out); if (!adapter.canMatch(in, out)) { if (adapt_debug) print("Can't match"); continue j; } adapter = adapter.plus(in, out); if (adapt_debug) printStructure(" ", adapter); } double v = adapter.size(); if (bestResult == null || v < bestValue) { bestResult = adapter.get(learn.get(k-j)); bestValue = v; if (adapt_debug) print("New best: " + formatDouble(bestValue, 1) + " -- " + bestResult); } } catch (Throwable __e) { printStackTrace(__e); } } return bestResult; } public String toString() { return "L log = gLog();\n S bestResult = null;\n double bestValue = 0;\n thislearn: for (L learn : gLearns()) {\n if (adapt_debug) print(\"Testing learn: \" + struct(learn));\n \n // j is starting point of match in log\n j: for (int j = l(log)-l(learn)+1; j < l(log); j++) pcall {\n if (adapt_debug) print(\"\\nl(log)=\" + l(log) + \", j=\" + j);\n Adapter adapter = new WordAdapter();\n int k;\n for (k = j; k < l(log); k++) {\n S in = learn.get(k-j), out = log.get(k);\n if (adapt_debug) print(in + \" => \" + out);\n if (!adapter.canMatch(in, out)) {\n if (adapt_debug) print(\"Can't match\");\n continue j;\n }\n adapter = adapter.plus(in, out);\n if (adapt_debug) printStructure(\" \", adapter);\n }\n double v = adapter.size();\n if (bestResult == null || v < bestValue) {\n bestResult = adapter.get(learn.get(k-j));\n bestValue = v;\n if (adapt_debug) print(\"New best: \" + formatDouble(bestValue, 1) + \" -- \" + bestResult);\n }\n }\n }\n ret bestResult;"; }}); gen(l, "grow suffix", new Object() { Object get() { String a = g1(), b = g0(); if (b.startsWith(a)) return b + b.substring(l(a)); return null; } public String toString() { return "S a = g1(), b = g0();\n if (b.startsWith(a))\n ret b + b.substring(l(a));\n null;"; }}); gen(l, "grow prefix", new Object() { Object get() { String a = g1(), b = g0(); return growPrefix(a, b); } public String toString() { return "S a = g1(), b = g0();\n ret growPrefix(a, b);"; }}); gen(l, "strip common prefix + grow prefix", new Object() { Object get() { String a = g1(), b = g0(); int l = lCommonPrefix(a, b); if (l == 0) return null; String s = growPrefix(a.substring(l), b.substring(l)); if (empty(s)) return null; return a.substring(0, l) + s; } public String toString() { return "S a = g1(), b = g0();\n int l = lCommonPrefix(a, b);\n if (l == 0) null;\n S s = growPrefix(a.substring(l), b.substring(l));\n if (empty(s)) null;\n ret a.substring(0, l) + s;"; }}); } static String findAdjective() { return findAdjective(gI()); } static String findAdjective(String s) { return findOneOfTheWords(s, "crazy", "nice"); } static int findAdjectiveComment(final String adjective) { if (adjective == null) return -1; return gSearchIdx(new Object() { Object get(String s) { return matchStart("that's", s) && find3(adjective, s) ; } public String toString() { return "matchStart(\"that's\", s) && find3(adjective, s)"; }}); } static Object gOneAssoc() { return new Object() { Object get() { List log = genLog(); for (int i = l(log)-2; i >= 0; i--) if (eqic(log.get(i), last(log))) return log.get(i+1); return null; } public String toString() { return "L log = genLog();\n for (int i = l(log)-2; i >= 0; i--)\n if (eqic(log.get(i), last(log)))\n ret log.get(i+1);\n null;"; }}; } static String struct(Object o) { return structure(o); } static Class getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static Class getClass(Object o) { return o instanceof Class ? (Class) o : o.getClass(); } static Class getClass(Object realm, String name) { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static String gI() { return last(genLog()); } static String gSearchNeqNoSystem(Object predicate) { return _get(genLog(), gSearchNeqNoSystemIdx(predicate)); } // replacement for class JavaTok // maybe incomplete, might want to add floating point numbers // todo also: extended multi-line strings static int javaTok_n, javaTok_elements; static boolean javaTok_opt; static List javaTok(String s) { return javaTok(s, null); } static List javaTok(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; List tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j+2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(quickSubstring(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); // cc is not needed in rest of loop body cc = s.substring(i, Math.min(i+2, l)); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (cc.equals("[[")) { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (cc.equals("[=") && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(quickSubstring(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static List javaTok(List tok) { return javaTok(join(tok), tok); } static boolean javaTok_isCopyable(String t, String s, int i, int j) { return t.length() == j-i && s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave } static int lCommonPrefix(String a, String b) { int i = 0; while (i < a.length() && i < b.length() && a.charAt(i) == b.charAt(i)) ++i; return i; } static String lineAbove(int i) { return get(genLog(), i-1); } // reduced NL parsing without quoted strings and some other stuff static List nlTok2(String s) { List tok = new ArrayList(); int l = s.length(); int i = 0; while (i < l) { int j = i; char c; // scan for whitespace while (j < l) { c = s.charAt(j); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); // scan for non-whitespace if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) /*|| s.charAt(j) == '\''*/)); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static String lineBelow(int i) { return get(genLog(), i+1); } static boolean empty(Collection c) { return isEmpty(c); } static boolean empty(String s) { return isEmpty(s); } static boolean empty(Map map) { return map == null || map.isEmpty(); } static boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); return false; } // assumes the function returns toString() static void gen(List l, Object func) { l.add(new Gen(str(func), func)); } static void gen(List l, String name, Object func) { l.add(new Gen(name, func)); } static void gen(List l, int line, Object func) { gen(l, str(line), func); } static void gen(List l, Quine q) { gen(l, q.text, q.value); } static boolean find3(String pat, String s) { return find3(pat, s, null); } static boolean find3(String pat, String s, Matches matches) { List tokpat = parse3(pat), toks = parse3(s); String[] m = find2(tokpat, toks); //print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static long sqr(long l) { return l*l; } static boolean matchStart(String pat, String s) { return matchStart(pat, s, null); } // matches are as you expect, plus an extra item for the rest string static boolean matchStart(String pat, String s, Matches matches) { if (s == null) return false; List tokpat = parse3(pat), toks = parse3(s); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, toks.subList(0, tokpat.size())); //print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) { matches.m = new String[m.length+1]; arraycopy(m, matches.m); matches.m[m.length] = join(toks.subList(tokpat.size(), toks.size())); // for Matches.rest() } return true; } } public static String join(String glue, Iterable strings) { StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String[] strings) { return join(glue, Arrays.asList(strings)); } public static String join(Iterable strings) { return join("", strings); } public static String join(String[] strings) { return join("", strings); } static void printStructure(String prefix, Object o) { print(prefix + structure(o)); } static void printStructure(Object o) { print(structure(o)); } static String findOneOfTheWords(String s, String... words) { List tok = nlTok(s); for (int i = 1; i < l(tok); i += 2) if (eqicOneOf(tok.get(i), words)) return tok.get(i); return null; } public static String formatDouble(double d, int digits) { String format = "0."; for (int i = 0; i < digits; i++) format += "#"; return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d); } static String growPrefix(String a, String b) { if (b.endsWith(a)) return b.substring(0, l(b)-l(a)) + b; return null; } static Map cloneMap(Map map) { // assume mutex is equal to collection, which will be true unless you explicitly pass a mutex to synchronizedList() which no one ever does. synchronized(map) { return new HashMap(map); } } static A last(List l) { return l.isEmpty() ? null : l.get(l.size()-1); } static boolean nempty(Collection c) { return !isEmpty(c); } static boolean nempty(CharSequence s) { return !isEmpty(s); } static boolean nempty(Object[] o) { return !isEmpty(o); } static boolean match(String pat, String s) { return match3(pat, s); } static boolean match(String pat, String s, Matches matches) { return match3(pat, s, matches); } static boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static String g0() { return last(genLog()); } static String g1() { return nextToLast(genLog()); } static boolean containsIgnoreCase(List l, String s) { for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String[] l, String s) { for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String s, char c) { return indexOfIgnoreCase(s, String.valueOf(c)) >= 0; } static boolean containsIgnoreCase(String a, String b) { return indexOfIgnoreCase(a, b) >= 0; } static int l(Object[] array) { return array == null ? 0 : array.length; } static int l(byte[] array) { return array == null ? 0 : array.length; } static int l(int[] array) { return array == null ? 0 : array.length; } static int l(char[] array) { return array == null ? 0 : array.length; } static int l(Collection c) { return c == null ? 0 : c.size(); } static int l(Map m) { return m == null ? 0 : m.size(); } static int l(String s) { return s == null ? 0 : s.length(); } static int l(Object o) { return l((List) o); // incomplete } static String lastNonSystemLine(List l) { for (int i = l(l)-1; i >= 0; i--) if (!isSystemLine(l.get(i))) return l.get(i); return null; } static String structure(Object o) { HashSet refd = new HashSet(); return structure_2(structure_1(o, 0, new IdentityHashMap(), refd), refd); } // leave to false, unless unstructure() breaks static boolean structure_allowShortening = false; static String structure_1(Object o, int stringSizeLimit, IdentityHashMap seen, HashSet refd) { if (o == null) return "null"; // these are never back-referenced (for readability) if (o instanceof String) return quote(stringSizeLimit != 0 ? shorten((String) o, stringSizeLimit) : (String) o); if (o instanceof BigInteger) return "bigint(" + o + ")"; if (o instanceof Double) return "d(" + quote(str(o)) + ")"; if (o instanceof Long) return o + "L"; if (o instanceof Integer) return str(o); if (o instanceof Boolean) return ((Boolean) o).booleanValue() ? "t" : "f"; if (o instanceof Character) return quoteCharacter((Character) o); if (o instanceof File) return "File " + quote(((File) o).getPath()); // referencable objects follow Integer ref = seen.get(o); if (ref != null) { refd.add(ref); return "r" + ref; } ref = seen.size()+1; seen.put(o, ref); String r = "m" + ref + " "; // marker String name = o.getClass().getName(); StringBuilder buf = new StringBuilder(); if (o instanceof HashSet) return r + "hashset " + structure_1(new ArrayList((Set) o), stringSizeLimit, seen, refd); if (o instanceof TreeSet) return r + "treeset " + structure_1(new ArrayList((Set) o), stringSizeLimit, seen, refd); if (o instanceof Collection) { for (Object x : (Collection) o) { if (buf.length() != 0) buf.append(", "); buf.append(structure_1(x, stringSizeLimit, seen, refd)); } return r + "[" + buf + "]"; } if (o instanceof Map) { for (Object e : ((Map) o).entrySet()) { if (buf.length() != 0) buf.append(", "); buf.append(structure_1(((Map.Entry) e).getKey(), stringSizeLimit, seen, refd)); buf.append("="); buf.append(structure_1(((Map.Entry) e).getValue(), stringSizeLimit, seen, refd)); } return r + (o instanceof HashMap ? "hashmap" : "") + "{" + buf + "}"; } if (o.getClass().isArray()) { int n = Array.getLength(o); for (int i = 0; i < n; i++) { if (buf.length() != 0) buf.append(", "); buf.append(structure_1(Array.get(o, i), stringSizeLimit, seen, refd)); } return r + "array{" + buf + "}"; } if (o instanceof Class) return r + "class(" + quote(((Class) o).getName()) + ")"; if (o instanceof Throwable) return r + "exception(" + quote(((Throwable) o).getMessage()) + ")"; if (o instanceof BitSet) { BitSet bs = (BitSet) o; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { if (buf.length() != 0) buf.append(", "); buf.append(i); } return "bitset{" + buf + "}"; } // Need more cases? This should cover all library classes... if (name.startsWith("java.") || name.startsWith("javax.")) return r + String.valueOf(o); String shortName = o.getClass().getName().replaceAll("^main\\$", ""); if (shortName.equals("Lisp")) { buf.append("l(" + structure_1(getOpt(o, "head"), stringSizeLimit, seen, refd)); List args = (List) ( getOpt(o, "args")); if (nempty(args)) for (int i = 0; i < l(args); i++) { buf.append(", "); Object arg = args.get(i); // sweet shortening if (arg != null && eq(arg.getClass().getName(), "main$Lisp") && isTrue(call(arg, "isEmpty"))) arg = get(arg, "head"); buf.append(structure_1(arg, stringSizeLimit, seen, refd)); } buf.append(")"); return r + str(buf); } int numFields = 0; String fieldName = ""; if (shortName.equals("DynamicObject")) { shortName = (String) get(o, "className"); Map fieldValues = (Map) get(o, "fieldValues"); for (String _fieldName : fieldValues.keySet()) { fieldName = _fieldName; Object value = fieldValues.get(fieldName); if (value != null) { if (buf.length() != 0) buf.append(", "); buf.append(fieldName + "=" + structure_1(value, stringSizeLimit, seen, refd)); } ++numFields; } } else { // regular class Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; fieldName = field.getName(); // skip outer object reference if (fieldName.indexOf("$") >= 0) continue; Object value; try { field.setAccessible(true); value = field.get(o); } catch (Exception e) { value = "?"; } // put special cases here... if (value != null) { if (buf.length() != 0) buf.append(", "); buf.append(fieldName + "=" + structure_1(value, stringSizeLimit, seen, refd)); } ++numFields; } c = c.getSuperclass(); } } String b = buf.toString(); if (numFields == 1 && structure_allowShortening) b = b.replaceAll("^" + fieldName + "=", ""); // drop field name if only one String s = shortName; if (buf.length() != 0) s += "(" + b + ")"; return r + s; } // drop unused markers static String structure_2(String s, HashSet refd) { List tok = javaTok(s); StringBuilder out = new StringBuilder(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("m") && isInteger(t.substring(1)) && !refd.contains(parseInt(t.substring(1)))) continue; out.append(t).append(tok.get(i+1)); } return str(out); } static boolean gLongestPrefixMatchNeqIdx_debug; static int gLongestPrefixMatchNeqIdx(String line) { line = line.toLowerCase(); if (gLongestPrefixMatchNeqIdx_debug) print("line=" + line); List log = gLog(); int best = -1, bestIdx = -1; for (int i = l(log)-1; i >= 0; i--) { String s = log.get(i).toLowerCase(); { if (eq(s, line)) continue; } int n = l(commonPrefix(s, line)); if (gLongestPrefixMatchNeqIdx_debug) print("i=" + i + ", n=" + n + ", line=" + quote(log.get(i))); if (n > best) { bestIdx = i; best = n; } } return bestIdx; } static List dropPunctuation2(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) /* && !dropPunctuation2_keep.contains(t)*/) { tok.set(i-1, tok.get(i-1) + tok.get(i+1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } static String dropPunctuation2(String s) { return join(dropPunctuation(nlTok2(s))); } static boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static boolean contains(String s, char c) { return s.indexOf(c) >= 0; } static List gLog() { return genLog(); } static void gLog_set(List log) { genLog_set(log); } static void gLog_clear() { genLog_clear(); } static volatile StringBuffer local_log = new StringBuffer(); // not redirected static volatile StringBuffer print_log = local_log; // might be redirected, e.g. to main bot // in bytes - will cut to half that static volatile int print_log_max = 1024*1024; static volatile int local_log_max = 100*1024; static boolean print_silent; // total mute if set static void print() { print(""); } // slightly overblown signature to return original object... static A print(A o) { if (print_silent) return o; String s = String.valueOf(o) + "\n"; StringBuffer loc = local_log; StringBuffer buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); return o; } static void print(long l) { print(String.valueOf(l)); } static void print(char c) { print(String.valueOf(c)); } static void print_append(StringBuffer buf, String s, int max) { synchronized(buf) { buf.append(s); max /= 2; if (buf.length() > max) try { int newLength = max/2; int ofs = buf.length()-newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } } } // accepts a string as predicate (then compares with "eq") static int gSearchIdx(Object predicate) { return gSearchIdx(predicate, 0); } static int gSearchIdx(Object predicate, int startIdx) { if (predicate == null) return -1; if (predicate instanceof String) { final String _s = (String) predicate; predicate = new Object() { Object get(String s) { return eq(s, _s) ; } public String toString() { return "eq(s, _s)"; }}; } List log = genLog(); for (int i = l(log)-startIdx-1; i >= 0; i--) if (isTrue(callF(predicate, log.get(i)))) return i; return -1; } static long parseLong(String s) { if (s == null) return 0; return Long.parseLong(dropSuffix("L", s)); } static long parseLong(Object s) { return Long.parseLong((String) s); } static int charToInt(String s) { return empty(s) ? 0 : (int) s.charAt(0); } static int charToInt(char c) { return (int) c; } static char intToChar(int i) { return (char) i; } static Object nuObject(String className, Object... args) { try { return nuObject(Class.forName(className), args); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static Object nuObject(Object realm, String className, Object... args) { return nuObject(_getClass(realm, className), args); } static A nuObject(Class c, Object... args) { try { Constructor m = nuObject_findConstructor(c, args); m.setAccessible(true); return (A) m.newInstance(args); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw new RuntimeException("Constructor with " + args.length + " matching parameter(s) not found in " + c.getName()); } static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static List> gLearns() { List log = gLog(); List> parts = new ArrayList(); for (int i = l(log)-1; i >= 0; i--) { String cmd = log.get(i); { if (!(cmd.startsWith("!learn"))) continue; } // fancy new "unless" syntax! Matches mm = new Matches(); { if (!(match("!learn *-*", log.get(i), mm))) continue; } int m = mm.psi(0), n = mm.psi(1); //print("i=" + i +", m=" + m + ", n=" + n); List part = subList(log, i-n, i-m+1); parts.add(part); } return parts; } static boolean startsWithIgnoreCase(String a, String b) { return a != null && a.regionMatches(true, 0, b, 0, b.length()); } static Object first(Object list) { return ((List) list).isEmpty() ? null : ((List) list).get(0); } static A first(List list) { return list.isEmpty() ? null : list.get(0); } static A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } // match2 matches multiple "*" (matches a single token) wildcards and zero or one "..." wildcards (matches multiple tokens) static String[] match2(List pat, List tok) { // standard case (no ...) int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); pat = new ArrayList(pat); // We're modifying it, so copy first pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); pat.add(i+1, ""); // doesn't matter } return match2_match(pat, tok); } static String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { /*if (debug) print("Size mismatch: " + structure(pat) + " vs " + structure(tok));*/ return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); /*if (debug) print("Checking " + p + " against " + t);*/ if (eq(p, "*")) result.add(t); else if (!equalsIgnoreCase(unquote(p), unquote(t))) // bold change - match quoted and unquoted now return null; } return result.toArray(new String[result.size()]); } static A nextToLast(List l) { return get(l, l(l)-2); } // class Matches is added by #752 static boolean match3(String pat, String s) { return match3(pat, s, null); } static boolean match3(String pat, String s, Matches matches) { if (s == null) return false; return match3(pat, parse3(s), matches); } static boolean match3(String pat, List toks, Matches matches) { List tokpat = parse3(pat); return match3(tokpat,toks,matches); } static boolean match3(List tokpat, List toks, Matches matches) { String[] m = match2(tokpat, toks); //print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static int gSearchNeqNoSystemIdx(Object predicate) { return gSearchNeqNoSystemIdx(predicate, 1); // no sense to start from 0 } static int gSearchNeqNoSystemIdx(final Object predicate, int startIdx) { return gSearchIdx(new Object() { Object get(String s) { return neq(s, gI()) && !isSystemLine(s) && isTrue(callF(predicate, s)) ; } public String toString() { return "neq(s, gI()) && !isSystemLine(s) && isTrue(callF(predicate, s))"; }}, startIdx); } static Object callF(Object f, Object... args) { return callFunction(f, args); } static Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static Class _getClass(Object o) { return o instanceof Class ? (Class) o : o.getClass(); } static Class _getClass(Object realm, String name) { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static boolean isInteger(String s) { return s != null && Pattern.matches("\\-?\\d+", s); } static String quote(String s) { if (s == null) return "null"; return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "\\r").replace("\n", "\\n") + "\""; } static String quote(long l) { return quote("" + l); } static String quote(char c) { return quote("" + c); } static String shorten(String s, int max) { if (s == null) return ""; return s.length() <= max ? s : s.substring(0, Math.min(s.length(), max)) + "..."; } public static String commonPrefix(String a, String b) { int i = 0; while (i < a.length() && i < b.length() && a.charAt(i) == b.charAt(i)) ++i; return a.substring(0, i); } static String quoteCharacter(char c) { if (c == '\'') return "'\\''"; if (c == '\\') return "'\\\\'"; return "'" + c + "'"; } static ThreadLocal> genLog_log; static List genLog() { genLog_init(); List log = genLog_log.get(); /*if (log == null) log = (L) callOpt(creator(), "genLog");*/ return assertNotNull("No log set for this thread", log); } static void genLog_set(List log) { genLog_init(); genLog_log.set(log); } static void genLog_clear() { genLog_init(); genLog_log.set(null); } static void genLog_init() { if (genLog_log == null) { genLog_log = (ThreadLocal) getOpt(creator(), "genLog_log"); if (genLog_log == null) genLog_log = new ThreadLocal(); } } // extended over Class.isInstance() to handle primitive types static boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static String classNameToVM(String name) { return name.replace(".", "$"); } static boolean eq(Object a, Object b) { if (a == null) return b == null; if (a.equals(b)) return true; if (a instanceof BigInteger) { if (b instanceof Integer) return a.equals(BigInteger.valueOf((Integer) b)); if (b instanceof Long) return a.equals(BigInteger.valueOf((Long) b)); } return false; } static String str(Object o) { return String.valueOf(o); } static boolean isSystemLine(String s) { return startsWith(s, "[system]"); } static A _get(List l, int idx) { return idx >= 0 && idx < l(l) ? l.get(idx) : null; } static String quickSubstring(String s, int i, int j) { if (i == j) return ""; return s.substring(i, j); } static List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static void arraycopy(Object[] a, Object[] b) { int n = min(a.length, b.length); for (int i = 0; i < n; i++) b[i] = a[i]; } static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { System.arraycopy(src, srcPos, dest, destPos, n); } // get purpose 1: access a list/array (safer version of x.get(y)) static A get(List l, int idx) { return idx >= 0 && idx < l(l) ? l.get(idx) : null; } static A get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } // get purpose 2: access a field by reflection or a map static Object get(Object o, String field) { if (o instanceof Class) return get((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); if (o.getClass().getName().equals("main$DynamicObject")) return call(get_raw(o, "fieldValues"), "get", field); return get_raw(o, field); } static Object get_raw(Object o, String field) { try { Field f = get_findField(o.getClass(), field); f.setAccessible(true); return f.get(o); } catch (Exception e) { throw new RuntimeException(e); } } static Object get(Class c, String field) { try { Field f = get_findStaticField(c, field); f.setAccessible(true); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static Field get_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field get_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } // We dropped the "***" support here (use match3 for that) static String[] find2(List pat, List tok) { for (int idx = 0; idx < tok.size(); idx += 2) { String[] result = find2(pat, tok, idx); if (result != null) return result; } return null; } static String[] find2(List pat, List tok, int idx) { if (idx+pat.size() > tok.size()) return null; List result = new ArrayList(); for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(idx+i); if (eq(p, "*")) result.add(t); else if (!p.equalsIgnoreCase(t)) return null; } return toStringArray(result); } static List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static List subList(List l, int startIndex, int endIndex) { startIndex = max(0, min(l(l), startIndex)); endIndex = max(0, min(l(l), endIndex)); if (startIndex > endIndex) return litlist(); return l.subList(startIndex, endIndex); } static List dropPunctuation_keep = litlist("*", "<", ">"); static List dropPunctuation(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) && !dropPunctuation_keep.contains(t)) { tok.set(i-1, tok.get(i-1) + tok.get(i+1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } static String dropPunctuation(String s) { return join(dropPunctuation(nlTok(s))); } static boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static String dropSuffix(String suffix, String s) { return s.endsWith(suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static Object call(Object o) { return callFunction(o); } // varargs assignment fixer for a single string array argument static Object call(Object o, String method, String[] arg) { return call(o, method, new Object[] {arg}); } static Object call(Object o, String method, Object... args) { try { if (o instanceof Class) { Method m = call_findStaticMethod((Class) o, method, args, false); m.setAccessible(true); return m.invoke(null, args); } else { Method m = call_findMethod(o, method, args, false); m.setAccessible(true); return m.invoke(o, args); } } catch (Exception e) { throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e); } } static Method call_findStaticMethod(Class c, String method, Object[] args, boolean debug) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (!m.getName().equals(method)) { if (debug) System.out.println("Method name mismatch: " + method); continue; } if ((m.getModifiers() & Modifier.STATIC) == 0 || !call_checkArgs(m, args, debug)) continue; return m; } c = c.getSuperclass(); } throw new RuntimeException("Method '" + method + "' (static) with " + args.length + " parameter(s) not found in " + _c.getName()); } static Method call_findMethod(Object o, String method, Object[] args, boolean debug) { Class c = o.getClass(); while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (m.getName().equals(method) && call_checkArgs(m, args, debug)) return m; } c = c.getSuperclass(); } throw new RuntimeException("Method '" + method + "' (non-static) with " + args.length + " parameter(s) not found in " + o.getClass().getName()); } private static boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static int parseInt(String s) { return empty(s) ? 0 : Integer.parseInt(s); } static boolean isTrue(Object o) { return booleanValue(o); } static List nlTok(String s) { return javaTokPlusPeriod(s); } static Object getOpt(Object o, String field) { if (o instanceof String) o = getBot ((String) o); if (o == null) return null; if (o instanceof Class) return getOpt((Class) o, field); if (o.getClass().getName().equals("main$DynamicObject")) return ((Map) getOpt_raw(o, "fieldValues")).get(field); if (o instanceof Map) return ((Map) o).get(field); return getOpt_raw(o, field); } static Object getOpt_raw(Object o, String field) { try { Field f = getOpt_findField(o.getClass(), field); if (f == null) return null; f.setAccessible(true); return f.get(o); } catch (Exception e) { throw new RuntimeException(e); } } static Object getOpt(Class c, String field) { try { if (c == null) return null; Field f = getOpt_findStaticField(c, field); if (f == null) return null; f.setAccessible(true); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static Field getOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Field getOpt_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static boolean eqicOneOf(String s, String... l) { for (String x : l) if (eqic(s, x)) return true; return false; } // works on lists and strings and null static int indexOfIgnoreCase(Object a, Object b) { if (a == null) return -1; if (a instanceof String) { Matcher m = Pattern.compile((String) b, Pattern.CASE_INSENSITIVE + Pattern.LITERAL).matcher((String) a); if (m.find()) return m.start(); else return -1; } if (a instanceof List) { for (int i = 0; i < ((List) a).size(); i++) { Object o = ((List) a).get(i); if (o != null && ((String) o).equalsIgnoreCase((String) b)) return i; } return -1; } throw fail("Unknown type: " + a); } static Object callFunction(Object f, Object... args) { if (f == null) return null; if (f instanceof Runnable) { ((Runnable) f).run(); return null; } else if (f instanceof String) return call(mc(), (String) f, args); else return call(f, "get", args); //else throw fail("Can't call a " + getClassName(f)); } static A assertNotNull(A a) { assertTrue(a != null); return a; } static A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static Object getBot(String botID) { return callOpt(getMainBot(), "getBot", botID); } static boolean neq(Object a, Object b) { return !eq(a, b); } static boolean equalsIgnoreCase(String a, String b) { return a == null ? b == null : a.equalsIgnoreCase(b); } static RuntimeException fail() { throw new RuntimeException("fail"); } static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static RuntimeException fail(String msg) { throw new RuntimeException(unnull(msg)); } // disabled for now to shorten some programs /*static RuntimeException fail(S msg, O... args) { throw new RuntimeException(format(msg, args)); }*/ // This is made for NL parsing. // It's javaTok extended with "..." token, "$n" and "#n" and // special quotes (which are converted to normal ones). static List javaTokPlusPeriod(String s) { List tok = new ArrayList(); int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j+2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); cc = s.substring(i, Math.min(i+2, l)); // scan for non-whitespace if (c == '\u201C' || c == '\u201D') c = '"'; // normalize quotes if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { char _c = s.charAt(j); if (_c == '\u201C' || _c == '\u201D') _c = '"'; // normalize quotes if (_c == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } if (j-1 >= i+1) { tok.add(opener + s.substring(i+1, j-1) + opener); i = j; continue; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); // for things like "this one's" else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (cc.equals("[=") && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else if (s.substring(j, Math.min(j+3, l)).equals("...")) j += 3; else if (c == '$' || c == '#') do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static boolean booleanValue(Object o) { return eq(true, o); } static int min(int a, int b) { return Math.min(a, b); } static double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static ArrayList litlist(A... a) { return new ArrayList(Arrays.asList(a)); } public static String unquote(String s) { if (s == null) return null; if (s.startsWith("[")) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i+1, s.length()-i-1); } } if (s.startsWith("\"") /*&& s.endsWith("\"")*/ && s.length() > 1) { String st = s.substring(1, s.endsWith("\"") ? s.length()-1 : s.length()); StringBuilder sb = new StringBuilder(st.length()); for (int i = 0; i < st.length(); i++) { char ch = st.charAt(i); if (ch == '\\') { char nextChar = (i == st.length() - 1) ? '\\' : st .charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' && st.charAt(i + 1) <= '7') { code += st.charAt(i + 1); i++; if ((i < st.length() - 1) && st.charAt(i + 1) >= '0' && st.charAt(i + 1) <= '7') { code += st.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch (nextChar) { case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\"': ch = '\"'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= st.length() - 5) { ch = 'u'; break; } int code = Integer.parseInt( "" + st.charAt(i + 2) + st.charAt(i + 3) + st.charAt(i + 4) + st.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: ch = nextChar; // added by Stefan } i++; } sb.append(ch); } return sb.toString(); } else return s; // return original } static WeakReference creator_class; static Class creator() { return creator_class == null ? null : creator_class.get(); } static int max(int a, int b) { return Math.max(a, b); } static long max(int a, long b) { return Math.max((long) a, b); } static long max(long a, long b) { return Math.max(a, b); } static double max(int a, double b) { return Math.max((double) a, b); } static int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static String[] toStringArray(List list) { return list.toArray(new String[list.size()]); } static String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof List) return toStringArray((List) o); else throw fail("Not a list or array: " + structure(o)); } static boolean startsWith(String a, String b) { return a != null && a.startsWith(b); } static boolean startsWith(List a, List b) { if (a == null || l(b) > l(a)) return false; for (int i = 0; i < l(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static String unnull(String s) { return s == null ? "" : s; } static List unnull(List l) { return l == null ? emptyList() : l; } static Object[] unnull(Object[] a) { return a == null ? new Object[0] : a; } static Object mainBot; static Object getMainBot() { return mainBot; } static void assertTrue(Object o) { assertEquals(true, o); } static boolean assertTrue(String msg, boolean b) { if (!b) throw fail(msg); return b; } static boolean assertTrue(boolean b) { if (!b) throw fail("oops"); return b; } static Class mc() { return getMainClass(); } static Object callOpt(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Method m = callOpt_findStaticMethod((Class) o, method, args, false); if (m == null) return null; m.setAccessible(true); return m.invoke(null, args); } else { Method m = callOpt_findMethod(o, method, args, false); if (m == null) return null; m.setAccessible(true); return m.invoke(o, args); } } catch (Exception e) { throw new RuntimeException(e); } } static Method callOpt_findStaticMethod(Class c, String method, Object[] args, boolean debug) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (!m.getName().equals(method)) { if (debug) System.out.println("Method name mismatch: " + method); continue; } if ((m.getModifiers() & Modifier.STATIC) == 0 || !callOpt_checkArgs(m, args, debug)) continue; return m; } c = c.getSuperclass(); } return null; } static Method callOpt_findMethod(Object o, String method, Object[] args, boolean debug) { Class c = o.getClass(); while (c != null) { for (Method m : c.getDeclaredMethods()) { if (debug) System.out.println("Checking method " + m.getName() + " with " + m.getParameterTypes().length + " parameters");; if (m.getName().equals(method) && callOpt_checkArgs(m, args, debug)) return m; } c = c.getSuperclass(); } return null; } private static boolean callOpt_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static Class getMainClass() { try { return Class.forName("main"); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static Class getMainClass(Object o) { try { return (o instanceof Class ? (Class) o : o.getClass()).getClassLoader().loadClass("main"); } catch (Throwable __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }} static A assertEquals(Object x, A y) { return assertEquals(null, x, y); } static A assertEquals(String msg, Object x, A y) { if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + structure(x) + " != " + structure(y)); return y; } static List emptyList() { return new ArrayList(); //ret Collections.emptyList(); } static class Gen { String name; Object func; Gen() {} Gen(String name, Object func) { this.func = func; this.name = name;} public String toString() { return name; } } static class Quine { String text; A value; Quine() {} Quine(String text, A value) { this.value = value; this.text = text;} } static class Matches { String[] m; String get(int i) { return i < m.length ? m[i] : null; } String unq(int i) { return unquote(get(i)); } String fsi(int i) { return formatSnippetID(unq(i)); } String fsi() { return fsi(0); } String tlc(int i) { return unq(i).toLowerCase(); } boolean bool(int i) { return "true".equals(unq(i)); } String rest() { return m[m.length-1]; } // for matchStart int psi(int i) { return Integer.parseInt(unq(i)); } } static String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static String formatSnippetID(long id) { return "#" + id; } static void printStackTrace(Throwable e) { // we go to system.out now - system.err is nonsense print(getStackTrace(e)); } static void printStackTrace() { printStackTrace(new Throwable()); } static String fsi(String id) { return formatSnippetID(id); } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static String getStackTrace(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return writer.toString(); } }