Author: Armin Rigo <ar...@tunes.org>
Branch: reverse-debugger
Changeset: r85093:9b64e55324a4
Date: 2016-06-11 10:28 +0200
http://bitbucket.org/pypy/pypy/changeset/9b64e55324a4/

Log:    Debug commands written in RPython

diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -1125,6 +1125,13 @@
         exc_data.exc_value = lltype.typeOf(evalue)._defl()
         return bool(etype)
 
+    def op_revdb_stop_point(self, *args):
+        pass
+
+    def op_revdb_send_output(self, ll_string):
+        from rpython.rtyper.annlowlevel import hlstr
+        sys.stdout.write(hlstr(ll_string))
+
 
 class Tracer(object):
     Counter = 0
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -566,6 +566,7 @@
     'instrument_count':     LLOp(),
 
     'revdb_stop_point':     LLOp(),
+    'revdb_send_output':    LLOp(),
 }
 # ***** Run test_lloperation after changes. *****
 
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -159,6 +159,10 @@
 
             self.c_entrypoint_name = pfname
 
+        if self.config.translation.reverse_debugger:
+            from rpython.translator.revdb import revdb_genc
+            revdb_genc.prepare_database(db)
+
         for obj in exports.EXPORTS_obj2name.keys():
             db.getcontainernode(obj)
         exports.clear()
diff --git a/rpython/translator/revdb/rdb-src/revdb.c 
b/rpython/translator/revdb/rdb-src/revdb.c
--- a/rpython/translator/revdb/rdb-src/revdb.c
+++ b/rpython/translator/revdb/rdb-src/revdb.c
@@ -7,6 +7,9 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include "preimpl.h"
+#include "structdef.h"
+#include "src/rtyper.h"
 #include "rdb-src/revdb_include.h"
 
 #define RDB_SIGNATURE   0x0A424452    /* "RDB\n" */
@@ -292,12 +295,36 @@
     return rpy_rev_buffer;
 }
 
+/* generated by RPython */
+extern char *rpy_revdb_command_names[];
+extern void (*rpy_revdb_command_funcs[])(RPyString *);
+
+static void execute_rpy_command(long index, char *arguments)
+{
+    size_t length = strlen(arguments);
+    RPyString *s;
+
+    while (length > 0 && isspace(arguments[length - 1]))
+        length--;
+    s = malloc(sizeof(RPyString) + length);
+    if (s == NULL) {
+        fprintf(stderr, "out of memory\n");
+        exit(1);
+    }
+    /* xxx assumes Boehm here for now */
+    memset(s, 0, sizeof(RPyString));
+    RPyString_Size(s) = length;
+    memcpy(_RPyString_AsString(s), arguments, length);
+
+    rpy_revdb_command_funcs[index](s);
+}
+
 struct action_s {
     const char *name;
     void (*act)(char *);
 };
 
-static void process_input(char *input, const char *kind,
+static void process_input(char *input, const char *kind, int rpycmd,
                           struct action_s actions[])
 {
     char *p;
@@ -310,24 +337,37 @@
         p++;
     if (*p != 0) {
         *p = 0;
-        p++;
+        do {
+            p++;
+        } while (isspace(*p));
     }
-    a = actions;
-    while (a->name != NULL && strcmp(a->name, input) != 0) {
-        a++;
+
+    if (rpycmd) {
+        long i;
+        for (i = 0; rpy_revdb_command_names[i] != NULL; i++) {
+            if (strcmp(rpy_revdb_command_names[i], input) == 0) {
+                execute_rpy_command(i, p);
+                return;
+            }
+        }
     }
-    if (a->name != NULL) {
-        while (isspace(*p))
-            p++;
-        a->act(p);
+
+    for (a = actions; a->name != NULL; a++) {
+        if (strcmp(a->name, input) == 0) {
+            a->act(p);
+            return;
+        }
     }
-    else if (strcmp(input, "help") == 0) {
-        a = actions;
+    if (strcmp(input, "help") == 0) {
         printf("select %s:\n", kind);
-        while (a->name != NULL) {
+        if (rpycmd) {
+            char **p;
+            for (p = rpy_revdb_command_names; *p != NULL; p++)
+                printf("\t%s\n", *p);
+        }
+        for (a = actions; a->name != NULL; a++) {
             if (*a->name != 0)
                 printf("\t%s\n", a->name);
-            a++;
         }
     }
     else {
@@ -552,7 +592,7 @@
         { "fork", act_info_fork },
         { NULL }
     };
-    process_input(p, "category", actions_info);
+    process_input(p, "category", 0, actions_info);
 }
 
 static void act_nop(char *p)
@@ -588,9 +628,10 @@
         fflush(stdout);
         if (fgets(input, sizeof(input), stdin) != input) {
             fprintf(stderr, "\n");
-            strcpy(input, "exit");
+            act_quit("");
+            abort();   /* unreachable */
         }
-        process_input(input, "command", actions_1);
+        process_input(input, "command", 1, actions_1);
     }
 }
 
@@ -606,5 +647,11 @@
     run_debug_process();
 }
 
+RPY_EXTERN
+void rpy_reverse_db_send_output(RPyString *output)
+{
+    fwrite(_RPyString_AsString(output), 1, RPyString_Size(output), stdout);
+}
+
 
 /* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/rdb-src/revdb_include.h 
b/rpython/translator/revdb/rdb-src/revdb_include.h
--- a/rpython/translator/revdb/rdb-src/revdb_include.h
+++ b/rpython/translator/revdb/rdb-src/revdb_include.h
@@ -56,11 +56,15 @@
 
 #define OP_REVDB_STOP_POINT(stop_point, r)                              \
     if (++rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break)      \
-        rpy_reverse_db_break(stop_point);
+        rpy_reverse_db_break(stop_point)
+
+#define OP_REVDB_SEND_OUTPUT(ll_string, r)                              \
+    rpy_reverse_db_send_output(ll_string)
 
 RPY_EXTERN void rpy_reverse_db_flush(void);
 RPY_EXTERN char *rpy_reverse_db_fetch(int expected_size);
 RPY_EXTERN void rpy_reverse_db_break(long stop_point);
+RPY_EXTERN void rpy_reverse_db_send_output(RPyString *output);
 
 
 /* ------------------------------------------------------------ */
diff --git a/rpython/translator/revdb/revdb_genc.py 
b/rpython/translator/revdb/revdb_genc.py
--- a/rpython/translator/revdb/revdb_genc.py
+++ b/rpython/translator/revdb/revdb_genc.py
@@ -1,6 +1,7 @@
 import py
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import lltype, rffi, rstr
 from rpython.translator.c.support import cdecl
+from rpython.rlib import exports
 
 
 def extra_files():
@@ -16,3 +17,26 @@
     if tp == 'void @':
         return emit_void(normal_code)
     return 'RPY_REVDB_EMIT(%s, %s, %s);' % (normal_code, cdecl(tp, '_e'), 
value)
+
+
+def prepare_database(db):
+    FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Ptr(rstr.STR)], lltype.Void))
+
+    bk = db.translator.annotator.bookkeeper
+    cmds = getattr(db.translator, 'revdb_commands', {}).items()
+
+    array_names = lltype.malloc(rffi.CArray(rffi.CCHARP), len(cmds) + 1,
+                                flavor='raw', immortal=True, zero=True)
+    array_funcs = lltype.malloc(rffi.CArray(FUNCPTR), len(cmds),
+                                flavor='raw', immortal=True, zero=True)
+
+    for i, (name, func) in enumerate(cmds):
+        fnptr = lltype.getfunctionptr(bk.getdesc(func).getuniquegraph())
+        assert lltype.typeOf(fnptr) == FUNCPTR
+        array_names[i] = rffi.str2charp(name)
+        array_funcs[i] = fnptr
+
+    exports.EXPORTS_obj2name[array_names._as_obj()] = 'rpy_revdb_command_names'
+    exports.EXPORTS_obj2name[array_funcs._as_obj()] = 'rpy_revdb_command_funcs'
+    db.get(array_names)
+    db.get(array_funcs)
diff --git a/rpython/translator/revdb/test/test_basic.py 
b/rpython/translator/revdb/test/test_basic.py
--- a/rpython/translator/revdb/test/test_basic.py
+++ b/rpython/translator/revdb/test/test_basic.py
@@ -181,3 +181,29 @@
         child.expectx('(3)$ ')
         child.sendline('info fork')
         child.expectx('latest_fork=3\r\n')
+
+
+class TestDebugCommands(InteractiveTests):
+
+    def setup_class(cls):
+        #
+        def blip(cmdline):
+            revdb.send_output('<<<' + cmdline + '>>>\n')
+            revdb.send_output('blipped\n')
+        lambda_blip = lambda: blip
+        #
+        def main(argv):
+            revdb.register_debug_command('r', lambda_blip)
+            for op in argv[1:]:
+                revdb.stop_point(42)
+                print op
+            return 9
+        compile(cls, main, [], backendopt=False)
+        assert run(cls, 'abc d ef') == 'abc\nd\nef\n'
+
+    def test_run_blip(self):
+        child = self.replay()
+        child.expectx('(3)$ ')
+        child.sendline('r  foo  bar  baz  ')
+        child.expectx('<<<foo  bar  baz>>>\r\nblipped\r\n')
+        child.expectx('(3)$ ')
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to