--- a/src/org/armedbear/lisp/BuiltInClass.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/BuiltInClass.java Sat Aug 01 07:18:46 2009 +0200 @@ -143,6 +143,10 @@ public static final BuiltInClass TWO_WAY_STREAM = addClass(Symbol.TWO_WAY_STREAM); public static final BuiltInClass VECTOR = addClass(Symbol.VECTOR); + public static final BuiltInClass STACK_FRAME = addClass(Symbol.STACK_FRAME); + public static final BuiltInClass LISP_STACK_FRAME = addClass(Symbol.LISP_STACK_FRAME); + public static final BuiltInClass JAVA_STACK_FRAME = addClass(Symbol.JAVA_STACK_FRAME); + public static final StructureClass STRUCTURE_OBJECT = new StructureClass(Symbol.STRUCTURE_OBJECT, list(CLASS_T)); static @@ -275,6 +279,13 @@ TWO_WAY_STREAM.setCPL(TWO_WAY_STREAM, STREAM, CLASS_T); VECTOR.setDirectSuperclasses(list(ARRAY, SEQUENCE)); VECTOR.setCPL(VECTOR, ARRAY, SEQUENCE, CLASS_T); + + STACK_FRAME.setDirectSuperclasses(CLASS_T); + STACK_FRAME.setCPL(STACK_FRAME, CLASS_T); + LISP_STACK_FRAME.setDirectSuperclasses(STACK_FRAME); + LISP_STACK_FRAME.setCPL(LISP_STACK_FRAME, STACK_FRAME, CLASS_T); + JAVA_STACK_FRAME.setDirectSuperclasses(STACK_FRAME); + JAVA_STACK_FRAME.setCPL(JAVA_STACK_FRAME, STACK_FRAME, CLASS_T); } static diff -r bffd7288416c src/org/armedbear/lisp/Debug.java --- a/src/org/armedbear/lisp/Debug.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/Debug.java Sat Aug 01 07:18:46 2009 +0200 @@ -51,6 +51,11 @@ trace(new Exception("BUG!")); } + public static final void warn(String s) + { + trace("WARN: " + s); + } + public static final void trace(String s) { System.err.println(s); diff -r bffd7288416c src/org/armedbear/lisp/Interpreter.java --- a/src/org/armedbear/lisp/Interpreter.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/Interpreter.java Sat Aug 01 07:18:46 2009 +0200 @@ -389,7 +389,7 @@ catch (Throwable t) { getStandardInput().clearInput(); out.printStackTrace(t); - thread.backtrace(); + thread.printBacktrace(); } } } @@ -408,7 +408,7 @@ out._writeLine("Error: unhandled condition: " + condition.writeToString()); if (thread != null) - thread.backtrace(); + thread.printBacktrace(); } catch (Throwable t) { diff -r bffd7288416c src/org/armedbear/lisp/JavaStackFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/armedbear/lisp/JavaStackFrame.java Sat Aug 01 07:18:46 2009 +0200 @@ -0,0 +1,115 @@ +/* + * JavaStackFrame.java + * + * Copyright (C) 2009 Mark Evenson + * $Id$ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on this library. If you modify this library, you may extend + * this exception to your version of the library, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +package org.armedbear.lisp; + +public class JavaStackFrame + extends StackFrame +{ + public final StackTraceElement javaFrame; + + public JavaStackFrame(StackTraceElement javaFrame) + { + this.javaFrame = javaFrame; + } + + @Override + public LispObject typeOf() { + return Symbol.JAVA_STACK_FRAME; + } + + @Override + public LispObject classOf() { return BuiltInClass.JAVA_STACK_FRAME; } + + @Override + public String writeToString() { + String result = null; + final String JAVA_STACK_FRAME = "JAVA-STACK-FRAME"; + try { + result = unreadableString(JAVA_STACK_FRAME + " " + + toLispString().toString()); + } catch (ConditionThrowable t) { + Debug.trace("Implementation error: "); + Debug.trace(t); + result = unreadableString(JAVA_STACK_FRAME); + } + return result; + } + + @Override + public LispObject typep(LispObject typeSpecifier) + throws ConditionThrowable + { + if (typeSpecifier == Symbol.JAVA_STACK_FRAME) + return T; + if (typeSpecifier == BuiltInClass.JAVA_STACK_FRAME) + return T; + return super.typep(typeSpecifier); + } + + static final Symbol CLASS = Packages.internKeyword("CLASS"); + static final Symbol METHOD = Packages.internKeyword("METHOD"); + static final Symbol FILE = Packages.internKeyword("FILE"); + static final Symbol LINE = Packages.internKeyword("LINE"); + static final Symbol NATIVE_METHOD = Packages.internKeyword("NATIVE-METHOD"); + + public LispObject toLispList() throws ConditionThrowable + { + LispObject result = Lisp.NIL; + + if ( javaFrame == null) + return result; + + result = result.push(CLASS); + result = result.push(new SimpleString(javaFrame.getClassName())); + result = result.push(METHOD); + result = result.push(new SimpleString(javaFrame.getMethodName())); + result = result.push(FILE); + result = result.push(new SimpleString(javaFrame.getFileName())); + result = result.push(LINE); + result = result.push(Fixnum.getInstance(javaFrame.getLineNumber())); + if (javaFrame.isNativeMethod()) { + result = result.push(NATIVE_METHOD); + result = result.push(Symbol.T); + } + + return result.nreverse(); + } + + public SimpleString toLispString() + throws ConditionThrowable + { + return new SimpleString(javaFrame.toString()); + } + +} diff -r bffd7288416c src/org/armedbear/lisp/Lisp.java --- a/src/org/armedbear/lisp/Lisp.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/Lisp.java Sat Aug 01 07:18:46 2009 +0200 @@ -320,15 +320,78 @@ } }; + /** + * Push "meaningful" Java stack frames to the invoking LispThread's stack. + * + * N.B. After this method is invoked, the invoking ListThread will + * not be restartable execept on the top level as its stack will + * contain Java stack frames. + */ + private static final void pushJavaStackFrames() + throws ConditionThrowable + { + final LispThread thread = LispThread.currentThread(); + final StackTraceElement[] frames = thread.getJavaStackTrace(); + + // Possibly trim the java stack between the top instance of + // "org.armedbear.lisp.Primitive" which is the last point in the + // Java stack where Lisp was executed, and bottom instance of + // "org.armedbear.lisp.Lisp.error" which is the only method that + // directly invokes this function. + int top = -1; + int bottom = -1; + final String topSymbol = "org.armedbear.lisp.Primitive."; + final String bottomSymbol = "org.armedbear.lisp.Lisp.error"; + + int i = 0; + for (StackTraceElement frame : frames) { + final String f = frame.toString(); + if (f.startsWith(topSymbol)) { + top = i; + } + if (f.startsWith(bottomSymbol)) { + bottom = i; + } + if (bottom != -1 && top != -1) { + break; + } + i++; + } + + // Sometimes the search for the the enclosing symbols fail, for + // instance when intializing the interpreter, so we explicitly + // guard against those cases. + if (top == -1) { + Debug.warn("Failed to find instance of '" + + topSymbol+ "' in Java stack trace."); + top = frames.length - 1; + } + if (bottom == -1) { + Debug.warn("Failed to find instance of '" + + bottomSymbol+ "' in Java stack trace."); + bottom = 0; + } + + i = top; + while (i >= bottom) { + thread.pushStackFrame(new JavaStackFrame(frames[i])); + i--; + } + return; + } + + public static final LispObject error(LispObject condition) throws ConditionThrowable { + pushJavaStackFrames(); return Symbol.ERROR.execute(condition); } public static final LispObject error(LispObject condition, LispObject message) throws ConditionThrowable { + pushJavaStackFrames(); return Symbol.ERROR.execute(condition, Keyword.FORMAT_CONTROL, message); } @@ -852,6 +915,14 @@ type_error(obj, Symbol.SINGLE_FLOAT); } + public static final StackFrame checkStackFrame(LispObject obj) + throws ConditionThrowable + { + if (obj instanceof StackFrame) + return (StackFrame) obj; + return (StackFrame)// Not reached. + type_error(obj, Symbol.STACK_FRAME); + } static { diff -r bffd7288416c src/org/armedbear/lisp/LispStackFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/armedbear/lisp/LispStackFrame.java Sat Aug 01 07:18:46 2009 +0200 @@ -0,0 +1,169 @@ +/* + * LispStackFrame.java + * + * Copyright (C) 2009 Mark Evenson + * $Id$ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on this library. If you modify this library, you may extend + * this exception to your version of the library, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +package org.armedbear.lisp; + +public class LispStackFrame + extends StackFrame +{ + public final LispObject operator; + private final LispObject first; + private final LispObject second; + private final LispObject third; + private final LispObject[] args; + + public LispStackFrame(LispObject operator) + { + this.operator = operator; + first = null; + second = null; + third = null; + args = null; + } + + public LispStackFrame(LispObject operator, LispObject arg) + { + this.operator = operator; + first = arg; + second = null; + third = null; + args = null; + } + + public LispStackFrame(LispObject operator, LispObject first, + LispObject second) + { + this.operator = operator; + this.first = first; + this.second = second; + third = null; + args = null; + } + + public LispStackFrame(LispObject operator, LispObject first, + LispObject second, LispObject third) + + { + this.operator = operator; + this.first = first; + this.second = second; + this.third = third; + args = null; + } + + public LispStackFrame(LispObject operator, LispObject... args) + { + this.operator = operator; + first = null; + second = null; + third = null; + final int length = args.length; + this.args = new LispObject[length]; + System.arraycopy(args, 0, this.args, 0, length); + } + + @Override + public LispObject typeOf() { + return Symbol.LISP_STACK_FRAME; + } + + @Override + public LispObject classOf() { + return BuiltInClass.LISP_STACK_FRAME; + } + + @Override + public String writeToString() + { + String result = ""; + final String LISP_STACK_FRAME = "LISP-STACK-FRAME"; + try { + result = unreadableString(LISP_STACK_FRAME + " " + + toLispString().getStringValue()); + } catch (ConditionThrowable t) { + Debug.trace("Implementation error: "); + Debug.trace(t); + result = unreadableString(LISP_STACK_FRAME); + } + return result; + } + + @Override + public LispObject typep(LispObject typeSpecifier) + throws ConditionThrowable + { + if (typeSpecifier == Symbol.LISP_STACK_FRAME) + return T; + if (typeSpecifier == BuiltInClass.LISP_STACK_FRAME) + return T; + return super.typep(typeSpecifier); + } + + public LispObject toLispList() + throws ConditionThrowable + { + LispObject list = Lisp.NIL; + if (args != null) { + for (int i = 0; i < args.length; i++) + list = list.push(args[i]); + } else { + do { + if (first != null) + list = list.push(first); + else + break; + if (second != null) + list = list.push(second); + else + break; + if (third != null) + list = list.push(third); + else + break; + } while (false); + } + list = list.nreverse(); + if (operator instanceof Operator) { + LispObject lambdaName = ((Operator)operator).getLambdaName(); + if (lambdaName != null && lambdaName != Lisp.NIL) + return list.push(lambdaName); + } + return list.push(operator); + } + + public SimpleString toLispString() + throws ConditionThrowable + { + return new SimpleString(toLispList().writeToString()); + } +} diff -r bffd7288416c src/org/armedbear/lisp/LispThread.java --- a/src/org/armedbear/lisp/LispThread.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/LispThread.java Sat Aug 01 07:18:46 2009 +0200 @@ -46,8 +46,8 @@ new ConcurrentHashMap(); private static ThreadLocal threads = new ThreadLocal(){ - @Override - public LispThread initialValue() { + @Override + public LispThread initialValue() { Thread thisThread = Thread.currentThread(); LispThread thread = LispThread.map.get(thisThread); if (thread == null) { @@ -117,6 +117,10 @@ javaThread.start(); } + public StackTraceElement[] getJavaStackTrace() { + return javaThread.getStackTrace(); + } + @Override public LispObject typeOf() { @@ -447,99 +451,6 @@ tag.writeToString() + ".")); } - private static class StackFrame - { - public final LispObject operator; - private final LispObject first; - private final LispObject second; - private final LispObject third; - private final LispObject[] args; - final StackFrame next; - - public StackFrame(LispObject operator, StackFrame next) - { - this.operator = operator; - first = null; - second = null; - third = null; - args = null; - this.next = next; - } - - public StackFrame(LispObject operator, LispObject arg, StackFrame next) - { - this.operator = operator; - first = arg; - second = null; - third = null; - args = null; - this.next = next; - } - - public StackFrame(LispObject operator, LispObject first, - LispObject second, StackFrame next) - { - this.operator = operator; - this.first = first; - this.second = second; - third = null; - args = null; - this.next = next; - } - - public StackFrame(LispObject operator, LispObject first, - LispObject second, LispObject third, StackFrame next) - { - this.operator = operator; - this.first = first; - this.second = second; - this.third = third; - args = null; - this.next = next; - } - - public StackFrame(LispObject operator, LispObject[] args, StackFrame next) - { - this.operator = operator; - first = null; - second = null; - third = null; - this.args = args; - this.next = next; - } - - public LispObject toList() throws ConditionThrowable - { - LispObject list = NIL; - if (args != null) { - for (int i = 0; i < args.length; i++) - list = list.push(args[i]); - } else { - do { - if (first != null) - list = list.push(first); - else - break; - if (second != null) - list = list.push(second); - else - break; - if (third != null) - list = list.push(third); - else - break; - } while (false); - } - list = list.nreverse(); - if (operator instanceof Operator) { - LispObject lambdaName = ((Operator)operator).getLambdaName(); - if (lambdaName != null && lambdaName != NIL) - return list.push(lambdaName); - } - return list.push(operator); - } - } - private StackFrame stack = null; @Deprecated @@ -560,40 +471,11 @@ Profiler.sample(this); } - public final void pushStackFrame(LispObject operator) + public final void pushStackFrame(StackFrame frame) throws ConditionThrowable { - stack = new StackFrame(operator, stack); - doProfiling(); - } - - public final void pushStackFrame(LispObject operator, LispObject arg) - throws ConditionThrowable - { - stack = new StackFrame(operator, arg, stack); - doProfiling(); - } - - public final void pushStackFrame(LispObject operator, LispObject first, - LispObject second) - throws ConditionThrowable - { - stack = new StackFrame(operator, first, second, stack); - doProfiling(); - } - - public final void pushStackFrame(LispObject operator, LispObject first, - LispObject second, LispObject third) - throws ConditionThrowable - { - stack = new StackFrame(operator, first, second, third, stack); - doProfiling(); - } - - public final void pushStackFrame(LispObject operator, LispObject... args) - throws ConditionThrowable - { - stack = new StackFrame(operator, args, stack); + frame.setNext(stack); + stack = frame; doProfiling(); } @@ -614,7 +496,7 @@ if (use_fast_calls) return function.execute(); - pushStackFrame(function); + pushStackFrame(new LispStackFrame(function)); try { return function.execute(); } @@ -631,7 +513,7 @@ if (use_fast_calls) return function.execute(arg); - pushStackFrame(function, arg); + pushStackFrame(new LispStackFrame(function, arg)); try { return function.execute(arg); } @@ -649,7 +531,7 @@ if (use_fast_calls) return function.execute(first, second); - pushStackFrame(function, first, second); + pushStackFrame(new LispStackFrame(function, first, second)); try { return function.execute(first, second); } @@ -667,7 +549,7 @@ if (use_fast_calls) return function.execute(first, second, third); - pushStackFrame(function, first, second, third); + pushStackFrame(new LispStackFrame(function, first, second, third)); try { return function.execute(first, second, third); } @@ -686,7 +568,7 @@ if (use_fast_calls) return function.execute(first, second, third, fourth); - pushStackFrame(function, first, second, third, fourth); + pushStackFrame(new LispStackFrame(function, first, second, third, fourth)); try { return function.execute(first, second, third, fourth); } @@ -705,7 +587,8 @@ if (use_fast_calls) return function.execute(first, second, third, fourth, fifth); - pushStackFrame(function, first, second, third, fourth, fifth); + pushStackFrame(new LispStackFrame(function, first, second, third, + fourth, fifth)); try { return function.execute(first, second, third, fourth, fifth); } @@ -725,7 +608,8 @@ if (use_fast_calls) return function.execute(first, second, third, fourth, fifth, sixth); - pushStackFrame(function, first, second, third, fourth, fifth, sixth); + pushStackFrame(new LispStackFrame(function, first, second, third, + fourth, fifth, sixth)); try { return function.execute(first, second, third, fourth, fifth, sixth); } @@ -746,8 +630,8 @@ return function.execute(first, second, third, fourth, fifth, sixth, seventh); - pushStackFrame(function, first, second, third, fourth, fifth, sixth, - seventh); + pushStackFrame(new LispStackFrame(function, first, second, third, fourth, + fifth, sixth, seventh)); try { return function.execute(first, second, third, fourth, fifth, sixth, seventh); @@ -769,8 +653,8 @@ return function.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); - pushStackFrame(function, first, second, third, fourth, fifth, sixth, - seventh, eighth); + pushStackFrame(new LispStackFrame(function, first, second, third, fourth, + fifth, sixth, seventh, eighth)); try { return function.execute(first, second, third, fourth, fifth, sixth, seventh, eighth); @@ -787,7 +671,7 @@ if (use_fast_calls) return function.execute(args); - pushStackFrame(function, args); + pushStackFrame(new LispStackFrame(function, args)); try { return function.execute(args); } @@ -796,13 +680,41 @@ popStackFrame(); } } - - public void backtrace() + + public LispObject backtrace() + throws ConditionThrowable { - backtrace(0); + return backtrace(0); } - public void backtrace(int limit) + public LispObject backtrace(int limit) + throws ConditionThrowable + { + LispObject result = NIL; + if (stack != null) { + int count = 0; + try { + StackFrame s = stack; + while (s != null) { + result = result.push(s); + if (limit > 0 && ++count == limit) + break; + s = s.next; + } + } + catch (Throwable t) { + t.printStackTrace(); + } + } + return result.nreverse(); + } + + public void printBacktrace() + { + printBacktrace(0); + } + + public void printBacktrace(int limit) { if (stack != null) { try { @@ -818,7 +730,7 @@ out._writeString(String.valueOf(count)); out._writeString(": "); - pprint(s.toList(), out.getCharPos(), out); + pprint(s.toLispList(), out.getCharPos(), out); out.terpri(); out._finishOutput(); if (limit > 0 && ++count == limit) @@ -832,35 +744,35 @@ } } + public LispObject backtraceAsList() + throws ConditionThrowable + { + return backtraceAsList(0); + } + public LispObject backtraceAsList(int limit) throws ConditionThrowable { LispObject result = NIL; - if (stack != null) { - int count = 0; - try { - StackFrame s = stack; - while (s != null) { - result = result.push(s.toList()); - if (limit > 0 && ++count == limit) - break; - s = s.next; - } - } - catch (Throwable t) { - t.printStackTrace(); - } - } - return result.nreverse(); + LispObject backtrace = backtrace(limit); + + StackFrame s = stack; + while (s != null) { + result = result.push(s.toLispList()); + s = s.getNext(); + } + return result.nreverse(); } public void incrementCallCounts() throws ConditionThrowable { StackFrame s = stack; while (s != null) { - LispObject operator = s.operator; - if (operator != null) - operator.incrementCallCount(); - s = s.next; + if (s instanceof LispStackFrame) { + LispObject operator = ((LispStackFrame)s).operator; + if (operator != null) + operator.incrementCallCount(); + } + s = s.getNext(); } } @@ -1120,9 +1032,25 @@ } }; + // ### backtrace + private static final Primitive BACKTRACE + = new Primitive("backtrace", PACKAGE_SYS, true) + { + @Override + public LispObject execute(LispObject[] args) + throws ConditionThrowable + { + if (args.length > 1) + return error(new WrongNumberOfArgumentsException(this)); + int limit = args.length > 0 ? Fixnum.getValue(args[0]) : 0; + return currentThread().backtrace(limit); + } + }; + + // ### backtrace-as-list private static final Primitive BACKTRACE_AS_LIST = - new Primitive("backtrace-as-list", PACKAGE_EXT, true, "", + new Primitive("backtrace-as-list", PACKAGE_SYS, true, "n", "Returns a backtrace of the invoking thread as a list.") { @Override @@ -1136,6 +1064,53 @@ } }; +// // ### print-backtrace +// private static final Primitive PRINT_BACKTRACE +// = new Primitive("print-backtrace", PACKAGE_SYS, true) +// { +// @Override +// public LispObject execute(LispObject[] args) +// throws ConditionThrowable +// { +// if (args.length > 1) +// return error(new WrongNumberOfArgumentsException(this)); +// int limit = args.length > 0 ? Fixnum.getValue(args[0]) : 0; +// currentThread().printBacktrace(limit); +// } + +// }; + + // ### frame-to-string + private static final Primitive FRAME_TO_STRING = + new Primitive("frame-to-string", PACKAGE_SYS, true, "frame") + { + @Override + public LispObject execute(LispObject[] args) + throws ConditionThrowable + { + if (args.length != 1) + return error(new WrongNumberOfArgumentsException(this)); + + return checkStackFrame(args[0]).toLispString(); + } + }; + + // ### frame-to-list + private static final Primitive FRAME_TO_LIST = + new Primitive("frame-to-list", PACKAGE_SYS, true, "frame") + { + @Override + public LispObject execute(LispObject[] args) + throws ConditionThrowable + { + if (args.length != 1) + return error(new WrongNumberOfArgumentsException(this)); + + return checkStackFrame(args[0]).toLispList(); + } + }; + + static { //FIXME: this block has been added for pre-0.16 compatibility // and can be removed the latest at release 0.22 diff -r bffd7288416c src/org/armedbear/lisp/StackFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/armedbear/lisp/StackFrame.java Sat Aug 01 07:18:46 2009 +0200 @@ -0,0 +1,61 @@ +/* + * StackFrame.java + * + * Copyright (C) 2009 Mark Evenson + * $Id$ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on this library. If you modify this library, you may extend + * this exception to your version of the library, but you are not + * obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +package org.armedbear.lisp; + +public abstract class StackFrame + extends LispObject +{ + @Override + public LispObject typep(LispObject typeSpecifier) + throws ConditionThrowable + { + if (typeSpecifier == Symbol.STACK_FRAME) + return T; + if (typeSpecifier == BuiltInClass.STACK_FRAME) + return T; + return super.typep(typeSpecifier); + } + + StackFrame next; + + void setNext(StackFrame nextFrame) { + this.next = nextFrame; + } + StackFrame getNext() { + return this.next; + } + + public abstract LispObject toLispList() throws ConditionThrowable; + public abstract SimpleString toLispString() throws ConditionThrowable; +} diff -r bffd7288416c src/org/armedbear/lisp/Symbol.java --- a/src/org/armedbear/lisp/Symbol.java Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/Symbol.java Sat Aug 01 07:18:46 2009 +0200 @@ -3032,6 +3032,13 @@ public static final Symbol STRING_OUTPUT_STREAM = PACKAGE_SYS.addInternalSymbol("STRING-OUTPUT-STREAM"); + public static final Symbol STACK_FRAME = + PACKAGE_SYS.addInternalSymbol("STACK-FRAME"); + public static final Symbol LISP_STACK_FRAME = + PACKAGE_SYS.addInternalSymbol("LISP-STACK-FRAME"); + public static final Symbol JAVA_STACK_FRAME = + PACKAGE_SYS.addInternalSymbol("JAVA-STACK-FRAME"); + // CDR6 public static final Symbol _INSPECTOR_HOOK_ = PACKAGE_EXT.addExternalSymbol("*INSPECTOR-HOOK*"); diff -r bffd7288416c src/org/armedbear/lisp/debug.lisp --- a/src/org/armedbear/lisp/debug.lisp Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/debug.lisp Sat Aug 01 07:18:46 2009 +0200 @@ -100,7 +100,7 @@ (simple-format *debug-io* " ~A~%" condition))))) (defun invoke-debugger (condition) - (let ((*saved-backtrace* (backtrace-as-list))) + (let ((*saved-backtrace* (sys:backtrace-as-list))) (when *debugger-hook* (let ((hook-function *debugger-hook*) (*debugger-hook* nil)) diff -r bffd7288416c src/org/armedbear/lisp/signal.lisp --- a/src/org/armedbear/lisp/signal.lisp Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/signal.lisp Sat Aug 01 07:18:46 2009 +0200 @@ -49,7 +49,7 @@ (let* ((old-bos *break-on-signals*) (*break-on-signals* nil)) (when (typep condition old-bos) - (let ((*saved-backtrace* (backtrace-as-list))) + (let ((*saved-backtrace* (sys:backtrace-as-list))) (break "~A~%BREAK called because of *BREAK-ON-SIGNALS* (now rebound to NIL)." condition)))) (loop diff -r bffd7288416c src/org/armedbear/lisp/top-level.lisp --- a/src/org/armedbear/lisp/top-level.lisp Fri Jul 31 00:49:28 2009 +0200 +++ b/src/org/armedbear/lisp/top-level.lisp Sat Aug 01 07:18:46 2009 +0200 @@ -102,6 +102,19 @@ (%format *debug-io* "~A~%" s)) (show-restarts (compute-restarts) *debug-io*))) +(defun print-frame (frame stream &key prefix) + (when prefix + (write-string prefix stream)) + (when (not (consp frame)) + (setf frame (sys:frame-to-list frame))) + (pprint-logical-block (stream nil :prefix "(" :suffix ")") + (ignore-errors + (prin1 (car frame) stream) + (let ((args (cdr frame))) + (if (listp args) + (format stream "~{ ~_~S~}" args) + (format stream " ~S" args)))))) + (defun backtrace-command (args) (let ((count (or (and args (ignore-errors (parse-integer args))) 8)) @@ -113,14 +126,7 @@ (*print-array* nil)) (dolist (frame *saved-backtrace*) (fresh-line *debug-io*) - (let ((prefix (format nil "~3D: (" n))) - (pprint-logical-block (*debug-io* nil :prefix prefix :suffix ")") - (ignore-errors - (prin1 (car frame) *debug-io*) - (let ((args (cdr frame))) - (if (listp args) - (format *debug-io* "~{ ~_~S~}" args) - (format *debug-io* " ~S" args)))))) + (print-frame frame *debug-io* :prefix (format nil "~3D: " n)) (incf n) (when (>= n count) (return)))))) @@ -136,12 +142,7 @@ (*print-readably* nil) (*print-structure* nil)) (fresh-line *debug-io*) - (pprint-logical-block (*debug-io* nil :prefix "(" :suffix ")") - (prin1 (car frame) *debug-io*) - (let ((args (cdr frame))) - (if (listp args) - (format *debug-io* "~{ ~_~S~}" args) - (format *debug-io* " ~S" args)))))) + (print-frame frame *debug-io*))) (setf *** ** ** * * frame)))